Skip to content

test(shader): replay native interpolation rows - #1572

Closed
Sanjaysrinivas wants to merge 6 commits into
boykopovar:mainfrom
Sanjaysrinivas:test/shader-interpolation-native
Closed

Sanjaysrinivas wants to merge 6 commits into
boykopovar:mainfrom
Sanjaysrinivas:test/shader-interpolation-native

Conversation

@Sanjaysrinivas

@Sanjaysrinivas Sanjaysrinivas commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What

Depends on: #697.

The F16 interpolation raster fixture skips on lavapipe because it requires fragment barycentrics. Add a separate compute execution test that replays the six published gfx1035 special-value results through the actual interpolation arithmetic emitters. Inputs come from storage-buffer loads; a second dispatch rotates the rows within each instruction family. The test checks literal output bits, unchanged inputs and trailing guards, without requiring fragment barycentrics.

Extend the existing positive ShaderMemory.cpp fragment compiles with independent Float64 and barycentric rejection checks for each of V_INTERP_P1LL_F16, V_INTERP_P1LV_F16 and V_INTERP_P2_F16.

This branch contains three attributed prerequisite commits from #697, followed by two test commits and one documentation commit. Daan Dehing retains authorship of the implementation and its rounding/NaN corrections. The follow-up adds only test code, test linkage and a clarification to the existing technical-debt entry. Review the follow-up with:

git diff 258a645f..cd330966

Related open PRs and merge order

The overlap bot reports real textual conflicts with two independent contributions. Read-only git merge-tree --write-tree checks confirmed the hunks below against #1524 head 46c50453 and #1547 head 9032b654. The decoder/IR conflicts originate in the included #697 prerequisite; the documentation conflict is between adjacent technical-debt entries.

Open PR Conflict Required integration
#1524, VOP3 F32 interpolation Both insert an early-return decoder branch after SetRdnaRawWords in RdnaVectorOpDecoder.cpp Keep both complete branches and their own returns: F32 opcodes 0x200–0x202 and F16 opcodes 0x342, 0x343, 0x35a. Preserve each branch's operand and modifier checks.
#1547, generated F32 barycentrics Both insert after GetInterpolationParameter in IrOpcode.hpp and its metadata table; both add adjacent debt entries Keep GetInterpolationParameterF16 alongside InterpolateHostP1/InterpolateHostP2, with matching enum/metadata order. Keep both debt entries. Preserve the F16 capability rejections; the F32 geometry fallback does not establish F16 SPI behavior.

Neither PR is a prerequisite for these tests: the fixture does not decode F32 VOP3 instructions or use the generated geometry stage. They are therefore related merge conflicts, not additional Depends on entries. Rebase and preserve both contributions when either lands. The branch has been rebased onto main at 4ddbf049; the combined open-PR branches have not been compiled or executed, and these checks do not claim otherwise. The informational overlap notice can remain while those independent branches are open.

The progress bot's three implemented instructions and percentage increase come from the included #697 implementation. The three follow-up commits add no unique opcodes and do not establish native RDNA2/PS5 execution or complete guest-mode support.

Evidence and scope

The oracle is the six raw tuples published by the gfx1035 tester. Expected results are literal hardware words, not values generated by another copy of the implementation. The source publishes these rows:

Instruction Delta, F16 bits Coordinate, F32 bits Base, F16 for P1 / F32 for P2 Hardware result
P1LL 0000 7f800000 7bff ffc00000
P1LL fc00 00000000 fe01 ffc00000
P1LL 7c00 7f7fffff fc00 ffc00000
P2 0000 7f800000 4f000000 fe00
P2 8000 ff800000 7fc00000 fe00
P2 fe01 3f800000 47800000 fe01

The compute fixture supplies exact already-expanded FP32 input bits, including NaN payloads. It tests interpolation arithmetic and P2 result packing; it bypasses guest decoding, half-input expansion, SPI coefficient generation, LDS access and fragment routing. The six rows contain P1LL and P2 cases; P1LV is covered here by compile/capability checks, not a newly published native arithmetic row. The half-expansion implementation and exhaustive tests remain in #1463 and #1505, so neither is a prerequisite for this isolated arithmetic fixture.

