mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-13 02:41:02 +00:00
In mirror mode the replay copied every range a shader wrote from the VRAM mirror back to guest memory at the end of the submission. TotK's particle emitters write a new particle's whole record into a free slot of a buffer the simulation shaders update, so the copy put the mirror's stale words over fresh spawns: the waterfall splashes and mist showed about once a second and the falling rain drifted. Now each written range gets a snapshot in the prologue of the part that first writes it, after the CPU-to-mirror copies, and at the end of the submission shaders/wb_merge.comp writes only the 32-bit words that differ from the snapshot. Words the GPU left alone keep what the CPU wrote. About 0.1 MiB and three or four dispatches a frame in rain. TOTK_WB_MERGE=0 restores the copies. The merge's push descriptors go through rec_push so they keep their place in the recorder's call order.
28 lines
1.3 KiB
Plaintext
28 lines
1.3 KiB
Plaintext
#version 450
|
|
// Write-back merge of a VRAM mirror (vk_memory.c, wb_merge_record): copies a 32-bit word of what the GPU left in the
|
|
// mirror into the pool's imported buffer (guest memory) only where it differs from the snapshot taken before the
|
|
// submission's GPU work, so words the GPU did not change keep what the CPU wrote meanwhile.
|
|
// One invocation per word of the listed ranges; ranges are sorted by their first invocation (x: word offset in the
|
|
// mirror and imported bindings, y: word offset in the snapshot binding, z: words, w: first invocation).
|
|
layout(local_size_x = 64) in;
|
|
layout(std430, set = 0, binding = 0) readonly buffer Post { uint post[]; };
|
|
layout(std430, set = 0, binding = 1) readonly buffer Pre { uint pre[]; };
|
|
layout(std430, set = 0, binding = 2) buffer Dst { uint dst[]; };
|
|
layout(std430, set = 0, binding = 3) readonly buffer Ranges { uvec4 rng[]; };
|
|
layout(push_constant) uniform Push { uint nranges, total; } pc;
|
|
|
|
void main() {
|
|
uint i = gl_GlobalInvocationID.x;
|
|
if (i >= pc.total) return;
|
|
uint lo = 0, hi = pc.nranges;
|
|
while (hi - lo > 1) {
|
|
uint m = (lo + hi) >> 1;
|
|
if (rng[m].w <= i) lo = m;
|
|
else hi = m;
|
|
}
|
|
uvec4 r = rng[lo];
|
|
uint k = i - r.w;
|
|
uint v = post[r.x + k];
|
|
if (v != pre[r.y + k]) dst[r.x + k] = v;
|
|
}
|