mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
The record's copies put the count the game's culling pass wrote into the first dispatch and, without a task stage, into the draw's instances as it was. A garbage count launched up to millions of workgroups that write nothing and instances that draw nothing, enough to keep the GPU past the driver's timeout; with the fallback now the default on AMD's driver for RDNA 1 and 2, such a count would have moved a hang there instead of removing it. A single-thread compute pass (shaders/meshfb_clamp.comp) cuts the count to the buffers' room, which changes nothing that is drawn; the report word keeps the count asked for, so record_check still logs a mesh-only draw that asked for more than the buffers hold. On for every device that uses the fallback: one dispatch and one barrier per indirect fallback draw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
30 lines
1.6 KiB
Plaintext
30 lines
1.6 KiB
Plaintext
#version 450
|
|
// The mesh fallback's pass between a draw's record and its first dispatch, for a draw whose workgroup count the GPU
|
|
// wrote (vk_mesh_fb.c vk_meshfb_clamp, vk_exec_draw.c mfb_draw). The record's copies put that count into the first
|
|
// dispatch and, without a task stage, into the draw's instances as it is; a garbage count (the game's culling pass
|
|
// reading memory nothing wrote) would launch up to millions of workgroups that write nothing and instances that draw
|
|
// nothing, past the buffers' end, and keep the GPU busy past the driver's timeout. The count is cut to what the
|
|
// buffers hold, which changes nothing that is drawn; the record's report word keeps the count asked for, so the log
|
|
// names such a draw (vk_mesh_fb.c record_check).
|
|
layout(local_size_x = 1) in;
|
|
|
|
layout(push_constant) uniform Params {
|
|
uint rec; // the record's first word in the record buffer
|
|
uint task; // 1: the count is the task dispatch's (word 0); 0: the mesh dispatch's and the draw's instances (4, 9)
|
|
uint room; // workgroups the buffers hold, at most what one dispatch may have
|
|
} pc;
|
|
|
|
// The record (meshfb_scan.comp): words 0-2 the task dispatch, 4-6 the mesh dispatch, 8-11 the draw (vertices,
|
|
// instances, first vertex, first instance), 12 the mesh workgroups asked for, 13 the task workgroups.
|
|
layout(set = 0, binding = 0) buffer Rec { uint w[]; } rec;
|
|
|
|
void main() {
|
|
if (pc.task != 0u) {
|
|
rec.w[pc.rec] = min(rec.w[pc.rec], pc.room);
|
|
} else {
|
|
uint m = min(rec.w[pc.rec + 4u], pc.room);
|
|
rec.w[pc.rec + 4u] = m;
|
|
rec.w[pc.rec + 9u] = m;
|
|
}
|
|
}
|