Files
NX2navi/runtime/shaders/meshfb_scan.comp
chrg6 a8c6e992ee Draw task and mesh programs through compute passes when the mesh fallback is on.
A mesh draw becomes its record (the workgroup count, copied on the GPU for an indirect draw), the task dispatch, a
scan that lists the mesh workgroups the tasks started, the mesh dispatch, and an instanced indirect draw with a
generated vertex stage and the program's fragment stage. The compute modules bind the resources of the task and mesh
stages, and their pipelines are made on a thread of their own while the program's draws are skipped.

The indirect mesh ring and the texture pool marks are released at a probe's shutdown.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 05:58:42 -05:00

48 lines
2.4 KiB
Plaintext

#version 450
// The mesh fallback's pass between a draw's task dispatch and its mesh dispatch (vk_mesh_fb.c vk_meshfb_scan,
// mesh_fb.c): every task workgroup wrote how many mesh workgroups it starts into its payload (word 1). This lists them
// in task order, so that mesh workgroup g finds its task and its index among that task's in list entry g, and writes
// the draw's record: how many mesh workgroups to dispatch and how many instances to draw.
//
// One thread walks the tasks: the order of the list is the order the primitives are drawn in, which has to be the
// same in every frame and in the depth and colour passes of one frame.
layout(local_size_x = 1) in;
layout(push_constant) uniform Params {
uint rec; // the record's first word in the record buffer
uint task_words; // words of a task workgroup's payload in the task buffer
uint fan; // mesh workgroups a task workgroup starts at most
uint slot_words; // words of a mesh workgroup's output in the mesh buffer
uint verts; // vertices drawn per mesh workgroup
uint max_groups; // workgroups one dispatch may have (maxComputeWorkGroupCount)
} pc;
// The record: words 0-2 the task dispatch (x written before this pass), 4-6 the mesh dispatch, 8-11 the draw (vertices,
// instances, first vertex, first instance), 12 the mesh workgroups the tasks asked for, 13 the task workgroups.
layout(set = 0, binding = 0) buffer Rec { uint w[]; } rec;
layout(set = 0, binding = 1) readonly buffer Task { uint w[]; } task;
layout(set = 0, binding = 2) writeonly buffer List { uint e[]; } list;
layout(set = 0, binding = 3) readonly buffer Mesh { uint w[]; } mesh; // read for its size alone
void main() {
uint asked = rec.w[pc.rec];
uint tasks = min(min(asked, uint(task.w.length()) / pc.task_words), 1u << 24);
uint room = min(min(uint(mesh.w.length()) / pc.slot_words, uint(list.e.length())), pc.max_groups);
uint fan = min(pc.fan, 255u);
uint m = 0u, want = 0u;
for (uint t = 0u; t < tasks; t++) {
uint c = min(task.w[t * pc.task_words + 1u], fan);
want += c;
for (uint j = 0u; j < c && m < room; j++) list.e[m++] = t | j << 24;
}
rec.w[pc.rec + 4u] = m;
rec.w[pc.rec + 5u] = 1u;
rec.w[pc.rec + 6u] = 1u;
rec.w[pc.rec + 8u] = pc.verts;
rec.w[pc.rec + 9u] = m;
rec.w[pc.rec + 10u] = 0u;
rec.w[pc.rec + 11u] = 0u;
rec.w[pc.rec + 12u] = want;
rec.w[pc.rec + 13u] = asked;
}