Repository navigation
fix(agc): draw geometry programs with the last provoking vertex - #7374
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.
|
| const auto maxPrimitives = outputSize == 2u && !fastLaunch ? std::max(primitives * amplification, maxVertices) : primitives * amplification; | ||
| const auto threads = std::max({(groupPrimitives - 1u) * inputStep + inputSize, primitives, maxVertices, maxPrimitives}); | ||
| result.mesh = ShaderRecompiler::MeshConfiguration{primitive, groupPrimitives, (groupPrimitives - 1u) * inputStep + inputSize, maxVertices, maxPrimitives, ((threads + result.vertexWaveSize - 1u) / result.vertexWaveSize) * result.vertexWaveSize, ((resources >> 19u) & 0xffu) * 128u, 0, esgsItemSize, outputSize}; | ||
| const auto raster = find(queue.context, 0x205); |
There was a problem hiding this comment.
Non-blocking coverage suggestion: this value also feeds the Layer selection in SpirvModuleEmitter.cpp (the emitted mesh primitive selects vertex[provokingVertex]), but the new execution fixture only checks flat and smooth fragment inputs. A focused fixture with distinct guest layer values on the vertices of an emitted primitive could verify that the first/last modes select the intended per-primitive layer in this translation. This would validate the new layer-mapping path; it would not establish the separately documented console-semantic assumption.
|
@thuanquang @MarcZX100 I tested this branch for #7118; here is the result and full runtime log. Test result for PR #7374 at The diagnostic source changes were stashed before checkout, The earlier captured shader Both CMD and PowerShell runs reach this same final refusal and SIGABRT. The screen remains black; the Bandai Namco logo is not visible in these runs. This establishes the next guard encountered, not rendering correctness of the earlier draw. We have not captured the new draw's decoded state, so cannot yet distinguish strip from fan or establish its fragment-input semantics. The test does not validate the later Videodec2 path. A separate Windows Bad Image dialog ( Same environment as #7118: Windows 11 Pro 25H2, Ryzen 7 2700X, RX 7800 XT, AMD Windows driver Full PowerShell runtime log below (the more readable of the two runs). Local installation paths and executable name are redacted; diagnostic addresses and guest virtual paths are retained. Report prepared with AI assistance; test and runtime logs supplied by the reporter. Full runtime log — PR #7374 test (redacted) |
|
Thanks, this is merged. One follow-up, not blocking, and a separate small PR is fine: under last-provoking-vertex mode the per-primitive Layer is still untested. Could you add a fixture where each vertex of a primitive writes a distinct layer, render to a 2-layer target, and check that last mode lands on the last vertex's layer? It's reachable only by mesh programs that write different layers per vertex of one primitive, but that is exactly the case the provoking-vertex selection decides. |
…st provoking vertex An RX 6700 XT hands a geometry shader odd strip triangle i as (i+1, i, i+2) with the last provoking vertex, which is the order the translator already uses, and since boykopovar#7374 last mode takes the flat outputs of the program's primitives from their last index. Keep the last-mode refusal for fans only, which reach the program as (i+1, i+2, 0) while the hardware gives (0, i+1, i+2). TEKKEN DARK RESURRECTION (PPSA31371) stops on such a strip draw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st provoking vertex An RX 6700 XT hands a geometry shader odd strip triangle i as (i+1, i, i+2) with the last provoking vertex, which is the order the translator already uses, and since boykopovar#7374 last mode takes the flat outputs of the program's primitives from their last index. Keep the last-mode refusal for fans only, which reach the program as (i+1, i+2, 0) while the hardware gives (0, i+1, i+2). TEKKEN DARK RESURRECTION (PPSA31371) stops on such a strip draw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st provoking vertex An RX 6700 XT hands a geometry shader odd strip triangle i as (i+1, i, i+2) with the last provoking vertex, which is the order the translator already uses, and since boykopovar#7374 last mode takes the flat outputs of the program's primitives from their last index. Keep the last-mode refusal for fans only, which reach the program as (i+1, i+2, 0) while the hardware gives (0, i+1, i+2). TEKKEN DARK RESURRECTION (PPSA31371) stops on such a strip draw. Co-Authored-By: Claude <noreply@anthropic.com>
What
TEKKEN DARK RESURRECTION (PPSA31371) still stops on
mainafter #7251 and #7252. @cavazzatommaso's capture on #7118 shows the refused draw: a geometry program on the mesh path (ShaderPath::Geometry) in last provoking vertex mode, with two smooth per-vertex pixel inputs.ValidateProvokingVertexrefuses every mesh-path draw in that mode:@MarcZX100 asked on #7118 which topology the capture's
LINE_LISTis, and what decides the values thePerVertexKHRinputs read.state.topologyandmesh.inputPrimitiveboth come from the draw's primitive type (register 0x242), soLINE_LISTis the geometry program's input.VGT_GS_OUT_PRIM_TYPE2 givesoutputPrimitiveSize3 andOutputTrianglesEXT.exp prim, in the guest's order. The emulator does not assemble the output primitives.For primitives a mesh shader emits, Vulkan reads
PerVertexKHRinputs as if the primitives were drawn as lists, and the list rows of the vertex order table are the same in both modes (Barycentric Interpolation). So the two smooth inputs read the same vertices in last mode as in first mode. Flat inputs take the last index of each primitive, because Vulkan picks the provoking vertex from the mesh output topology and the pipeline's mode (Flat Shading).VkPipelineRasterizationProvokingVertexStateCreateInfoEXTis already chained into mesh pipelines too.The one value the emulator picks itself is the per-primitive layer, which
MeshConfiguration::provokingVertextook from vertex 0 in both modes.DecodeShaderStagesnow sets that field to the last vertex of the output primitive whenPA_SU_SC_MODE_CNTL.PROVOKING_VTX_LASTis set. The field is already part of every mesh cache key.ValidateProvokingVertexnow lets a mesh-path geometry draw through in last mode. These still throw:Assumption, not measured: under bit 19 the console takes the last index of an exported primitive as its provoking vertex, as it does for native primitives. The debt entry says so.
A program the driver prepared at registration was prepared with no rasterizer state, so with provoking vertex 0. A last-mode draw of it compiles its own variant at the draw, with the usual "no artifact prepared at registration" line. On
mainthat draw threw.Overlap: #6612 moves the
MeshConfigurationconstruction inDecodeShaderStagesinto a helper that still passes 0, so whichever of the two lands second has to carry the bit-19 read into it. #6741 and #7332 edit the same debt line ("throws for generated mesh or tessellation primitives").Tested
Windows 11 26200, AMD Radeon RX 6700 XT (gfx1031), driver 32.0.21045.5002, WinLibs GCC 15.2.0 r7, Release,
BUILD_TESTING=ON,ANYPS5_REQUIRE_VULKAN=1:agc_driver_mesh_provoking_vertex, a full PM4 draw through the guest NGG geometry program fromMeshGeometryFixture.hpp. The triangle's vertices are red, green and blue.v_interp_mov_f32P0 must draw red in first mode and blue in last mode (first, last, first).v_interp_p1_f32/v_interp_p2_f32, compiled to per-vertex values as the title's inputs are) must draw the same pixels, bit for bit, in both modes.mainit fails with the title's message. With this change it passes.agc_driver_graphics:DecodeStateandDecodeShaderStagesgive provoking vertex 0 without bit 19, and with it 2 for triangle-strip output and 1 for line-strip output.ValidateProvokingVertexaccepts mesh draws with point, line and triangle-list input and refuses strip or fan input, tessellation and flat per-vertex inputs.mainit fails withlast provoking vertex is unsupported for generated primitive pipelines.ctest --parallel 4 --timeout 120onmain2626e5ee7with this change: 1462 tests. The only failures are three known on this GPU and unrelated to this change:agc_driver_lds_mixed_width_atomics(fix(shader): release the LDS lock with an exchange and drop fences inside it #6976),agc_driver_lds_lock_budget(AGC: AMD device-backed LDS lock-budget case returns half of expected sum #7344) andagc_driver_layered_volume_vertex_no_gpl(AMD Windows: alpha-to-coverage still fails at the original executable path after #6436 #4768, which passed in the same run on0bb238b4a).python tools/check_conventions.py --base origin/mainwith this title and body passes.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)main; what comes after it is not known)🤖 Generated with Claude Code