Commit Graph
598 Commits
Author SHA1 Message Date
Adrià 76dec1794b Merge pull request #8998 from MarcZX10/codex/f32-image-store-rtz-8282
fix(agc): round 16-bit float image stores toward zero
2026-10-27 07:59:23 +01:00
Adrià 4c486ca322 Merge pull request #10515 from JJenkx/fix/agc-two-sample-dithered-a2c
fix(agc): emulate two-sample DB_ALPHA_TO_MASK 0xe701 dithered alpha-to-coverage
2026-10-27 04:52:02 +01:00
Dean 37c6b4bc25 Merge pull request #8077 from 0xcrstn/ufc6/descriptor-web-fold
fix(shader): split descriptor webs whose paths fold or hold invalid arms
2026-10-27 14:56:47 +13:00
Dean 630211a866 Merge pull request #6612 from milescoviello/feat/tess-geometry
feat(agc): draw tessellation followed by an NGG geometry stage
2026-10-27 14:56:18 +13:00
Dean 7d1ed9bb1e Merge pull request #8879 from MarcZX10/codex/masked-select-single-pass
perf(shader): stop masked-select elimination after one analysis pass
2026-10-27 14:26:37 +13:00
MarcZX10 9d6b917388 fix(agc): round 16-bit float image stores toward zero 2026-10-26 23:51:54 +00:00
0xcrstnandClaude Opus 5.5 ac0c125999 Merge upstream main into ufc6/descriptor-web-fold
Resolve the overlap with main's WindowLaneGuard and image-resource changes
by keeping both sides: DescriptorFault sits next to WindowLaneGuard in the
opcode list, metadata and side-effect switch, and its emitter next to
EmitWindowLaneGuard; optionalDescriptor is serialized after
remappedDepth1D; undefinedImageWords follows the new image helpers; the
descriptor web debt entry follows main's new entries.

