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 455abc4..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,