X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Ftransferqueue.cpp;h=9fc941401ed90ef954b4a156ae7b1b801baf149f;hb=7d221b1fd6194e59bc0783740a2a17ac71fa4da5;hp=8040f245f5360a33ae31fb6a23b34cd392c8dbf9;hpb=5c35768c310847df816d216eecf8fa2e93f5f8b8;p=libs%2Fgl.git diff --git a/source/backends/vulkan/transferqueue.cpp b/source/backends/vulkan/transferqueue.cpp index 8040f245..9fc94140 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,36 +13,68 @@ TransferQueue::TransferQueue(Device &d): device(d) { } -TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(void *object, bool ordered, size_t size) +void TransferQueue::allocate_staging(PendingTransfer &transfer, size_t size) { - unsigned &order = next_orders[object]; - order += !order; - order += (order&1)|ordered; + auto i = find_if(buffers, [size](const StagingBuffer &b){ return b.used+size<=b.size; }); + if(i==buffers.end()) + { + buffers.emplace_back(device, max(default_buffer_size, size)); + i = prev(buffers.end()); + } - auto j = upper_bound_member(transfers, order, &PendingTransfer::order); + transfer.buffer_index = distance(buffers.begin(), i); + transfer.offset = i->used; + transfer.size = size; + transfer.staging_address = static_cast(i->mapped_address)+transfer.offset; - PendingTransfer &transfer = *transfers.emplace(j); - transfer.order = order; + 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) { - auto i = find_if(buffers, [size](const StagingBuffer &b){ return b.used+size<=b.size; }); - if(i==buffers.end()) - { - buffers.emplace_back(device, max(default_buffer_size, size)); - i = prev(buffers.end()); - } + 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)); +} - transfer.buffer_index = distance(buffers.begin(), i); - transfer.offset = i->used; - transfer.size = size; +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); +} - i->used += size; - } +TransferQueue::PendingTransfer &TransferQueue::insert_transfer(PendingTransfer &&pt) +{ + bool ordered = pt.order; + + unsigned &order = next_orders[pt.object]; + order += !order; + order += (order&1)|ordered; + + auto j = upper_bound_member(transfers, order, &PendingTransfer::order); + j = transfers.emplace(j, move(pt)); + j->order = order; order += ordered; - return transfer; + return *j; } void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) @@ -49,6 +82,7 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) if(transfers.empty()) return; + ++current_frame; for(auto i=transfers.begin(); i!=transfers.end(); ) { auto j = i; @@ -61,11 +95,18 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) { 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