aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 11:31:05 -0500
committerSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 14:53:47 -0500
commita1f781fa24cc16e6d636213a5596cfed4123f493 (patch)
treea2a1df52ac83d8ea44544abb5a6e4dedb8cef2e3 /src
parente46c6cbfb0f6735ca35f1150338c300f3c9c18fe (diff)
video_core: flush GPU-written code when capturing native shaders
10e7063905 moved native program capture from one ReadBlock per instruction to ReadBlockUnsafe per 4 KiB page. ReadBlockUnsafe skips the rasterizer flush, so code that a GPU copy had written and not yet flushed to guest memory was captured stale. The speed-up comes from reading a page at a time, not from skipping the flush: read each page (and the odd single instruction outside a fully mapped page) with ReadBlock, which flushes once per page instead of once per instruction. Follow-up to 10e7063905. Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader_environment.cpp10
1 files changed, 5 insertions, 5 deletions
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 8d340ba881..0c7d8a0d42 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -328,9 +328,9 @@ Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr,
namespace {
// Reads a native program a 4 KiB page at a time instead of one 16-byte instruction at a time.
-// The reads do not flush the GPU caches first (ReadBlockUnsafe): the previous per-instruction
-// ReadBlock did, once per instruction. An instruction that is not inside a fully mapped page is
-// left to the caller.
+// Each page is read with ReadBlock, so GPU-written code is flushed first, once per page instead
+// of once per instruction. An instruction that is not inside a fully mapped page is left to the
+// caller.
class NativeInstructionReader {
public:
using Instruction = Shader::Ampere::Instruction;
@@ -365,7 +365,7 @@ private:
page_begin = address;
page_end = address;
if (length >= sizeof(Instruction) && gpu_memory.IsFullyMappedRange(address, length)) {
- gpu_memory.ReadBlockUnsafe(address, page.data(), length);
+ gpu_memory.ReadBlock(address, page.data(), length);
page_end = next_page;
}
}
@@ -415,7 +415,7 @@ std::shared_ptr<const LoweredNativeCode> GenericEnvironment::LowerNativeCode(u32
if (!native.empty()) break;
throw Shader::RuntimeError("Unmapped native shader instruction at {:#x}", address);
}
- gpu_memory->ReadBlockUnsafe(address, &instruction, sizeof(instruction));
+ gpu_memory->ReadBlock(address, &instruction, sizeof(instruction));
}
native.push_back(instruction);
const auto status = capture.Observe(instruction, index);