Introduce dynamic pipeline state
Adds a DynamicState struct to GrPipeline that has a field for the
scissor rect. Eventually this should become the only way to specify a
scissor rectangle and may grow to contain more fields. Adds an array of
DynamicStates to GrGpuCommandBuffer::draw and implements support in GL
and Vulkan.
Bug: skia:
Change-Id: If5aebbf9da5d192acf7e68e7def4674ffc7ec310
Reviewed-on: https://skia-review.googlesource.com/18510
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 6f39cfa..6e9c292 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -468,7 +468,8 @@
sk_sp<GrVkPipelineState> GrVkGpuCommandBuffer::prepareDrawState(
const GrPipeline& pipeline,
const GrPrimitiveProcessor& primProc,
- GrPrimitiveType primitiveType) {
+ GrPrimitiveType primitiveType,
+ bool hasDynamicState) {
CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
SkASSERT(cbInfo.fRenderPass);
@@ -492,7 +493,18 @@
pipelineState->bind(fGpu, cbInfo.currentCmdBuf());
- GrVkPipeline::SetDynamicState(fGpu, cbInfo.currentCmdBuf(), pipeline);
+ GrRenderTarget* rt = pipeline.getRenderTarget();
+
+ if (!pipeline.getScissorState().enabled()) {
+ GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt,
+ SkIRect::MakeWH(rt->width(), rt->height()));
+ } else if (!hasDynamicState) {
+ GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt,
+ pipeline.getScissorState().rect());
+ }
+ GrVkPipeline::SetDynamicViewportState(fGpu, cbInfo.currentCmdBuf(), rt);
+ GrVkPipeline::SetDynamicBlendConstantState(fGpu, cbInfo.currentCmdBuf(), rt->config(),
+ pipeline.getXferProcessor());
return pipelineState;
}
@@ -533,7 +545,8 @@
void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline,
const GrPrimitiveProcessor& primProc,
- const GrMesh* meshes,
+ const GrMesh meshes[],
+ const GrPipeline::DynamicState dynamicStates[],
int meshCount,
const SkRect& bounds) {
GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(pipeline.getRenderTarget());
@@ -557,11 +570,14 @@
GrPrimitiveType primitiveType = meshes[0].primitiveType();
sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
primProc,
- primitiveType);
+ primitiveType,
+ SkToBool(dynamicStates));
if (!pipelineState) {
return;
}
+ CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
+
for (int i = 0; i < meshCount; ++i) {
const GrMesh& mesh = meshes[i];
if (mesh.primitiveType() != primitiveType) {
@@ -573,17 +589,24 @@
primitiveType = mesh.primitiveType();
pipelineState = this->prepareDrawState(pipeline,
primProc,
- primitiveType);
+ primitiveType,
+ SkToBool(dynamicStates));
if (!pipelineState) {
return;
}
}
+ if (dynamicStates) {
+ if (pipeline.getScissorState().enabled()) {
+ GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(),
+ target, dynamicStates[i].fScissorRect);
+ }
+ }
+
SkASSERT(pipelineState);
mesh.sendToGpu(primProc, this);
}
- CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
cbInfo.fBounds.join(bounds);
cbInfo.fIsEmpty = false;
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index 6836fac..9ef166e 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -53,11 +53,13 @@
sk_sp<GrVkPipelineState> prepareDrawState(const GrPipeline&,
const GrPrimitiveProcessor&,
- GrPrimitiveType);
+ GrPrimitiveType,
+ bool hasDynamicState);
void onDraw(const GrPipeline& pipeline,
const GrPrimitiveProcessor& primProc,
- const GrMesh* mesh,
+ const GrMesh mesh[],
+ const GrPipeline::DynamicState[],
int meshCount,
const SkRect& bounds) override;
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index 2732c6f..0b4289e 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -481,65 +481,56 @@
GR_VK_CALL(gpu->vkInterface(), DestroyPipeline(gpu->device(), fPipeline, nullptr));
}
-static void set_dynamic_scissor_state(GrVkGpu* gpu,
- GrVkCommandBuffer* cmdBuffer,
- const GrPipeline& pipeline,
- const GrRenderTarget& target) {
- // We always use one scissor and if it is disabled we just make it the size of the RT
- const GrScissorState& scissorState = pipeline.getScissorState();
- VkRect2D scissor;
- if (scissorState.enabled() &&
- !scissorState.rect().contains(0, 0, target.width(), target.height())) {
- // This all assumes the scissorState has previously been clipped to the device space render
- // target.
- scissor.offset.x = SkTMax(scissorState.rect().fLeft, 0);
- scissor.extent.width = scissorState.rect().width();
- if (kTopLeft_GrSurfaceOrigin == target.origin()) {
- scissor.offset.y = scissorState.rect().fTop;
- } else {
- SkASSERT(kBottomLeft_GrSurfaceOrigin == target.origin());
- scissor.offset.y = target.height() - scissorState.rect().fBottom;
- }
- scissor.offset.y = SkTMax(scissor.offset.y, 0);
- scissor.extent.height = scissorState.rect().height();
-
- SkASSERT(scissor.offset.x >= 0);
- SkASSERT(scissor.offset.y >= 0);
- } else {
- scissor.extent.width = target.width();
- scissor.extent.height = target.height();
- scissor.offset.x = 0;
- scissor.offset.y = 0;
+void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu,
+ GrVkCommandBuffer* cmdBuffer,
+ const GrRenderTarget* renderTarget,
+ SkIRect scissorRect) {
+ if (!scissorRect.intersect(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()))) {
+ scissorRect.setEmpty();
}
+
+ VkRect2D scissor;
+ scissor.offset.x = scissorRect.fLeft;
+ scissor.extent.width = scissorRect.width();
+ if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) {
+ scissor.offset.y = scissorRect.fTop;
+ } else {
+ SkASSERT(kBottomLeft_GrSurfaceOrigin == renderTarget->origin());
+ scissor.offset.y = renderTarget->height() - scissorRect.fBottom;
+ }
+ scissor.extent.height = scissorRect.height();
+
+ SkASSERT(scissor.offset.x >= 0);
+ SkASSERT(scissor.offset.y >= 0);
cmdBuffer->setScissor(gpu, 0, 1, &scissor);
}
-static void set_dynamic_viewport_state(GrVkGpu* gpu,
- GrVkCommandBuffer* cmdBuffer,
- const GrRenderTarget& target) {
+void GrVkPipeline::SetDynamicViewportState(GrVkGpu* gpu,
+ GrVkCommandBuffer* cmdBuffer,
+ const GrRenderTarget* renderTarget) {
// We always use one viewport the size of the RT
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
- viewport.width = SkIntToScalar(target.width());
- viewport.height = SkIntToScalar(target.height());
+ viewport.width = SkIntToScalar(renderTarget->width());
+ viewport.height = SkIntToScalar(renderTarget->height());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
cmdBuffer->setViewport(gpu, 0, 1, &viewport);
}
-static void set_dynamic_blend_constant_state(GrVkGpu* gpu,
- GrVkCommandBuffer* cmdBuffer,
- const GrPipeline& pipeline) {
+void GrVkPipeline::SetDynamicBlendConstantState(GrVkGpu* gpu,
+ GrVkCommandBuffer* cmdBuffer,
+ GrPixelConfig pixelConfig,
+ const GrXferProcessor& xferProcessor) {
GrXferProcessor::BlendInfo blendInfo;
- pipeline.getXferProcessor().getBlendInfo(&blendInfo);
+ xferProcessor.getBlendInfo(&blendInfo);
GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
float floatColors[4];
if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
// Swizzle the blend to match what the shader will output.
- const GrSwizzle& swizzle = gpu->caps()->shaderCaps()->configOutputSwizzle(
- pipeline.getRenderTarget()->config());
+ const GrSwizzle& swizzle = gpu->caps()->shaderCaps()->configOutputSwizzle(pixelConfig);
GrColor blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
GrColorToRGBAFloat(blendConst, floatColors);
} else {
@@ -547,12 +538,3 @@
}
cmdBuffer->setBlendConstants(gpu, floatColors);
}
-
-void GrVkPipeline::SetDynamicState(GrVkGpu* gpu,
- GrVkCommandBuffer* cmdBuffer,
- const GrPipeline& pipeline) {
- const GrRenderTarget& target = *pipeline.getRenderTarget();
- set_dynamic_scissor_state(gpu, cmdBuffer, pipeline, target);
- set_dynamic_viewport_state(gpu, cmdBuffer, target);
- set_dynamic_blend_constant_state(gpu, cmdBuffer, pipeline);
-}
diff --git a/src/gpu/vk/GrVkPipeline.h b/src/gpu/vk/GrVkPipeline.h
index 585014e..d05974b 100644
--- a/src/gpu/vk/GrVkPipeline.h
+++ b/src/gpu/vk/GrVkPipeline.h
@@ -16,10 +16,13 @@
class GrPipeline;
class GrPrimitiveProcessor;
+class GrRenderTarget;
+class GrXferProcessor;
class GrStencilSettings;
class GrVkCommandBuffer;
class GrVkGpu;
class GrVkRenderPass;
+struct SkIRect;
class GrVkPipeline : public GrVkResource {
public:
@@ -36,7 +39,11 @@
VkPipeline pipeline() const { return fPipeline; }
- static void SetDynamicState(GrVkGpu*, GrVkCommandBuffer*, const GrPipeline&);
+ static void SetDynamicScissorRectState(GrVkGpu*, GrVkCommandBuffer*, const GrRenderTarget*,
+ SkIRect);
+ static void SetDynamicViewportState(GrVkGpu*, GrVkCommandBuffer*, const GrRenderTarget*);
+ static void SetDynamicBlendConstantState(GrVkGpu*, GrVkCommandBuffer*, GrPixelConfig,
+ const GrXferProcessor&);
#ifdef SK_TRACE_VK_RESOURCES
void dumpInfo() const override {