Skip to content

fix(agc): widen a vertex format the device lacks to the buffer element's - #9436

Merged
adriadam10 merged 4 commits into
boykopovar:mainfrom
ycbuzi:fix/agc-vertex-format-widen
Oct 24, 2026
Merged

adriadam10 merged 4 commits into
boykopovar:mainfrom
ycbuzi:fix/agc-vertex-format-widen

Conversation

@ycbuzi

@ycbuzi ycbuzi commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

On a GPU without vertex buffer support for the Vulkan format DecodeVertexFormat picks, a draw stops in BuildVertexInputLayout with AGC graphics: device does not support vertex format N. MADiSON stops there on Windows with an AMD Radeon RX 5600 XT, as reported by Hiro_02 on the AnyPS5 Discord (#showcase thread "MADiSON"; Ryzen 5 5600G, RX 5600 XT, 16 GB). The menu runs, and entering the level ends with:

[videoout] presentation failed: AGC graphics: device does not support vertex format 90
terminate called after throwing an instance of 'std::runtime_error'
  what():  AGC graphics: device does not support vertex format 90

Format 90 is VK_FORMAT_R16G16B16_SFLOAT. The attribute's buffer format is 71, 16_16_16_16_FLOAT, whose elements are 8 bytes, and the shader reads three components, so DecodeVertexFormat takes the three-component format.

BuildVertexInputLayout keeps that format when the device supports it, as before. Otherwise it takes the next wider form of the same buffer format that the device supports, up to the element's own component count: four components for 8_8_8_8_*, 16_16_16_16_* and 32_32_32_32_*, two for 8_8_*, 16_16_* and 32_32_*. The read stays inside the guest element, the numeric type and component width do not change, and the shader input does not change (VertexAttributeSignature still uses the attribute's component count), since Vulkan discards the components the input does not consume ("If the vertex shader has fewer components, the extra components are discarded", Vertex Input Extraction). A format with no wider form, such as 32_32_32_*, still throws.

The wider format reads more bytes per vertex, so prepareDrawInputs adds the difference to the vertex copy and to the zero buffer of a null or out-of-range attribute; otherwise the last vertex's read would end past the copy. The difference comes from VertexReadBytes, the size of the format the layout holds, so a layout taken from the cache or a recipe gets it as well.

Tested

Windows 11 Home 10.0.26200, MinGW-w64 GCC 15.2.0 (ucrt-posix-seh r7), Release, BUILD_TESTING=ON, NVIDIA GeForce RTX 4070 SUPER (616.92), on main 0c6a5bd.

  • agc_driver_graphics, extended: with a faked format query that lacks R16G16B16_SFLOAT and R8G8B8_UNORM but has the four-component formats, a three-component 16_16_16_16_FLOAT attribute gets R16G16B16A16_SFLOAT (8 bytes read, stride 8) with the shader input still f32x3, a three-component 8_8_8_8_UNORM one gets R8G8B8A8_UNORM, and a three-component 32_32_32_FLOAT one still throws device does not support vertex format 106; the existing four-component case still throws.
  • The same 15 focused tests on main 0c6a5bd and on this branch, with ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1, --repeat until-fail:2: all pass on both (agc_driver_graphics, vertex_fetch, zero_stride_vertex_fetch, zero_position_vertex, draw_cache_reuse and its _inline, _off and _verify runs, draw_offset_indices, pipelined_indirect_draw, pipelined_prefetch, draw_write_ranges, vertex_user_data_tail, queued_index_read_order, inactive_vertex_point_size).
  • Validation layer, after merging main da54c65 into this branch (head 7b391f8889): the same 15 tests (their ctest names start with agc_driver_) on that main and on this head, built one after the other in the same build directory, with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (Vulkan SDK 1.4.363.0), ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1 and ctest -V, on the RTX 4070 SUPER (616.92) and on the Radeon iGPU (25.10.30.02), each picked with ANYPS5_GPU. All four runs pass 15/15. No log reports was not found but was requested by env var VK_INSTANCE_LAYERS, and none has a VUID- error. Each log has the same 10 layer warnings on both trees: 9 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering and 1 Undefined-Value-ShaderOutputNotConsumed. The runs are from a non-elevated process: an elevated one ignores VK_LAYER_PATH, and runs made that way had neither those warnings nor the was not found line. main's ImageArrayWindowPastLayerLimit.cpp does not compile on MinGW (the alignment error test(agc): align the array window test's texels at run time #8310 fixes), so both trees were built with ninja -k 0; no other target failed.
  • check_conventions.py --base origin/main passes on 7b391f8889. pr_overlap.py reports feat(agc): draw triangle strips through the barycentric tessellation stages #8083, which adds StripPatches right above zeroVertexBuffer in Draw.cpp; merged together, that is the only conflict. feat(agc): draw triangle strips through the barycentric tessellation stages #8083's author agreed that feat(agc): draw triangle strips through the barycentric tessellation stages #8083 lands first and this PR then rebases onto it, keeping both.