The ImageResource field-count assertion is derived from the merged
structure (44 fields: main's 43 plus optionalDescriptor). sizeof
(ImageResource) stays 96 and sizeof(MemoryInfo) stays 80, so those
assertions are unchanged. The undefined-format test keeps its captured
regions in a variable, as MemoryRegionView no longer binds a temporary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 14:10:30 +02:00
Dean 9bbb7f37c6 Merge pull request #8898 from camezaro-intc/format11-11-10-float-stores
fix(shader_recompiler): pack format 11_11_10 float image stores in shader
2026-10-27 01:03:40 +13:00
Dean d9f5bf4d91 Merge pull request #11120 from shahulmubeen-a/fix/shader-1d-store-through-2d-array
fix(shader): write 1D storage images through 2D-array stores at slice 0
2026-10-26 21:58:24 +13:00
Dean 943ea8acb2 Merge pull request #9957 from mrfelek/fix/shader-runtime-buffer-presence
fix(shader): read a buffer V#'s presence at run time instead of specializing it
2026-10-26 16:54:34 +13:00
Shahul Mubeen AandClaude Opus 5.5 b9d00c5d80 fix(shader): write 1D storage images through 2D-array stores at slice 0
An image_store with DIM 2D_ARRAY through a 1D T# had no runtime image
mode, so the dispatch stopped with "image descriptor is incompatible
with the static runtime image interface". #2348 added a 1D mode for
DIM 2D stores only.

Write-only 2D-array storage images now get the same 1D mode as the 2D
case. On RDNA2 (gfx1036, hardware oracle) such a store writes texel x
and ignores y when the slice is 0, and writes nothing for any other
slice, with DEPTH 0 or 3, so the store is skipped unless the slice is 0.

New execution test agc_driver_image_store_line_through_plane_array.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 00:10:03 +05:30
Adrià e317f41d59 Merge pull request #10440 from SuarezPM/ai/atomic64-keyed-tables
feat(shader): support 64-bit image atomics through keyed image tables
2026-10-25 11:58:35 +01:00
milescovielloandClaude Opus 5.5 b6da343d20 fix(agc): keep the negated-predicate proof when a negated condition isn't implied
ImpliesNot returned at a negated condition, so a predicate !!a against
the condition !a, or !!a in either order of a conjunction, never reached
the negated-predicate and conjunction cases, which prove it. Lane-bit
lowering makes such a predicate from a complemented own-lane ballot of
!a, and the address evaluator then read both arms of a select on !a
instead of the one the predicate implies. Each case now falls through
when it does not prove the negation. Three hull reads under that
complemented ballot bit, alone and conjoined on either side, check it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 08:32:48 +00:00
milescovielloandClaude Opus 5.5 cd5fc9e838 feat(agc): draw tessellation followed by an NGG geometry stage
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from #6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 08:32:37 +00:00
camezaro-intc e3f644040c fix(shader_recompiler): pack format 11_11_10 float image stores in shader 2026-10-24 21:32:14 -06:00
JJenkxandClaude Opus 5.5 2ff14f34e3 fix(agc): emulate two-sample DB_ALPHA_TO_MASK 0xe701 dithered alpha-to-coverage
Bugsnax (PPSA01503) draws with DB_ALPHA_TO_MASK 0xe701 (quad offsets
3, 1, 2, 3 without OFFSET_ROUND) on a two-sample target and stopped on
the refusal of every dither but the eight-sample 0x18701. The pixel
shader now applies an eight-level per-quad table for it, measured
natively on gfx1032, and the request's dither byte selects that table
(serialization version 47). It is accepted only for two matched raster
and DB_EQAA samples, the two measured location pairs and FP16_ABGR or
32_ABGR exports.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 16:40:02 -04:00
Adrià 66de8e7a12 Merge pull request #9177 from milescoviello/perf/draw-allocations
perf(agc): drop three per-draw allocations on the draw and materialize paths
2026-10-24 18:29:19 +02:00
Adrià c9b2660d56 Merge pull request #9567 from Izamaru/fix/rve-descriptor-references
fix(shader): refresh descriptor sources after redundant value elimination
2026-10-24 15:46:56 +02:00
Adrià 522e32e3b6 Merge pull request #7550 from gjonn/fix/shader-resinfo-any-descriptor-dimension
fix(shader): answer image_get_resinfo on any T# dimension
2026-10-24 15:30:15 +02:00
mrfelek 20311903c3 fix(shader): read a buffer V#'s presence at run time instead of specializing it
A buffer V#'s presence came from the dispatch's V# snapshot as the
specialization constant BufferBase + 2, which buildSpecializedModule
turns into a literal. One guest program then compiled to two SPIR-V
modules, one with the buffer bound and one with it still null, each a
separate pipeline. descriptor() now reads presence from the V# words at
run time, as registration modules already do, and the formatted-buffer
helper takes it from its valid parameter.

AI-assisted. Tested by me on my own machine.
2026-10-24 12:59:47 +00:00
Adrià 924b5628b3 Merge pull request #8632 from JJenkx/fix/srt-unsigned-bound-compare
fix(shader): decide an unsigned bound compare from its extreme operand
2026-10-24 11:56:35 +02:00
Adrià FranchandClaude Sonnet 5.5 424b8f90b1 fix(shader): a negated predicate excludes only conditions that imply its operand
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-24 08:40:33 +02:00
xQuakes 418db9d2f8 fix(shader): accept a local tessellation index that nothing observes
A local program that keeps the relative patch index only on inactive
lanes, or in a vector-window slot nothing reloads, was refused as a
data use. Follow the index through the values that carry it, and
refuse only when a side effect still observes it.
2026-10-24 08:40:33 +02:00
Adrià a5a2c946a3 Merge pull request #10396 from CrimsonMac/fix/lds-misaligned-atomic64-fault
fix(shader): fault on misaligned 64-bit LDS atomics under the workgroup lock
2026-10-24 07:33:30 +02:00
JJenkxandClaude Opus 5.5 9ed24c8b41 fix(shader): decide an unsigned bound compare from its extreme operand
A resource block behind v_cmpx_gt_u32 exec, s, v0 and s_cbranch_execz keeps
its condition only if the compare can decide it, but UGreaterThan32 and
ULessThan32 needed both operands and v0 is a lane value. When the uniform
operand is 0 (or 0xffffffff on the other side) no lane can pass the compare,
so the walk can skip the block without the lane value.

UGreaterThan32 now yields false when its first operand is 0 or its second is
0xffffffff, and ULessThan32 when its first is 0xffffffff or its second is 0,
in the SRT interpreter and in the SRT tape alike; MayDecide keeps such a
condition when either operand is evaluable. Fully evaluable compares are
unchanged.

Destruction AllStars (PPSA02630) dispatches compute shader 0x200a220000 with
a thread count of 0 and leaves the V# in the skipped block stale (one
dispatch holds 00000000 00000000 00000000 ffffffff), which stopped it at
about 40 s with "buffer descriptor uses an unsupported type".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 23:59:32 -04:00
Adrià FranchandClaude Opus 5.5 7b4b9d9814 fix(shader): zero the resinfo layer count for DIMs without layers
image_get_resinfo returns 0 in its third component when the instruction's
DIM has no layers (1D, 2D, 2D MSAA) and the T# is not 3D, as measured on
RDNA 2 in #7550. Keep 1D-array T#s on their first layer and MSAA T#s
refused, and record the unmeasured forms in the shader debt file.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 04:21:06 +02:00
Gjon Gojcevic 3ba1d39db6 fix(shader): answer image_get_resinfo on any T# dimension
image_get_resinfo with DIM 1D on a cube, 3D or 2D-array T# was refused
with "image address has too few coordinate components": the tracker made
a 1D image that only the query uses, and no 1D mode matches such a T#.
The returned size, layer count and levels come from the T#; DIM only sets
the number of address registers. A 1D image used only by dimension
queries now decodes the T#'s own dimension and accepts 2D, 1D array,
2D array, 3D and cube views.
The flag is stored in the shader disk cache, so FormatVersion moves to 38.

