diff options
author | egdaniel <egdaniel@google.com> | 2016-03-18 12:50:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-18 12:50:27 -0700 |
commit | 470d77a1d7dc286cdad98b145dac735cd7638e56 (patch) | |
tree | b858138d3904d73fe7191fd1e0c5dd4540ce969f /src/gpu/vk | |
parent | 58fc94e55fb52704f86aa6fde97719131a3c9ed4 (diff) |
Use dynamic state from vulkan pipelines
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1813913002
Review URL: https://codereview.chromium.org/1813913002
Diffstat (limited to 'src/gpu/vk')
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.cpp | 63 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.h | 38 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 6 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipeline.cpp | 143 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipeline.h | 4 |
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) {} |