]> git.tdb.fi Git - libs/gl.git/commitdiff
Track the order of transfers involving the same objects
authorMikko Rasa <tdb@tdb.fi>
Wed, 1 Dec 2021 07:45:38 +0000 (09:45 +0200)
committerMikko Rasa <tdb@tdb.fi>
Wed, 1 Dec 2021 07:45:38 +0000 (09:45 +0200)
Mipmap generation requires barriers between the steps, since each level
is generated using the previous one.

source/backends/vulkan/buffer_backend.cpp
source/backends/vulkan/texture1d_backend.cpp
source/backends/vulkan/texture2d_backend.cpp
source/backends/vulkan/texture3d_backend.cpp
source/backends/vulkan/texturecube_backend.cpp
source/backends/vulkan/transferqueue.cpp
source/backends/vulkan/transferqueue.h

index 14164daf208a8b67f4fdba00284b10df2d2aedc3..21e1dabeac041665e03aa076fccbd37e360b2977 100644 (file)
@@ -52,7 +52,7 @@ void VulkanBuffer::allocate()
 
 void VulkanBuffer::sub_data(size_t off, size_t sz, const void *d)
 {
-       void *staging = device.get_transfer_queue().prepare_transfer(sz,
+       void *staging = device.get_transfer_queue().prepare_transfer(this, false, sz,
                [this, off, sz](){
                        device.get_synchronizer().write_buffer(handle, off, sz);
                },
index d97576ce0990e0170c433c8356ad3df6ab1d3a69..e28ec4236cd9ae1b9758c9b77478830c43dbf214 100644 (file)
@@ -30,7 +30,7 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void *
        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,
+       void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
                        unsigned n_levels = static_cast<const Texture1D *>(this)->levels;
                        change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
index e568d14f75843ea7ae57e6a6bbb520a777ed5712..71fb90cdbd4d90eec9bbbbcc91d2b06950dfa596 100644 (file)
@@ -31,7 +31,7 @@ void VulkanTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsig
        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,
+       void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
                        unsigned n_levels = static_cast<const Texture2D *>(this)->levels;
                        change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
index 4c9873d9dfaaebb912fd243a26efa80ec564e743..581206c671bf40498344d59a2387eb1c68fe1817 100644 (file)
@@ -36,7 +36,7 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd
        bool discard = (x==0 && y==0 && z==0 && wd==level_size.x && ht==level_size.y && dp==level_size.z);
 
        size_t data_size = wd*ht*dp*get_pixel_size(storage_fmt);
-       void *staging = device.get_transfer_queue().prepare_transfer(data_size,
+       void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
                        unsigned n_levels = static_cast<const Texture3D *>(this)->levels;
                        change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
index f421e20d68be259dc110eb20820a3867f4fa5e31..5b7bd368760f257698765aeff638ce8a427188ff 100644 (file)
@@ -33,7 +33,7 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u
        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,
+       void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
                        unsigned n_levels = static_cast<const TextureCube *>(this)->levels;
                        change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
index 7f1cfa914884a518a7c766abe385204f72766e66..87afc3c0b516fcefc0ec395fb93e1a4fa63dd3a8 100644 (file)
@@ -12,8 +12,17 @@ TransferQueue::TransferQueue(Device &d):
        device(d)
 { }
 
-TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(size_t size)
+TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(void *object, bool ordered, size_t size)
 {
+       unsigned &order = next_orders[object];
+       order += !order;
+       order += (order&1)|ordered;
+
+       auto j = upper_bound_member(transfers, order, &PendingTransfer::order);
+
+       PendingTransfer &transfer = *transfers.emplace(j);
+       transfer.order = order;
+
        auto i = find_if(buffers, [size](const StagingBuffer &b){ return b.used+size<=b.size; });
        if(i==buffers.end())
        {
@@ -21,15 +30,15 @@ TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(size_t size)
                i = prev(buffers.end());
        }
 
-       PendingTransfer transfer;
        transfer.buffer_index = distance(buffers.begin(), i);
        transfer.offset = i->used;
        transfer.size = size;
-       transfers.push_back(transfer);
 
        i->used += size;
 
-       return transfers.back();
+       order += ordered;
+
+       return transfer;
 }
 
 void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer)
@@ -37,18 +46,23 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer)
        if(transfers.empty())
                return;
 
-       for(const PendingTransfer &t: transfers)
-               t.synchronize();
+       for(auto i=transfers.begin(); i!=transfers.end(); )
+       {
+               auto j = i;
+               for(; (j!=transfers.end() && j->order==i->order); ++j)
+                       j->synchronize();
 
-       device.get_synchronizer().barrier(command_buffer);
+               device.get_synchronizer().barrier(command_buffer);
 
-       for(const PendingTransfer &t: transfers)
-       {
-               VkBuffer buffer = buffers[t.buffer_index].buffer;
-               t.transfer(command_buffer, buffer, t.offset);
+               for(; i!=j; ++i)
+               {
+                       VkBuffer buffer = buffers[i->buffer_index].buffer;
+                       i->transfer(command_buffer, buffer, i->offset);
+               }
        }
 
        transfers.clear();
+       next_orders.clear();
 }
 
 
index a25519c8a121b417b0fe1dc1a60692bc7f7f90ff..b8719d627513bd8962dec3df4c1b52ddd2a8dbc5 100644 (file)
@@ -30,6 +30,7 @@ private:
 
        struct PendingTransfer
        {
+               unsigned order = 0;
                unsigned buffer_index = 0;
                std::size_t offset = 0;
                std::size_t size = 0;
@@ -41,24 +42,25 @@ private:
        std::size_t default_buffer_size = 16*1048576;
        std::vector<StagingBuffer> buffers;
        std::vector<PendingTransfer> transfers;
+       std::map<void *, unsigned> next_orders;
 
 public:
        TransferQueue(Device &);
 
        template<typename S, typename T>
-       void *prepare_transfer(std::size_t, S &&, T &&);
+       void *prepare_transfer(void *, bool, std::size_t, S &&, T &&);
 
 private:
-       PendingTransfer &prepare_transfer(std::size_t);
+       PendingTransfer &prepare_transfer(void *, bool, std::size_t);
 
 public:
        void dispatch_transfers(VkCommandBuffer);
 };
 
 template<typename S, typename T>
-void *TransferQueue::prepare_transfer(std::size_t size, S &&synchronize, T &&transfer)
+void *TransferQueue::prepare_transfer(void *object, bool ordered, std::size_t size, S &&synchronize, T &&transfer)
 {
-       PendingTransfer &pt = prepare_transfer(size);
+       PendingTransfer &pt = prepare_transfer(object, ordered, size);
        pt.synchronize = std::forward<S>(synchronize);
        pt.transfer = std::forward<T>(transfer);
        return static_cast<char *>(buffers[pt.buffer_index].mapped_address)+pt.offset;