Index: src/gpu/vk/GrVkCommandBuffer.cpp |
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e43c50fc4ac44bdeaeb546002cc86fd6a614f920 |
--- /dev/null |
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp |
@@ -0,0 +1,371 @@ |
+/* |
+* Copyright 2015 Google Inc. |
+* |
+* Use of this source code is governed by a BSD-style license that can be |
+* found in the LICENSE file. |
+*/ |
+ |
+#include "GrVkCommandBuffer.h" |
+ |
+#include "GrVkFramebuffer.h" |
+#include "GrVkImageView.h" |
+#include "GrVkRenderPass.h" |
+#include "GrVkRenderTarget.h" |
+#include "GrVkProgram.h" |
+#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 |
+ SkASSERT(!fActiveRenderPass); |
+} |
+ |
+void GrVkCommandBuffer::invalidateState() { |
+ fBoundVertexBuffer = 0; |
+ fBoundVertexBufferIsValid = false; |
+ fBoundIndexBuffer = 0; |
+ fBoundIndexBufferIsValid = false; |
+} |
+ |
+void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const { |
+ SkASSERT(!fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ for (int i = 0; i < fTrackedResources.count(); ++i) { |
+ fTrackedResources[i]->unref(gpu); |
+ } |
+ |
+ // Destroy the fence, if any |
+ if (VK_NULL_HANDLE != fSubmitFence) { |
+ GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); |
+ } |
+ |
+ GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(), |
+ 1, &fCmdBuffer)); |
+} |
+ |
+void GrVkCommandBuffer::abandonSubResources() const { |
+ for (int i = 0; i < fTrackedResources.count(); ++i) { |
+ fTrackedResources[i]->unrefAndAbandon(); |
+ } |
+} |
+ |
+void GrVkCommandBuffer::begin(const GrVkGpu* gpu) { |
+ SkASSERT(!fIsActive); |
+ 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_ONE_TIME_SUBMIT_BIT; |
+ cmdBufferBeginInfo.pInheritanceInfo = nullptr; |
+ |
+ GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer, |
+ &cmdBufferBeginInfo)); |
+ fIsActive = true; |
+} |
+ |
+void GrVkCommandBuffer::end(const GrVkGpu* gpu) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer)); |
+ this->invalidateState(); |
+ fIsActive = false; |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+void GrVkCommandBuffer::beginRenderPass(const GrVkGpu* gpu, |
+ const GrVkRenderPass* renderPass, |
+ const GrVkRenderTarget& target) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ VkRenderPassBeginInfo beginInfo; |
+ VkSubpassContents contents; |
+ renderPass->getBeginInfo(target, &beginInfo, &contents); |
+ GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents)); |
+ fActiveRenderPass = renderPass; |
+ this->addResource(renderPass); |
+ target.addResources(*this); |
+ |
+} |
+ |
+void GrVkCommandBuffer::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) { |
+ SkASSERT(!fIsActive); |
+ |
+ VkResult err; |
+ VkFenceCreateInfo fenceInfo; |
+ memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); |
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |
+ err = GR_VK_CALL(gpu->vkInterface(), CreateFence(gpu->device(), &fenceInfo, nullptr, |
+ &fSubmitFence)); |
+ SkASSERT(!err); |
+ |
+ VkSubmitInfo submitInfo; |
+ memset(&submitInfo, 0, sizeof(VkSubmitInfo)); |
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |
+ submitInfo.pNext = nullptr; |
+ submitInfo.waitSemaphoreCount = 0; |
+ submitInfo.pWaitSemaphores = nullptr; |
+ submitInfo.commandBufferCount = 1; |
+ submitInfo.pCommandBuffers = &fCmdBuffer; |
+ submitInfo.signalSemaphoreCount = 0; |
+ submitInfo.pSignalSemaphores = nullptr; |
+ GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence)); |
+ |
+ if (GrVkGpu::kForce_SyncQueue == sync) { |
+ err = GR_VK_CALL(gpu->vkInterface(), |
+ WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX)); |
+ if (VK_TIMEOUT == err) { |
+ SkDebugf("Fence failed to signal: %d\n", err); |
+ SkFAIL("failing"); |
+ } |
+ SkASSERT(!err); |
+ |
+ // Destroy the fence |
+ GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); |
+ fSubmitFence = VK_NULL_HANDLE; |
+ } |
+} |
+ |
+bool GrVkCommandBuffer::finished(const GrVkGpu* gpu) const { |
+ if (VK_NULL_HANDLE == fSubmitFence) { |
+ return true; |
+ } |
+ |
+ VkResult err = GR_VK_CALL(gpu->vkInterface(), GetFenceStatus(gpu->device(), fSubmitFence)); |
+ switch (err) { |
+ case VK_SUCCESS: |
+ return true; |
+ |
+ case VK_NOT_READY: |
+ return false; |
+ |
+ default: |
+ SkDebugf("Error getting fence status: %d\n", err); |
+ SkFAIL("failing"); |
+ break; |
+ } |
+ |
+ return false; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// CommandBuffer commands |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu, |
+ VkPipelineStageFlags srcStageMask, |
+ VkPipelineStageFlags dstStageMask, |
+ bool byRegion, |
+ BarrierType barrierType, |
+ void* barrier) const { |
+ SkASSERT(fIsActive); |
+ 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) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ this->addResource(srcImage->resource()); |
+ this->addResource(dstImage->resource()); |
+ GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer, |
+ srcImage->textureImage(), |
+ srcLayout, |
+ dstImage->textureImage(), |
+ dstLayout, |
+ copyRegionCount, |
+ copyRegions)); |
+} |
+ |
+void GrVkCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, |
+ GrVkImage* srcImage, |
+ VkImageLayout srcLayout, |
+ GrVkTransferBuffer* dstBuffer, |
+ uint32_t copyRegionCount, |
+ const VkBufferImageCopy* copyRegions) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ this->addResource(srcImage->resource()); |
+ this->addResource(dstBuffer->resource()); |
+ GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer, |
+ srcImage->textureImage(), |
+ srcLayout, |
+ dstBuffer->buffer(), |
+ copyRegionCount, |
+ copyRegions)); |
+} |
+ |
+void GrVkCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, |
+ GrVkTransferBuffer* srcBuffer, |
+ GrVkImage* dstImage, |
+ VkImageLayout dstLayout, |
+ uint32_t copyRegionCount, |
+ const VkBufferImageCopy* copyRegions) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ this->addResource(srcBuffer->resource()); |
+ this->addResource(dstImage->resource()); |
+ GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer, |
+ srcBuffer->buffer(), |
+ dstImage->textureImage(), |
+ dstLayout, |
+ copyRegionCount, |
+ copyRegions)); |
+} |
+ |
+void GrVkCommandBuffer::clearColorImage(const GrVkGpu* gpu, |
+ GrVkImage* image, |
+ const VkClearColorValue* color, |
+ uint32_t subRangeCount, |
+ const VkImageSubresourceRange* subRanges) { |
+ SkASSERT(fIsActive); |
+ SkASSERT(!fActiveRenderPass); |
+ this->addResource(image->resource()); |
+ GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer, |
+ image->textureImage(), |
+ image->currentLayout(), |
+ color, |
+ subRangeCount, |
+ 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)); |
+} |
+ |
+void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, |
+ GrVkProgram* program, |
+ 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)); |
+ program->addUniformResources(*this); |
+} |
+ |
+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)); |
+} |