|
|
|
@ -24,25 +24,38 @@ using namespace Common::Literals; |
|
|
|
|
|
|
|
// Maximum potential alignment of a Vulkan buffer
|
|
|
|
constexpr VkDeviceSize MAX_ALIGNMENT = 256; |
|
|
|
// Maximum size to put elements in the stream buffer
|
|
|
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB; |
|
|
|
// Stream buffer size in bytes
|
|
|
|
constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; |
|
|
|
constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; |
|
|
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB; |
|
|
|
|
|
|
|
size_t Region(size_t iterator) noexcept { |
|
|
|
return iterator / REGION_SIZE; |
|
|
|
size_t GetStreamBufferSize(const Device& device) { |
|
|
|
VkDeviceSize size{0}; |
|
|
|
if (device.HasDebuggingToolAttached()) { |
|
|
|
ForEachDeviceLocalHostVisibleHeap(device, [&size](size_t index, VkMemoryHeap& heap) { |
|
|
|
size = std::max(size, heap.size); |
|
|
|
}); |
|
|
|
// If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
|
|
|
|
// loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
|
|
|
|
// as the heap will be much larger.
|
|
|
|
if (size <= 256_MiB) { |
|
|
|
size = size * 40 / 100; |
|
|
|
} |
|
|
|
} else { |
|
|
|
size = MAX_STREAM_BUFFER_SIZE; |
|
|
|
} |
|
|
|
return std::min(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE); |
|
|
|
} |
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, |
|
|
|
Scheduler& scheduler_) |
|
|
|
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} { |
|
|
|
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, |
|
|
|
stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size / |
|
|
|
StagingBufferPool::NUM_SYNCS} { |
|
|
|
VkBufferCreateInfo stream_ci = { |
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
|
|
|
.pNext = nullptr, |
|
|
|
.flags = 0, |
|
|
|
.size = STREAM_BUFFER_SIZE, |
|
|
|
.size = stream_buffer_size, |
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | |
|
|
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, |
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
|
|
|
@ -63,7 +76,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem |
|
|
|
StagingBufferPool::~StagingBufferPool() = default; |
|
|
|
|
|
|
|
StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) { |
|
|
|
if (!deferred && usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { |
|
|
|
if (!deferred && usage == MemoryUsage::Upload && size <= region_size) { |
|
|
|
return GetStreamBuffer(size); |
|
|
|
} |
|
|
|
return GetStagingBuffer(size, usage, deferred); |
|
|
|
@ -101,7 +114,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { |
|
|
|
used_iterator = iterator; |
|
|
|
free_iterator = std::max(free_iterator, iterator + size); |
|
|
|
|
|
|
|
if (iterator + size >= STREAM_BUFFER_SIZE) { |
|
|
|
if (iterator + size >= stream_buffer_size) { |
|
|
|
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, |
|
|
|
current_tick); |
|
|
|
used_iterator = 0; |
|
|
|
|