This adds regression coverage, not opcode coverage or a verified guest-mode contract. The implementation's existing technical-debt entry remains applicable. #981 and the mode-related hold on #697 remain unresolved; #1442 owns initial mode metadata, and #1252 owns native conversion/host float-control work. No competing implementation of those contributions is included.

Tested

Current rebase: cd33096612973c547027db9b5587f6295e191b1a on main 4ddbf0497dbdd16f885fb27d30941a772185370d. The CMake conflict keeps all upstream prepared-shader test includes and the interpolation arithmetic compiler linkage. The inherited rounding and NaN-priority patches are unchanged. Normal Release targets were rebuilt with GCC 13.3 on Ubuntu 24.04/WSL2, SPIRV-Tools integration disabled. Three focused CTest cases were repeated three times: shader-memory compilation/capability checks and interpolation arithmetic passed; the F16 raster fixture retained its barycentrics capability skip on lavapipe. Fresh full GitHub CI is pending; earlier CI and captured-module results below identify their original revisions.

Earlier captured-module validation was based on main at fd5342b6d6e2ff572d51e23ee4559dba53887881, head 4c45ecbb69f8f9fb1192fa31dc74bedf770942d0. Normal CMake Release targets were rebuilt after the rebase on Ubuntu 24.04 under WSL with GCC 13.3; no title or PS5 was run. SPIRV-Tools integration was disabled for this build, then the captured module was independently checked with spirv-val --target-env vulkan1.1.

Before this rebase, head 09df288e also passed the complete Linux CI job, Windows CI job, conventions and report checks. The refreshed head triggers new checks; those earlier results are not presented as completed CI for the new head.

Check Result
agc_shader_memory Pass; each of three isolated programs compiles, and independently rejects missing Float64 and missing barycentrics: 3 positive compiles, 6 expected rejections
agc_driver_interpolation_arithmetic, lavapipe / LLVM 20.1.2 Pass; 6 unique published rows, 2 dispatches, 12 output comparisons
Existing agc_driver_interpolation_f16 raster fixture Skipped: lavapipe has no fragmentShaderBarycentric
Same captured SPIR-V, Windows Vulkan, RTX 4070 Laptop (10de:2820, raw driver 2585198592) Pass; 12 output comparisons, 36 unchanged input words, 8 guard words
Same captured SPIR-V, Windows Vulkan, Radeon 780M (1002:1900, raw driver 8389003) Pass; 12 output comparisons, 36 unchanged input words, 8 guard words
Change first expected word from ffc00000 to ffc00001 in diagnostic copy Fails, exit 1: got 0xffc00000, expected 0xffc00001
Restore only the pre-NaN-fix Interpolate function from #697 commit 6534b25c, keeping the other current emitter functions Fails, exit 1: got 0x7fc00000, expected 0xffc00000
Independent SPIR-V validation Pass, Vulkan 1.1; SPIR-V 1.3, 38,668 bytes

Captured module SHA-256: 25f7a2a019457ae1de3de6f5d050706a372e7e1631802548e29e4e4889f1d5a1.

The Windows checks replay the captured module through a small Vulkan storage-buffer runner; they are not a Windows build of the C++ fixture. The two native devices are local host GPUs, not RDNA2 or PS5 hardware. Across the three backends there are 36 output comparisons of the same six unique oracle rows; neither repeated dispatches nor the source comment's unpublished aggregate totals are counted as additional unique cases.

Focused reproduction after a normal test build:

cmake --build build --target agc_shader_memory_tests agc_driver_interpolation_arithmetic_tests agc_driver_interpolation_f16_tests
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 ctest --test-dir build --output-on-failure -R '^(agc_shader_memory|agc_driver_interpolation_(arithmetic|f16))$'

Validation logs and diagnostic runners are kept outside tracked source. The permanent C++ test is sufficient to replay the six rows on any supported Vulkan device with Float64.

Checklist

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Progress report (4ddbf04 → cd33096)

📈 GPU shader instructions: 98.46% (+0.26%, +3 implemented instructions)

