mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
gpu: preserve finite buffer descriptors across sparse PRT holes
This commit is contained in:
@@ -764,7 +764,10 @@ void RenderExecutor::FindBuffers(std::span<PreparedBindings* const> stages) {
|
||||
size = std::min({size, uint64_t {256} * 1024 * 1024, limit});
|
||||
}
|
||||
}
|
||||
size = Libs::LibKernel::Memory::ClampRangeSize(address, size);
|
||||
// Finite GPU descriptors can span sparse PRT holes; clamp only oversized/sentinel ranges.
|
||||
if (size >= (uint64_t {1} << 30u) || descriptor.NumRecords() == UINT32_MAX) {
|
||||
size = Libs::LibKernel::Memory::ClampRangeSize(address, size);
|
||||
}
|
||||
source = {address, size, cache.FindBuffer(address, size)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13474,6 +13474,49 @@ public:
|
||||
return program;
|
||||
};
|
||||
|
||||
{
|
||||
constexpr uint64_t page = 0x10000;
|
||||
constexpr uint64_t address = base - page;
|
||||
constexpr u32 resident_value = 0x13572468u;
|
||||
void *reservation = reinterpret_cast<void *>(address);
|
||||
Require(name, "sparse descriptor reservation",
|
||||
LibKernel::Memory::KernelReserveVirtualRange(&reservation, page, 0x10, page) == 0,
|
||||
"leading sparse page reservation failed");
|
||||
resources.MapMemory(address, page);
|
||||
LibKernel::Memory::WriteBacking(base, &resident_value, sizeof(resident_value));
|
||||
const auto program = make_buffer_program(ShaderType::Compute, {.read = true});
|
||||
ShaderRecompiler::IR::ResourceSnapshot snapshot;
|
||||
auto &value = snapshot.buffers.emplace_back();
|
||||
value.dword_count = 4;
|
||||
value.dwords = {static_cast<u32>(address), static_cast<u32>(address >> 32), 2u * page};
|
||||
ShaderStageRuntime runtime{&program, &snapshot};
|
||||
PreparedBindings bindings;
|
||||
executor.PrepareBindings(runtime, bindings);
|
||||
std::array<PreparedBindings *, 1> stages{&bindings};
|
||||
executor.FindBuffers(stages);
|
||||
executor.RebindBuffers(bindings);
|
||||
const auto &source = bindings.buffer_sources[0];
|
||||
const auto &owner = resources.GetBufferCache().GetBuffer(source.id);
|
||||
Require(name, "finite sparse descriptor extent",
|
||||
source.address == address && source.size == 2u * page &&
|
||||
bindings.buffers[0].range == 2u * page,
|
||||
"finite descriptor lost its leading hole or resident tail");
|
||||
auto output = CreateHostBuffer(name, 2u * sizeof(u32), vk::BufferUsageFlagBits::eTransferDst, {});
|
||||
const std::array<vk::BufferCopy, 2> copies{{
|
||||
{owner.Offset(address), 0, sizeof(u32)},
|
||||
{owner.Offset(base), sizeof(u32), sizeof(u32)}}};
|
||||
scheduler.Current().Handle().copyBuffer(owner.Handle(), output.buffer, copies.size(), copies.data());
|
||||
scheduler.Finish();
|
||||
Require(name, "finite sparse descriptor upload",
|
||||
ReadBuffer(name, output, 2) == std::vector<u32>{0u, resident_value},
|
||||
"sparse descriptor upload lost zero-filled holes or resident bytes");
|
||||
DestroyBuffer(&output);
|
||||
resources.UnmapMemory(address, page);
|
||||
Require(name, "sparse descriptor reservation release",
|
||||
LibKernel::Memory::KernelMunmap(address, page) == 0,
|
||||
"leading sparse page reservation release failed");
|
||||
}
|
||||
|
||||
{
|
||||
const auto buffer_program = make_buffer_program(ShaderType::Compute, {.read = true});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user