X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Ftransferqueue.cpp;h=4ad50d860f126952ad4024c6d9208cd05149f055;hb=bec8444ce5f844d156f5aac90ce9f0a92750cf62;hp=7f1cfa914884a518a7c766abe385204f72766e66;hpb=d9c769b5847beefa378d2c5555f5b5d8e5d26c0e;p=libs%2Fgl.git diff --git a/source/backends/vulkan/transferqueue.cpp b/source/backends/vulkan/transferqueue.cpp index 7f1cfa91..4ad50d86 100644 --- a/source/backends/vulkan/transferqueue.cpp +++ b/source/backends/vulkan/transferqueue.cpp @@ -1,4 +1,5 @@ #include +#include #include "device.h" #include "transferqueue.h" #include "vulkan.h" @@ -12,7 +13,7 @@ TransferQueue::TransferQueue(Device &d): device(d) { } -TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(size_t size) +void TransferQueue::allocate_staging(PendingTransfer &transfer, size_t size) { auto i = find_if(buffers, [size](const StagingBuffer &b){ return b.used+size<=b.size; }); if(i==buffers.end()) @@ -21,15 +22,59 @@ 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); + transfer.staging_address = static_cast(i->mapped_address)+transfer.offset; i->used += size; + ++i->async_count; +} + +TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(const void *object, bool ordered, size_t size) +{ + PendingTransfer transfer; + transfer.object = object; + transfer.order = ordered; + + if(size) + { + allocate_staging(transfer, size); + auto i = lower_bound_member(async_transfers, transfer.staging_address, &PendingTransfer::staging_address); + i = async_transfers.emplace(i, move(transfer)); + return *i; + } + else + return insert_transfer(move(transfer)); +} + +void TransferQueue::finalize_transfer(void *staging) +{ + auto i = lower_bound_member(async_transfers, staging, &PendingTransfer::staging_address); + if(i==async_transfers.end() || i->staging_address!=staging) + throw key_error(staging); + + if(i->buffer_index>=0) + --buffers[i->buffer_index].async_count; + insert_transfer(move(*i)); + async_transfers.erase(i); +} + +TransferQueue::PendingTransfer &TransferQueue::insert_transfer(PendingTransfer &&pt) +{ + bool ordered = pt.order; + + unsigned &order = next_orders[pt.object]; + order += !order; + order += (order&1)|ordered; - return transfers.back(); + auto j = upper_bound_member(transfers, order, &PendingTransfer::order); + j = transfers.emplace(j, move(pt)); + j->order = order; + + order += ordered; + + return *j; } void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) @@ -37,18 +82,31 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) if(transfers.empty()) return; - for(const PendingTransfer &t: transfers) - t.synchronize(); - - device.get_synchronizer().barrier(command_buffer); - - for(const PendingTransfer &t: transfers) + ++current_frame; + for(auto i=transfers.begin(); i!=transfers.end(); ) { - VkBuffer buffer = buffers[t.buffer_index].buffer; - t.transfer(command_buffer, buffer, t.offset); + auto j = i; + for(; (j!=transfers.end() && j->order==i->order); ++j) + j->synchronize(); + + device.get_synchronizer().barrier(command_buffer); + + for(; i!=j; ++i) + { + VkBuffer buffer = (i->buffer_index>=0 ? buffers[i->buffer_index].buffer : 0); + i->transfer(command_buffer, buffer, i->offset); + if(i->buffer_index>=0) + buffers[i->buffer_index].last_frame = current_frame; + } } transfers.clear(); + next_orders.clear(); + + unsigned n_frames_in_flight = device.get_n_frames_in_flight(); + for(StagingBuffer &b: buffers) + if(!b.async_count && b.last_frame+n_frames_in_flight