| 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));
|
| +}
|
|
|