mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Give mesh output components outside the program's output map Maxwell's default of (0, 0, 0, 1).
A mesh program's header lists the components of each output vector it has; the fragment stage may read the others. The native mesh entry function never wrote them, so they read as whatever the output held, and the fallback's vertex stage wrote 0 for all of them, w included. Maxwell gives an unwritten component (0, 0, 0, 1), as the pipeline code already pads a missing vertex output. Both paths now write that default: MeshSpirv.cs after copying each vertex's lines, mesh_fb.c meshfb_vs with w as the bits of 1.0f whatever the type. Checked: all 520 task and mesh programs of an installed shader cache translate and pass spirv-val (vulkan1.3); 500 mesh modules gained about 730 bytes each on average, so many of the game's mesh programs have partly listed vectors. --probe-meshfb passes (fallback pictures equal the mesh pipeline's), and its module part converts all 520 new translations with 0 failures, all 1,020 modules pass spirv-val and their compute pipelines build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,7 +121,11 @@ Grep-level look on 2026-10-22, statuses updated 2026-10-26; "saw" is what the gr
|
||||
not just their base location: an FS `vec4[16]` requires all 16 locations even when it only accesses some elements.
|
||||
The same reflected mask feeds recorded-pipeline prewarm, independent stage-library unions and direct pipeline builds.
|
||||
Our translator never links stages, so its `InitializeVertexOutputs` would initialise no user output;
|
||||
translator patch 0006 initialises the unlinked outputs. **Implemented; array-span runtime validation pending.**
|
||||
translator patch 0006 initialises the unlinked outputs. Mesh programs: a component of a position or generic vector
|
||||
that the program's output map leaves out is written as (0, 0, 0, 1) by the mesh entry function
|
||||
(`tools/xlate/MeshSpirv.cs`) and by the fallback's vertex stage (`runtime/mesh_fb.c` `meshfb_vs`); a whole location
|
||||
the fragment stage reads and the mesh program lacks is still not padded with mesh shaders (`have = ~0u` for mesh in
|
||||
`vk_pipeline.c`). **Implemented; array-span runtime validation pending.**
|
||||
3. **Masked clears.** `vk_exec.c` skips colour clears with a partial channel mask (`W_CLEAR_MASK`); `clear_ds` skips stencil
|
||||
clears with a partial mask (`W_STENCIL_MASK`). NX2navi issues such clears. Check the log for
|
||||
`colour clear with channel mask` and `stencil clear with mask`. The hardware recipe (1.3) shows what the replay must do: colour clear = scissor 0 + channel mask, stencil clear = `value & mask` merged under the front write mask; so a draw with `colorWriteMask` / `stencilWriteMask` set to the clear mask is the exact equivalent. **Missing.**
|
||||
|
||||
@@ -583,9 +583,11 @@ uint32_t *meshfb_vs(const MeshFbInfo *m, uint32_t out_mask, const uint8_t out_ty
|
||||
for (int g = 0; g < 32; g++) {
|
||||
if (!loc_var[g]) continue;
|
||||
int t = out_type[g] < 3 ? out_type[g] : 0;
|
||||
// A component outside the program's output map reads as Maxwell gives an unwritten one: (0, 0, 0, 1), the w
|
||||
// as the bits of 1.0f whatever the type, as vk_pipeline.c spirv_add_outputs pads a missing output.
|
||||
uint32_t comp[4];
|
||||
for (int k = 0; k < 4; k++) {
|
||||
uint32_t word_k = gen[g][k] ? gen[g][k] : k0;
|
||||
uint32_t word_k = gen[g][k] ? gen[g][k] : k == 3 ? K(&c, 0x3f800000) : k0;
|
||||
comp[k] = t == 2 ? word_k : E(&c, OpBitcast, t_scalar[t], word_k);
|
||||
}
|
||||
DO(&c, OpStore, loc_var[g], E(&c, OpCompositeConstruct, t_v4[t], comp[0], comp[1], comp[2], comp[3]));
|
||||
|
||||
@@ -306,6 +306,9 @@ static class MeshSpirv
|
||||
// outputs
|
||||
uint tV4 = Ty(OpTypeVector, tFloat, 4);
|
||||
uint pOutFloat = Ptr(ScOutput, tFloat);
|
||||
uint fZero = Id(), fOne = Id();
|
||||
globals.Add(new Insn(OpConstant, new[] { tFloat, fZero, 0u }));
|
||||
globals.Add(new Insn(OpConstant, new[] { tFloat, fOne, 0x3f800000u }));
|
||||
uint posVar = 0, sizeVar = 0;
|
||||
var generic = new Dictionary<int, uint>();
|
||||
foreach (int a in m.Lines)
|
||||
@@ -343,6 +346,16 @@ static class MeshSpirv
|
||||
uint ptr = comp == uint.MaxValue ? Emit(OpAccessChain, pOutFloat, var, v) : Emit(OpAccessChain, pOutFloat, var, v, C(comp));
|
||||
Do(OpStore, ptr, value);
|
||||
}
|
||||
// A component of an output vector that the program's output map leaves out reads as Maxwell gives an
|
||||
// unwritten one, (0, 0, 0, 1), instead of whatever the output held.
|
||||
void Defaults(uint var, int first)
|
||||
{
|
||||
for (int k = 0; k < 4; k++)
|
||||
if (!m.Lines.Contains(first + 4 * k))
|
||||
Do(OpStore, Emit(OpAccessChain, pOutFloat, var, v, C((uint)k)), k == 3 ? fOne : fZero);
|
||||
}
|
||||
if (posVar != 0) Defaults(posVar, 0x70);
|
||||
foreach (var (g, var) in generic) Defaults(var, 0x80 + 16 * g);
|
||||
});
|
||||
}
|
||||
for (int k = 0; k * threads < maxP; k++)
|
||||
|
||||
Reference in New Issue
Block a user