mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
graphics: skip GPU-clean empty indirect dispatches before shader preparation
Co-authored-by: fxpw <fxpw@outlook.com>
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/ResourceMaterialization.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
#include "kernel/eventQueue.h"
|
||||
#include "kernel/memory.h"
|
||||
#include "kernel/pthread.h"
|
||||
#include "libs/errno.h"
|
||||
|
||||
@@ -444,6 +445,12 @@ void RenderExecutor::DispatchIndirect(uint64_t submit_id, CommandBuffer& buffer,
|
||||
static_cast<uint32_t>(args_addr), static_cast<uint32_t>(args_addr >> 32u),
|
||||
0, mode, buffer.GetShaders().GetCs().cs_regs.data_addr);
|
||||
Common::LockGuard lock(m_context.GetMutex());
|
||||
vk::DispatchIndirectCommand args {};
|
||||
if (!m_context.GetBufferCache().HasGpuDirtyBytes(args_addr, sizeof(args)) &&
|
||||
LibKernel::Memory::TryReadBacking(args_addr, &args, sizeof(args)) &&
|
||||
(args.x == 0 || args.y == 0 || args.z == 0)) {
|
||||
return;
|
||||
}
|
||||
const auto& cs_regs = buffer.GetShaders().GetCs();
|
||||
if (cs_regs.cs_regs.data_addr == 0) {
|
||||
return;
|
||||
|
||||
@@ -10566,6 +10566,34 @@ public:
|
||||
auto &cache = context.GetBufferCache();
|
||||
auto &shaders = processor.GetShCtx();
|
||||
context.MapMemory(base, allocation_size);
|
||||
// Empty CPU-owned arguments must not inspect the shader, even on a GPU-dirty page.
|
||||
constexpr auto empty_args = base + allocation_size - case_size;
|
||||
constexpr auto neighbor = empty_args + 0x100u;
|
||||
constexpr std::array<std::array<u32, 3>, 3> empty_dimensions{{
|
||||
{0, 1, 1}, {1, 0, 1}, {1, 1, 0}}};
|
||||
Require(name, "empty arguments",
|
||||
LibKernel::Memory::TryWriteBacking(empty_args, empty_dimensions.data(),
|
||||
sizeof(empty_dimensions)),
|
||||
"empty indirect arguments could not be written");
|
||||
shaders.SetCsShader({.data_addr = 1});
|
||||
for (const bool dirty_neighbor : {false, true}) {
|
||||
if (dirty_neighbor) {
|
||||
auto [buffer, offset] = cache.ObtainBuffer(neighbor, sizeof(sentinel), true);
|
||||
buffer->Fill(offset, sizeof(sentinel), sentinel + 1u);
|
||||
}
|
||||
Require(name, "exact argument ownership",
|
||||
!cache.HasGpuDirtyBytes(empty_args, sizeof(empty_dimensions)) &&
|
||||
cache.IsRegionGpuModified(empty_args, sizeof(empty_dimensions)) == dirty_neighbor,
|
||||
"empty arguments did not retain independent byte ownership");
|
||||
const auto tick = scheduler.CurrentTick();
|
||||
for (size_t i = 0; i < empty_dimensions.size(); ++i) {
|
||||
processor.DispatchIndirect(empty_args + i * sizeof(empty_dimensions[0]), 0x41u);
|
||||
}
|
||||
Require(name, "empty dispatch avoids readback",
|
||||
scheduler.CurrentTick() == tick &&
|
||||
cache.HasGpuDirtyBytes(neighbor, sizeof(sentinel)) == dirty_neighbor,
|
||||
"empty dispatch submitted work or read back neighboring GPU data");
|
||||
}
|
||||
const auto set_buffer = [&](u32 sgpr, uint64_t address, u32 records, u32 stride = 0) {
|
||||
ShaderBufferResource descriptor{};
|
||||
descriptor.UpdateAddress48(address);
|
||||
|
||||
Reference in New Issue
Block a user