From: Mikko Rasa Date: Tue, 30 Nov 2021 22:17:53 +0000 (+0200) Subject: Use another callback for pre-transfer synchronization X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=d9c769b5847beefa378d2c5555f5b5d8e5d26c0e;p=libs%2Fgl.git Use another callback for pre-transfer synchronization --- diff --git a/source/backends/vulkan/buffer_backend.cpp b/source/backends/vulkan/buffer_backend.cpp index 9290b42a..14164daf 100644 --- a/source/backends/vulkan/buffer_backend.cpp +++ b/source/backends/vulkan/buffer_backend.cpp @@ -52,17 +52,19 @@ void VulkanBuffer::allocate() void VulkanBuffer::sub_data(size_t off, size_t sz, const void *d) { - device.get_synchronizer().write_buffer(handle, off, sz); - - void *staging = device.get_transfer_queue().prepare_transfer(sz, [this, off, sz](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = device.get_functions(); - - VkBufferCopy region = { }; - region.srcOffset = src_off; - region.dstOffset = off; - region.size = sz; - vk.CmdCopyBuffer(cmd_buf, staging_buf, handle, 1, ®ion); - }); + void *staging = device.get_transfer_queue().prepare_transfer(sz, + [this, off, sz](){ + device.get_synchronizer().write_buffer(handle, off, sz); + }, + [this, off, sz](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ + const VulkanFunctions &vk = device.get_functions(); + + VkBufferCopy region = { }; + region.srcOffset = src_off; + region.dstOffset = off; + region.size = sz; + vk.CmdCopyBuffer(cmd_buf, staging_buf, handle, 1, ®ion); + }); const char *src = static_cast(d); copy(src, src+sz, static_cast(staging)); diff --git a/source/backends/vulkan/texture1d_backend.cpp b/source/backends/vulkan/texture1d_backend.cpp index 91c6252a..d97576ce 100644 --- a/source/backends/vulkan/texture1d_backend.cpp +++ b/source/backends/vulkan/texture1d_backend.cpp @@ -27,10 +27,14 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void * const Texture1D &self = *static_cast(this); unsigned level_size = self.get_level_size(level); - change_layout(self.levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (x==0 && wd==level_size)); + bool discard = (x==0 && wd==level_size); size_t data_size = wd*get_pixel_size(storage_fmt); void *staging = device.get_transfer_queue().prepare_transfer(data_size, + [this, level, discard](){ + unsigned n_levels = static_cast(this)->levels; + change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); + }, [this, level, x, wd](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ const VulkanFunctions &vk = device.get_functions(); diff --git a/source/backends/vulkan/texture2d_backend.cpp b/source/backends/vulkan/texture2d_backend.cpp index d3db86d3..e568d14f 100644 --- a/source/backends/vulkan/texture2d_backend.cpp +++ b/source/backends/vulkan/texture2d_backend.cpp @@ -28,10 +28,14 @@ void VulkanTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsig const Texture2D &self = *static_cast(this); auto level_size = self.get_level_size(level); - change_layout(self.levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (x==0 && y==0 && wd==level_size.x && ht==level_size.y)); + bool discard = (x==0 && y==0 && wd==level_size.x && ht==level_size.y); size_t data_size = wd*ht*get_pixel_size(storage_fmt); void *staging = device.get_transfer_queue().prepare_transfer(data_size, + [this, level, discard](){ + unsigned n_levels = static_cast(this)->levels; + change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); + }, [this, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ const VulkanFunctions &vk = device.get_functions(); diff --git a/source/backends/vulkan/texture3d_backend.cpp b/source/backends/vulkan/texture3d_backend.cpp index 03a95734..4c9873d9 100644 --- a/source/backends/vulkan/texture3d_backend.cpp +++ b/source/backends/vulkan/texture3d_backend.cpp @@ -34,10 +34,13 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd auto level_size = self.get_level_size(level); bool discard = (x==0 && y==0 && z==0 && wd==level_size.x && ht==level_size.y && dp==level_size.z); - change_layout(self.levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); size_t data_size = wd*ht*dp*get_pixel_size(storage_fmt); void *staging = device.get_transfer_queue().prepare_transfer(data_size, + [this, level, discard](){ + unsigned n_levels = static_cast(this)->levels; + change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); + }, [this, level, x, y, z, wd, ht, dp](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ const VulkanFunctions &vk = device.get_functions(); diff --git a/source/backends/vulkan/texturecube_backend.cpp b/source/backends/vulkan/texturecube_backend.cpp index 38348f34..f421e20d 100644 --- a/source/backends/vulkan/texturecube_backend.cpp +++ b/source/backends/vulkan/texturecube_backend.cpp @@ -30,10 +30,14 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u const TextureCube &self = *static_cast(this); unsigned level_size = self.get_level_size(level); - change_layout(self.levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (x==0 && y==0 && wd==level_size && ht==level_size)); + bool discard = (x==0 && y==0 && wd==level_size && ht==level_size); size_t data_size = wd*ht*get_pixel_size(storage_fmt); void *staging = device.get_transfer_queue().prepare_transfer(data_size, + [this, level, discard](){ + unsigned n_levels = static_cast(this)->levels; + change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); + }, [this, face, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ const VulkanFunctions &vk = device.get_functions(); diff --git a/source/backends/vulkan/transferqueue.cpp b/source/backends/vulkan/transferqueue.cpp index d0ccb0d5..7f1cfa91 100644 --- a/source/backends/vulkan/transferqueue.cpp +++ b/source/backends/vulkan/transferqueue.cpp @@ -34,13 +34,18 @@ TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(size_t size) void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) { - if(!transfers.empty()) - device.get_synchronizer().barrier(command_buffer); + if(transfers.empty()) + return; + + for(const PendingTransfer &t: transfers) + t.synchronize(); + + device.get_synchronizer().barrier(command_buffer); for(const PendingTransfer &t: transfers) { VkBuffer buffer = buffers[t.buffer_index].buffer; - t.callback(command_buffer, buffer, t.offset); + t.transfer(command_buffer, buffer, t.offset); } transfers.clear(); diff --git a/source/backends/vulkan/transferqueue.h b/source/backends/vulkan/transferqueue.h index 419760bd..a25519c8 100644 --- a/source/backends/vulkan/transferqueue.h +++ b/source/backends/vulkan/transferqueue.h @@ -28,14 +28,13 @@ private: ~StagingBuffer(); }; - using TransferCallback = void(VkCommandBuffer, VkBuffer, std::size_t); - struct PendingTransfer { unsigned buffer_index = 0; std::size_t offset = 0; std::size_t size = 0; - std::function callback; + std::function synchronize; + std::function transfer; }; Device &device; @@ -46,8 +45,8 @@ private: public: TransferQueue(Device &); - template - void *prepare_transfer(std::size_t, T &&); + template + void *prepare_transfer(std::size_t, S &&, T &&); private: PendingTransfer &prepare_transfer(std::size_t); @@ -56,11 +55,12 @@ public: void dispatch_transfers(VkCommandBuffer); }; -template -void *TransferQueue::prepare_transfer(std::size_t size, T &&callback) +template +void *TransferQueue::prepare_transfer(std::size_t size, S &&synchronize, T &&transfer) { PendingTransfer &pt = prepare_transfer(size); - pt.callback = std::forward(callback); + pt.synchronize = std::forward(synchronize); + pt.transfer = std::forward(transfer); return static_cast(buffers[pt.buffer_index].mapped_address)+pt.offset; }