Not tested: a GPU that lacks one of these formats. The RTX 4070 SUPER, a GTX 1650 SUPER and the Radeon iGPU of a Ryzen 9 7900 (AMD 25.10.30.02) in this machine all report VERTEX_BUFFER_BIT for format 90 (vulkaninfo --show-formats), so the wider path ran only with the faked query. MADiSON was not run here; the RX 5600 XT run is the check.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: feat(agc): draw triangle strips through the barycentric tessellation stages #8083 (lands first; this PR then resolves the one conflict in Draw.cpp)
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 4070 SUPER, driver 616.92, Windows 11 10.0.26200; AMD Radeon(TM) Graphics (Ryzen 9 7900 iGPU), driver 25.10.30.02, Windows 11 10.0.26200 (on both, the wider-format path only with a faked format query)
  • AI-assisted: yes

🤖 Generated with Claude Code

A 16_16_16_16, 8_8_8_8 or 32_32_32_32 attribute that the shader reads
with fewer components is bound with the narrower Vulkan format, such as
R16G16B16_SFLOAT for three components of 16_16_16_16_FLOAT. A device
without vertex buffer support for that format (MADiSON on an RX 5600 XT
stops with "device does not support vertex format 90") now gets the next
wider form of the same buffer format it supports, up to the element's
own width: the shader input is unchanged and Vulkan discards the extra
components. The vertex copy and the zero buffer grow by the widened
bytes so the last vertex's read stays inside them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

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.

Pull request Shared files not compared
PR 1191 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1368 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5441 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6280 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6481 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6539 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6804 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6959 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7275 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7668 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8212 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8223 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 8246 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9335 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9401 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9489 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9675 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9700 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9875 core/libs/prx/libSceAgcDriver/Graphics/include/VertexInput.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9891 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10046 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10049 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10348 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10420 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10442 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10515 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10581 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp

@github-actions github-actions Bot added the agc libSceAgc* label Oct 22, 2026

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation is narrowly scoped and the reported wider-format path exercises the intended Vulkan fallback, but three merge blockers remain under the repository checklist:

  1. The PR changes AGC vertex input handling, and CONTRIBUTING.md requires the same focused tests on main and this change with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, and ANYPS5_REQUIRE_VULKAN=1, with ctest -V logs confirming the layer loaded and a comparison showing no new VUID- errors. The description says the layer is not installed and no comparison was made. Please rerun that paired validation on a machine with the layer, or leave this as an explicit unresolved validation blocker for a maintainer with the required environment. The hosted Linux and Windows jobs are skipped, so they do not supply this evidence.

  2. The overlap report names open PR #8083 in Draw.cpp. The description says whichever lands second will need a one-line rebase, but the checklist says Depends on: none and does not record an agreed landing order. Please coordinate the order with #8083's author and list the prerequisite on the checklist, or document that the overlap has been resolved and refresh the overlap check.

  3. The Unblocks line identifies a MADiSON stop but explicitly lacks both the title ID and a Game bring-up discussion. The repository checklist requires both for a title-blocking PR. Please add the verified title ID and discussion reference, or use none if the report cannot be tied to a qualifying bring-up entry.

The change-specific tests in the description are author-reported (15 focused tests on main and the branch, repeated twice); I did not run them locally because no matching PR checkout/build is available in this workspace. Current automated checks show conventions, eligibility, labels, and report passing; Linux, Windows, relinker, ASAN, register-context, and write-watch jobs are skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ycbuzi

ycbuzi commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@MarcZX10 thanks. On the three points:

  1. Validation layer. I merged main da54c65 into the branch (head 7b391f8889) and ran the 15 focused tests on that main and on this head with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1 and ctest -V, on an RTX 4070 SUPER (616.92) and a Radeon iGPU (25.10.30.02), Windows 11. All four runs pass 15/15, none reports was not found but was requested by env var VK_INSTANCE_LAYERS, and none has a VUID- error. The layer loaded in each: every log has the same 10 layer warnings on both trees (9 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering, 1 Undefined-Value-ShaderOutputNotConsumed). The description has the details.

    One thing for other Windows runs: from an elevated (administrator) process the loader ignores VK_LAYER_PATH. My first runs were elevated, and they had neither the layer's warnings nor the was not found line, so that check alone did not catch the missing layer. The runs above are from a non-elevated process.

  2. feat(agc): draw triangle strips through the barycentric tessellation stages #8083: I proposed there that it lands first and this PR rebases onto it; the only conflict is StripPatches landing right above zeroVertexBuffer. I'll put it in Depends on once its author agrees.

  3. Unblocks is now none: the report has no title ID and there is no Game bring-up discussion. The MADiSON report and its log line stay in the description.

@ycbuzi

ycbuzi commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@MarcZX10 #8083's author agreed to the order: #8083 lands first, and this PR then rebases onto it. Depends on now lists #8083.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 22, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 22, 2026
@adriadam10 adriadam10 self-assigned this Oct 23, 2026
@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 24, 2026 10:21

Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.

@adriadam10
adriadam10 merged commit 8d3ec0a into boykopovar:main Oct 24, 2026
10 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Re-checked against current main: the head is unchanged and merges cleanly. Checked the widening in BuildVertexInputLayout and DecodeVertexFormat (never narrower, capped at each format's own component count, 32_32_32_* still throws), the extra bytes added to the vertex copy and zero buffer through VertexReadBytes, and the new agc_driver_graphics cases (they throw on main). The validation-layer and #8083 order points from the earlier review are addressed; merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants