mirror of
https://github.com/Takiiiiiiii/strato.git
synced 2025-07-17 08:46:39 +00:00
Rewrite buffer megabuffering to be per view and more efficient
This commit implements several key optimisations in megabuffering that are all inherently interlinked. - Megabuffering is moved from per-buffer to per-view copies, this makes megabuffering possible for small views into larger underlying buffers which is often the case with even the simplest of games, - Megabuffering is no longer the default option, it is only enabled for buffer views that have had inline GPU writes applied to them in the past as that is the only case where they are beneficial. In any other case the cost of copying, even with a 128KiB limit can be significant. - With both of these changes, there is now possibility for overlapping views where one uses megabuffering and one does not. In order to allow GPU inline writes to work consistently in such cases a system of 'host immutability' has been implemented, when a buffer is marked as host immutable for a given cycle, all writes to the buffer from that point to the point the cycle is signalled will be performed on the GPU, ensuring that the backing contents are correctly sequenced
This commit is contained in:
@ -57,15 +57,20 @@ namespace skyline::gpu {
|
||||
|
||||
// Transfer all views from the overlapping buffer to the new buffer with the new buffer and updated offset, ensuring pointer stability
|
||||
vk::DeviceSize overlapOffset{static_cast<vk::DeviceSize>(overlap->guest->begin() - newBuffer->guest->begin())};
|
||||
if (overlapOffset != 0) {
|
||||
// This is a slight hack as we really shouldn't be changing the underlying set elements without a rehash but without writing our own set impl this is the best we can do
|
||||
for (auto it{overlap->views.begin()}; it != overlap->views.end(); it++)
|
||||
for (auto it{overlap->views.begin()}; it != overlap->views.end(); it++) {
|
||||
if (overlapOffset)
|
||||
// This is a slight hack as we really shouldn't be changing the underlying non-mutable set elements without a rehash but without writing our own set impl this is the best we can do
|
||||
const_cast<Buffer::BufferViewStorage *>(&*it)->offset += overlapOffset;
|
||||
|
||||
// All current hashes are invalidated by above loop so rehash the container
|
||||
overlap->views.rehash(0);
|
||||
// Reset the sequence number to the initial one, if the new buffer was created from any GPU dirty overlaps then the new buffer's sequence will be incremented past this thus forcing a reacquire if neccessary
|
||||
// This is fine to do in the set since the hash and operator== do not use this value
|
||||
it->lastAcquiredSequence = Buffer::InitialSequenceNumber;
|
||||
}
|
||||
|
||||
if (overlapOffset)
|
||||
// All current hashes are invalidated by above loop if overlapOffset is nonzero so rehash the container
|
||||
overlap->views.rehash(0);
|
||||
|
||||
// Merge the view sets, this will keep pointer stability hence avoiding any reallocation
|
||||
newBuffer->views.merge(overlap->views);
|
||||
|
||||
|
Reference in New Issue
Block a user