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:
Jim Van Verth 2021-06-22 10:30:50 -04:00 committed by Skia Commit-Bot
parent 90401eb437
commit f87f5b02ec
11 changed files with 122 additions and 71 deletions

View File

@ -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",

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
}
GR_NORETAIN_END

View File

@ -109,17 +109,27 @@ void GrMtlPipelineStateDataManager::uploadAndBindUniformBuffers(
GrMtlGpu* gpu,
GrMtlRenderCommandEncoder* renderCmdEncoder) const {
if (fUniformSize && fUniformsDirty) {
fUniformsDirty = false;
if (@available(macOS 10.11, iOS 8.3, *)) {
SkASSERT(fUniformSize <= gpu->caps()->maxPushConstantsSize());
if (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");
return;
}
fUniformsDirty = false;
}
// 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);
}
}

View File

@ -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) {
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) {
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)) {
}
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) {
SkASSERT(index < 16);
if (fCurrentTexture[index] != texture) {
[fCommandEncoder setFragmentTexture:texture
atIndex:index];
fCurrentTexture[index] = texture;
}
}
void setFragmentSamplerState(GrMtlSampler* sampler, NSUInteger 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) {
if (depthStencilState != fCurrentDepthStencilState) {
[fCommandEncoder setDepthStencilState:depthStencilState];
fCurrentDepthStencilState = depthStencilState;
}
}
void setScissorRect(const MTLScissorRect& 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

View File

@ -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

View File

@ -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 {