PPSA01317 queries a 64x64 cube with DIM 1D in a pixel shader.

AI-assisted: yes
2026-10-24 04:07:24 +02:00
Dean e2b9700a98 Merge pull request #7880 from klosixgaming-arch/fix/shader-indirect-column-phi-pointer
fix(shader): resolve table column pointers through Phi nodes
2026-10-24 13:22:58 +13:00
SuarezPM 9c3ffcf5b0 feat(shader): support 64-bit image atomics through keyed image tables
Table T#s keyed at runtime feeding image_atomic64_* now lower to
OpAtomic* on the table Atomic64View instead of faulting, mirroring
the 32-bit path: gate, dedup identity, binding flags and view
selection. Packed formats and BY element counts still fault; hosts
need VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT for the view format.
2026-10-23 21:14:39 -03:00
Adrià d48007d462 Merge pull request #8883 from EagleBearerYS/perf/shader-plan-retention
perf(shader): keep only what a resource plan's branch conditions can evaluate
2026-10-24 01:00:04 +02:00
Adrià 495b7c10ab Merge pull request #8792 from SuarezPM/ai/image-atomics-keyed-tables
feat(shader): support 32-bit image atomics through keyed image tables
2026-10-24 00:00:03 +02:00
Adrià dcd7e3a61e Merge pull request #8564 from JAB-dev/feat/agc-4-4-4-4-partial-writes
feat(agc): merge partial writes into 4_4_4_4 UNORM color targets
2026-10-23 23:23:11 +02:00
Adrià a0e858ff7b Merge pull request #8881 from thuanquang/fix/writelane-spill-window
fix(shader): keep a v_writelane lane known across computed-index window stores
2026-10-23 23:17:12 +02:00
Crimson cd329c060a fix(shader): fault on misaligned 64-bit LDS atomics under the workgroup lock 2026-10-23 23:59:53 +03:00
Adrià 11e8ad2934 Merge pull request #8713 from SeifKaroui/fix/shader-unused-phi-cycles
fix(shader): remove unused phi cycles before resource planning
2026-10-23 22:46:22 +02:00
Adrià 3c44638fc6 Merge pull request #8727 from hamb3r/perf/shader-cse-srt-readconst
perf(shader): eliminate redundant GetSrtResource and ReadConst in RVE
2026-10-23 21:54:52 +02:00
Yunus Shaikh 6f36f29ea3 fix(shader): answer phis and null bases in a trimmed plan as the program does
A plan copies a branch condition only as far as the evaluator reads it,
and an operation the evaluator does not read is kept without its
arguments. Two questions the walk asks still read below such a leaf.
ResolveInvariantPhi compares a phi's incoming values with
EquivalentValue, which follows their arguments, so two leaves with the
same operation looked equal in the copy where their arguments differ
in the program: a phi whose incoming values differ only below a vector
load resolved in the plan and not in the program, and the plan decided
a condition the program leaves open. LoadedFromMemory looks for a read
from memory anywhere below a raw read's handle, so a handle that
reaches memory only below a leaf lost it in the copy: a read from a
null base counted as a null root, and its condition stayed open where
the program decides it.

