diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.cpp | 534 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.h | 186 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 4 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkRenderPass.cpp | 19 | ||||
-rw-r--r-- | src/gpu/vk/GrVkRenderPass.h | 4 | ||||
-rw-r--r-- | src/gpu/vk/GrVkResourceProvider.cpp | 4 | ||||
-rw-r--r-- | src/gpu/vk/GrVkResourceProvider.h | 6 |
8 files changed, 443 insertions, 316 deletions
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index bc8c20f016..9604355aad 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -16,24 +16,6 @@ #include "GrVkTransferBuffer.h" #include "GrVkUtil.h" -GrVkCommandBuffer* GrVkCommandBuffer::Create(const GrVkGpu* gpu, VkCommandPool cmdPool) { - const VkCommandBufferAllocateInfo cmdInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType - NULL, // pNext - cmdPool, // commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level - 1 // bufferCount - }; - - VkCommandBuffer cmdBuffer; - VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(), - &cmdInfo, - &cmdBuffer)); - if (err) { - return nullptr; - } - return new GrVkCommandBuffer(cmdBuffer); -} GrVkCommandBuffer::~GrVkCommandBuffer() { // Should have ended any render pass we're in the middle of @@ -79,7 +61,206 @@ void GrVkCommandBuffer::abandonSubResources() const { } } -void GrVkCommandBuffer::begin(const GrVkGpu* gpu) { +//////////////////////////////////////////////////////////////////////////////// +// CommandBuffer commands +//////////////////////////////////////////////////////////////////////////////// + +void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + bool byRegion, + BarrierType barrierType, + void* barrier) const { + SkASSERT(fIsActive); + // For images we can have barriers inside of render passes but they require us to add more + // support in subpasses which need self dependencies to have barriers inside them. Also, we can + // never have buffer barriers inside of a render pass. For now we will just assert that we are + // not in a render pass. + SkASSERT(!fActiveRenderPass); + VkDependencyFlags dependencyFlags = byRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0; + + switch (barrierType) { + case kMemory_BarrierType: { + const VkMemoryBarrier* barrierPtr = reinterpret_cast<VkMemoryBarrier*>(barrier); + GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, + dstStageMask, dependencyFlags, + 1, barrierPtr, + 0, nullptr, + 0, nullptr)); + break; + } + + case kBufferMemory_BarrierType: { + const VkBufferMemoryBarrier* barrierPtr = + reinterpret_cast<VkBufferMemoryBarrier*>(barrier); + GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, + dstStageMask, dependencyFlags, + 0, nullptr, + 1, barrierPtr, + 0, nullptr)); + break; + } + + case kImageMemory_BarrierType: { + const VkImageMemoryBarrier* barrierPtr = + reinterpret_cast<VkImageMemoryBarrier*>(barrier); + GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, + dstStageMask, dependencyFlags, + 0, nullptr, + 0, nullptr, + 1, barrierPtr)); + break; + } + } + +} + +void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu, + int numAttachments, + const VkClearAttachment* attachments, + int numRects, + const VkClearRect* clearRects) const { + SkASSERT(fIsActive); + SkASSERT(fActiveRenderPass); + SkASSERT(numAttachments > 0); + SkASSERT(numRects > 0); +#ifdef SK_DEBUG + for (int i = 0; i < numAttachments; ++i) { + if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { + uint32_t testIndex; + SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex)); + SkASSERT(testIndex == attachments[i].colorAttachment); + } + } +#endif + GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer, + numAttachments, + attachments, + numRects, + clearRects)); +} + +void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, + GrVkPipelineState* pipelineState, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t setCount, + const VkDescriptorSet* descriptorSets, + uint32_t dynamicOffsetCount, + const uint32_t* dynamicOffsets) { + SkASSERT(fIsActive); + GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, + firstSet, + setCount, + descriptorSets, + dynamicOffsetCount, + dynamicOffsets)); + pipelineState->addUniformResources(*this); +} + +void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) { + SkASSERT(fIsActive); + 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, + uint32_t firstIndex, + int32_t vertexOffset, + uint32_t firstInstance) const { + SkASSERT(fIsActive); + SkASSERT(fActiveRenderPass); + GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer, + indexCount, + instanceCount, + firstIndex, + vertexOffset, + firstInstance)); +} + +void GrVkCommandBuffer::draw(const GrVkGpu* gpu, + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance) const { + SkASSERT(fIsActive); + SkASSERT(fActiveRenderPass); + GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer, + vertexCount, + instanceCount, + 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)); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PrimaryCommandBuffer +//////////////////////////////////////////////////////////////////////////////// +GrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(const GrVkGpu* gpu, + VkCommandPool cmdPool) { + const VkCommandBufferAllocateInfo cmdInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType + NULL, // pNext + cmdPool, // commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level + 1 // bufferCount + }; + + VkCommandBuffer cmdBuffer; + VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(), + &cmdInfo, + &cmdBuffer)); + if (err) { + return nullptr; + } + return new GrVkPrimaryCommandBuffer(cmdBuffer); +} + +void GrVkPrimaryCommandBuffer::begin(const GrVkGpu* gpu) { SkASSERT(!fIsActive); VkCommandBufferBeginInfo cmdBufferBeginInfo; memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); @@ -93,7 +274,7 @@ void GrVkCommandBuffer::begin(const GrVkGpu* gpu) { fIsActive = true; } -void GrVkCommandBuffer::end(const GrVkGpu* gpu) { +void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer)); @@ -101,9 +282,7 @@ void GrVkCommandBuffer::end(const GrVkGpu* gpu) { fIsActive = false; } -/////////////////////////////////////////////////////////////////////////////// - -void GrVkCommandBuffer::beginRenderPass(const GrVkGpu* gpu, +void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu, const GrVkRenderPass* renderPass, const GrVkRenderTarget& target) { SkASSERT(fIsActive); @@ -117,14 +296,26 @@ void GrVkCommandBuffer::beginRenderPass(const GrVkGpu* gpu, target.addResources(*this); } -void GrVkCommandBuffer::endRenderPass(const GrVkGpu* gpu) { +void GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) { SkASSERT(fIsActive); SkASSERT(fActiveRenderPass); GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer)); fActiveRenderPass = nullptr; } -void GrVkCommandBuffer::submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync) { +void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu, + const GrVkSecondaryCommandBuffer* buffer) { + SkASSERT(fIsActive); + SkASSERT(fActiveRenderPass); + SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass)); + + GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer)); + this->addResource(buffer); +} + +void GrVkPrimaryCommandBuffer::submitToQueue(const GrVkGpu* gpu, + VkQueue queue, + GrVkGpu::SyncQueue sync) { SkASSERT(!fIsActive); VkResult err; @@ -163,7 +354,7 @@ void GrVkCommandBuffer::submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu } } -bool GrVkCommandBuffer::finished(const GrVkGpu* gpu) const { +bool GrVkPrimaryCommandBuffer::finished(const GrVkGpu* gpu) const { if (VK_NULL_HANDLE == fSubmitFence) { return true; } @@ -185,67 +376,13 @@ bool GrVkCommandBuffer::finished(const GrVkGpu* gpu) const { return false; } -//////////////////////////////////////////////////////////////////////////////// -// CommandBuffer commands -//////////////////////////////////////////////////////////////////////////////// - -void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - bool byRegion, - BarrierType barrierType, - void* barrier) const { - SkASSERT(fIsActive); - // For images we can have barriers inside of render passes but they require us to add more - // support in subpasses which need self dependencies to have barriers inside them. Also, we can - // never have buffer barriers inside of a render pass. For now we will just assert that we are - // not in a render pass. - SkASSERT(!fActiveRenderPass); - VkDependencyFlags dependencyFlags = byRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0; - - switch (barrierType) { - case kMemory_BarrierType: { - const VkMemoryBarrier* barrierPtr = reinterpret_cast<VkMemoryBarrier*>(barrier); - GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, - dstStageMask, dependencyFlags, - 1, barrierPtr, - 0, nullptr, - 0, nullptr)); - break; - } - - case kBufferMemory_BarrierType: { - const VkBufferMemoryBarrier* barrierPtr = - reinterpret_cast<VkBufferMemoryBarrier*>(barrier); - GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, - dstStageMask, dependencyFlags, - 0, nullptr, - 1, barrierPtr, - 0, nullptr)); - break; - } - - case kImageMemory_BarrierType: { - const VkImageMemoryBarrier* barrierPtr = - reinterpret_cast<VkImageMemoryBarrier*>(barrier); - GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, - dstStageMask, dependencyFlags, - 0, nullptr, - 0, nullptr, - 1, barrierPtr)); - break; - } - } - -} - -void GrVkCommandBuffer::copyImage(const GrVkGpu* gpu, - GrVkImage* srcImage, - VkImageLayout srcLayout, - GrVkImage* dstImage, - VkImageLayout dstLayout, - uint32_t copyRegionCount, - const VkImageCopy* copyRegions) { +void GrVkPrimaryCommandBuffer::copyImage(const GrVkGpu* gpu, + GrVkImage* srcImage, + VkImageLayout srcLayout, + GrVkImage* dstImage, + VkImageLayout dstLayout, + uint32_t copyRegionCount, + const VkImageCopy* copyRegions) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(srcImage->resource()); @@ -259,16 +396,16 @@ void GrVkCommandBuffer::copyImage(const GrVkGpu* gpu, copyRegions)); } -void GrVkCommandBuffer::blitImage(const GrVkGpu* gpu, - const GrVkResource* srcResource, - VkImage srcImage, - VkImageLayout srcLayout, - const GrVkResource* dstResource, - VkImage dstImage, - VkImageLayout dstLayout, - uint32_t blitRegionCount, - const VkImageBlit* blitRegions, - VkFilter filter) { +void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu, + const GrVkResource* srcResource, + VkImage srcImage, + VkImageLayout srcLayout, + const GrVkResource* dstResource, + VkImage dstImage, + VkImageLayout dstLayout, + uint32_t blitRegionCount, + const VkImageBlit* blitRegions, + VkFilter filter) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(srcResource); @@ -283,12 +420,12 @@ void GrVkCommandBuffer::blitImage(const GrVkGpu* gpu, filter)); } -void GrVkCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, - GrVkImage* srcImage, - VkImageLayout srcLayout, - GrVkTransferBuffer* dstBuffer, - uint32_t copyRegionCount, - const VkBufferImageCopy* copyRegions) { +void GrVkPrimaryCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, + GrVkImage* srcImage, + VkImageLayout srcLayout, + GrVkTransferBuffer* dstBuffer, + uint32_t copyRegionCount, + const VkBufferImageCopy* copyRegions) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(srcImage->resource()); @@ -301,12 +438,12 @@ void GrVkCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, copyRegions)); } -void GrVkCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, - GrVkTransferBuffer* srcBuffer, - GrVkImage* dstImage, - VkImageLayout dstLayout, - uint32_t copyRegionCount, - const VkBufferImageCopy* copyRegions) { +void GrVkPrimaryCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, + GrVkTransferBuffer* srcBuffer, + GrVkImage* dstImage, + VkImageLayout dstLayout, + uint32_t copyRegionCount, + const VkBufferImageCopy* copyRegions) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(srcBuffer->resource()); @@ -319,11 +456,11 @@ void GrVkCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, copyRegions)); } -void GrVkCommandBuffer::clearColorImage(const GrVkGpu* gpu, - GrVkImage* image, - const VkClearColorValue* color, - uint32_t subRangeCount, - const VkImageSubresourceRange* subRanges) { +void GrVkPrimaryCommandBuffer::clearColorImage(const GrVkGpu* gpu, + GrVkImage* image, + const VkClearColorValue* color, + uint32_t subRangeCount, + const VkImageSubresourceRange* subRanges) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(image->resource()); @@ -335,11 +472,11 @@ void GrVkCommandBuffer::clearColorImage(const GrVkGpu* gpu, subRanges)); } -void GrVkCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu, - GrVkImage* image, - const VkClearDepthStencilValue* color, - uint32_t subRangeCount, - const VkImageSubresourceRange* subRanges) { +void GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu, + GrVkImage* image, + const VkClearDepthStencilValue* color, + uint32_t subRangeCount, + const VkImageSubresourceRange* subRanges) { SkASSERT(fIsActive); SkASSERT(!fActiveRenderPass); this->addResource(image->resource()); @@ -351,124 +488,65 @@ void GrVkCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu, subRanges)); } -void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu, - int numAttachments, - const VkClearAttachment* attachments, - int numRects, - const VkClearRect* clearRects) const { - SkASSERT(fIsActive); - SkASSERT(fActiveRenderPass); - SkASSERT(numAttachments > 0); - SkASSERT(numRects > 0); -#ifdef SK_DEBUG - for (int i = 0; i < numAttachments; ++i) { - if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { - uint32_t testIndex; - SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex)); - SkASSERT(testIndex == attachments[i].colorAttachment); - } - } -#endif - GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer, - numAttachments, - attachments, - numRects, - clearRects)); -} +/////////////////////////////////////////////////////////////////////////////// +// SecondaryCommandBuffer +//////////////////////////////////////////////////////////////////////////////// -void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, - GrVkPipelineState* pipelineState, - VkPipelineLayout layout, - uint32_t firstSet, - uint32_t setCount, - const VkDescriptorSet* descriptorSets, - uint32_t dynamicOffsetCount, - const uint32_t* dynamicOffsets) { - SkASSERT(fIsActive); - GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, - firstSet, - setCount, - descriptorSets, - dynamicOffsetCount, - dynamicOffsets)); - pipelineState->addUniformResources(*this); -} +GrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create( + const GrVkGpu* gpu, + VkCommandPool cmdPool, + const GrVkRenderPass* compatibleRenderPass) { + const VkCommandBufferAllocateInfo cmdInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType + NULL, // pNext + cmdPool, // commandPool + VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level + 1 // bufferCount + }; -void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) { - SkASSERT(fIsActive); - GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline->pipeline())); - addResource(pipeline); + VkCommandBuffer cmdBuffer; + VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(), + &cmdInfo, + &cmdBuffer)); + if (err) { + return nullptr; + } + return new GrVkSecondaryCommandBuffer(cmdBuffer, compatibleRenderPass); } -void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu, - uint32_t indexCount, - uint32_t instanceCount, - uint32_t firstIndex, - int32_t vertexOffset, - uint32_t firstInstance) const { - SkASSERT(fIsActive); - SkASSERT(fActiveRenderPass); - GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer, - indexCount, - instanceCount, - firstIndex, - vertexOffset, - firstInstance)); -} -void GrVkCommandBuffer::draw(const GrVkGpu* gpu, - uint32_t vertexCount, - uint32_t instanceCount, - uint32_t firstVertex, - uint32_t firstInstance) const { - SkASSERT(fIsActive); +void GrVkSecondaryCommandBuffer::begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer) { + SkASSERT(!fIsActive); SkASSERT(fActiveRenderPass); - GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer, - vertexCount, - instanceCount, - 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]; - } -} + VkCommandBufferInheritanceInfo inheritanceInfo; + memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); + inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; + inheritanceInfo.pNext = nullptr; + inheritanceInfo.renderPass = fActiveRenderPass->vkRenderPass(); + inheritanceInfo.subpass = 0; // Currently only using 1 subpass for each render pass + inheritanceInfo.framebuffer = framebuffer ? framebuffer->framebuffer() : VK_NULL_HANDLE; + inheritanceInfo.occlusionQueryEnable = false; + inheritanceInfo.queryFlags = 0; + inheritanceInfo.pipelineStatistics = 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]; - } + VkCommandBufferBeginInfo cmdBufferBeginInfo; + memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); + cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmdBufferBeginInfo.pNext = nullptr; + cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + cmdBufferBeginInfo.pInheritanceInfo = &inheritanceInfo; + + GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer, + &cmdBufferBeginInfo)); + fIsActive = true; } -void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu, - const float blendConstants[4]) { +void GrVkSecondaryCommandBuffer::end(const GrVkGpu* gpu) { SkASSERT(fIsActive); - if (memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) { - GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants)); - memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float)); - } + GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer)); + this->invalidateState(); + fIsActive = false; } + diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h index b513a47f29..709e4c6044 100644 --- a/src/gpu/vk/GrVkCommandBuffer.h +++ b/src/gpu/vk/GrVkCommandBuffer.h @@ -13,6 +13,7 @@ #include "GrVkUtil.h" #include "vk/GrVkDefines.h" +class GrVkFramebuffer; class GrVkPipeline; class GrVkRenderPass; class GrVkRenderTarget; @@ -20,24 +21,10 @@ class GrVkTransferBuffer; class GrVkCommandBuffer : public GrVkResource { public: - static GrVkCommandBuffer* Create(const GrVkGpu* gpu, VkCommandPool cmdPool); ~GrVkCommandBuffer() override; - void begin(const GrVkGpu* gpu); - void end(const GrVkGpu* gpu); - void invalidateState(); - // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used - // in the render pass. - void beginRenderPass(const GrVkGpu* gpu, - const GrVkRenderPass* renderPass, - const GrVkRenderTarget& target); - void endRenderPass(const GrVkGpu* gpu); - - void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync); - bool finished(const GrVkGpu* gpu) const; - //////////////////////////////////////////////////////////////////////////// // CommandBuffer commands //////////////////////////////////////////////////////////////////////////// @@ -105,6 +92,98 @@ public: void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]); + // Commands that only work inside of a render pass + void clearAttachments(const GrVkGpu* gpu, + int numAttachments, + const VkClearAttachment* attachments, + int numRects, + const VkClearRect* clearRects) const; + + void drawIndexed(const GrVkGpu* gpu, + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + int32_t vertexOffset, + uint32_t firstInstance) const; + + void draw(const GrVkGpu* gpu, + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance) const; + + // Add ref-counted resource that will be tracked and released when this + // command buffer finishes execution + void addResource(const GrVkResource* resource) { + resource->ref(); + fTrackedResources.push_back(resource); + } + +protected: + GrVkCommandBuffer(VkCommandBuffer cmdBuffer, const GrVkRenderPass* rp = VK_NULL_HANDLE) + : fTrackedResources(kInitialTrackedResourcesCount) + , fIsActive(false) + , fActiveRenderPass(rp) + , fCmdBuffer(cmdBuffer) + , fSubmitFence(VK_NULL_HANDLE) + , fBoundVertexBufferIsValid(false) + , fBoundIndexBufferIsValid(false) { + this->invalidateState(); + } + SkTArray<const GrVkResource*, true> fTrackedResources; + + // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add + // new commands to the buffer; + bool fIsActive; + + // Stores a pointer to the current active render pass (i.e. begin has been called but not + // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own + // the render pass. + const GrVkRenderPass* fActiveRenderPass; + + VkCommandBuffer fCmdBuffer; + VkFence fSubmitFence; + +private: + static const int kInitialTrackedResourcesCount = 32; + + void freeGPUData(const GrVkGpu* gpu) const override; + void abandonSubResources() const override; + + VkBuffer fBoundVertexBuffer; + bool fBoundVertexBufferIsValid; + + VkBuffer fBoundIndexBuffer; + bool fBoundIndexBufferIsValid; + + // Cached values used for dynamic state updates + VkViewport fCachedViewport; + VkRect2D fCachedScissor; + float fCachedBlendConstant[4]; +}; + +class GrVkSecondaryCommandBuffer; + +class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer { +public: + static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, VkCommandPool cmdPool); + + void begin(const GrVkGpu* gpu); + void end(const GrVkGpu* gpu); + + // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used + // in the render pass. + void beginRenderPass(const GrVkGpu* gpu, + const GrVkRenderPass* renderPass, + const GrVkRenderTarget& target); + void endRenderPass(const GrVkGpu* gpu); + + // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are + // currently inside a render pass that is compatible with the one used to create the + // SecondaryCommandBuffer. + void executeCommands(const GrVkGpu* gpu, + const GrVkSecondaryCommandBuffer* secondaryBuffer); + // Commands that only work outside of a render pass void clearColorImage(const GrVkGpu* gpu, GrVkImage* image, @@ -169,75 +248,32 @@ public: uint32_t copyRegionCount, const VkBufferImageCopy* copyRegions); - // Commands that only work inside of a render pass - void clearAttachments(const GrVkGpu* gpu, - int numAttachments, - const VkClearAttachment* attachments, - int numRects, - const VkClearRect* clearRects) const; - - void drawIndexed(const GrVkGpu* gpu, - uint32_t indexCount, - uint32_t instanceCount, - uint32_t firstIndex, - int32_t vertexOffset, - uint32_t firstInstance) const; - - void draw(const GrVkGpu* gpu, - uint32_t vertexCount, - uint32_t instanceCount, - uint32_t firstVertex, - uint32_t firstInstance) const; - - // Add ref-counted resource that will be tracked and released when this - // command buffer finishes execution - void addResource(const GrVkResource* resource) { - resource->ref(); - fTrackedResources.push_back(resource); - } + void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync); + bool finished(const GrVkGpu* gpu) const; private: - static const int kInitialTrackedResourcesCount = 32; - - explicit GrVkCommandBuffer(VkCommandBuffer cmdBuffer) - : fTrackedResources(kInitialTrackedResourcesCount) - , fCmdBuffer(cmdBuffer) - , fSubmitFence(VK_NULL_HANDLE) - , fBoundVertexBufferIsValid(false) - , fBoundIndexBufferIsValid(false) - , fIsActive(false) - , fActiveRenderPass(nullptr) { - this->invalidateState(); - } - - void freeGPUData(const GrVkGpu* gpu) const override; - void abandonSubResources() const override; + explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer) : INHERITED(cmdBuffer) {} - SkTArray<const GrVkResource*, true> fTrackedResources; - - VkCommandBuffer fCmdBuffer; - VkFence fSubmitFence; + typedef GrVkCommandBuffer INHERITED; +}; - VkBuffer fBoundVertexBuffer; - bool fBoundVertexBufferIsValid; +class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer { +public: + static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, VkCommandPool cmdPool, + const GrVkRenderPass* compatibleRenderPass); - VkBuffer fBoundIndexBuffer; - bool fBoundIndexBufferIsValid; + void begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer); + void end(const GrVkGpu* gpu); - // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add new - // commands to the buffer; - bool fIsActive; +private: + explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, + const GrVkRenderPass* compatibleRenderPass) + : INHERITED(cmdBuffer, compatibleRenderPass) { + } - // Stores a pointer to the current active render pass (i.e. begin has been called but not end). - // A nullptr means there is no active render pass. The GrVKCommandBuffer does not own the render - // pass. - const GrVkRenderPass* fActiveRenderPass; + friend class GrVkPrimaryCommandBuffer; - // Cached values used for dynamic state updates - VkViewport fCachedViewport; - VkRect2D fCachedScissor; - float fCachedBlendConstant[4]; + typedef GrVkCommandBuffer INHERITED; }; - #endif diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index fb533e317e..d18481c08a 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -128,7 +128,7 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options, // must call this after creating the CommandPool fResourceProvider.init(); - fCurrentCmdBuffer = fResourceProvider.createCommandBuffer(); + fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer(); SkASSERT(fCurrentCmdBuffer); fCurrentCmdBuffer->begin(this); } @@ -169,7 +169,7 @@ void GrVkGpu::submitCommandBuffer(SyncQueue sync) { // Release old command buffer and create a new one fCurrentCmdBuffer->unref(this); - fCurrentCmdBuffer = fResourceProvider.createCommandBuffer(); + fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer(); SkASSERT(fCurrentCmdBuffer); fCurrentCmdBuffer->begin(this); diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 506b2379f6..00055ad87c 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -214,7 +214,7 @@ private: // Created by GrVkGpu GrVkResourceProvider fResourceProvider; VkCommandPool fCmdPool; - GrVkCommandBuffer* fCurrentCmdBuffer; + GrVkPrimaryCommandBuffer* fCurrentCmdBuffer; VkPhysicalDeviceMemoryProperties fPhysDevMemProps; #ifdef ENABLE_VK_LAYERS diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp index 6a0f953a1c..a49393800f 100644 --- a/src/gpu/vk/GrVkRenderPass.cpp +++ b/src/gpu/vk/GrVkRenderPass.cpp @@ -233,11 +233,8 @@ void GrVkRenderPass::getBeginInfo(const GrVkRenderTarget& target, *contents = VK_SUBPASS_CONTENTS_INLINE; } -bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { - AttachmentsDescriptor desc; - AttachmentFlags flags; - target.getAttachmentsDescriptor(&desc, &flags); - +bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc, + const AttachmentFlags& flags) const { if (flags != fAttachmentFlags) { return false; } @@ -261,6 +258,18 @@ bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { return true; } +bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { + AttachmentsDescriptor desc; + AttachmentFlags flags; + target.getAttachmentsDescriptor(&desc, &flags); + + return this->isCompatible(desc, flags); +} + +bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const { + return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags); +} + bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps, const LoadStoreOps& resolveOps, const LoadStoreOps& stencilOps) const { diff --git a/src/gpu/vk/GrVkRenderPass.h b/src/gpu/vk/GrVkRenderPass.h index b4f4b2b2bb..997989d073 100644 --- a/src/gpu/vk/GrVkRenderPass.h +++ b/src/gpu/vk/GrVkRenderPass.h @@ -110,6 +110,8 @@ public: // basic RenderPasses that can be used when creating a VkFrameBuffer object. bool isCompatible(const GrVkRenderTarget& target) const; + bool isCompatible(const GrVkRenderPass& renderPass) const; + bool equalLoadStoreOps(const LoadStoreOps& colorOps, const LoadStoreOps& resolveOps, const LoadStoreOps& stencilOps) const; @@ -126,6 +128,8 @@ private: const LoadStoreOps& resolveOps, const LoadStoreOps& stencilOps); + bool isCompatible(const AttachmentsDescriptor&, const AttachmentFlags&) const; + void freeGPUData(const GrVkGpu* gpu) const override; VkRenderPass fRenderPass; diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp index cd3ba47bca..ae333bc69e 100644 --- a/src/gpu/vk/GrVkResourceProvider.cpp +++ b/src/gpu/vk/GrVkResourceProvider.cpp @@ -215,8 +215,8 @@ void GrVkResourceProvider::getUniformDescriptorSet(VkDescriptorSet* ds, *outPool = fUniformDescPool; } -GrVkCommandBuffer* GrVkResourceProvider::createCommandBuffer() { - GrVkCommandBuffer* cmdBuffer = GrVkCommandBuffer::Create(fGpu, fGpu->cmdPool()); +GrVkPrimaryCommandBuffer* GrVkResourceProvider::createPrimaryCommandBuffer() { + GrVkPrimaryCommandBuffer* cmdBuffer = GrVkPrimaryCommandBuffer::Create(fGpu, fGpu->cmdPool()); fActiveCommandBuffers.push_back(cmdBuffer); cmdBuffer->ref(); return cmdBuffer; diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h index e754501cba..d4383af96a 100644 --- a/src/gpu/vk/GrVkResourceProvider.h +++ b/src/gpu/vk/GrVkResourceProvider.h @@ -25,7 +25,7 @@ class GrPipeline; class GrPrimitiveProcessor; class GrTextureParams; -class GrVkCommandBuffer; +class GrVkPrimaryCommandBuffer; class GrVkGpu; class GrVkPipeline; class GrVkRenderTarget; @@ -77,7 +77,7 @@ public: const GrVkRenderPass::LoadStoreOps& stencilOps); - GrVkCommandBuffer* createCommandBuffer(); + GrVkPrimaryCommandBuffer* createPrimaryCommandBuffer(); void checkCommandBuffers(); // Finds or creates a compatible GrVkDescriptorPool for the requested type and count. @@ -201,7 +201,7 @@ private: SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray; // Array of CommandBuffers that are currently in flight - SkSTArray<4, GrVkCommandBuffer*> fActiveCommandBuffers; + SkSTArray<4, GrVkPrimaryCommandBuffer*> fActiveCommandBuffers; // Stores GrVkSampler objects that we've already created so we can reuse them across multiple // GrVkPipelineStates |