Repository navigation
feat(agc): blend into color targets with a reversed component order - #5200
adriadam10 merged 4 commits into
Conversation
64071f5 to
66ae603
Compare
|
Setup: Windows 11 (26200), WinLibs GCC 15.2.0 r7, Release, CI configure flags, an RTX 4070 Laptop GPU (NVIDIA 595.97) and an Intel Raptor Lake-S iGPU (32.0.101.6790). Both run the split cases, so neither skips for lack of dual-source blending. I tested the head 66ae603 as pushed, and the earlier 64071f5 merged into
Written with AI assistance. |
|
It also conflicts with main in |
66ae603 to
8c9a939
Compare
adriadam10
left a comment
There was a problem hiding this comment.
Checked on Linux (lavapipe): agc_driver_reversed_order_blend, agc_driver_graphics and agc_shader_memory pass on this head. Two things block the merge:
- Intel result outside tolerance. As @kr4y4 and @oneandonlydean reported,
agc_driver_reversed_order_blendfails on an Intel iGPU (161 vs 159.75, tolerance ±1), while the same blend through Vulkan alone gives 160 on both vendors. Either make the split path round like the native one, or show from the Vulkan blend-precision rules why this case needs a wider tolerance and pin it with that reason. Widening it without that leaves the test unable to catch a real regression on that row. - Conflicts with
main.mainnow writes request version 25 (dithered alpha-to-coverage), so version 24 is taken:RequestSerializer.cpp,Recompiler.hpp,DrawRegisterKey.cppandtests/ShaderMemory.cppconflict. The code needs to move to the next free version and the legacy-request cases inShaderMemory.cppmust keep their layouts. Please rebase after the first point, rerun the five tests you list, and note the new version in the body.
8c9a939 to
9a88161
Compare
adriadam10
left a comment
There was a problem hiding this comment.
Thanks for the rebase; the version 26 move resolves the conflicts. The first point of the last review is still open:
- Intel result outside tolerance.
agc_driver_reversed_order_blendstill compares UNORM8 with<= 1.0(ReversedOrderBlend.cpp:392), and the blend code is unchanged, so the Intel iGPU run reported by @kr4y4 and @oneandonlydean (161 vs 159.75) should still fail. Either make the split path round like the native one, or show from the Vulkan blend-precision rules why this case needs a wider tolerance and pin it with that reason. Widening it without that leaves the test unable to catch a real regression on that row.
Checked on Linux with the rebased head: agc_driver_graphics, agc_shader_memory and agc_driver_reversed_order_blend pass.
|
@adriadam10 Thanks. I took the first option: the split path now rounds like the native blend, and the ±1 bound is unchanged. Thanks also to @kr4y4 for the Intel runs. Cause of the 161. The previous revision computed the factor in the pixel shader. For
So this was not specific to Intel. On the RTX 5080 and lavapipe, the old split path also differed from the same draw into a What changed (0866138 and 1d6edc4, on top of 9a88161). The pixel shader now only copies the export. Each channel of the second color is the exported alpha, the channel's own export, 0 or 1. An MRT0 channel whose source factor is
What Vulkan does and does not promise here. The two paths now ask the blend for the same expression on the same values; they differ only in that some values arrive as the second color (and, for the How it was verified.
@kr4y4, could you re-run AI-assisted: written with Claude Code; I checked the change and ran the tests described. |
adriadam10
left a comment
There was a problem hiding this comment.
Re-checked 0866138 and 1d6edc4: the pixel shader now only copies the export (alpha, own channel, 0/1) into the second color, so the blend forms 1 - x and the products from the same converted values as a plain Vulkan blend, and the ±1 bound stays. The new agc_driver_reversed_order_blend comparison against the same draw into a SWAP_STD target pins this bit for bit, and the combinations that still needed shader arithmetic throw again.
Checked on Linux with the merged tree: agc_driver_graphics, agc_shader_memory, agc_driver_reversed_order_blend and request_serializer_tests pass; without the change the tests do not compile. Not run here: Intel/AMD hardware (@kr4y4, a rerun of the Intel iGPU on this head would close the original report). Merging once the full Build is green.
1d6edc4 to
313c296
Compare
|
Re-checked 313c296 after the rebase: the added and removed lines are identical to 1d6edc4, which we approved. On the merged tree |
313c296 to
db0f4bc
Compare
|
On the rebased tree |
db0f4bc to
899d83e
Compare
|
On the rebased tree |
8_8_8_8 and 16_16_16_16 targets with COMP_SWAP 2 or 3 keep the exported alpha in their first channel and red or blue in their fourth, so a plain Vulkan blend would run the alpha equation on a color channel. Such draws threw "blending into a color target with a reversed component order is not implemented" (Gran Turismo 7, boykopovar#4782). The AMD SI and CIK register references describe CB_TARGET_MASK in the order of components after blending and before COMP_SWAP is applied, and RADV programs CB_BLENDn_CONTROL without regard to the swap while it renders R4G4B4A4, B4G4R4A4, R5G5B5A1 and B5G5R5A1 through SWAP_STD_REV and SWAP_ALT_REV and passes the CTS blend tests on Navi10. The color block is therefore taken to blend in export order: the alpha equation and source-alpha factors use the exported alpha and the destination alpha is the first channel. TranslateReversedBlend keeps the factor pairs Vulkan applies per channel in the pipeline. Other source factors are computed by the pixel shader from its MRT0 export (clamped for UNORM targets, as BLEND_CLAMP says) and handed to the blend as a dual-source second color, which the fragment output post-pass adds at location 0 index 1; when both positions need it, the export is premultiplied by its source factor. The code is a pipeline specialization, serialized in request version 26, and stays out of the prepared shader key. sRGB, SNORM and integer targets, constant and second-source factors, destination alpha in the color equation, destination factors the two equations do not share, different color and alpha operations, MIN or MAX with factors other than ONE, other color exports when the shader computes factors, and devices without dualSrcBlend still throw, now with the blend control, mapping and format in the message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reversed-order blend computed the factors Vulkan cannot apply per channel in the pixel shader (1 - x in fp32, a clamp for UNORM targets and, when both positions needed it, a premultiplied export) and passed them to the blend as a dual-source second color. A plain blend converts the export once and forms 1 - x and the products from that converted value, so the two paths can round differently. On UNORM8 the difference reaches one step per substituted factor: an Intel iGPU stored 161 where the exact blend is 159.75 for SRC_COLOR + ONE_MINUS_SRC_COLOR with an export of 0.5 over 192 (160 through SWAP_STD), and on an RTX 5080 and lavapipe the split path differed from the same draw into a SWAP_STD target by up to 2 steps on other inputs. The pixel shader now only copies values. Each channel of the second color is the exported alpha, the channel's own export or the constant 0 or 1, and a channel of the first color whose source factor is ONE may become 1 with its export moved into the factor. Every factor, 1 - x and product comes from the blend through SRC1_COLOR, SRC1_ALPHA and their ONE_MINUS forms, applied to copies of the same export values that the first color carries. TranslateReversedBlend searches for Vulkan factors and copy routes that reproduce each channel's guest factors and throws for combinations no routing reproduces, such as ONE_MINUS_SRC_ALPHA in the alpha equation next to SRC_COLOR in the color equation: of the 1995 factor combinations the shader used to compute, 932 are routed and the others throw again, as on main. GT7's 0x65010504 is among the routed ones. The code is now four 2-bit routes for each color, the same for every format, and the post-pass emits no arithmetic. agc_driver_reversed_order_blend also draws each case into a SWAP_STD target, which Vulkan blends alone, and requires identical stored bits; the comparison with the exact blend keeps its 1-step tolerance. agc_driver_graphics checks every factor combination TranslateReversedBlend accepts against the guest equations and that the post-pass adds no arithmetic instructions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TranslateReversedBlend may write 1 into a channel of the first color whose source factor is ONE and take that channel's export into the factor through the second color, when one second color cannot carry both the source and the destination factor. None of the blends in agc_driver_reversed_order_blend took that route, so no GPU test ran it. The test now also blends 0x61010504 (SRC_ALPHA + ONE_MINUS_SRC_ALPHA, alpha ONE + ONE), whose alpha channel is routed that way, into both formats with both reversed swaps, and compares it with the exact blend and bit for bit with the same draw into a SWAP_STD target. It passes on an RTX 5080 and lavapipe. With 9a88161's shader-computed factors it fails on the RTX 5080: 160 where SWAP_STD stores 159. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fixture message Co-Authored-By: Claude <noreply@anthropic.com>
|
The full Build on the previous head failed
On the rebased tree |
899d83e to
3e3c3bf
Compare
|
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.
|
What
Gran Turismo 7 (PPSA01317) stops at this refusal in #4782 ("Next stop"), once the earlier stops are past:
The register values come from the reporter's local build. On
mainthe same throw inDecodeState(State.cpp) prints no values.#1425 renders 8_8_8_8 and 16_16_16_16 targets with
COMP_SWAP2 (SWAP_STD_REV) or 3 (SWAP_ALT_REV). It does this by permuting the pixel exports onto an RGBA attachment. Mapping 0x1b leaves the attachment holding (A, B, G, R) and 0x93 leaves it holding (A, R, G, B). Vulkan blends channels 0-2 with the color equation and channel 3 with the alpha equation. A plain Vulkan blend would therefore blend the exported alpha as a color and read source alpha from red or blue. That is why #1425 refused blending.GT7's
CB_BLEND0_CONTROL0x65010504 has separate alpha. Field layout and factor numbering from Mesa 26.2.2's gfx10.json (the same as CIK pp. 226-228):SRC_ALPHA * src + ONE_MINUS_SRC_ALPHA * dstONE * src + ONE_MINUS_SRC_ALPHA * dstSemantics. The color block blends in shader export order and applies
COMP_SWAPafterwards. This means:Sources:
CB_TARGET_MASKis described in "the order of components after blending and before COMP_SWAP is applied". The same CIK reference (p. 233) hasBLEND_CLAMPclamp UNORM, SNORM and sRGB sources to the format range before blending.CB_BLENDn_CONTROLfrom the Vulkan state without looking at the swap (radv_pipeline_graphics.c). It rendersR4G4B4A4,B4G4R4A4,R5G5B5A1andB5G5R5A1throughSWAP_STD_REVandSWAP_ALT_REV(vk_format.c, ac_formats.c).results.csv.zstartifacts pass all 400blend.format.<format>.statescases for each of those four formats. Those cases use separate color and alpha factors, includingDST_ALPHA, against a reference blended in API order. Mesa treats the PS5's gfx1013 as GFX10 like Navi10 (ac_gpu_info.c).This has not been measured on gfx1013 or on 8_8_8_8 and 16_16_16_16 targets. Carrying it over to them relies on
COMP_SWAPbeing the same field for every format. The new entry indocs/dev/debt/libSceAgcDriver.mdsays so.Design.
TranslateReversedBlend(State.cpp) keeps factor pairs that Vulkan applies per channel as Vulkan factors. These areZERO/ZERO,ONE/ONE,SRC_COLOR/SRC_ALPHA,DST_COLOR/DST_ALPHAand theONE_MINUSforms. For other combinations it searches for Vulkan factors that reproduce the guest blend from copies of the export (since 0866138; see the update of 2026-10-14 below):ONEmay become 1, with its export moved into the factor;1 -and product throughSRC1_COLOR,SRC1_ALPHAand theirONE_MINUSforms. The shader computes nothing.For GT7 that gives the following in attachment order, which equals the guest blend for both mappings:
(1, a, a, a)SRC1_COLOR/ONE_MINUS_SRC1_ALPHA,SRC1_ALPHA/ONE_MINUS_SRC1_ALPHA,ADDThe shader side reuses #1492's fragment output post-pass (
FragmentOutputSpecialization.hpp). It adds the location 0 index 1 output and rewrites each whole store to MRT0. The emitter is unchanged. The code is a pipeline specialization constant (ReversedBlend), so it is in the module and draw keys but not in the prepared shader key, and a registered pixel shader is reused. Request serialization goes to version 26. Pipelines with a code needdualSrcBlend, and shader validation accepts the index 1 output for them.Still refused, each with its own message that now includes the blend control, the mapping and the format:
DST_ALPHA,ONE_MINUS_DST_ALPHAandSRC_ALPHA_SATURATEin the color equation (they need the first channel in the other three);ONE_MINUS_SRC_ALPHAin the alpha equation withSRC_COLORin the color equation;MIN/MAXwith factors other thanONE(CIK p. 228: MIN and MAX do not force the factors to ONE);dualSrcBlend.GT7's
CB_COLOR0_INFOandCB_SHADER_MASKfor that draw are unknown. If the target is sRGB or the shader exports more than one MRT, GT7 stops at the new, more specific message instead.Overlaps:
main, leaves blending off for a target withCB_COLOR_INFO.BLEND_BYPASS, so a bypassed reversed-order target is written without blending and never reachesTranslateReversedBlend.maintook request version 22 for the tessellation patches per group (fix(agc): bound tessellation patch records by the draw's patch count #4114), version 23 with specialization id 8234 for the layer export flag (fix(shader): read the ancillary render target index from Layer when the draw exports it #5097), version 24 for the tessellation primitive group size (feat(agc): rebuild the hull's relative patch index when it is used as data #4201) and version 25 for the dithered alpha-to-coverage flag (feat(agc): emulate default eight-sample dithered alpha coverage #4451), so this PR uses version 26 and id 8235. Open PR feat(shader): link callees of calls whose target is loaded from a table #4706 also writes version 26, fix(shader): number an instanced draw's hull patches across its instances #4450, feat(agc): remap a viewport depth range the device cannot express into the vertex shader #4650, fix(shader): honour SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS for the front-face input #5314 and fix(shader): propagate color view slice to pixel ancillary input #5500 write versions 22 to 24, and feat(agc): replay proven finite stencil reference exports #5466 and fix(shader): propagate color view slice to pixel ancillary input #5500 use id 8235; whichever lands later renumbers.wip/ppsa01317-world-map-testbranch, marked "do not upstream" and not opened as a pull request. This PR does not use them.Tested
WSL2 Ubuntu 26.04, GCC 15.2.0, Release,
-DANYPS5_ENABLE_SPIRV_TOOLS=ON. Tests ran on lavapipe (llvmpipe, LLVM 21.1.8) with CI'sVK_ICD_FILENAMES=<lvp_icd>,ANYPS5_REQUIRE_VULKAN=1andGALLIUM_OVERRIDE_CPU_CAPS=avx.main14036cb, with only the declarations they need added (the tworeversedBlendfields, theReversedBlendstruct, twoReversedBlendCodeconstants and aTranslateReversedBlendthat throwsmain's message):agc_driver_reversed_order_blendandagc_driver_graphicsstop withblending into a color target with a reversed component order is not implemented;agc_shader_memoryfails with "pixel fields or export mappings were lost in serialization".main.ctest: 1050 tests, no failures (1007 pass, 43 skip).main14036cb: 1049 tests, no failures (1006 pass, 43 skip).agc_driver_reversed_order_blendtakes 0.3 s.maine152ba8 without conflicts: 1062 tests, no failures (1019 pass, 43 skip).maine152ba8 alone: 1061 tests, no failures (1018 pass, 43 skip). The only difference is the new test.CB_BLEND_CONTROLwith factors 0-10 and 13-20 and functions 0-4, with and without separate alpha, went throughTranslateReversedBlendfor both mappings, the three accepted formats andFORCE_DST_ALPHA_1on and off (39 million cases). The 217,620 accepted cases were blended through a model of the post-pass and the Vulkan blend, with 12 inputs each, including UNORM exports outside [0, 1]. Each result equals theCB_BLEND_CONTROLdefinition applied in export order and then swapped.FORCE_DST_ALPHA_1,SRC_ALPHA_SATURATEin the color equation becomesZERO, asmainalready does for every target. That differs from min(As, 0) when a float target gets a negative alpha.spirv-valaccepts, and its stores matched the model on 600 inputs each, including NaN and infinities. It accepts exactly the 1,201 valid codes.agc_driver_reversed_order_blendfail:Windows 11 Pro, NVIDIA GeForce RTX 5080 (driver 616.92, Vulkan 1.4.351), WinLibs GCC 15.2.0 r7, Release.
ctest -R agc_gives 475 tests with no failures. One skip is expected:agc_driver_stencil_ref_export, because the driver has noVK_EXT_shader_stencil_export.agc_driver_reversed_order_blend,agc_driver_dual_source_blend,agc_driver_swap_alt_blend,agc_driver_graphicsandagc_shader_memorypass with--repeat until-fail:3.agc_driver_reversed_order_blendtakes 0.4 s.New tests:
agc_driver_reversed_order_blend, a GPU execution test.SWAP_STD_REVandSWAP_ALT_REV.DecodeStateon a register set. The draw goes through the registered-shader path.0x65010504(with all four channels written and with only red, green and blue),0x65810584,0x40000501,0x61000104,0x61020302,0x61010504(since 1d6edc4),0x60060008,0x40000101and0x40000141.CB_BLEND_CONTROLfields, blends in logical RGBA with the AMD factor definitions (clamping the source for UNORM), and places the channels in memory by the AMDCOMP_SWAPtext. Tolerance is ±1 code for UNORM8 and 2^-11 · max(1, |value|) for FP16. Pixels outside the scissor and channels outside the write mask must be unchanged.agc_driver_graphics:TranslateReversedBlendcalled directly;ValidateShaders;agc_shader_memory: version 26 round-trip; the version 25 layout read without the new four bytes, the 23 and 24 layouts without the dither flag as well, and the 19 to 22 layouts without the layer export flag as well.request_serializer:main's fixtures now upgrade to version 26 with the four zero bytes, and its version 24 fixtures are also read as version 25, with and without the dither flag.maintest that expected a ONE/ZERO blend into a reversed target to be refused now expects it to be accepted.This change was not run on AMD hardware or on a PS5. A request for a reviewer with an RDNA GPU and RADV:
deqp-vk --deqp-case='dEQP-VK.pipeline.monolithic.blend.format.*_unorm_pack16.states.*'. Itsr4g4b4a4,b4g4r4a4,r5g5b5a1andb5g5r5a1cases exercise exactly this export-order blend onSWAP_STD_REV/SWAP_ALT_REVtargets. The Navi10 run covers GFX10, the PS5's generation in Mesa; a GFX10.3 or later pass would show the behaviour did not change after it.ctest -R agc_driver_reversed_order_blendthere.Whether GT7 runs past this stop was not verified by us.
main'stools/check_conventions.py --base origin/main --title ... --body ...passes.Final branch, one commit (64071f5) on
main759c665, after moving the request serialization from version 22 to 23 becausemaintook 22 for #4114:agc_driver_reversed_order_blend,agc_shader_memory,agc_driver_graphics,agc_driver_dual_source_blendandagc_driver_swap_alt_blendpass, and the fullctestpasses 1063 of 1063.ctest -R 'agc_shader|agc_driver|shader|recompiler'passes 386 of 386.Rebased onto
mainfdefd76 (66ae603). #5097 had taken request version 23 and specialization id 8234 for the layer export flag, so the reversed-order blend code moved to version 24; the writer emits the layer flag and then the code, the reader reads the flag from version 23 and the code from version 24, and the module key and specialization constants keep the same order. WSL2 Ubuntu 26.04, lavapipe (Mesa 26.0.8), CI configuration: the five blend and serialization tests pass, and the fullctestpasses 1074 of 1074.Rebased on 2026-10-14 onto
main0b6d033 (8c9a939). Two conflicts:State.cpp: fix(agc): leave blending off for a color target with CB_COLOR_INFO.BLEND_BYPASS #4862 changed theblendEnableline next to the removed throw and dropped the BLEND_BYPASSRequireat the top of the blend branch. Resolved by keepingmain's line and its removal of theRequire, and removing only the reversed-order throw.docs/dev/debt/libSceAgcDriver.md: feat(agc): execute INDEX_ATTRIBUTES_INDIRECT (PM4 0x91) #4895 added the INDEX_ATTRIBUTES_INDIRECT entry above the 16-bit RGBA entry this PR edits; both are kept.The added and removed lines against the merge base are the same before and after the rebase; only context lines changed.
mainstill writes request version 23 and its highest pixel specialization id is still 8234, so version 24 and id 8235 stay. #5137's version 21 and 22 trailer handling onmainreads after the pixel info and is unaffected. The refusal is unchanged onmain0b6d033. #4782 was closed on 2026-10-14 with its earlier stops (#4834, #4809, #1418) onmainand this stop left to this PR; we did not run GT7.agc_driver_reversed_order_blend,agc_shader_memory,agc_driver_graphics,agc_driver_dual_source_blend,agc_driver_swap_alt_blendandrequest_serializerpass. The fullctestruns 1111 tests with no failures (1068 pass, 43 skip).ANYPS5_REQUIRE_VULKAN=1.Rebased again on 2026-10-14 onto
main1015c55 (9a88161). #4201 took request version 24 for the tessellation primitive group size and #4451 took version 25 for a dithered alpha-to-coverage flag written after the layer export flag. That conflicted inRequestSerializer.cpp,Recompiler.hpp,DrawRegisterKey.cppandShaderMemory.cpp. The reversed-order blend code moved to version 26: it follows the dither flag inShaderPixelStageInfoand in the writer, the reader reads it from version 26, andsameDecodecompares both fields.mainhas no specialization id 8235, so it stays; the module key and the specialization constants are unchanged, because #4451 put its flag in the prepared shader key instead.agc_shader_memorynow also reads the version 23 to 25 layouts, andmain'srequest_serializerexpects version 26 with the four extra bytes. Apart from that, the added and removed lines against the merge base are the same as before.mainrefuses alpha-to-coverage into a component-swapped MRT0 target, dithered or not, so #4451's coverage never reads a reversed-order export.agc_driver_reversed_order_blend,agc_shader_memory,agc_driver_graphics,agc_driver_dual_source_blend,agc_driver_swap_alt_blendandrequest_serializerpass. The fullctestruns 1149 tests: 1102 pass, 46 skip for device or display limits, andagc_driver_waterfall_imagesfails SPIR-V validation (DerivativeGroupQuadsKHRwith an 8x1 local size).main1015c55 fails that test the same way in its own linux CI job.request_serializerandagc_shader_memoryfail.Update 2026-10-14 (0866138 and 1d6edc4, on top of 9a88161): the reversed-order path now rounds like the plain blend.
1 - x(and, for some rows, the premultiplied export) in the pixel shader and handed it to the blend as the second color. A plain blend converts the export once and forms1 - xfrom that converted value; the split path converted 0.5 forSRC_COLORand, separately, the shader's1 - 0.5for the destination factor. Vulkan only asks the blend for a precision no lower than the destination's (Blending), so the inputs may sit on the 8-bit grid, and a conversion to that grid may go to either neighbour (fundamentals, conversion to normalized fixed-point: "one of the two ... closest", round to nearest only recommended), and 0.5 · 255 = 127.5 is a tie. With 0.5 converted to 128/255 on both inputs, the plain blend gives 64.25 + 192 · 127/255 = 159.87 → 160 and the split path 64.25 + 192 · 128/255 = 160.63 → 161, which matches the reported values; the RTX 5080 rounds this tie down and stored 160 and 159. So it was not Intel-specific: on the RTX 5080 and lavapipe the old split path differed from the same draw into aSWAP_STDtarget by up to 2 steps on other inputs, and on the RTX 5080 in 27% to 68% of the 16_16_16_16 FLOAT values for every swept control except 0x61000104.ONEsource factor moved into the factor, as1 · xinstead ofx · 1). Vulkan gives the second color no precision rule of its own (Dual-Source Blending), so bit equality with the plain blend rests on the device converting it like the first color. It does on the RTX 5080 and lavapipe, and RADV exports the second color in the first one's format (radv_pipeline_graphics.c); the test checks it on each device instead of widening the bound. Factor combinations that need shader arithmetic throw again, as onmain: of the 1,995 combinations of factors 0-10 (color and separate alpha) that the previous revision computed in the shader, 932 are routed (GT7's 0x65010504 among them) and 1,063 throw. No tolerance was widened.agc_driver_reversed_order_blendalso draws every case into aSWAP_STDtarget, which Vulkan blends alone, and requires identical stored bits, besides the ±1 comparison with the exact blend.agc_driver_graphicschecks every factor combinationTranslateReversedBlendaccepts against the guest equations (121 plain, 932 routed) and that the post-pass emits no arithmetic. With the new test on 9a88161, the comparison fails on both devices in the first case,0x65010504intoSWAP_STD_REV: 160 whereSWAP_STDstores 159 (channel 1 on the RTX 5080, channel 0 on lavapipe); the ±1 comparison alone passed there. Letting the test continue past failures on the RTX 5080, 14 cases fail on 9a88161, among them0x61020302with exports outside [0, 1]: channel 2 of pixel (3, 0) holds 159 whereSWAP_STDholds 160, the pixel of the Intel report rounded the other way. 1d6edc4 adds0x61010504(SRC_ALPHA + ONE_MINUS_SRC_ALPHA, alphaONE + ONE), which moves the export into the factor; it also fails on 9a88161.agc_driver_reversed_order_blendpasses 10 of 10 runs andagc_driver_graphics,agc_shader_memory,agc_driver_dual_source_blend,agc_driver_swap_alt_blendandrequest_serializerpass. A local sweep of seven routed controls (export values on and between the 1/255 grid, outside [0, 1], hashed destinations) found 0 of 1,179,648 channel values different fromSWAP_STDper control, format (8_8_8_8 UNORM and 16_16_16_16 FLOAT) and swap on both devices. The full WSLctestruns 1149 tests: 1102 pass, 46 skip for device or display limits, andagc_driver_waterfall_imagesfails as onmain1015c55. The fullctestran at 0866138; 1d6edc4 changes only the execution test. The branch still merges intomain84b01f9 without conflicts, andmainstill writes request version 25 and has no specialization id 8235.Rebased on 2026-10-14 onto
maine27ff7c (313c296). The only conflict wasGraphics/include/State.hpp: #4767 gaveDecodeColorBufferanallowMultisampleDccparameter next to this PR'sReversedBlenddeclarations; both are kept, and every existing call still matches through the default argument. The added and removed lines against the merge base are identical to before.mainstill writes request version 25, so this PR's version 26 and specialization id 8235 stay. WSL2 Ubuntu 26.04, GCC 15.2.0, lavapipe (Mesa 26.0.8), CI configuration:request_serializer,agc_shader_memory,agc_driver_graphics,agc_driver_dual_source_blend,agc_driver_reversed_order_blendandagc_driver_swap_alt_blendpass, andagc_driver_reversed_order_blendpasses 10 of 10 repeats. The fullctestpasses 1189 of 1191; the two failures are the relinker'sfile_writer_binaryandfile_writer_text, which stop withcoreutils: unknown program 'running'because Ubuntu 26.04 ships coreutils as one multi-call program. They are unrelated to this PR, which does not touch the relinker.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