ownPlanValues now checks both after it copies. Each phi it copied in
part must resolve in the copy to the copy of what it resolves to in
the program, and each raw read's handle must be loaded from memory in
the copy when it is in the program. A phi that differs is copied whole;
a handle that differs keeps the arguments along its shortest path to a
read from memory (its whole closure if that path is already kept), and
the copy is made again. The checks only add values, so the loop ends,
at worst with the whole copy. IsMemoryRead names the operations that
LoadedFromMemory and the path both stop at.

Tested: agc_shader_memory's verifyPlanCopyAnswers walks a phi whose
incoming values differ only below a vector load, and a read from a null
base whose handle reaches memory only through a select arm the active
mask never takes, through the plan's tape, the plan's interpreter and
the program's own walk, and all three agree. Without the checks the
plan decides the first condition and leaves the second open.
2026-10-23 21:40:20 +02:00
fablevoid 402f891787 fix(shader): keep only what a resource plan's conditions can evaluate
A resource plan owns copies of the IR values its run-time evaluation
reads: the descriptor sources, the SRT reads, the uniform fills, and
the branch conditions that tell which images a dispatch can reach.
Below a scalar load from memory, the copy took every value the load
depends on, whether the evaluator can compute it or not. A condition
that reads memory after vector work (a load predicated by a vector
compare, an address computed from vector data) brought the program's
whole vector graph into the plan: in a title's programs 2.4 million of
2.6 million retained values, about 500 MiB, belonged to twelve or so
conditions per program.

Below a condition, the copy now follows only what the evaluator reads:
the arguments of values it can compute, and for a load from memory the
words of its descriptor and its offset; a value the evaluator cannot
compute is kept without its arguments, which is what evaluating it
needs (it does not evaluate). Descriptor sources keep their whole
closure, which the device image pre-pass walks.

Tested with a new test (agc_driver_resource_plan_retention): the plan
of a program whose branch condition reads a scalar load at an address
taken from vector data now keeps the same number of values for vector
chains of 1, 16 and 64 steps before the load (84, 114 and 210 before);
the device table, written image, buffer descriptor, memory and SRT
range and shader disk cache tests pass; in a title's corpus the plans
of 314 programs hold 40 thousand values instead of 837 thousand; the
corpus recompile with SPIR-V validation has no invalid module.

Resolved onto main: the retention test runs on DeviceTableFixture.hpp,
which main does not have, so the test and its CMake line are left out
here; the next commits test this on main.
2026-10-23 21:40:20 +02:00
fablevoid 9796a23046 fix(shader): copy only what the SRT evaluator reads of plan branch conditions
ExtractPlan copied the whole argument closure of every control-flow
condition into the plan. The draw-time walk (SrtDescriptorEvaluation)
uses a condition only when the evaluator computes it, and an operation
outside the evaluator's set ends the evaluation without reading its
arguments. For conditions on vector loads, image results or values
carried around loops the copy reached most of the program, and none of
it was ever read.

Detail::Evaluator::Reads names what the evaluator reads of a value:
nothing (an operation it does not evaluate, an immediate), its
arguments (the operations it evaluates, identities, phis, and the pairs
CompositeExtract reads through), or its whole closure (a raw read, whose
handle LoadedFromMemory walks). EvaluateInst returns early for a value
it reads nothing of, so the two cannot drift apart. ownPlanValues still
copies descriptor sources, SRT reads and fill values whole, and copies
a condition only as far as Reads goes: an operation it does not read is
copied without its arguments. The pure and guarded flat slots are
computed before the copy, from the same values as before.

