Add state checks in GrMtlRenderCommandEncoder.
Change-Id: I9dcfc0dd559fe1596019f0d8051f665f69a6960d Reviewed-on: https://skia-review.googlesource.com/c/skia/+/419163 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
90401eb437
commit
f87f5b02ec
@ -817,7 +817,6 @@ skia_metal_sources = [
|
||||
"$_src/gpu/mtl/GrMtlPipelineStateDataManager.h",
|
||||
"$_src/gpu/mtl/GrMtlPipelineStateDataManager.mm",
|
||||
"$_src/gpu/mtl/GrMtlRenderCommandEncoder.h",
|
||||
"$_src/gpu/mtl/GrMtlRenderCommandEncoder.mm",
|
||||
"$_src/gpu/mtl/GrMtlRenderTarget.h",
|
||||
"$_src/gpu/mtl/GrMtlRenderTarget.mm",
|
||||
"$_src/gpu/mtl/GrMtlResourceProvider.h",
|
||||
|
@ -89,6 +89,12 @@ void GrRingBuffer::startSubmit(GrGpu* gpu) {
|
||||
fPreviousBuffers.clear();
|
||||
|
||||
if (fNewAllocation) {
|
||||
#ifdef SK_BUILD_FOR_MAC
|
||||
// Since we're using a Managed buffer on MacOS we need to unmap to write back to GPU
|
||||
// TODO: once we set up persistently mapped UPLOAD buffers on D3D, we can remove the
|
||||
// platform restriction.
|
||||
fCurrentBuffer->unmap();
|
||||
#endif
|
||||
SubmitData* submitData = new SubmitData();
|
||||
submitData->fOwner = this;
|
||||
submitData->fLastHead = fHead;
|
||||
|
@ -295,7 +295,8 @@ void GrMtlCaps::initGrCaps(id<MTLDevice> device) {
|
||||
fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
|
||||
fMaxTextureSize = fMaxRenderTargetSize;
|
||||
|
||||
fMaxPushConstantsSize = 4*1024;
|
||||
fMaxPushConstantsSize = 0; // TODO: should be 4*1024 but disabled for now
|
||||
fTransferBufferAlignment = 1;
|
||||
|
||||
// Init sample counts. All devices support 1 (i.e. 0 in skia).
|
||||
fSampleCounts.push_back(1);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "src/gpu/GrFinishCallbacks.h"
|
||||
#include "src/gpu/GrGpu.h"
|
||||
#include "src/gpu/GrRenderTarget.h"
|
||||
#include "src/gpu/GrRingBuffer.h"
|
||||
#include "src/gpu/GrSemaphore.h"
|
||||
#include "src/gpu/GrStagingBufferManager.h"
|
||||
#include "src/gpu/GrTexture.h"
|
||||
@ -114,6 +115,8 @@ public:
|
||||
this->didWriteToSurface(surface, origin, bounds);
|
||||
}
|
||||
|
||||
GrRingBuffer* uniformsRingBuffer() override { return &fUniformsRingBuffer; }
|
||||
|
||||
private:
|
||||
GrMtlGpu(GrDirectContext*, const GrContextOptions&, id<MTLDevice>,
|
||||
id<MTLCommandQueue>, GrMTLHandle binaryArchive, MTLFeatureSet);
|
||||
@ -303,6 +306,7 @@ private:
|
||||
|
||||
GrMtlResourceProvider fResourceProvider;
|
||||
GrStagingBufferManager fStagingBufferManager;
|
||||
GrRingBuffer fUniformsRingBuffer;
|
||||
|
||||
bool fDisconnected;
|
||||
|
||||
|
@ -149,6 +149,7 @@ GrMtlGpu::GrMtlGpu(GrDirectContext* direct, const GrContextOptions& options,
|
||||
, fOutstandingCommandBuffers(sizeof(OutstandingCommandBuffer), kDefaultOutstandingAllocCnt)
|
||||
, fResourceProvider(this)
|
||||
, fStagingBufferManager(this)
|
||||
, fUniformsRingBuffer(this, 128 * 1024, 256, GrGpuBufferType::kVertex)
|
||||
, fDisconnected(false) {
|
||||
fMtlCaps.reset(new GrMtlCaps(options, fDevice, featureSet));
|
||||
this->initCapsAndCompiler(fMtlCaps);
|
||||
@ -225,8 +226,8 @@ GrMtlCommandBuffer* GrMtlGpu::commandBuffer() {
|
||||
}
|
||||
|
||||
void GrMtlGpu::takeOwnershipOfBuffer(sk_sp<GrGpuBuffer> buffer) {
|
||||
SkASSERT(fCurrentCmdBuffer);
|
||||
fCurrentCmdBuffer->addGrBuffer(std::move(buffer));
|
||||
SkASSERT(buffer);
|
||||
this->commandBuffer()->addGrBuffer(std::move(buffer));
|
||||
}
|
||||
|
||||
void GrMtlGpu::submit(GrOpsRenderPass* renderPass) {
|
||||
|
@ -64,7 +64,6 @@ private:
|
||||
|
||||
void setVertexBuffer(GrMtlRenderCommandEncoder*, const GrBuffer*, size_t offset,
|
||||
size_t inputBufferIndex);
|
||||
void resetBufferBindings();
|
||||
void precreateCmdEncoder();
|
||||
|
||||
GrMtlGpu* fGpu;
|
||||
@ -76,7 +75,7 @@ private:
|
||||
SkRect fBounds;
|
||||
size_t fCurrentVertexStride;
|
||||
|
||||
static constexpr size_t kNumBindings = GrMtlUniformHandler::kLastUniformBinding + 3;
|
||||
static constexpr size_t kNumBindings = GrMtlUniformHandler::kUniformBindingCount + 2;
|
||||
struct {
|
||||
id<MTLBuffer> fBuffer;
|
||||
size_t fOffset;
|
||||
|
@ -191,7 +191,6 @@ void GrMtlOpsRenderPass::initRenderState(GrMtlRenderCommandEncoder* encoder) {
|
||||
(double) fRenderTarget->width(), (double) fRenderTarget->height(),
|
||||
0.0, 1.0 };
|
||||
encoder->setViewport(viewport);
|
||||
this->resetBufferBindings();
|
||||
encoder->popDebugGroup();
|
||||
}
|
||||
|
||||
@ -415,29 +414,8 @@ void GrMtlOpsRenderPass::setVertexBuffer(GrMtlRenderCommandEncoder* encoder,
|
||||
auto mtlBuffer = static_cast<const GrMtlBuffer*>(buffer);
|
||||
id<MTLBuffer> mtlVertexBuffer = mtlBuffer->mtlBuffer();
|
||||
SkASSERT(mtlVertexBuffer);
|
||||
// Apple recommends using setVertexBufferOffset: when changing the offset
|
||||
// for a currently bound vertex buffer, rather than setVertexBuffer:
|
||||
// TODO: ensure this is tracking state properly, or track in GrMtlRenderCommandEncoder.
|
||||
size_t offset = mtlBuffer->offset() + vertexOffset;
|
||||
if (fBufferBindings[index].fBuffer != mtlVertexBuffer) {
|
||||
encoder->setVertexBuffer(mtlVertexBuffer, offset, index);
|
||||
fBufferBindings[index].fBuffer = mtlVertexBuffer;
|
||||
fBufferBindings[index].fOffset = offset;
|
||||
} else if (fBufferBindings[index].fOffset != offset) {
|
||||
if (@available(macOS 10.11, iOS 8.3, *)) {
|
||||
encoder->setVertexBufferOffset(offset, index);
|
||||
} else {
|
||||
// We only support iOS 9.0+, so we should never hit this
|
||||
SK_ABORT("Missing interface. Skia only supports Metal on iOS 9.0 and higher");
|
||||
}
|
||||
fBufferBindings[index].fOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void GrMtlOpsRenderPass::resetBufferBindings() {
|
||||
for (size_t i = 0; i < kNumBindings; ++i) {
|
||||
fBufferBindings[i].fBuffer = nil;
|
||||
}
|
||||
encoder->setVertexBuffer(mtlVertexBuffer, offset, index);
|
||||
}
|
||||
|
||||
GR_NORETAIN_END
|
||||
|
@ -109,17 +109,27 @@ void GrMtlPipelineStateDataManager::uploadAndBindUniformBuffers(
|
||||
GrMtlGpu* gpu,
|
||||
GrMtlRenderCommandEncoder* renderCmdEncoder) const {
|
||||
if (fUniformSize && fUniformsDirty) {
|
||||
if (@available(macOS 10.11, iOS 8.3, *)) {
|
||||
SkASSERT(fUniformSize <= gpu->caps()->maxPushConstantsSize());
|
||||
renderCmdEncoder->setVertexBytes(fUniformData.get(), fUniformSize,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
renderCmdEncoder->setFragmentBytes(fUniformData.get(), fUniformSize,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
} else {
|
||||
// We only support iOS 9.0+, so we should never hit this
|
||||
SK_ABORT("Missing interface. Skia only supports Metal on iOS 9.0 and higher");
|
||||
}
|
||||
fUniformsDirty = false;
|
||||
if (@available(macOS 10.11, iOS 8.3, *)) {
|
||||
if (fUniformSize <= gpu->caps()->maxPushConstantsSize()) {
|
||||
renderCmdEncoder->setVertexBytes(fUniformData.get(), fUniformSize,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
renderCmdEncoder->setFragmentBytes(fUniformData.get(), fUniformSize,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// upload the data
|
||||
GrRingBuffer::Slice slice = gpu->uniformsRingBuffer()->suballocate(fUniformSize);
|
||||
GrMtlBuffer* buffer = (GrMtlBuffer*) slice.fBuffer;
|
||||
char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset;
|
||||
memcpy(destPtr, fUniformData.get(), fUniformSize);
|
||||
|
||||
renderCmdEncoder->setVertexBuffer(buffer->mtlBuffer(), slice.fOffset,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
renderCmdEncoder->setFragmentBuffer(buffer->mtlBuffer(), slice.fOffset,
|
||||
GrMtlUniformHandler::kUniformBinding);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
#define GrMtlRenderCommandEncoder_DEFINED
|
||||
|
||||
#include <memory>
|
||||
#include "src/gpu/GrSamplerState.h"
|
||||
#include "src/gpu/mtl/GrMtlSampler.h"
|
||||
#include "src/gpu/mtl/GrMtlUniformHandler.h"
|
||||
#include "src/gpu/mtl/GrMtlUtil.h"
|
||||
|
||||
class GrMtlSampler;
|
||||
@ -39,7 +41,10 @@ public:
|
||||
}
|
||||
|
||||
void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
|
||||
[fCommandEncoder setRenderPipelineState:pso];
|
||||
if (fCurrentRenderPipelineState != pso) {
|
||||
[fCommandEncoder setRenderPipelineState:pso];
|
||||
fCurrentRenderPipelineState = pso;
|
||||
}
|
||||
}
|
||||
|
||||
void setTriangleFillMode(MTLTriangleFillMode fillMode) {
|
||||
@ -55,35 +60,80 @@ public:
|
||||
}
|
||||
|
||||
void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
|
||||
[fCommandEncoder setVertexBuffer:buffer
|
||||
offset:offset
|
||||
atIndex:index];
|
||||
if (@available(macOS 10.11, iOS 8.3, *)) {
|
||||
if (fCurrentVertexBuffer[index] == buffer) {
|
||||
this->setVertexBufferOffset(offset, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (fCurrentVertexBuffer[index] != buffer || fCurrentVertexOffset[index] != offset) {
|
||||
[fCommandEncoder setVertexBuffer:buffer
|
||||
offset:offset
|
||||
atIndex:index];
|
||||
fCurrentVertexBuffer[index] = buffer;
|
||||
fCurrentVertexOffset[index] = offset;
|
||||
}
|
||||
}
|
||||
void setVertexBufferOffset(NSUInteger offset, NSUInteger index) SK_API_AVAILABLE(ios(8.3)) {
|
||||
[fCommandEncoder setVertexBufferOffset:offset
|
||||
void setVertexBufferOffset(NSUInteger offset, NSUInteger index)
|
||||
SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
|
||||
if (fCurrentVertexOffset[index] != offset) {
|
||||
[fCommandEncoder setVertexBufferOffset:offset
|
||||
atIndex:index];
|
||||
fCurrentVertexOffset[index] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
|
||||
if (@available(macOS 10.11, iOS 8.3, *)) {
|
||||
if (fCurrentFragmentBuffer[index] == buffer) {
|
||||
this->setFragmentBufferOffset(offset, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (fCurrentFragmentBuffer[index] != buffer || fCurrentFragmentOffset[index] != offset) {
|
||||
[fCommandEncoder setFragmentBuffer:buffer
|
||||
offset:offset
|
||||
atIndex:index];
|
||||
fCurrentFragmentBuffer[index] = buffer;
|
||||
fCurrentFragmentOffset[index] = offset;
|
||||
}
|
||||
}
|
||||
void setFragmentBufferOffset(NSUInteger offset, NSUInteger index)
|
||||
SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
|
||||
if (fCurrentFragmentOffset[index] != offset) {
|
||||
[fCommandEncoder setFragmentBufferOffset:offset
|
||||
atIndex:index];
|
||||
fCurrentFragmentOffset[index] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index)
|
||||
SK_API_AVAILABLE(ios(8.3)) {
|
||||
SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
|
||||
[fCommandEncoder setVertexBytes:bytes
|
||||
length:length
|
||||
atIndex:index];
|
||||
}
|
||||
void setFragmentBytes(void* bytes, NSUInteger length, NSUInteger index)
|
||||
SK_API_AVAILABLE(ios(8.3)) {
|
||||
void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index)
|
||||
SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
|
||||
[fCommandEncoder setFragmentBytes:bytes
|
||||
length:length
|
||||
atIndex:index];
|
||||
}
|
||||
|
||||
void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) {
|
||||
[fCommandEncoder setFragmentTexture:texture
|
||||
atIndex:index];
|
||||
SkASSERT(index < 16);
|
||||
if (fCurrentTexture[index] != texture) {
|
||||
[fCommandEncoder setFragmentTexture:texture
|
||||
atIndex:index];
|
||||
fCurrentTexture[index] = texture;
|
||||
}
|
||||
}
|
||||
void setFragmentSamplerState(GrMtlSampler* sampler, NSUInteger index) {
|
||||
[fCommandEncoder setFragmentSamplerState: sampler->mtlSampler()
|
||||
atIndex: index];
|
||||
if (fCurrentSampler[index] != sampler) {
|
||||
[fCommandEncoder setFragmentSamplerState: sampler->mtlSampler()
|
||||
atIndex: index];
|
||||
fCurrentSampler[index] = sampler;
|
||||
}
|
||||
}
|
||||
|
||||
void setBlendColor(SkPMColor4f blendConst) {
|
||||
@ -104,11 +154,20 @@ public:
|
||||
[fCommandEncoder setStencilReferenceValue:referenceValue];
|
||||
}
|
||||
void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
|
||||
[fCommandEncoder setDepthStencilState:depthStencilState];
|
||||
if (depthStencilState != fCurrentDepthStencilState) {
|
||||
[fCommandEncoder setDepthStencilState:depthStencilState];
|
||||
fCurrentDepthStencilState = depthStencilState;
|
||||
}
|
||||
}
|
||||
|
||||
void setScissorRect(const MTLScissorRect& scissorRect) {
|
||||
[fCommandEncoder setScissorRect:scissorRect];
|
||||
if (fCurrentScissorRect.x != scissorRect.x ||
|
||||
fCurrentScissorRect.y != scissorRect.y ||
|
||||
fCurrentScissorRect.width != scissorRect.width ||
|
||||
fCurrentScissorRect.height != scissorRect.height) {
|
||||
[fCommandEncoder setScissorRect:scissorRect];
|
||||
fCurrentScissorRect = scissorRect;
|
||||
}
|
||||
}
|
||||
|
||||
void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
|
||||
@ -179,6 +238,16 @@ private:
|
||||
: fCommandEncoder(encoder) {}
|
||||
|
||||
id<MTLRenderCommandEncoder> fCommandEncoder = nil;
|
||||
|
||||
__weak id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
|
||||
__weak id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
|
||||
__weak id<MTLBuffer> fCurrentVertexBuffer[2 + GrMtlUniformHandler::kUniformBindingCount];
|
||||
NSUInteger fCurrentVertexOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
|
||||
__weak id<MTLBuffer> fCurrentFragmentBuffer[GrMtlUniformHandler::kUniformBindingCount];
|
||||
NSUInteger fCurrentFragmentOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
|
||||
__weak id<MTLTexture> fCurrentTexture[GrSamplerState::kNumUniqueSamplers];
|
||||
GrMtlSampler* fCurrentSampler[GrSamplerState::kNumUniqueSamplers] = { 0 };
|
||||
MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
|
||||
};
|
||||
|
||||
GR_NORETAIN_END
|
||||
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/mtl/GrMtlRenderCommandEncoder.h"
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error This file must be compiled with Arc. Use -fobjc-arc flag
|
||||
#endif
|
||||
|
||||
//GR_NORETAIN_BEGIN
|
||||
// Uncomment when we have code here
|
||||
//
|
||||
//GR_NORETAIN_END
|
@ -26,6 +26,7 @@ public:
|
||||
kUniformBinding = 0,
|
||||
kLastUniformBinding = kUniformBinding,
|
||||
};
|
||||
static constexpr int kUniformBindingCount = kLastUniformBinding + 1;
|
||||
|
||||
// fUBOffset is only valid if the GrSLType of the fVariable is not a sampler
|
||||
struct MtlUniformInfo : public UniformInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user