Implement GrGpu::transferFromBufferToBuffer on Vulkan Bug: skia:13427 Bug: skia:12720 Change-Id: I91c2707bda1c3ed6a850627f9187cfc5b4b81517 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/550706 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ganesh/vk/GrVkBuffer.cpp b/src/gpu/ganesh/vk/GrVkBuffer.cpp index f029bf3..1fe9c0c 100644 --- a/src/gpu/ganesh/vk/GrVkBuffer.cpp +++ b/src/gpu/ganesh/vk/GrVkBuffer.cpp
@@ -184,19 +184,6 @@ GrVkMemory::UnmapAlloc(gpu, fAlloc); } -static VkAccessFlags buffer_type_to_access_flags(GrGpuBufferType type) { - switch (type) { - case GrGpuBufferType::kIndex: - return VK_ACCESS_INDEX_READ_BIT; - case GrGpuBufferType::kVertex: - return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - default: - // This helper is only called for static buffers so we should only ever see index or - // vertex buffers types - SkUNREACHABLE; - } -} - void GrVkBuffer::copyCpuDataToGpuBuffer(const void* src, size_t size) { SkASSERT(src); @@ -220,15 +207,12 @@ return; } - gpu->copyBuffer(std::move(transferBuffer), sk_ref_sp(this), /*srcOffset=*/0, - /*dstOffset=*/0, size); + gpu->transferFromBufferToBuffer(std::move(transferBuffer), + /*srcOffset=*/0, + sk_ref_sp(this), + /*dstOffset=*/0, + size); } - - this->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, - buffer_type_to_access_flags(this->intendedType()), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - /*byRegion=*/false); } void GrVkBuffer::addMemoryBarrier(VkAccessFlags srcAccessMask,
diff --git a/src/gpu/ganesh/vk/GrVkCaps.cpp b/src/gpu/ganesh/vk/GrVkCaps.cpp index b0a9ce7..1dad2dc 100644 --- a/src/gpu/ganesh/vk/GrVkCaps.cpp +++ b/src/gpu/ganesh/vk/GrVkCaps.cpp
@@ -62,6 +62,7 @@ fTransferFromBufferToTextureSupport = true; fTransferFromSurfaceToBufferSupport = true; + fTransferFromBufferToBufferSupport = true; fMaxRenderTargetSize = 4096; // minimum required by spec fMaxTextureSize = 4096; // minimum required by spec
diff --git a/src/gpu/ganesh/vk/GrVkGpu.cpp b/src/gpu/ganesh/vk/GrVkGpu.cpp index 70fbb5b..b7ef05b 100644 --- a/src/gpu/ganesh/vk/GrVkGpu.cpp +++ b/src/gpu/ganesh/vk/GrVkGpu.cpp
@@ -536,6 +536,55 @@ return success; } +// If dst is a vertex/index buffer then this functions inserts a mem barrier for that use case. +// Otherwise, does nothing. +static void add_dst_buffer_mem_barrier(GrVkGpu* gpu, GrVkBuffer* dst, size_t offset, size_t size) { + if (dst->intendedType() != GrGpuBufferType::kIndex && + dst->intendedType() != GrGpuBufferType::kVertex) { + return; + } + VkAccessFlags dstAccessMask = dst->intendedType() == GrGpuBufferType::kIndex + ? VK_ACCESS_INDEX_READ_BIT + : VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + VkBufferMemoryBarrier bufferMemoryBarrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType + nullptr, // pNext + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask + dstAccessMask, // dstAccessMask + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex + dst->vkBuffer(), // buffer + offset, // offset + size, // size + }; + + gpu->addBufferMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + /*byRegion=*/false, + &bufferMemoryBarrier); + +} + +bool GrVkGpu::onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src, + size_t srcOffset, + sk_sp<GrGpuBuffer> dst, + size_t dstOffset, + size_t size) { + if (!this->currentCommandBuffer()) { + return false; + } + + VkBufferCopy copyRegion; + copyRegion.srcOffset = srcOffset; + copyRegion.dstOffset = dstOffset; + copyRegion.size = size; + this->currentCommandBuffer()->copyBuffer(this, std::move(src), dst, 1, ©Region); + + add_dst_buffer_mem_barrier(this, static_cast<GrVkBuffer*>(dst.get()), dstOffset, size); + + return true; +} + bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, SkIRect rect, GrColorType surfaceColorType, @@ -1137,29 +1186,15 @@ //////////////////////////////////////////////////////////////////////////////// -void GrVkGpu::copyBuffer(sk_sp<GrGpuBuffer> srcBuffer, - sk_sp<GrGpuBuffer> dstBuffer, - VkDeviceSize srcOffset, - VkDeviceSize dstOffset, - VkDeviceSize size) { - if (!this->currentCommandBuffer()) { - return; - } - VkBufferCopy copyRegion; - copyRegion.srcOffset = srcOffset; - copyRegion.dstOffset = dstOffset; - copyRegion.size = size; - this->currentCommandBuffer()->copyBuffer(this, std::move(srcBuffer), std::move(dstBuffer), 1, - ©Region); -} - bool GrVkGpu::updateBuffer(sk_sp<GrVkBuffer> buffer, const void* src, VkDeviceSize offset, VkDeviceSize size) { if (!this->currentCommandBuffer()) { return false; } // Update the buffer - this->currentCommandBuffer()->updateBuffer(this, std::move(buffer), offset, size, src); + this->currentCommandBuffer()->updateBuffer(this, buffer, offset, size, src); + + add_dst_buffer_mem_barrier(this, static_cast<GrVkBuffer*>(buffer.get()), offset, size); return true; }
diff --git a/src/gpu/ganesh/vk/GrVkGpu.h b/src/gpu/ganesh/vk/GrVkGpu.h index 44bd21d..b1f2522 100644 --- a/src/gpu/ganesh/vk/GrVkGpu.h +++ b/src/gpu/ganesh/vk/GrVkGpu.h
@@ -174,8 +174,6 @@ std::unique_ptr<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override; - void copyBuffer(sk_sp<GrGpuBuffer> srcBuffer, sk_sp<GrGpuBuffer> dstBuffer, - VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size); bool updateBuffer(sk_sp<GrVkBuffer> buffer, const void* src, VkDeviceSize offset, VkDeviceSize size); @@ -286,6 +284,12 @@ int mipLevelCount, bool prepForTexSampling) override; + bool onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src, + size_t srcOffset, + sk_sp<GrGpuBuffer> dst, + size_t dstOffset, + size_t size) override; + bool onTransferPixelsTo(GrTexture*, SkIRect, GrColorType textureColorType,
diff --git a/tests/GrGpuBufferTest.cpp b/tests/GrGpuBufferTest.cpp index 455abc49..5b03707 100644 --- a/tests/GrGpuBufferTest.cpp +++ b/tests/GrGpuBufferTest.cpp
@@ -195,7 +195,7 @@ return rp->createBuffer(points.get(), totalVertices*sizeof(SkPoint), GrGpuBufferType::kXferCpuToGpu, - kStream_GrAccessPattern); + kDynamic_GrAccessPattern); }; auto create_vertex_buffer = [&](sk_sp<GrGpuBuffer> srcBuffer,