aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-06-06 12:27:16 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-07 18:26:11 +0000
commit46983b7dd88603bb2a9a3c3e1ce3e147f5615f2f (patch)
treecb2dccc7b6d44b1100dc34af92c60d7b243d01c7 /src/gpu
parent912e6b883782cd6a53348056012ff7ed38658c79 (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/gpu')
-rw-r--r--src/gpu/GrGpuCommandBuffer.cpp3
-rw-r--r--src/gpu/GrGpuCommandBuffer.h5
-rw-r--r--src/gpu/GrPipeline.cpp22
-rw-r--r--src/gpu/GrPipeline.h21
-rw-r--r--src/gpu/gl/GrGLGpu.cpp9
-rw-r--r--src/gpu/gl/GrGLGpu.h3
-rw-r--r--src/gpu/gl/GrGLGpuCommandBuffer.h5
-rw-r--r--src/gpu/ops/GrMeshDrawOp.cpp3
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.cpp35
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.h6
-rw-r--r--src/gpu/vk/GrVkPipeline.cpp76
-rw-r--r--src/gpu/vk/GrVkPipeline.h9
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 {