forked from suyu/suyu
vk_staging_buffer_pool: Get a staging buffer instead of waiting
Avoids waiting idle while the GPU finishes to do work, and fixes an issue where we'd wait forever if a single command buffer (logic tick) all the data.
This commit is contained in:
parent
75fd3f95a3
commit
7402442442
2 changed files with 18 additions and 9 deletions
|
@ -130,10 +130,7 @@ StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) {
|
|||
if (usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) {
|
||||
return GetStreamBuffer(size);
|
||||
}
|
||||
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
|
||||
return *ref;
|
||||
}
|
||||
return CreateStagingBuffer(size, usage);
|
||||
return GetStagingBuffer(size, usage);
|
||||
}
|
||||
|
||||
void StagingBufferPool::TickFrame() {
|
||||
|
@ -145,17 +142,20 @@ void StagingBufferPool::TickFrame() {
|
|||
}
|
||||
|
||||
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
||||
for (size_t region = Region(free_iterator) + 1,
|
||||
region_end = std::min(Region(iterator + size) + 1, NUM_SYNCS);
|
||||
region < region_end; ++region) {
|
||||
// If we'd have to wait, get a staging buffer to avoid waiting
|
||||
if (!scheduler.IsFree(sync_ticks[region])) {
|
||||
return GetStagingBuffer(size, MemoryUsage::Upload);
|
||||
}
|
||||
}
|
||||
for (size_t region = Region(used_iterator), region_end = Region(iterator); region < region_end;
|
||||
++region) {
|
||||
sync_ticks[region] = scheduler.CurrentTick();
|
||||
}
|
||||
used_iterator = iterator;
|
||||
|
||||
for (size_t region = Region(free_iterator) + 1,
|
||||
region_end = std::min(Region(iterator + size) + 1, NUM_SYNCS);
|
||||
region < region_end; ++region) {
|
||||
scheduler.Wait(sync_ticks[region]);
|
||||
}
|
||||
if (iterator + size > free_iterator) {
|
||||
free_iterator = iterator + size;
|
||||
}
|
||||
|
@ -180,6 +180,13 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
|||
};
|
||||
}
|
||||
|
||||
StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage) {
|
||||
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
|
||||
return *ref;
|
||||
}
|
||||
return CreateStagingBuffer(size, usage);
|
||||
}
|
||||
|
||||
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
|
||||
MemoryUsage usage) {
|
||||
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];
|
||||
|
|
|
@ -67,6 +67,8 @@ private:
|
|||
|
||||
StagingBufferRef GetStreamBuffer(size_t size);
|
||||
|
||||
StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage);
|
||||
|
||||
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
|
||||
|
||||
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);
|
||||
|
|
Loading…
Reference in a new issue