Evidence: a title that registers about 5,700 shaders at load held
24.1 M copied IR values in its plans (about 5.4 GiB by value size), of
which 2.1 M were reachable from descriptor sources, SRT reads and fills
(counted by a local report over the recompiler's source map).

Tested: agc_shader_memory gains verifyPlanConditionPruning: a condition
on a load with a 64-addition address keeps the load as a leaf and none
of the additions, and conditions read through an extracted pair and
through a raw read still evaluate. It fails without the change. Full
ctest passes.

Resolved onto main: Reads is a static member of BasicEvaluator next to
MayEvaluate, and its operation list is main's evaluator's
(evaluatedArguments adds BitCount32, FindILsb32 and FindUMsb32; the
undefined values, which main never evaluates, read nothing). The
EvaluateInst guard reads the node's value, so it covers the compact
plans too. ownPlanValues now runs after the flat slots and before the
compact plan, and gives a value it keeps without arguments an empty
operand list, so the leaf drops the operand capacity main's IrValue
constructor reserves. Main's MayEvaluate already drops the condition on
the vector load, so the test checks that it is gone.
2026-10-23 21:40:20 +02:00
SuarezPM 548267bfa3 feat(shader): support 32-bit image atomics through keyed image tables
Table T#s keyed at runtime no longer fault on image_atomic_*32: the
table operation stays supported, elements carry the atomic flag through
dedup into the descriptor binding, and the table path binds AtomicView
like the direct path. 64-bit atomics stay unsupported, packed and BY
formats stay unsupported, and the debt entry records the relaxed
Device-scoped emission and the remaining gaps.
2026-10-23 21:22:29 +02:00
JAB-devandClaude Sonnet 5.5 8d54357e79 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 21:18:00 +02:00
Adrià ad19afc31e Merge pull request #8518 from JJenkx/fix/srt-guard-condition
fix(shader): decide resource branch conditions from their uniform operand
2026-10-23 20:50:37 +02:00
milescovielloandClaude Opus 5.5 ad6a55121e fix(agc): read FMASK of up to 8 samples in every storage width
Since the synthetic FMASK mode was removed, a direct FMASK load reads
the stored word and only Fmask32_S8_F8 is accepted. A load from any
other FMASK format of up to 8 samples now reads the 8-, 16- or 32-bit
surface and expands it in the shader to 4 bits per sample, an index
past the fragment count reading 8 (unknown). One runtime image mode
handles every such format, reading the format from the descriptor at
run time or from a specialization constant.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 16:34:33 +00:00
Adrià 15e71dbe11 Merge pull request #7882 from klosixgaming-arch/fix/image-table-sampler-deduplication
fix(shader): deduplicate sampler table elements in ResolveImageTables
2026-10-23 17:47:25 +02:00
Adrià 83694b3db9 Merge pull request #7803 from thuanquang/fix/msaa-2d-sample-zero
fix(shader): read a 2D MSAA T# through DIM 2D as its sample 0
2026-10-23 17:24:59 +02:00
Izamaru 140cc40efe chore: merge current main into descriptor reference fix 2026-10-23 10:18:41 -03:00
Adrià 0cc23ad8ba Merge pull request #7811 from santhoshkumar-dev/codex/fix-pixel-wqm-interpolation
fix(shader): keep host interpolation across entry EXEC copies
2026-10-23 13:30:25 +02:00
JAB-devandClaude Sonnet 5.5 8415906b22 Merge branch 'feat/agc-4-4-4-4-color-target' into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 12:09:28 +02:00
Dean 348157914f Merge pull request #6218 from harry-z-kang/codex/issue-6119-packed-storage
fix(agc): support packed 16-bit storage images
2026-10-23 22:44:30 +13:00
JAB-devandClaude Sonnet 5.5 870bacd092 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 08:59:06 +02:00