diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-06-06 12:27:16 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-07 18:26:11 +0000 |
commit | 46983b7dd88603bb2a9a3c3e1ce3e147f5615f2f (patch) | |
tree | cb2dccc7b6d44b1100dc34af92c60d7b243d01c7 /src | |
parent | 912e6b883782cd6a53348056012ff7ed38658c79 (diff) |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.h | 5 | ||||
-rw-r--r-- | src/gpu/GrPipeline.cpp | 22 | ||||
-rw-r--r-- | src/gpu/GrPipeline.h | 21 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpuCommandBuffer.h | 5 | ||||
-rw-r--r-- | src/gpu/ops/GrMeshDrawOp.cpp | 3 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.cpp | 35 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.h | 6 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipeline.cpp | 76 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipeline.h | 9 |
12 files changed, 123 insertions, 74 deletions
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp index 5570a5a65e..9659ca3b9a 100644 --- a/src/gpu/GrGpuCommandBuffer.cpp +++ b/src/gpu/GrGpuCommandBuffer.cpp @@ -39,6 +39,7 @@ void GrGpuCommandBuffer::clearStencilClip(GrRenderTarget* rt, const GrFixedClip& bool GrGpuCommandBuffer::draw(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrMesh meshes[], + const GrPipeline::DynamicState dynamicStates[], int meshCount, const SkRect& bounds) { #ifdef SK_DEBUG @@ -58,7 +59,7 @@ bool GrGpuCommandBuffer::draw(const GrPipeline& pipeline, this->gpu()->stats()->incNumFailedDraws(); return false; } - this->onDraw(pipeline, primProc, meshes, meshCount, bounds); + this->onDraw(pipeline, primProc, meshes, dynamicStates, meshCount, bounds); return true; } diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h index fb5dc00943..3a6a3e7005 100644 --- a/src/gpu/GrGpuCommandBuffer.h +++ b/src/gpu/GrGpuCommandBuffer.h @@ -9,6 +9,7 @@ #define GrGpuCommandBuffer_DEFINED #include "GrColor.h" +#include "GrPipeline.h" #include "ops/GrDrawOp.h" class GrOpFlushState; @@ -69,6 +70,7 @@ public: bool draw(const GrPipeline&, const GrPrimitiveProcessor&, const GrMesh[], + const GrPipeline::DynamicState[], int meshCount, const SkRect& bounds); @@ -99,7 +101,8 @@ private: // overridden by backend-specific derived class to perform the draw call. virtual void onDraw(const GrPipeline&, const GrPrimitiveProcessor&, - const GrMesh*, + const GrMesh[], + const GrPipeline::DynamicState[], int meshCount, const SkRect& bounds) = 0; diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 8d1b926be1..9d8b2ef984 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -112,15 +112,19 @@ void GrPipeline::addDependenciesTo(GrRenderTargetProxy* rtp) const { } } -GrPipeline::GrPipeline(GrRenderTarget* rt, SkBlendMode blendmode) - : fRenderTarget(rt) - , fScissorState() - , fWindowRectsState() - , fUserStencilSettings(&GrUserStencilSettings::kUnused) - , fFlags() - , fXferProcessor(GrPorterDuffXPFactory::MakeNoCoverageXP(blendmode)) - , fFragmentProcessors() - , fNumColorProcessors(0) {} +GrPipeline::GrPipeline(GrRenderTarget* rt, ScissorState scissorState, SkBlendMode blendmode) + : fRenderTarget(rt) + , fScissorState() + , fWindowRectsState() + , fUserStencilSettings(&GrUserStencilSettings::kUnused) + , fFlags() + , fXferProcessor(GrPorterDuffXPFactory::MakeNoCoverageXP(blendmode)) + , fFragmentProcessors() + , fNumColorProcessors(0) { + if (ScissorState::kEnabled == scissorState) { + fScissorState.set({0, 0, 0, 0}); // caller will use the DynamicState struct. + } +} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index 078cb68437..3fd518985d 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -68,6 +68,11 @@ public: return flags; } + enum ScissorState : bool { + kEnabled = true, + kDisabled = false + }; + struct InitArgs { uint32_t fFlags = 0; const GrProcessorSet* fProcessors = nullptr; // Must be finalized @@ -80,16 +85,26 @@ public: }; /** + * Graphics state that can change dynamically without creating a new pipeline. + **/ + struct DynamicState { + // Overrides the scissor rectangle (if scissor is enabled in the pipeline). + // TODO: eventually this should be the only way to specify a scissor rectangle, as is the + // case with the simple constructor. + SkIRect fScissorRect; + }; + + /** * A Default constructed pipeline is unusable until init() is called. **/ GrPipeline() = default; /** * Creates a simple pipeline with default settings and no processors. The provided blend mode - * must be "Porter Duff" (<= kLastCoeffMode). This pipeline is initialized without requiring - * a call to init(). + * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must + * specify a scissor rectangle through the DynamicState struct. **/ - GrPipeline(GrRenderTarget*, SkBlendMode); + GrPipeline(GrRenderTarget*, ScissorState, SkBlendMode); GrPipeline(const InitArgs& args) { this->init(args); } diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index b6c807656f..50c0edba45 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2449,6 +2449,7 @@ GrGLenum gPrimitiveType2GLMode[] = { void GrGLGpu::draw(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrMesh meshes[], + const GrPipeline::DynamicState dynamicStates[], int meshCount) { this->handleDirtyContext(); @@ -2468,6 +2469,14 @@ void GrGLGpu::draw(const GrPipeline& pipeline, this->xferBarrier(pipeline.getRenderTarget(), barrierType); } + if (dynamicStates) { + if (pipeline.getScissorState().enabled()) { + GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget()); + this->flushScissor(dynamicStates[i].fScissorRect, + glRT->getViewport(), glRT->origin()); + } + } + meshes[i].sendToGpu(primProc, this); } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 1785eae143..639b589f50 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -101,7 +101,8 @@ public: // on GrGLGpuCommandBuffer. void draw(const GrPipeline&, const GrPrimitiveProcessor&, - const GrMesh*, + const GrMesh[], + const GrPipeline::DynamicState[], int meshCount); diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h index c7c76a4a9c..c6e7208f4c 100644 --- a/src/gpu/gl/GrGLGpuCommandBuffer.h +++ b/src/gpu/gl/GrGLGpuCommandBuffer.h @@ -49,7 +49,8 @@ private: void onDraw(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, - const GrMesh* mesh, + const GrMesh mesh[], + const GrPipeline::DynamicState dynamicStates[], int meshCount, const SkRect& bounds) override { GrGLRenderTarget* target = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget()); @@ -57,7 +58,7 @@ private: fRenderTarget = target; } SkASSERT(target == fRenderTarget); - fGpu->draw(pipeline, primProc, mesh, meshCount); + fGpu->draw(pipeline, primProc, mesh, dynamicStates, meshCount); } void onClear(GrRenderTarget* rt, const GrFixedClip& clip, GrColor color) override { diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp index d6c2ced38a..d1367e9c9c 100644 --- a/src/gpu/ops/GrMeshDrawOp.cpp +++ b/src/gpu/ops/GrMeshDrawOp.cpp @@ -74,7 +74,8 @@ void GrMeshDrawOp::onExecute(GrOpFlushState* state) { const QueuedDraw& draw = fQueuedDraws[currDrawIdx]; SkASSERT(draw.fPipeline->getRenderTarget() == state->drawOpArgs().fRenderTarget); state->commandBuffer()->draw(*draw.fPipeline, *draw.fGeometryProcessor.get(), - fMeshes.begin() + currMeshIdx, draw.fMeshCnt, this->bounds()); + fMeshes.begin() + currMeshIdx, nullptr, draw.fMeshCnt, + this->bounds()); currMeshIdx += draw.fMeshCnt; state->flushToken(); } diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index 6f39cfa545..6e9c292f04 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -468,7 +468,8 @@ void GrVkGpuCommandBuffer::bindGeometry(const GrPrimitiveProcessor& primProc, 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 @@ sk_sp<GrVkPipelineState> GrVkGpuCommandBuffer::prepareDrawState( 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 @@ static void prepare_sampled_images(const GrResourceIOProcessor& processor, GrVkG 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 @@ void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline, 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 @@ void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline, 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 6836fac0ca..9ef166e7db 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.h +++ b/src/gpu/vk/GrVkGpuCommandBuffer.h @@ -53,11 +53,13 @@ private: 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 2732c6fc80..0b4289edec 100644 --- a/src/gpu/vk/GrVkPipeline.cpp +++ b/src/gpu/vk/GrVkPipeline.cpp @@ -481,65 +481,56 @@ void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const { 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(); +void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu, + GrVkCommandBuffer* cmdBuffer, + const GrRenderTarget* renderTarget, + SkIRect scissorRect) { + if (!scissorRect.intersect(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()))) { + scissorRect.setEmpty(); + } - SkASSERT(scissor.offset.x >= 0); - SkASSERT(scissor.offset.y >= 0); + VkRect2D scissor; + scissor.offset.x = scissorRect.fLeft; + scissor.extent.width = scissorRect.width(); + if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) { + scissor.offset.y = scissorRect.fTop; } else { - scissor.extent.width = target.width(); - scissor.extent.height = target.height(); - scissor.offset.x = 0; - scissor.offset.y = 0; + 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 @@ static void set_dynamic_blend_constant_state(GrVkGpu* gpu, } 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 585014e53c..d05974b102 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 @@ public: 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 { |