aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/vk
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2016-03-18 12:50:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-18 12:50:27 -0700
commit470d77a1d7dc286cdad98b145dac735cd7638e56 (patch)
treeb858138d3904d73fe7191fd1e0c5dd4540ce969f /src/gpu/vk
parent58fc94e55fb52704f86aa6fde97719131a3c9ed4 (diff)
Use dynamic state from vulkan pipelines
Diffstat (limited to 'src/gpu/vk')
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.cpp63
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.h38
-rw-r--r--src/gpu/vk/GrVkGpu.cpp6
-rw-r--r--src/gpu/vk/GrVkPipeline.cpp143
-rw-r--r--src/gpu/vk/GrVkPipeline.h4
5 files changed, 184 insertions, 70 deletions
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index d26d06d1c3..c05e9555cb 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -9,6 +9,7 @@
#include "GrVkFramebuffer.h"
#include "GrVkImageView.h"
+#include "GrVkPipeline.h"
#include "GrVkRenderPass.h"
#include "GrVkRenderTarget.h"
#include "GrVkProgram.h"
@@ -40,10 +41,20 @@ GrVkCommandBuffer::~GrVkCommandBuffer() {
}
void GrVkCommandBuffer::invalidateState() {
- fBoundVertexBuffer = 0;
+ fBoundVertexBuffer = VK_NULL_HANDLE;
fBoundVertexBufferIsValid = false;
- fBoundIndexBuffer = 0;
+ fBoundIndexBuffer = VK_NULL_HANDLE;
fBoundIndexBufferIsValid = false;
+
+ memset(&fCachedViewport, 0, sizeof(VkViewport));
+ fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0
+
+ memset(&fCachedScissor, 0, sizeof(VkRect2D));
+ fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid
+
+ for (int i = 0; i < 4; ++i) {
+ fCachedBlendConstant[i] = -1.0;
+ }
}
void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
@@ -355,6 +366,15 @@ void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
program->addUniformResources(*this);
}
+void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) {
+ SkASSERT(fIsActive);
+ SkASSERT(fActiveRenderPass);
+ GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ pipeline->pipeline()));
+ addResource(pipeline);
+}
+
void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu,
uint32_t indexCount,
uint32_t instanceCount,
@@ -384,3 +404,42 @@ void GrVkCommandBuffer::draw(const GrVkGpu* gpu,
firstVertex,
firstInstance));
}
+
+void GrVkCommandBuffer::setViewport(const GrVkGpu* gpu,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport* viewports) {
+ SkASSERT(fIsActive);
+ SkASSERT(1 == viewportCount);
+ if (memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) {
+ GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer,
+ firstViewport,
+ viewportCount,
+ viewports));
+ fCachedViewport = viewports[0];
+ }
+}
+
+void GrVkCommandBuffer::setScissor(const GrVkGpu* gpu,
+ uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D* scissors) {
+ SkASSERT(fIsActive);
+ SkASSERT(1 == scissorCount);
+ if (memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) {
+ GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer,
+ firstScissor,
+ scissorCount,
+ scissors));
+ fCachedScissor = scissors[0];
+ }
+}
+
+void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu,
+ const float blendConstants[4]) {
+ SkASSERT(fIsActive);
+ if (memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) {
+ GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants));
+ memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float));
+ }
+}
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 5cdb2c0b2f..f63a191426 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -9,11 +9,11 @@
#define GrVkCommandBuffer_DEFINED
#include "GrVkGpu.h"
-#include "GrVkPipeline.h"
#include "GrVkResource.h"
#include "GrVkUtil.h"
#include "vulkan/vulkan.h"
+class GrVkPipeline;
class GrVkRenderPass;
class GrVkRenderTarget;
class GrVkTransferBuffer;
@@ -39,15 +39,6 @@ public:
bool finished(const GrVkGpu* gpu) const;
////////////////////////////////////////////////////////////////////////////
- // CommandBuffer State/Object bindings
- ////////////////////////////////////////////////////////////////////////////
-#if 0
- void bindPipeline(const GrVkGpu* gpu) const;
- void bindDynamicState(const GrVkGpu* gpu) const;
- void bindDescriptorSet(const GrVkGpu* gpu) const;
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
// CommandBuffer commands
////////////////////////////////////////////////////////////////////////////
enum BarrierType {
@@ -91,13 +82,6 @@ public:
}
}
- void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) {
- GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- pipeline->pipeline()));
- addResource(pipeline);
- }
-
void bindDescriptorSets(const GrVkGpu* gpu,
GrVkProgram*,
VkPipelineLayout layout,
@@ -107,6 +91,18 @@ public:
uint32_t dynamicOffsetCount,
const uint32_t* dynamicOffsets);
+ void setViewport(const GrVkGpu* gpu,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport* viewports);
+
+ void setScissor(const GrVkGpu* gpu,
+ uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D* scissors);
+
+ void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
+
// Commands that only work outside of a render pass
void clearColorImage(const GrVkGpu* gpu,
GrVkImage* image,
@@ -149,6 +145,9 @@ public:
int numRects,
const VkClearRect* clearRects) const;
+ void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
+
+
void drawIndexed(const GrVkGpu* gpu,
uint32_t indexCount,
uint32_t instanceCount,
@@ -205,6 +204,11 @@ private:
// A nullptr means there is no active render pass. The GrVKCommandBuffer does not own the render
// pass.
const GrVkRenderPass* fActiveRenderPass;
+
+ // Cached values used for dynamic state updates
+ VkViewport fCachedViewport;
+ VkRect2D fCachedScissor;
+ float fCachedBlendConstant[4];
};
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index ee87f49b07..96c74ddd5d 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1533,6 +1533,9 @@ bool GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
(*program)->setData(this, primProc, pipeline);
(*program)->bind(this, fCurrentCmdBuffer);
+
+ GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
+
return true;
}
@@ -1548,6 +1551,8 @@ void GrVkGpu::onDraw(const GrPipeline& pipeline,
const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
SkASSERT(renderPass);
+ fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
+
GrVkProgram* program = nullptr;
GrPrimitiveType primitiveType = meshes[0].primitiveType();
if (!this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass, &program)) {
@@ -1590,7 +1595,6 @@ void GrVkGpu::onDraw(const GrPipeline& pipeline,
false);
}
- fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
for (int i = 0; i < meshCount; ++i) {
if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index c0197cd735..7571a40d58 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -9,7 +9,7 @@
#include "GrGeometryProcessor.h"
#include "GrPipeline.h"
-
+#include "GrVkCommandBuffer.h"
#include "GrVkGpu.h"
#include "GrVkProgramDesc.h"
#include "GrVkRenderTarget.h"
@@ -188,52 +188,18 @@ void setup_depth_stencil_state(const GrVkGpu* gpu,
void setup_viewport_scissor_state(const GrVkGpu* gpu,
const GrPipeline& pipeline,
const GrVkRenderTarget* vkRT,
- VkPipelineViewportStateCreateInfo* viewportInfo,
- VkViewport* viewport,
- VkRect2D* scissor) {
+ VkPipelineViewportStateCreateInfo* viewportInfo) {
memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportInfo->pNext = nullptr;
viewportInfo->flags = 0;
- viewport->x = 0.0f;
- viewport->y = 0.0f;
- viewport->width = SkIntToScalar(vkRT->width());
- viewport->height = SkIntToScalar(vkRT->height());
- viewport->minDepth = 0.0f;
- viewport->maxDepth = 1.0f;
viewportInfo->viewportCount = 1;
- viewportInfo->pViewports = viewport;
+ viewportInfo->pViewports = nullptr; // This is set dynamically
+
+ viewportInfo->scissorCount = 1;
+ viewportInfo->pScissors = nullptr; // This is set dynamically
- const GrScissorState& scissorState = pipeline.getScissorState();
- if (scissorState.enabled() &&
- !scissorState.rect().contains(0, 0, vkRT->width(), vkRT->height())) {
- // This all assumes the scissorState has previously been clipped to the device space render
- // target.
- scissor->offset.x = scissorState.rect().fLeft;
- scissor->extent.width = scissorState.rect().width();
- if (kTopLeft_GrSurfaceOrigin == vkRT->origin()) {
- scissor->offset.y = scissorState.rect().fTop;
- } else {
- SkASSERT(kBottomLeft_GrSurfaceOrigin == vkRT->origin());
- scissor->offset.y = vkRT->height() - scissorState.rect().fBottom;
- }
- scissor->extent.height = scissorState.rect().height();
-
- viewportInfo->scissorCount = 1;
- viewportInfo->pScissors = scissor;
- SkASSERT(scissor->offset.x >= 0);
- SkASSERT(scissor->offset.x + scissor->extent.width <= (uint32_t)vkRT->width());
- SkASSERT(scissor->offset.y >= 0);
- SkASSERT(scissor->offset.y + scissor->extent.height <= (uint32_t)vkRT->height());
- } else {
- scissor->extent.width = vkRT->width();
- scissor->extent.height = vkRT->height();
- scissor->offset.x = 0;
- scissor->offset.y = 0;
- viewportInfo->scissorCount = 1;
- viewportInfo->pScissors = scissor;
- }
SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
}
@@ -381,9 +347,7 @@ void setup_color_blend_state(const GrVkGpu* gpu,
colorBlendInfo->logicOpEnable = VK_FALSE;
colorBlendInfo->attachmentCount = 1;
colorBlendInfo->pAttachments = attachmentState;
- if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
- GrColorToRGBAFloat(blendInfo.fBlendConstant, colorBlendInfo->blendConstants);
- }
+ // colorBlendInfo->blendConstants is set dynamically
}
VkCullModeFlags draw_face_to_vk_cull_mode(GrPipelineBuilder::DrawFace drawFace) {
@@ -422,11 +386,17 @@ void setup_raster_state(const GrVkGpu* gpu,
void setup_dynamic_state(const GrVkGpu* gpu,
const GrPipeline& pipeline,
- VkPipelineDynamicStateCreateInfo* dynamicInfo) {
+ VkPipelineDynamicStateCreateInfo* dynamicInfo,
+ VkDynamicState* dynamicStates) {
memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- // TODO: mask out any state we might want to set dynamically
- dynamicInfo->dynamicStateCount = 0;
+ dynamicInfo->pNext = VK_NULL_HANDLE;
+ dynamicInfo->flags = 0;
+ dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
+ dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
+ dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
+ dynamicInfo->dynamicStateCount = 3;
+ dynamicInfo->pDynamicStates = dynamicStates;
}
GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
@@ -454,9 +424,7 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
GrRenderTarget* rt = pipeline.getRenderTarget();
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
VkPipelineViewportStateCreateInfo viewportInfo;
- VkViewport viewport;
- VkRect2D scissor;
- setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo, &viewport, &scissor);
+ setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo);
VkPipelineMultisampleStateCreateInfo multisampleInfo;
setup_multisample_state(pipeline, &multisampleInfo);
@@ -469,8 +437,9 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
VkPipelineRasterizationStateCreateInfo rasterInfo;
setup_raster_state(gpu, pipeline, &rasterInfo);
+ VkDynamicState dynamicStates[3];
VkPipelineDynamicStateCreateInfo dynamicInfo;
- setup_dynamic_state(gpu, pipeline, &dynamicInfo);
+ setup_dynamic_state(gpu, pipeline, &dynamicInfo, dynamicStates);
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
@@ -511,3 +480,77 @@ void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const {
}
+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 = scissorState.rect().fLeft;
+ 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.extent.height = scissorState.rect().height();
+
+ SkASSERT(scissor.offset.x >= 0);
+ SkASSERT(scissor.offset.x + scissor.extent.width <= (uint32_t)target.width());
+ SkASSERT(scissor.offset.y >= 0);
+ SkASSERT(scissor.offset.y + scissor.extent.height <= (uint32_t)target.height());
+ } else {
+ scissor.extent.width = target.width();
+ scissor.extent.height = target.height();
+ scissor.offset.x = 0;
+ scissor.offset.y = 0;
+ }
+ cmdBuffer->setScissor(gpu, 0, 1, &scissor);
+}
+
+void set_dynamic_viewport_state(GrVkGpu* gpu,
+ GrVkCommandBuffer* cmdBuffer,
+ const GrRenderTarget& target) {
+ // 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.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+ cmdBuffer->setViewport(gpu, 0, 1, &viewport);
+}
+
+void set_dynamic_blend_constant_state(GrVkGpu* gpu,
+ GrVkCommandBuffer* cmdBuffer,
+ const GrPipeline& pipeline) {
+ GrXferProcessor::BlendInfo blendInfo;
+ pipeline.getXferProcessor().getBlendInfo(&blendInfo);
+ GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
+ GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
+ float floatColors[4];
+ if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
+ GrColorToRGBAFloat(blendInfo.fBlendConstant, floatColors);
+ } else {
+ memset(floatColors, 0, 4 * sizeof(float));
+ }
+ 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 e1c946a7e7..46f53a7974 100644
--- a/src/gpu/vk/GrVkPipeline.h
+++ b/src/gpu/vk/GrVkPipeline.h
@@ -17,6 +17,7 @@
class GrNonInstancedVertices;
class GrPipeline;
class GrPrimitiveProcessor;
+class GrVkCommandBuffer;
class GrVkGpu;
class GrVkRenderPass;
@@ -34,6 +35,9 @@ public:
VkPipeline pipeline() const { return fPipeline; }
+ static void SetDynamicState(GrVkGpu*, GrVkCommandBuffer*, const GrPipeline&);
+
+
private:
GrVkPipeline(VkPipeline pipeline) : INHERITED(), fPipeline(pipeline) {}