Repository navigation
feat(shader): read hull patch constants in domain programs - #4175
tibzejoker wants to merge 3 commits into
Conversation
…and level clamps DecodeShaderStages accepted only triangle patches with clockwise output and HOS level clamps that leave [1, 63] untouched, so tessellated terrain drawn as quad patches with TRI_CCW output and VGT_HOS_MAX_TESS_LEVEL 9 aborted. Quad domains and TRI_CCW now decode and emit Quads and VertexOrderCcw; isolines, other partitionings and point or line output still throw. VGT_HOS_MIN/MAX_TESS_LEVEL travel in the tessellation configuration (draw keys, hull cache key, recompile request version 17) and clamp the factors the hull writes; zero, negative and NaN outer factors still cull. Clamps outside 0 <= min <= 63, max >= 1, min <= max throw. Quad hulls write four outer and two inner factors per patch at a 24-byte stride, the layout Mesa's TF ring store uses; quad hulls that use the 16-byte triangle stride are refused.
TessellationLowering proved ring and LDS addresses affine over a relative patch index of up to 256. A hull that lays its patch-constant records out downwards, at 0x8000 - 208 * (rel + 1) like the quad particle hull in Ghost of Yotei, then reached a negative address for the last slot and aborted as "not affine". The relative patch index of hull and domain programs stays below VGT_LS_HS_CONFIG.NUM_PATCHES (bits 7:0, patches per threadgroup), which is 63 for that draw. DecodeShaderStages now carries NUM_PATCHES as patchesPerGroup in the tessellation configuration (draw keys, hull and domain cache keys, recompile request version 18) and refuses zero, and the lowering bounds the relative patch index by it. Configurations without it keep 256.
TessellationLowering refused every domain read of the off-chip ring whose relative patch coefficient is not a whole patch of control points, so a domain program that reads the patch constants its hull wrote stopped with "domain shader reads of patch constants or other patches are unsupported" (GTA V PPSA04264 at pc 0x9c, on top of the descending records of boykopovar#4114). A domain read that stays inside its own patch's control points is still a control point read. A read at the control point record stride inside the group's control point region is left to the existing "outside its patch's control points" refusal. Any other read becomes a per-patch input, provided the domain also reads a control point (the patch interface location follows the control point record size), its address lies past the patch's control points and its records do not overlap those of the neighbouring patches. Hull patch outputs and domain patch inputs share one layout: the offset inside the record is the ring address modulo the patch record stride, and the interface is one record stride wide. Both stages derive the stride from their own accesses, so separately compiled hull and domain programs agree on locations without knowing where the hull placed its records (ascending, or descending from 0x8000 as in boykopovar#4114). The tessellation execution test draws the triangle patches with a domain program that takes two control point x coordinates from the hull's patch constants and checks each patch's shape at mid-height. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
|
Thanks for stacking this on #4082 and #4114, good to see GTA V hitting the same stop. Heads-up so we don't make double work for the reviewers: #4163 (opened about 20 minutes before this one, on the same base) reads the hull's patch constants in domain programs too, from Yōtei's terrain domain, which reads its hull's records at The two take slightly different routes to agreeing on the record layout between the stages, so it would be useful to know whether either one covers both games. If you get a chance, could you try GTA V's domain at pc 0x9c on #4163's head? I'll check Yōtei's on this one in return, and then we can suggest one of them to the maintainers. |
|
Closing in favour of #4163, which covers GTA V's domain program as well (tested on its head, details there). Thanks @Celegans12. AI-assisted (Claude Code). |
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
|
What
Stacked on #4114 (which is stacked on #4082). Only the last commit,
feat(shader): read hull patch constants in domain programs, is new here; the two commits below it are #4082 and #4114 as they are.With #4082 and #4114, GTA V (PPSA04264) gets past its hull program and stops on its domain program:
The domain program reads the patch constants that its hull wrote at
0x8000 - stride * (rel + 1). TessellationLowering refused every domain read of the off-chip ring whose relative patch coefficient is not a whole patch of control points.What changes:
TessellationAttribute::PatchInput). This requires that the domain program also reads a control point, because the patch interface location comes from the control point record size. It also requires that the address lies past the patch's control points and that the records do not overlap the neighbouring patches' records. Unproven shapes still throw.The limit is listed in TechnicalDebt.md. A domain read of another patch's constants that is a whole number of strides away from its own record reads its own record, because neither stage knows where the other's records begin.
Tested
Windows 11, RTX 4090, WinLibs GCC 15.2.
agc_driver_tessellation: new casedomain program reading its patch constants. The existing triangle hull (patch constants at0x8000 - 16 * (rel + 1)) is drawn with a domain program that takes two control point x coordinates from those patch constants instead of the control points. The case also checks each drawn patch's shape at mid-height. This shape check was added to everyRequirePatchescase.tessellation lowering: domain shader reads of patch constants or other patches are unsupported at pc 0x38.Tessellation tests passed.patch 0 is not the triangle of its control points at mid-height, so the check sees wrong values.DomainPatchReadrefusal case is replaced byDomainNeighbourRead(a read of the next patch's control point), which is still refused on both fix(agc): bound tessellation patch records by the draw's patch count #4114 and this branch.ctest -R "agc_driver|agc_masked|agc_shader|agc_vector|tess" -j8: 336/337 pass on fix(agc): bound tessellation patch records by the draw's patch count #4114 and the same set passes on this branch.agc_driver_prepared_shaders_registered_workgroup_syncfails on both.agc_driversometimes exits with 0xc0000374 under -j8 on both and passes when run alone.python tools/check_conventions.py --base upstream/main: passed.GTA V result: on
main325e0a8 with #4082, #4114 and this commit (plus the other PRs GTA needs that are unrelated to tessellation: #425, #290, #637, #448, #423, #4021), the domain program that stopped at pc 0x9c compiles and Story mode runs past it; the log of a 150 s prologue run has no tessellation error.Checklist
main; no other open PR implements the same functions (stacked on fix(agc): bound tessellation patch records by the draw's patch count #4114, which is 11 commits behind main)NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code
https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
🤖 Generated with Claude Code
https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV