Repository navigation
test(agc): skip cull distance cases on devices without shaderCullDistance - #10612
oneandonlydean merged 2 commits into
Conversation
…ance The driver refuses a draw that enables a cull distance when the device has no shaderCullDistance, and agc_driver_vertex_clip_cull_distances, agc_driver_vertex_clip_cull_draw (with and without the draw key) and agc_driver_vertex_user_data_tail ran their cull distance cases anyway, so on MoltenVK all four failed at that refusal. They now skip only those cases when the target lacks CapabilityCullDistance, as they already skip the mesh case without VK_EXT_mesh_shader, and the shader debt entry records the refusal.
| - [Vertex entry merged wave info](../../../core/shader/recompiler/Translation/src/InstructionTranslator.cpp) (recompiler) - `s3` of every vertex-path shader is set to `waveSize | waveSize << 8` (vertex and primitive count of a full wave, wave index 0), or to `32 | 32 << 8` for a wave64 program on a 32-lane host subgroup, which runs it at one lane per invocation and holds no lanes 32-63. On a device whose `subgroupSupportedStages` lacks the vertex stage (lavapipe, MoltenVK), vertex and local programs run as one-lane waves: `s3` is `1 | 1 << 8`, the lane id is 0, a ballot is the invocation's own bit, a shuffle or broadcast returns the invocation's value, an elect is true and a subgroup reduction is the value itself, so no `GroupNonUniform` capability is declared. Layout taken from the prologue Mesa's ACO emits for NGG vertex shaders (`s_bfe_u64 exec` from `s3`), not measured on hardware. The driver gives every graphics program user data from `s8`, so the condition does not tell NGG from legacy vertex shaders: they just never read `s3`. A draw whose last wave is partial still reports a full wave, and so does a host wave with idle invocations (an RTX 5070 ran every vertex warp of a non-indexed triangle list with 30 of its 32 invocations). | ||
| - [s_barrier in vertex-path programs](../../../core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp) (recompiler) - emits no instruction when the program has no LDS or GDS access and no memory write or atomic, so no wave of the subgroup can observe another, or when the barrier runs before every memory access of the program (it is on the entry's straight-line path with no load, store, atomic, image or LDS access ahead of it), so it orders nothing; the `GS_ALLOC_REQ` such a barrier orders on NGG passthrough programs is already dropped on the vertex path. The Vertex execution model has no workgroup barrier. Other programs with LDS, GDS or memory writes throw. Not measured on hardware | ||
| - [Vertex clip and cull distances](../../../core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp) (libSceAgcDriver) - `PA_CL_VS_OUT_CNTL` enable bit `s` of `CLIP_DIST_ENA`/`CULL_DIST_ENA` is taken to select component `s` of the `pos1`/`pos2` exports, with the Vulkan array index counted by the enabled bits below it, and `VS_OUT_CCDIST0_VEC_ENA` as bit 22; this follows the recompiler's existing position-export mapping, not hardware or documentation. The guest clip distances share one `gl_ClipDistance` array with the all-zero clip position distance, which takes the index after them. A vertex program whose own code has no `pos1`..`pos3` export is compiled and prepared without these bits (`PositionExportLayout`), so registration and draws agree on its artifact; an export in a subroutine it calls is not seen by that scan | ||
| - [Vertex clip and cull distances](../../../core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp) (libSceAgcDriver) - `PA_CL_VS_OUT_CNTL` enable bit `s` of `CLIP_DIST_ENA`/`CULL_DIST_ENA` is taken to select component `s` of the `pos1`/`pos2` exports, with the Vulkan array index counted by the enabled bits below it, and `VS_OUT_CCDIST0_VEC_ENA` as bit 22; this follows the recompiler's existing position-export mapping, not hardware or documentation. The guest clip distances share one `gl_ClipDistance` array with the all-zero clip position distance, which takes the index after them. A vertex program whose own code has no `pos1`..`pos3` export is compiled and prepared without these bits (`PositionExportLayout`), so registration and draws agree on its artifact; an export in a subroutine it calls is not seen by that scan A device without `shaderCullDistance` (MoltenVK) throws on a draw that enables a cull distance; none is emulated. |
There was a problem hiding this comment.
Small documentation fix: this entry joins the new sentence directly to the previous one (...seen by that scan A device...). Please add a sentence boundary before “A device” so the debt note reads cleanly.
There was a problem hiding this comment.
Thanks, fixed in 0a8503d73d: the entry now reads "...an export in a subroutine it calls is not seen by that scan. A device without shaderCullDistance (MoltenVK) throws on a draw that enables a cull distance; none is emulated."
AI-assisted: yes
… cull distance note
|
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.
|
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed updated head 0a8503d. The new filters inspect only CULL_DIST_ENA bits 8–15, leave clip-distance cases enabled, and skip the cull-enabled rows/steps only when TargetHasCapability(..., CapabilityCullDistance) is false. The corrected debt sentence now has a proper sentence boundary. I did not reproduce the GPU run locally; the reported MoltenVK baseline/candidate comparison includes the required validation-layer and VUID comparison, and the current hosted eligibility, conventions, labels, and report checks pass. Hosted product jobs were skipped.
What
On a device without
shaderCullDistancethe driver refuses a draw that enables a cull distance (ShaderValidation.cpp:vertex clip or cull distance needs shaderClipDistance or shaderCullDistance, which the device lacks). Four tests ran their cull distance cases anyway, so on MoltenVK, which has noshaderCullDistance, all four failed at that refusal:agc_driver_vertex_clip_cull_distances,agc_driver_vertex_clip_cull_draw,agc_driver_vertex_clip_cull_draw_no_keyandagc_driver_vertex_user_data_tail.They now skip only the cases whose
PA_CL_VS_OUT_CNTLenables a cull distance (CULL_DIST_ENA, bits 8 to 15) when the target lacksCapabilityCullDistance, read through the existingTargetHasCapability, and print a line saying so, asagc_driver_vertex_clip_cull_distancesalready does for its mesh case withoutVK_EXT_mesh_shader. On a device withshaderCullDistanceevery case runs as before. The clip distance cases still run everywhere.The shader debt entry for vertex clip and cull distances now records that a device without
shaderCullDistancethrows on such a draw; nothing emulates it.Tested
Apple M4 Pro, macOS 27.0.1, MoltenVK 1.4.2 (Vulkan SDK 1.4.363.0), x86-64 Release under Rosetta 2.
maindoes not build on macOS yet, so both sides ran on #8658'sfeat/macos-port(564e005acb), whose three test files andShaderValidation.cppcheck matchmain: without and with this PR's test changes,ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation,ctest -R '^agc_driver_vertex_(clip_cull_distances|clip_cull_draw|clip_cull_draw_no_key|user_data_tail)$' -V:agc_driver_vertex_clip_cull_distancesPA_CL_VS_OUT_CNTL=0x00400100refusedagc_driver_vertex_clip_cull_draw0x00400400refusedagc_driver_vertex_clip_cull_draw_no_key0x00400400refusedagc_driver_vertex_user_data_tail0x00400100refusedwas not found but was requestedVUID-VUID-VkDeviceCreateInfo-pProperties-04451, 14 linesThe validation message is MoltenVK's portability subset at device creation, the same on both sides. Not run on a device with
shaderCullDistance; there the new check is true and no case is skipped.check_conventions.py --base upstream/mainpasses.pr_overlap.pylists no pull request with conflicting lines or the same exports, only ones it could not compare ondocs/dev/debt/shader.mdbecause they conflict withmainon their own.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)