Add Metal support for dynamic texture state
Bug: skia:9604
Change-Id: I16f487137c79e37493cd24b63ee29ac2e22d6cec
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254981
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index db8aeab..a8e6b34 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -293,6 +293,8 @@
fCrossContextTextureSupport = false;
fHalfFloatVertexAttributeSupport = true;
+
+ fDynamicStateArrayGeometryProcessorTextureSupport = true;
}
static bool format_is_srgb(MTLPixelFormat format) {
diff --git a/src/gpu/mtl/GrMtlOpsRenderPass.mm b/src/gpu/mtl/GrMtlOpsRenderPass.mm
index e60f655..39110df 100644
--- a/src/gpu/mtl/GrMtlOpsRenderPass.mm
+++ b/src/gpu/mtl/GrMtlOpsRenderPass.mm
@@ -89,6 +89,7 @@
programInfo.pipeline().getXferProcessor());
bool hasDynamicScissors = programInfo.hasDynamicScissors();
+ bool hasDynamicTextures = programInfo.hasDynamicPrimProcTextures();
if (!programInfo.pipeline().isScissorEnabled()) {
GrMtlPipelineState::SetDynamicScissorRectState(fActiveRenderCmdEncoder,
@@ -103,6 +104,10 @@
programInfo.fixedScissor());
}
+ if (!hasDynamicTextures) {
+ pipelineState->bindTextures(fActiveRenderCmdEncoder);
+ }
+
for (int i = 0; i < meshCount; ++i) {
const GrMesh& mesh = meshes[i];
SkASSERT(nil != fActiveRenderCmdEncoder);
@@ -113,6 +118,11 @@
fOrigin,
programInfo.dynamicScissor(i));
}
+ if (hasDynamicTextures) {
+ auto meshProxies = programInfo.dynamicPrimProcTextures(i);
+ pipelineState->setTextures(programInfo, meshProxies);
+ pipelineState->bindTextures(fActiveRenderCmdEncoder);
+ }
mesh.sendToGpu(this);
}
diff --git a/src/gpu/mtl/GrMtlPipelineState.h b/src/gpu/mtl/GrMtlPipelineState.h
index e71aee2..a2e41f0 100644
--- a/src/gpu/mtl/GrMtlPipelineState.h
+++ b/src/gpu/mtl/GrMtlPipelineState.h
@@ -48,6 +48,10 @@
void setData(const GrRenderTarget*, const GrProgramInfo&);
+ void setTextures(const GrProgramInfo& programInfo,
+ const GrTextureProxy* const primProcTextures[]);
+ void bindTextures(id<MTLRenderCommandEncoder> renderCmdEncoder);
+
void setDrawState(id<MTLRenderCommandEncoder>, const GrSwizzle& outputSwizzle,
const GrXferProcessor&);
@@ -97,7 +101,7 @@
void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin);
- void bind(id<MTLRenderCommandEncoder>);
+ void bindUniforms(id<MTLRenderCommandEncoder>);
void setBlendConstants(id<MTLRenderCommandEncoder>, const GrSwizzle&, const GrXferProcessor&);
diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm
index fadaf4e6..cde1722 100644
--- a/src/gpu/mtl/GrMtlPipelineState.mm
+++ b/src/gpu/mtl/GrMtlPipelineState.mm
@@ -58,19 +58,33 @@
void GrMtlPipelineState::setData(const GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo) {
-
- // Note: the Metal backend currently only supports fixed primProc textures
- SkASSERT(!programInfo.hasDynamicPrimProcTextures());
- auto proxies = programInfo.hasFixedPrimProcTextures() ? programInfo.fixedPrimProcTextures()
- : nullptr;
-
this->setRenderTargetState(renderTarget, programInfo.origin());
fGeometryProcessor->setData(fDataManager, programInfo.primProc(),
GrFragmentProcessor::CoordTransformIter(programInfo.pipeline()));
+
+ if (!programInfo.hasDynamicPrimProcTextures()) {
+ auto proxies = programInfo.hasFixedPrimProcTextures() ? programInfo.fixedPrimProcTextures()
+ : nullptr;
+ this->setTextures(programInfo, proxies);
+ }
+ fDataManager.resetDirtyBits();
+
+#ifdef SK_DEBUG
+ if (programInfo.pipeline().isStencilEnabled()) {
+ SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
+ SkASSERT(renderTarget->renderTargetPriv().numStencilBits() == 8);
+ }
+#endif
+
+ fStencil = programInfo.nonGLStencilSettings();
+}
+
+void GrMtlPipelineState::setTextures(const GrProgramInfo& programInfo,
+ const GrTextureProxy* const primProcTextures[]) {
fSamplerBindings.reset();
for (int i = 0; i < programInfo.primProc().numTextureSamplers(); ++i) {
const auto& sampler = programInfo.primProc().textureSampler(i);
- auto texture = static_cast<GrMtlTexture*>(proxies[i]->peekTexture());
+ auto texture = static_cast<GrMtlTexture*>(primProcTextures[i]->peekTexture());
fSamplerBindings.emplace_back(sampler.samplerState(), texture, fGpu);
}
@@ -104,31 +118,23 @@
}
SkASSERT(fNumSamplers == fSamplerBindings.count());
- fDataManager.resetDirtyBits();
-
-#ifdef SK_DEBUG
- if (programInfo.pipeline().isStencilEnabled()) {
- SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
- SkASSERT(renderTarget->renderTargetPriv().numStencilBits() == 8);
- }
-#endif
-
- fStencil = programInfo.nonGLStencilSettings();
}
void GrMtlPipelineState::setDrawState(id<MTLRenderCommandEncoder> renderCmdEncoder,
const GrSwizzle& outputSwizzle,
const GrXferProcessor& xferProcessor) {
[renderCmdEncoder pushDebugGroup:@"setDrawState"];
- this->bind(renderCmdEncoder);
+ this->bindUniforms(renderCmdEncoder);
this->setBlendConstants(renderCmdEncoder, outputSwizzle, xferProcessor);
this->setDepthStencilState(renderCmdEncoder);
[renderCmdEncoder popDebugGroup];
}
-void GrMtlPipelineState::bind(id<MTLRenderCommandEncoder> renderCmdEncoder) {
+void GrMtlPipelineState::bindUniforms(id<MTLRenderCommandEncoder> renderCmdEncoder) {
fDataManager.uploadAndBindUniformBuffers(fGpu, renderCmdEncoder);
+}
+void GrMtlPipelineState::bindTextures(id<MTLRenderCommandEncoder> renderCmdEncoder) {
SkASSERT(fNumSamplers == fSamplerBindings.count());
for (int index = 0; index < fNumSamplers; ++index) {
[renderCmdEncoder setFragmentTexture: fSamplerBindings[index].fTexture