X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Ftransferqueue.cpp;h=9fc941401ed90ef954b4a156ae7b1b801baf149f;hb=7d221b1fd6194e59bc0783740a2a17ac71fa4da5;hp=87afc3c0b516fcefc0ec395fb93e1a4fa63dd3a8;hpb=682d3ceda19df700ce6590028717e4f0042783ec;p=libs%2Fgl.git diff --git a/source/backends/vulkan/transferqueue.cpp b/source/backends/vulkan/transferqueue.cpp index 87afc3c0..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,17 +13,8 @@ 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 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()) { @@ -33,12 +25,56 @@ TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(void *object, bo transfer.buffer_index = distance(buffers.begin(), i); transfer.offset = i->used; transfer.size = size; + 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; + + 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) @@ -46,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; @@ -56,13 +93,20 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) for(; i!=j; ++i) { - VkBuffer buffer = buffers[i->buffer_index].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