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) {
|
if (usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) {
|
||||||
return GetStreamBuffer(size);
|
return GetStreamBuffer(size);
|
||||||
}
|
}
|
||||||
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
|
return GetStagingBuffer(size, usage);
|
||||||
return *ref;
|
|
||||||
}
|
|
||||||
return CreateStagingBuffer(size, usage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StagingBufferPool::TickFrame() {
|
void StagingBufferPool::TickFrame() {
|
||||||
|
@ -145,17 +142,20 @@ void StagingBufferPool::TickFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
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;
|
for (size_t region = Region(used_iterator), region_end = Region(iterator); region < region_end;
|
||||||
++region) {
|
++region) {
|
||||||
sync_ticks[region] = scheduler.CurrentTick();
|
sync_ticks[region] = scheduler.CurrentTick();
|
||||||
}
|
}
|
||||||
used_iterator = iterator;
|
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) {
|
if (iterator + size > free_iterator) {
|
||||||
free_iterator = iterator + size;
|
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,
|
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
|
||||||
MemoryUsage usage) {
|
MemoryUsage usage) {
|
||||||
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];
|
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];
|
||||||
|
|
|
@ -67,6 +67,8 @@ private:
|
||||||
|
|
||||||
StagingBufferRef GetStreamBuffer(size_t size);
|
StagingBufferRef GetStreamBuffer(size_t size);
|
||||||
|
|
||||||
|
StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage);
|
||||||
|
|
||||||
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
|
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
|
||||||
|
|
||||||
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);
|
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);
|
||||||
|
|
Loading…
Reference in a new issue