Repository navigation
feat(agc): draw tessellation followed by an NGG geometry stage - #6612
Conversation
|
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.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
jotitadev
left a comment
There was a problem hiding this comment.
Two failures on Linux that the PR body doesn't list.
Machine: NVIDIA GeForce RTX 3070, driver 595.99.02, Vulkan 1.4.329, plus lavapipe (Mesa 26.0.3, LLVM 21.1.8) on the same machine. Ubuntu 26.04 (kernel 7.0.0-38), i7-8700, GCC 15.2, Release, BUILD_TESTING=ON. Head 89aa76a76 merged into main 5d9dcc42d (clean merge).
1. agc_driver_prepared_graphics fails with this PR on every run.
- RTX 3070: 5/5 fail, also with
ANYPS5_NO_SHADER_CACHE=1. lavapipe: 3/3 fail. Unchangedmainpasses it on both. - It stops at
AGC driver: registered program refers to an incompatible shader binary type, the check at the end ofRegisteredPrograminShaderRegistry.cpp. The last lines before it are theReportPreparedAtUsenotes for stages 5 and 7. - The other 15
^agc_driver_preparedtests pass. - The body's run (
^agc_driver_|..., 468 of 469) should include this test, so maybe that binary was stale?
2. On lavapipe, which the Linux CI job uses, the new tessellation cases fail.
agc_driver_tessellation:AGC graphics: subgroup capability 61 is unsupported for shader stage 2.agc_driver_tessellation_geometry: the same forshader stage 4.- Both fail 3/3. Capability 61 is
GroupNonUniform, and lavapipe'ssubgroupSupportedStagesis only fragment, compute, task and mesh, so it refuses the merged program's tessellation-control and tessellation-evaluation modules. The RTX 3070 has subgroups in those stages, and there both tests pass 3/3. - With the PR's sources and
main'sTessellation.cpp(the separate local/hull pair only),agc_driver_tessellationpasses 3/3 on lavapipe. So the existing coverage still works there, and only the new merged case and the new test need subgroup support in tessellation stages. - They probably need a skip (or a non-subgroup lowering) when
subgroupSupportedStageslacks those stages. A skip message that names subgroup support already passestools/check_skips.py.
Otherwise, on the RTX 3070:
agc_driver_tessellation,agc_driver_tessellation_geometryandagc_driver_graphicspass 3/3.- The test-only build doesn't compile against
main(new state fields), as the body says. ctest -R "^agc|shader|recompiler" -j1(flip, display andlds_atomics64excluded): 2 failures. One isprepared_graphicsabove. The other isstore_over_untracked, which also fails onmainhere (#6347).
GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), lavapipe (Mesa 26.0.3, LLVM 21.1.8), Ubuntu 26.04
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.
|
@jotitadev Thank you, both are real, and both are fixed in 0eeb815. 1. 2. lavapipe. As you found, the merged program and the captured domain half need subgroup operations in tessellation-control and tessellation-evaluation shaders. The merged case of I've added your runs to the description. AI-assisted: yes |
jotitadev
left a comment
There was a problem hiding this comment.
Both fixes confirmed on my machine at 0eeb8159b.
Machine: NVIDIA GeForce RTX 3070, driver 595.99.02, Vulkan 1.4.329, plus lavapipe (Mesa 26.0.3, LLVM 21.1.8) on the same machine. Ubuntu 26.04, i7-8700, GCC 15.2, Release, BUILD_TESTING=ON. Head 0eeb8159b merged into main 5d9dcc42d (clean merge), -j1 --timeout 30.
agc_driver_prepared_graphics: passes 3/3 on the RTX 3070 and 3/3 on lavapipe (previously 5/5 and 3/3 failures).- lavapipe:
agc_driver_tessellationpasses 3/3 with the merged case skipped ("needs subgroup operations in tessellation-control shaders");agc_driver_tessellation_geometryskips 3/3. - RTX 3070: both tessellation tests pass 3/3, merged case included.
^agc_driver_(prepared|graphics$|tessellation|ngg|mesh|vertex|registered): 30/30 on the RTX 3070. On lavapipe, 30/30 with 6 skipped:tessellation_geometryplus the 5 mesh/NGG/clip-distance tests that also skip onmain.tools/check_skips.py --job linuxon that lavapipe JUnit: all 6 skips expected.
GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), lavapipe (Mesa 26.0.3, LLVM 21.1.8), Ubuntu 26.04
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.
|
Data from 007 First Light (PPSA11386 v01.018.000), which registers its tessellation hull programs as type 3 too, on Linux 7.2.10, RTX 3080, driver 615.78.08, in a bubblewrap sandbox. Stack:
AI-assisted: yes (Claude Code) |
|
Thanks @SleglJan, that settles it. #6612's type-3 split requires the hull user-data address, and 007 First Light leaves it unset. Your #6679 handles that and also keeps VGPRs live across the barrier, which my split can't. So #6679 should own registered merged hulls. I'll restack #6612 on #6679: drop its type-3 split and keep only the tessellation-to-geometry path, marked "Depends on: #6679". Then I'll check that Crimson Desert gets past its 13 s stop on #6679's merged hull. Its merged program passes 16-bit values through LDS, so that's the part to check. A trial merge conflicts in 8 files (draw decode, registry, cache key, stage IO, tessellation lowering, recompiler), so it will take a while. I'll post here when it's done. AI-assisted: yes |
|
Thanks, sounds good. One heads-up for the Crimson Desert check: #6679 keeps AI-assisted: yes (Claude Code) |
0eeb815 to
de9f0f7
Compare
|
Restacked on #6679 at de9f0f7 (the first commit is #6679's 8f93aa0). The type-3 split is gone; draw decode takes #6679's merged hull on the tessellation-plus-geometry path too. @SleglJan, your two points are in: a AI-assisted: yes |
|
I reviewed the parts of de9f0f7 that touch #6679's merged hull: the 16-bit The lowering looks right. A half write's read now uses The new test case doesn't exercise the write side, though:
The variant below splits the x-position write instead. It writes the high half first, so the second write's read-modify-write has to keep it. The x position has non-zero low halves, differs per control point, and is read back through the own-record alignas(256) constexpr auto MergedHullHalfRecord = [] {
std::array<std::uint32_t, MergedHullCode.size() + 6u> code{};
std::size_t at = 0;
for (std::size_t index = 0; index < MergedHullCode.size(); ++index) {
const auto word = MergedHullCode[index];
if (word == 0xbf88001cu) {
code[at++] = 0xbf880020u;
} else if (word == 0xd9340000u) {
++index;
for (const auto value : {0xda840002u, 0x0000080au, 0xd87c0000u, 0x0000080au, 0xd8340004u, 0x0000090au}) code[at++] = value;
} else if (word == 0xd8d80048u) {
const auto operands = MergedHullCode[++index];
for (const auto value : {0xd8f00048u, operands, 0xda9c004au, operands}) code[at++] = value;
} else {
code[at++] = word;
}
}
return code;
}();That turns A coverage gap on the lane side: this PR lets the merged hull run with Tested on Linux 7.2.10 (CachyOS), RTX 3080, NVIDIA 615.78.08, GCC 16.2.1, Release:
AI-assisted: yes (Claude Code) |
|
Thanks @SleglJan, you're right on both counts. 2920dce adds your For the lane side, AI-assisted: yes |
2920dce to
6038e33
Compare
6038e33 to
e4c4725
Compare
|
Windows 11 VM (GT 1030, 582.78, WinLibs GCC 15.2.0 r7, Release) on AI-assisted: yes (Claude Code) |
|
Rebased onto AI-assisted: yes (Claude Code) |
|
Rebased onto AI-assisted: yes (Claude Code) |
|
Rebased onto AI-assisted: yes (Claude Code) |
|
Additional AMD Linux qualification of public head Physical GPU: AMD Radeon RX 6650 XT (RADV NAVI23), Linux. Required Vulkan, no AnyPS5 shader cache, disabled Mesa shader cache, and Driver qualification: these passing results use a separate X11-capable Mesa 26.2.5 build with the previously isolated two Cocoon PPSA08766: a fresh private startup comparison on that same X11 driver, no input and cold private caches, still reaches no game scene. Both 45-second captures are black; both runs abort at about82s:
Here Conventions pass. The test source already mixes CRLF/LF on main and preserves the upstream PR's bytes; default whitespace checking flags its CRLF additions, while Download focused logs, driver patch, source pins and reviewed results; SHA-256 AI-assisted: yes (Codex). |
|
@JJenkx thank you for the RX 6650 XT run, and for pinning the RADV linking crash on On Cocoon: this path takes AI-assisted: yes (Claude Code) |
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d: local, hull, domain and NGG geometry stages, the hull halves merged in one registered type-3 program, the domain and geometry halves in one type-2 program. The domain half runs as the tessellation evaluation stage and captures each vertex's ESGS item, and a mesh shader runs the geometry half on the captured items. Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS reads and writes in tessellation stages, which Crimson Desert's merged hull uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… hull The first 16-bit case split a write that the hull part never reads back. The new case splits the x position's write into its high and low halves, so the second half's read-modify-write must keep the first, and reads it back through the control point's own record. The registered merged hull is also resolved with HS_W32, which Crimson Desert sets. Co-Authored-By: Jan Šlégl <slegl.jan@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pipeline journal guards State and ShaderStages, which this branch extends. The recipe codec and canonical state now carry the hull wave size, the geometry stage after tessellation, the merged hull flag (TessellationConfiguration keeps its size, so its guard can't see it) and rasterizer discard, and the journal format becomes 12 (main took 5 for the recipe codec change of boykopovar#5656, 6 for the polygon modes of boykopovar#7869, 7 for the truncated coverage of boykopovar#8115, 8 for the point lists of boykopovar#6801 9 for the 4_4_4_4 UNORM target merges of boykopovar#8564 and 10 for the colour logic operation of boykopovar#9348; boykopovar#8365 uses 11, and the number is set to main+1 when this lands). A draw's tessellation capture validates against that draw's capture buffers, which a replay doesn't have, so it isn't journaled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The entry was over the 1000-character limit the conventions check warns about. Same content, tighter wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A triangle patch at level n tessellates into about 3n²/2 triangles, more than the (n + 1)² slots its capture had from level 5 on, and the capture shader drops the triangles past its capacity. Every domain now gets 2(n + 1)² slots per patch, which covers both triangles and quads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sn't implied ImpliesNot returned at a negated condition, so a predicate !!a against the condition !a, or !!a in either order of a conjunction, never reached the negated-predicate and conjunction cases, which prove it. Lane-bit lowering makes such a predicate from a complemented own-lane ballot of !a, and the address evaluator then read both arms of a select on !a instead of the one the predicate implies. Each case now falls through when it does not prove the negation. Three hull reads under that complemented ballot bit, alone and conjoined on either side, check it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Rebased onto
AI-assisted: yes (Claude Code) |
|
Test run (not a code review). I merged this PR onto current It still aborts with: So this PR does not get Cocoon past that point in my run. Builds fine otherwise. |
|
@klosixgaming-arch thanks for the Windows run. That abort is this PR's guard, and the value tells why: Handling AI-assisted: yes (Claude Code) |
|
@milescoviello Thanks, the two-pass draw and the wave32 hull admission read right to me. One case still looks open: Could you either add the rasterization-disabled state to |
…pass The capture pass of a tessellation-geometry draw runs a pipeline with rasterizer discard, which Pipeline::Begin opens without attachments. Its render-pass key matched an ordinary draw to the same targets, so when one was already in the open pass, StartDrawPass continued it and the capture pipeline drew inside a rendering with attachments (VUID-vkCmdDraw-colorAttachmentCount-06179). DrawRenderPassKey now mixes in rasterizer discard, so the capture draw starts its own pass. agc_driver_tessellation_geometry gains a case that records an ordinary draw and then a tessellation-geometry draw into the same resident target in one batch and compares the image with the ordinary draw alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@oneandonlydean thanks, you're right: the capture pass's key matched an ordinary draw's, so it could continue that draw's pass with attachments. I've added rasterizer discard to
The Khronos comparison is queued now: that test on the current head without the key change, against the fix, over the 12 tessellation and journal tests. Then the tests 3 times on Linux and my Windows VM. I'll push and post the VUID counts from both sides when they're in. AI-assisted: yes (Claude Code) |
|
@oneandonlydean pushed 004f498. Under the Khronos layer 1.4.363, over the 12 tessellation and journal tests:
All 12 tests pass on both, and 3 of 3 on Linux with the change. On my Windows VM (GT 1030), the merge base passes 11 of 11 3 of 3 and this head 12 of 12 3 of 3. That GPU has no mesh shaders, so the tessellation-geometry case skips there. I've added this to Tested. AI-assisted: yes (Claude Code) |
|
@milescoviello Here are the measured details from the Cocoon (PPSA08766) abort on current 1. Root Cause & Register StateThe
2. Guard MismatchIn validate((value & ~0x0067ed2du) == 0 && (value & 0x02002000u) == 0x2000u && (value & 3u) == 1u && ((value >> 3u) & 3u) == 1u, "unsupported tessellation and geometry routing");This requires 3. What the ES Program Reads
AI-assisted: yes. Written with AI assistance and reviewed by me. |
|
@klosixgaming-arch thanks, that pins it down: the hull's specials give LS/HS ( What the guard can't tell is how the console runs that ES stage with tessellation on. An experiment you can run:
A screenshot of the area around the draw that used to abort would help either way. AI-assisted: yes (Claude Code) |
What
Crimson Desert (PPSA25286, 01.000.568) stops on
main12 to 14 s in, while it resolves the shader ABIs of its first graphics stages:Its tessellated draws feed an NGG geometry stage. From a throwaway print of the first one:
VGT_SHADER_STAGES_EN0x60212dSPI_SHADER_PGM_LO_LS(0x148)SPI_SHADER_PGM_LO_HSSPI_SHADER_PGM_LO_ES(0xc8)VGT_LS_HS_CONFIG/VGT_TF_PARAM0x1043f/0x4004aVGT_ESGS_RING_ITEMSIZE/VGT_GS_MAX_VERT_OUT/GE_MAX_OUTPUT_PER_SUBGROUPmainrefuses the combination, and with that refusal lifted it would refuse wave32 tessellation next. The enum already hasShaderPath::TessellationGeometry, unused until now. This PR draws that path.How
The geometry half needs the subgroup: its threads share LDS, use
s_barrierand allocate their output withGS_ALLOC_REQ, which only the mesh path runs. A Vulkan geometry shader can't run it per triangle, and a mesh shader can't follow the tessellator. So the draw takes two passes:s_cbranch_execz, which skips the vertex threads' part. Its ESGS LDS writes (thread index × item size) become domain outputs. A generated geometry shader (BuildTessellationCaptureGeometryShader) appends each tessellated triangle's three items to a device-local buffer and keeps the mesh draw arguments in a small header: one group perprimitivesPerGrouptriangles, and three indices per triangle.s3. Its entry copies the group's captured items into LDS where the vertex half would have written them, then runs the geometry half unchanged. It is drawn withvkCmdDrawMeshTasksIndirectEXTfrom the header, after a geometry-shader-write to indirect/mesh-read barrier, in a new render pass.The hull side:
ControlSharedrecords, the read of a write uses the lane's own record, and the bounds checks use the 2-byte end.HS_W32andGS_W32are accepted: local and hull programs compile with the hull wave size, domain and mesh programs with the geometry one.The compile modes follow from fields the request already serializes (a mesh configuration on a domain program, a tessellation configuration on a mesh program). The request format doesn't change beyond #6679's version 37; the cache key gains a word for each new mode.
The approximations are in the technical debt files: triangles reach the geometry half in the order the capture claims them, at most 2^20 per draw, the geometry half's primitive ID is the captured triangle's index, and instanced draws throw.
Tested
Capture draw after an ordinary draw in one batch (004f498, after @oneandonlydean's review): the capture pass now keys its render pass by rasterizer discard, so it can't continue an open pass that has attachments. A new
agc_driver_tessellation_geometrycase records an ordinary tessellation draw and then a tessellation-geometry draw into the same resident target with no wait between, and compares the image with the ordinary draw alone.Khronos layer 1.4.363 over the 12 tessellation and journal tests: with the new case and without the key change (a371244bf8),
VUID-vkCmdDrawIndexed-colorAttachmentCount-06179x2. With the change, noVUID-messages; 12 of 12 pass on both.The 12 tests pass 3 of 3 on Linux. On the Windows 11 VM (GT 1030, WinLibs GCC 15.2.0 r7), the merge base passes 11 of 11 3 of 3 and this head 12 of 12 3 of 3.
Current head
1168a21b8c, rebased ontomain2dc8560, which changedDraw(): it takes aDrawTraceContext(feat(agc): trace shader failures through draw submission batches #5431) and the driver'sDraw.cppgained<algorithm>.drawTessellationGeometrynow takes the draw's trace context and passes it to both of its inner draws, so traced tessellation-geometry draws keep their trace; the include conflict keepsmain's<algorithm>and this branch's<map>. The journal format stays 12 (mainis at 10), and the guards stay 904 / 160 (main's 832 / 112 plus this branch's fields), confirmed by the build. The 12 tests below pass 3 of 3 on this head. On the Windows 11 VM (GT 1030, WinLibs GCC 15.2.0 r7), the merge base passes 11 of 11 and this head 12 of 12, 3 runs each, withagc_driver_tessellation_geometryskipped there (no mesh shaders).75a06af9a9, rebased ontomainc035bd5 after b76ab1f (one-fragment multisampled colour targets) grewStateto 832 bytes there; the only conflict was the journal's size guard, which is now 904 (832 plus this branch's 72), withShaderStagesat 160. The 12 tests below pass 3 of 3 on this head.d175c08f94, rebased ontomaind0e7fe7 after feat(agc): apply the color logic operation of CB_COLOR_CONTROL #9348 took journal format 10; the only conflict was that line, and this branch keeps its provisional 12 (feat(agc): store the pipeline journal's modules compressed #8365 takes 11) until it is set tomain+1 at landing. The 12 tests below pass 3 of 3 on this head.b6f3131b54, rebased ontomainc9b7582 after feat(agc): draw DB depth copies with a driver pixel program #8999, which conflicted inDraw():mainnow opens it withDepthCopySourceScope, and this branch's early return for tessellation followed by a geometry stage comes right after that scope, so it covers those draws too. The 12 tests below pass 3 of 3 on this head.ce4748f0fa:e6db936606plus a fix from @oneandonlydean's review.ImpliesNotreturned at a negated condition, so a predicate!!a(a complemented own-lane ballot bit of!aafter lane-bit lowering) never proved!afalse, alone or in either order of a conjunction; each check now falls through when it doesn't prove the negation. Three newagc_tessellation_loweringcases build that hull read and must lower at its address; withmain'sImpliesNotall three are refused 3 of 3 (not a whole number of control points), and with the fix the 12 tests below pass 3 of 3.e6db936606was rebased ontomaind098eca, which conflicted inTessellationLowering.cpp:mainaddedImpliesNot, which covers what this branch'sExcludesdid (a predicate that implies a condition's negation) and also a negated condition, so the branch callsImpliesNotat its two sites and dropsExcludes. The journal commit takes format 12.mainis at 9, and 10 is also used by fix(agc): render layered mesh targets within device limits #6959, fix(agc): build one compute pipeline when results differ only in a table's size #8212 and fix(agc): start the context at its reset state for color targets and viewports #10420 and 11 by feat(agc): store the pipeline journal's modules compressed #8365, so this bump can't merge silently with any of theirs. Linux (Ubuntu 26.04.1, GCC 15.2, Release, RTX 4070 Ti, 615.71.09): the tessellation, pipeline journal,agc_driver_graphicsand pixel LDS tests (12) pass 3 of 3.Previous head
ae86a022f6, onmain11d6efa: the same 12 passed 3 of 3 on Linux, and onf28839f3c5on the Windows 11 VM (GT 1030, 582.66, WinLibs GCC 15.2.0 r7), withagc_driver_tessellation_geometryskipped there (no mesh shaders).Earlier heads: Linux (Ubuntu 24.04, GCC 13.3, Release), RTX 4070 Ti, NVIDIA 595.99.
agc_driver_tessellation_geometry(new, GPU). It drawsTessellation.cpp's three patches (levels 1, 0 and 5) through the plain tessellation path, then through the new path, with a merged domain and geometry program. That program writes the same position and colour as an 8-dword item, and its geometry half (the mesh fixture's NGG program reading items instead of indices) emits each triangle unchanged. The two images must be equal in every pixel, unculled and back-face culled, for wave64 and wave32 stages. The same comparison runs again into a resident tiled target, where both draws are recorded into the open batch (the path titles take), byte for byte. A last part registers a type-3 merged hull and the merged domain program and resolves their graphics ABI, which compiles all four roles through draw decode, once at wave64 and once withHS_W32(as Crimson Desert sets it). A throwaway check that throws when a wave32 merged hull is compiled fails only with theHS_W32registration.agc_driver_tessellation: two variants of feat(agc): run registered merged hull programs (binary type 3) #6679's merged hull program use 16-bit LDS accesses with the same values, so the patches must draw exactly as with the 32-bit program. @SleglJan's case splits the local part's x-position write intods_write_b16_d16_hi(high half first) andds_write_b16. The second half's read-modify-write must then keep the first, and the value is read back through the control point's own record. It fails if that read uses control point 0's record, or if it merges into 0 instead of the record's current word. The other case splits a 32-bit read of the level intods_read_u16andds_read_u16_d16_hi. My first version split only a write that is never read back, which SleglJan found didn't check the write side. With feat(agc): run registered merged hull programs (binary type 3) #6679 alone, the cases fail withonly 32-bit LDS reads and writes are supported in tessellation stages at pc 0x84.agc_driver_graphics:0x60212ddecodes as TessellationGeometry with the expected subgroup (10 triangles of 30 vertices, 192 threads, wave32 hull and domain) and only registers the draw key covers.0x0260210ddecodes as wave32 tessellation. PRIMGEN_PASSTHRU or a missing PRIMGEN_EN with GS_EN is refused.agc_driver_tessellation_geometryandagc_driver_graphicsuse the new state fields and the capture shader, so they don't build onmainor on feat(agc): run registered merged hull programs (binary type 3) #6679. The newTessellation.cppcase fails on feat(agc): run registered merged hull programs (binary type 3) #6679 as above. All three pass 3 of 3 with this PR.mainb7a451d (head8783ad1e29), after feat(agc): rasterize geometry points with their point size #6801 merged, as @oneandonlydean asked. The journal format is 9, andsizeof(State)is 896 on the rebased tree, confirmed by the build'sstatic_assert.ShaderStagesstays 160. The recipe codec and canonical state carry feat(agc): rasterize geometry points with their point size #6801's point fields and this PR's rasterizer discard.ShaderRegistry.cppkeeps feat(agc): rasterize geometry points with their point size #6801'sApplyPointSizeand this PR'sStageMeshConfiguration, andShaderInputInfoBuilder.cppkeeps both new flags. The 17 tests matching^agc_driver_graphics$|tessellation|journal|serializer|mesh|geometrypass 3 of 3. With the Khronos validation layer (1.4.363),mainpasses 16 of 16 and this head 17 of 17, with no VUID. On the Windows 11 VM (GT 1030, R580), the 18 matching tests pass 3 of 3 on this head,agc_driver_tessellation_geometryincluded.mainf6075c2 (heada785b13a95), after feat(agc): expose expanded FMASK for tracked native owners #7948 grewStatefrom 784 to 800 bytes. The one conflict was the size check inPipelineJournal.cpp; it is now 872,main's 800 plus this PR's 72, andShaderStagesstays 160. The build confirms both. On that head (Ubuntu 26.04.1, GCC 15.2, RTX 4070 Ti, 615.71.09), the 17 tests matching^agc_driver_graphics$|tessellation|journal|serializer|mesh|geometrypass 3 of 3. Under the Khronos 1.4.363 layer, the same set passes onmain(16, without this PR's test) and on this head (17), with noVUID-message on either side. The journal format stays 7 here; feat(agc): draw one-sample color targets beside a multisampled depth target with sample 0's coverage #8115 and feat(agc): store the pipeline journal's modules compressed #8365 also take 7, so whichever lands later renumbers.maincc00785 (head6aa4f7cc7f). refactor(agc): split Graphics::Draw into a prepare and a record step #8992 splitGraphics::Drawinto a prepare and a record step.drawTessellationGeometrynow sits just before the newDraw, and the hand-off to it is at the top of that function. It still draws both passes throughDraw, and theDraw.cppchange is otherwise line for line the same. The journal format stays 7 andsizeof(State)stays 856. The 17 tests matching^agc_driver_graphics$|tessellation|journal|serializer|mesh|geometrypass 3 of 3,agc_driver_tessellation_geometryamong them.main275e896 (head dfc290f). feat(agc): draw point and line polygon modes #7869 took journal format 6 for its polygon modes, so the journal commit now takes 7.Pipeline.cppkeepsmain'spolygonModelines, with this PR'srasterizerDiscardEnableafter them.sizeof(State)stays 856. The 8 tests matchingtess|Tess|hull|Hull|pipeline_journal|^agc_driver_graphics$pass 2 of 2.main3aa4448), head 09356fe. feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941 merged with request version 38, so feat(agc): run registered merged hull programs (binary type 3) #6679 now reads its merged-hull flag from 39, and this PR reads it from there with the rest of feat(agc): run registered merged hull programs (binary type 3) #6679 (it adds no version of its own). Four conflicts came frommain's mesh barycentric change (feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941). InCacheKey.hpp,appendMeshkeeps feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941's pixel key and barycentric layout, and this PR's domain-stage ESGS key and tessellation tag. The tag comes before the barycentric block, which can return early. InShaderValidation.cpp, both added extension clauses stay, along with feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941's per-primitive checks and this PR's position check under rasterizer discard. InDraw.cpp, the tessellation geometry stage is inserted before feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941's barycentric pairing. InDrawCapture.cpp, this PR's push limit and mesh configuration take feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941's barycentric argument. The 16 tests matching^agc_driver_graphics$|tessellation|journal|serializer|mesh|geometrypass 3 of 3. Under the LunarG SDK's 1.4.363 layer,^agc_driver_graphics$|tessellation|journal|mesh|geometrygives no validation messages on feat(agc): run registered merged hull programs (binary type 3) #6679's head (14 tests) or on this head (15).main0fbfd91), head 77d218a. feat(agc): run registered merged hull programs (binary type 3) #6679 now writes request version 38 and resolves both conflicts adriadam10 listed: perf(agc): queue CPU-path indirect draws on the draw pipeline #6931's indirect record words and the serializer fixtures. This PR's three commits apply on it without a conflict. The 635 broad-set tests pass onmain, and 636 of 636 with this PR. The tessellation, journal and serializer tests pass 3 of 3. Under the LunarG SDK's 1.4.363 layer,tess|journalreports nothing onmainor on this head.VUID-vkCmdDrawIndexed-colorAttachmentCount-06179×12 in the capture pass. A discarding pipeline has no fragment output state, so it has no color attachments, while the pass began rendering with the draw's targets.Pipeline::Beginnow begins a discarding pass with no attachments. Under 1.4.363,tess|journalreports nothing onmainf72c7aa or on this head. The 631 broad-set tests pass, and the tessellation, journal and serializer tests pass 3 of 3.VK_LAYER_PATH,VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest -V, RTX 4070 Ti,tess|journal). Neither log reports the layer missing. On 235f513 it found two errors this PR added, 9 each, inagc_driver_tessellation_geometry:VUID-VkGraphicsPipelineCreateInfo-pStages-06894andVUID-RuntimeSpirv-OpEntryPoint-08743. The capture pass discards its primitives but still carried the pixel program, which reads a location the capture geometry stage doesn't write. Head 7570d58 leaves the pixel program out of that pass: it has four stages, andValidateShadersexpects four and checks no color exports for it. The pixel program still runs in the mesh pass that draws the captured triangles. Nowmainf72c7aa and this PR report onlyVkDeviceCreateInfo-pNext-pNextandVkGraphicsPipelineCreateInfo-pLibraries-06681, which this older layer gives for every device-creating test, and nothing new. The 631 broad-set tests pass, and the tessellation, journal and serializer tests pass 3 of 3.mainf72c7aa (head 235f513), with feat(agc): run registered merged hull programs (binary type 3) #6679's commit still first, as @adriadam10 asked. The one conflict wasmain'sbool quadList(feat(libSceAgcDriver): support quad-list primitive type #6529) next to this PR'srasterizerDiscardandtessellationCaptureinState.hpp, and both are kept.sizeof(State)stays 856, because the bool fits in padding, so the journal guards are unchanged. Quad-list draws are never journaled:Draw.cppclearsrecipeOutfor them, and the recorder returnsNotRecordable. So the codec doesn't carryquadList, and a decoded recipe'sfalseis what it was recorded with. The 630 tests in the broad driver/recompiler/journal set pass on f72c7aa, and 631 of 631 with this PR. The tessellation, journal and serializer tests pass 3 of 3.StagePushLimitnow also takes the depth remap limit, inmain's order: mesh, tessellation before rasterization, depth remap, then the slot. The push-constant validation keeps both the depth-remap push and the tessellation capture terms. The journal guards name the newState(856 bytes) andShaderStages(160 bytes) sizes, and the journal format becomes 6, since perf(agc): data-only draw hits compare only the user words a stage reads #5656 took 5 onmain. The AGC, shader, request, journal and tessellation set passes 614 of 615, against 613 of 614 on 3b69fde alone; the one failure on both isagc_driver_bda_device(agc_driver_bda_device times out in vkWaitForFences since the BDA anchor lookup (#5859, d422c760c) #7584). The 6 tessellation, serializer and journal tests pass 3 of 3.main324e0e4), head 9825024; it merges withmain7bc7905 cleanly. Two conflicts, both frommain: inShaderRegistry.cppthe stage loop now computes the push offset, then the deferral check, then decodes the vertex stage inside itstry, and this PR'sStageWaveSizeandStageMeshConfigurationreplace the fixed wave size andstages.meshthere; inDraw.cppthis PR's|| capturedsits besidemain'sKeepMultisampleTargetloop. The AGC, shader, request, journal and tessellation set passes 609 of 610, against 608 of 609 on 4e7fa2b alone; the one failure on both isagc_driver_bda_device(agc_driver_bda_device times out in vkWaitForFences since the BDA anchor lookup (#5859, d422c760c) #7584). The 6 tessellation, serializer and journal tests pass 3 of 3.main17cfb1f cleanly: the 6 tessellation, geometry, merged hull, journal and serializer tests pass 3 of 3, and the AGC area suite passes 897 of 898. The one failure isagc_driver_store_over_untracked, which also fails under-j6here without this PR and passes alone.main3e3e8b9 (723155e; feat(agc): run registered merged hull programs (binary type 3) #6679's commit still first). fix(agc): draw geometry programs with the last provoking vertex #7374 now sets the provoking vertex of geometry programs fromPA_SU_SC_MODE_CNTL.PROVOKING_VTX_LASTwhereDecodeShaderStagesbuilds theMeshConfiguration. This PR builds it in the sharedmeshConfiguration, so that computation moved there, and the tessellation geometry path gets it too.ctest -R ^agc_: 710/710 pass, including the two provoking vertex tests.main4524944: the 7 tessellation, geometry, merged hull, journal and serializer tests pass 3 of 3, and the 502 area tests pass exceptmain'sagc_driver_graphics(Linux GCC13.3: agc_driver_graphics reports VOP2 for an all-zero vertex request #6792) andagc_driver_store_over_untracked.main82ddae7 (10-16). feat(agc): draw line-strip output of NGG geometry programs as mesh lines #5884's line-strip output (outputPrimitiveSize) now goes through the sharedmeshConfigurationinState.cpp, which the tessellation-geometry path also uses; fix(agc): stop pixel invocations on BDA faults when supported #5804's terminate-invocation checks and this PR's capture rules both stay inShaderValidation.cpp. perf(agc): journal the pipelines of a run and build them ahead on the next one #5875's pipeline journal guardsStateandShaderStages, so e4c4725 adds the hull wave size, the geometry stage after tessellation, the merged hull flag and rasterizer discard to its codec and canonical state, with journal format 4. A pipeline drawn with a tessellation capture validates against that draw's capture buffers, so it isn't journaled. ctest (^agc_driver_|^agc_vertex_barrier|recompiler|shader_cache|request_serializer|spirv|^agc_shader|bda|journal, 502 tests, with test(agc): keep the vertex terminate case's code in static storage #6789's one-line test fix applied soagc_driver_graphicsruns to the end): 501 pass.agc_driver_tessellation,agc_driver_tessellation_geometry,agc_driver_graphics,agc_driver_prepared_graphicsand the journal tests pass 3 of 3; a recipe with these fields must decode with them.agc_driver_store_over_untrackedfails the same way onmain; test(agc): keep waiting for the neighbour copy case's result #6385 addresses it. feat(agc): run registered merged hull programs (binary type 3) #6679 then read its merged hull flag under request version 31, whichmainuses for feat(agc): draw line-strip output of NGG geometry programs as mesh lines #5884; SleglJan moved it to version 32 (36529f1). (On an earlier head, jotitadev found anagc_driver_prepared_graphicsfailure that my stale binary had hidden. That code is now feat(agc): run registered merged hull programs (binary type 3) #6679's, and the test passes.)Crimson Desert, scripted pad input:
main5d9dcc4SPIR-V emission failed: ... opcode=Barrier reason=s_barrier in a vertex program that accesses LDS or GDS or writes memory is not implementedThe title is still building shaders and pipelines then and hasn't issued a draw, so it hasn't drawn the new path yet. With #6706 as well, which makes its large compute pipelines about 3x faster to create, it reaches its first draw at 597 s and stops there on
AGC graphics: fragment shader must export float4 colors to its attachments, which is a separate change. In a 905 s run (the previous head with #6613 and #6178), the shaders finish after about 7 minutes. After that, eleven compute pipelines of 110,000 to 870,000 SPIR-V words take 2 to 137 s each to create on NVIDIA, about 570 s in all, and the first draw still hasn't come. That's a separate problem, which I'm looking at. The rendering is checked by the tests above only.On the previous head (0eeb815), jotitadev ran it on an RTX 3070 (595.99.02) and on lavapipe (Mesa 26.0.3), Ubuntu 26.04, and confirmed the area tests there.
SleglJan reviewed the merged hull parts of de9f0f71c on an RTX 3080 (NVIDIA 615.78.08, CachyOS).
ctest -R 'tess|hull|prepared_graphics|shader_memory|request'passed 10 of 10, andagc_driver_tessellationandagc_driver_tessellation_geometrypassed 3 of 3 each.On de9f0f7:
^agc_driver_(prepared|graphics$|tessellation|ngg|mesh|vertex|registered)pass or skip, andtools/check_skips.py --job linuxaccepts the 6 skips.agc_driver_tessellationnow runs its merged hull cases there, because feat(agc): run registered merged hull programs (binary type 3) #6679 runs the merged hull at one lane per invocation.agc_driver_tessellation_geometrystill skips, since the capture needs subgroup operations in tessellation stages.agc_driver_tessellationandagc_driver_tessellation_geometrypass 3 of 3 with no skips.@LeandroLP23 ran it on Windows 11 with an AMD Radeon 860M (RDNA 3.5, driver 32.0.13058.8001) (comment), in one build of
main6efb726 with this PR and six other pull requests:agc_driver_tessellation,agc_driver_tessellation_geometry,agc_driver_graphics,agc_driver_prepared_graphicsandagc_driver_store_over_untrackedpass 3 runs of 3.@JJenkx ran this head, rebased unchanged onto
main25c1aa1, on an AMD Radeon RX 6650 XT (RADV NAVI23, Linux) with Khronos validation (comment). They used a Mesa 26.2.5 build with twonir_opt_varyings.cfixes, because system RADV already segfaults while linkingmain's tessellation test pipelines. The nine groups both builds share pass 3 of 3 onmain, and the same groups plusagc_driver_tessellation_geometrypass 3 of 3 with this PR, with no VUID. Cocoon (PPSA08766) stops at about 82 s on both builds. On this PR it stops at the routing guard, since itsVGT_SHADER_STAGES_EN0x2135 setsES_ENto 2 where this path takes 1.@klosixgaming-arch ran Cocoon on Windows with this PR merged onto current
main(comment): it builds, and the title still stops after about 80 s at this PR's guard onVGT_SHADER_STAGES_EN=0x2135. That value has LS and HS on withES_EN= 2, a routing this PR does not take (it takesES_EN= 1, the domain shader in the ES stage); see the note to JJenkx.2 · level²slots per patch, where triangle patches hadlevel², too few from level 5 on (3n²/2triangles). A newagc_driver_tessellation_geometrycase draws the level-5 triangle patch alone atVGT_HOS_MAX_TESS_LEVEL5 and must match the tessellation path's image. With the old sizing it fails 3 of 3 (a dropped triangle). With the fix it passes 3 of 3, as doesagc_driver_tessellation.Not checked on a console.
Other open PRs touch neighbouring lines in the same files (for example #6176 in
ConstantFolder.cpp, #6188 inDrawCapture.cpp, #6215 inDraw.cpp). None of them draws this path; whichever lands second needs a small rebase.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code