mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
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>
48 lines
2.4 KiB
Plaintext
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;
|
|
}
|