Repository navigation
vk: mesh programs with control topology 1 draw points, with the point sprite coordinate (grass shadow mesh on AMD, #302) - #482
Merged
Conversation
… sprite coordinate NVN2's mesh control section says 3 for triangles; OoT's four mesh stages with a 1 (the grass drawn into the 2400 x 2400 shadow map around Link, programs 02ee95fbf9e0050d and b0b3b40244c71ec7 among them) draw points: one index byte per primitive at 4 + i, the vertex count as the primitive count, and a point size. Read as lines (GL's 1), each primitive joined vertex 2i to 2i + 1 of its meshlet: long thin streaks in the shadow map and a flickering dark mesh on the ground, the water and Link around him on AMD (issue 302). - Control topology 1 maps to GL 0, points: OutputPoints, PrimitivePointIndicesEXT (a scalar per primitive), one map byte per primitive (MeshInfo::Corners()). - Their fragment program reads generic 5 (s, t, r), which the mesh program never writes: the hardware's point sprite coordinate, with which it cuts each point out of an alpha mask. The generics a point mesh program leaves unwritten are now gl_PointCoord (s, t, 0, 1) (RuntimeInfo::point_coord_generics); left at (0, 0, 0, 1) every point was a filled square. - tests/test_mesh_point_topology.py checks both, game-free. Tested on an RX 7700S (Adrenalin 26.10.1, Windows 11) in Hyrule Field: the mesh is gone, the grass casts its shadow again, and F9 dumps of the shadow map show rounded points instead of streaks. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
Merged into main (c072313); it ships in the next release. |
This was referenced Nov 8, 2026
3 tasks done
This was referenced Nov 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
NVN2's mesh control section (
+0x5f) says 3 for triangles. Four mesh stages in OoT say 1 (ef6e1a5fde0988f0,df6cf52500d013a4,ed01e3e8ff1c102b,644dba7ae7b8bced). They draw the grass into the 2400 x 2400 shadow map thatfollows Link, in programs
02ee95fbf9e0050dandb0b3b40244c71ec7among others.mesh_registers_ofpassed that 1 onas GL's 1, lines, but these programs draw points. Their native code:
popc(ballot & lanemask_lt)and writes one map byte, at4 + i, with the valuei;popc(ballot), the number of vertices;1b 1c 1d 1e 1f).Read as lines, primitive
pjoined vertex2pto2p + 1, and the second half of the index bytes was never written.The grass patch around Link came out in the shadow map as long thin streaks spanning the patch, and the shadow mask
drew them on everything near him: a flickering dark diagonal mesh on the ground, the water, rocks and Link.
Their fragment program then reads generic 5 (
s, t, r, perspective), which the mesh program never writes. It samplesan alpha mask with it and discards: that is the hardware's point sprite coordinate, which gives each point its shape.
Left at
(0, 0, 0, 1), every point was a filled square.Change
vk_shader.cpp: control topology 1 maps to GL 0 (points); 3 stays 4 (triangles).MeshInfo::Corners(): index bytes per primitive (points 1, lines 2, triangles 3). It is used for the map region's size,the index builtin and the epilogue.
OutputPoints,PrimitivePointIndicesEXT(oneuintper primitive, stored as a scalar), one index byte at4 + primitive. The lines path stays for a real GL 1.RuntimeInfo::point_coord_generics: when the mesh program draws points, the generics its fragment program reads andthe mesh program never writes are
gl_PointCoord(s, t, 0, 1). The perspective factor Eden's IPA applies togenerics cancels out as it does for the others.
tests/test_mesh_point_topology.py(game-free, wired intosource-regressions.yml): evaluates the control-to-GLmapping and
Corners(), and checks that the translator accepts points, the SPIR-V side declares and stores them, andthe point sprite coordinate replaces only the unwritten generics of point mesh programs. It fails on
main, andwithout either half of the change.
This touches the translator, so the shader stamp changes and caches are rebuilt on the first start.
Tested
AMD Radeon RX 7700S 8 GB (laptop), Adrenalin 26.10.1, Windows 11, Hyrule Field, in the sun with grass around Link.
RX_VK_SKIP_PROG=53509044401d78d2,02ee95fbf9e0050d,b0b3b40244c71ec7, which also drops the grass shadow.shadow mask pass
3427a1dbefd5e02c) show the patch as separate rounded points instead of streaks; with points aloneand no point coordinate they were squares.
The tested build also carried #475 (the mesh stage buffer zeroed in the prologue). This change does not depend on it:
with points, the epilogue reads only the index bytes the program writes. Not tested on NVIDIA.
Addresses the grass shadow mesh in #302. The crops and bushes that vanish when Link gets close are a separate problem
and are not fixed by this.
🤖 Generated with Claude Code