✅ 3 implemented
Encoding Name
VOP3 V_INTERP_P1LL_F16
VOP3 V_INTERP_P1LV_F16
VOP3 V_INTERP_P2_F16

@Sanjaysrinivas
Sanjaysrinivas force-pushed the test/shader-interpolation-native branch from 09df288 to 4c45ecb Compare October 8, 2026 13:28
@Sanjaysrinivas
Sanjaysrinivas marked this pull request as ready for review October 8, 2026 14:23
@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 8, 2026
@Sanjaysrinivas
Sanjaysrinivas force-pushed the test/shader-interpolation-native branch from 4c45ecb to ede6c8f Compare October 8, 2026 18:19
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 8, 2026
queeeef and others added 6 commits October 8, 2026 20:20
…terp_p2_f16

Decode the three VOP3 16-bit interpolation instructions (attribute, channel
and high-half select in the src0 field, the I/J VGPR in src1, P0 or the first
step's result in src2) and translate them with a new
GetInterpolationParameterF16 IR value. It reads the selected 16-bit half of
each vertex's parameter through VK_KHR_fragment_shader_barycentric, so P10 and
P20 are vertex differences rounded to f16; both steps are a multiply and an
add, as in the f32 forms.

An input in FP16_INTERP_MODE whose low half is defaulted is still declared at
its slot when its high half is read, and the high half takes its default from
USE_DEFAULT_ATTR1 and DEFAULT_VAL_ATTR1. Without barycentrics, on an input
without FP16_INTERP_MODE or on a pass-through input the instructions throw.

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

Prerequisite from boykopovar#697; retain original author and feature scope.
(cherry picked from commit 73777c7)
Measured on RDNA2 in boykopovar#697: v_interp_p1ll_f16 and v_interp_p1lv_f16 are a
fused multiply-add rounded once to f32, and v_interp_p2_f16 rounds the exact
P20 * J + S2 once to f16. The separate multiply and add matched about 85% and
4% of the measured rows.

Both steps now use FPInterpolateF32 and FPInterpolateF16: the f16 delta times
the f32 coordinate is exact in f64, the sum is rounded to odd and then once to
nearest even at the target precision, so no driver can split or reround it.
Infinite and NaN operands take the unbounded f64 result.

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

Prerequisite from boykopovar#697; retain original author and feature scope.
(cherry picked from commit 6534b25)
Measured on RDNA2 in boykopovar#697: an invalid product or sum (inf * 0, inf - inf)
gives the negative default NaN, 0xffc00000 or 0xfe00, and beats a NaN
addend. A NaN delta, then a NaN coordinate, still wins, quieted; a NaN
addend is returned quieted only when the product is valid.

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

Prerequisite from boykopovar#697; retain original author and feature scope.
(cherry picked from commit bd0a0e5)
Replay six published gfx1035 tuples through the interpolation arithmetic emitters with runtime buffer inputs. Rotate the rows for a second dispatch and check inputs and guards. This runs without fragment barycentrics.

Oracle: boykopovar#697 (comment)

Use exact expanded FP32 arguments to isolate arithmetic from guest half conversion, SPI, LDS and guest mode handling. No new opcode semantics or native RDNA2/PS5 execution are claimed.
Compile an isolated guest program for each of P1LL, P1LV and P2 with Float64 and fragment barycentrics, then independently omit each capability and require its specific rejection.
Distinguish the raster fixture that skips without barycentrics from the standalone arithmetic regression. Keep unverified SPI coefficients and guest floating-point modes explicit.
@Sanjaysrinivas
Sanjaysrinivas force-pushed the test/shader-interpolation-native branch from ede6c8f to cd33096 Compare October 8, 2026 18:26
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
#1547 core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrOpcode.hpp L459
core/shader/recompiler/IntermediateRepresentation/src/IrOpcode.cpp L500
docs/dev/TechnicalDebt.md L279

@adriadam10

Copy link
Copy Markdown
Collaborator

Thanks for this. I'm closing it as superseded by the updated #697.

The one check #697 doesn't have is the Float64 capability gate in verifyF16InterpolationCapabilities. If you want to keep it, a small PR with just that on top of main (after #697 lands) is welcome.

@adriadam10 adriadam10 closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants