Commit Graph

202 Commits

Author SHA1 Message Date
Adrià a9ac7bc4c3
Merge pull request #1580 from Zheorgyan/feat/storage-buffers-update-after-bind
feat(agc): bind storage buffers update-after-bind above the per-stage limit
2026-10-10 03:12:01 +02:00
Zheorgyan 27e6ad1ad2 feat(agc): bind storage buffers update-after-bind above the per-stage limit 2026-10-10 02:08:15 +02:00
Celegans12 619ec7ad39 feat(agc): accept samplers that force sRGB decoding of sRGB textures
A sampler with FORCE_DEGAMMA (S# word 0 bit 20) threw at decode, so
every dispatch or draw sampling through one was skipped.

DecodeSamplerResource now records the bit, but accepts it only for a
caller that pairs the sampler with its images. The direct sampler
binding does, and RequireDegammaFormat checks each sampled image
against its paired samplers: only already sRGB formats (8, 8_8 and
8_8_8_8 SRGB, BC1, BC2, BC3 and BC7 SRGB) pass, decoded once, as
shadPS4 (PS4) models it. Other textures and unpaired decodes still
throw; gfx10 behaviour is not measured.
2026-10-10 01:38:17 +02:00
Adrià 27965d8ae7
Merge pull request #1170 from MichonGoddijn231849/fix/dcc-keys-fill-over-aliased-images
fix(agc): a fill of a surface's DCC keys is a key fill over other images' memory
2026-10-10 00:32:43 +02:00
Adrià c6e3aa767b
Merge pull request #1146 from alfalfa-star/perf/agc-draw-snapshot-budget
perf(agc): keep draw snapshots of storage buffers up to 1 GiB
2026-10-10 00:25:31 +02:00
Adrià fc063cff85
Merge pull request #1074 from alfalfa-star/feat/agc-graphics-int64-atomics
feat(agc): accept 64-bit atomics in graphics shaders when the device enables them
2026-10-10 00:14:56 +02:00
Adrià 2d537f13bb
Merge pull request #1073 from alfalfa-star/feat/agc-uint16-color-export
feat(agc): accept UINT16_ABGR color exports into unsigned integer targets
2026-10-10 00:13:23 +02:00
Dean 330cfae722
Merge pull request #2176 from oneandonlydean/up639/adjusted-regions
perf(agc): bind misaligned draw buffer regions in place through the view adjustment
2026-10-10 10:49:12 +13:00
Dean d93bc7763c
Merge pull request #1004 from Celegans12/perf/agc-staging-pool-reuse
perf(agc): pool device staging buffers by size class
2026-10-10 08:06:32 +13:00
Celegans12 28345b0eac perf(agc): pool device staging buffers by size class
The device-local tier of BufferPool only reused a buffer of the exact
size and usage it was asked for. Partial storage-image detiles and
retiles ask for a new size and the other transfer direction almost
every time, so the tier sat at its budget and missed and evicted
dozens of buffers per frame, and the vkFreeMemory calls on the release
thread held up submits and allocations on the recording threads.

Device-tier requests of 1 MiB and more now round up to an eighth of
their octave, the tier's buffers are created for storage and both
transfer directions, and a request takes the smallest retained buffer
from its own class up to twice its size. Host tiers, the budget and
eviction are unchanged. agc_buffer_pool covers the classes, the fit
and its bound, reuse only after release, the budget and the unchanged
lists.
2026-10-09 14:58:21 +02:00
Celegans12 e804ce85f7 perf(agc): skip unchanged heap mirror runs and idle mirror sweeps in address-based builds
A build served by the cached address space walked every region of the
space for its mirrors, sorted the heap mirrors, compared each heap
mirror's blocks with the write tracker under its own lock and swept the
whole mirror registry. In an offline replay with 37,000 heap mirrors
that took about 10 ms per build, every build.

The space now keeps its writable mirrors, its sorted heap mirrors and
their adjacent runs from when it is published. Each run is still
flushed and collected; a run with no block stamped since the generation
its last complete check collected skips the per-mirror compare, and that
generation is stored only once the build's blocks were copied. The
registry sweep is skipped while every live mirror's range is held by the
cached address space's lease and no mirror was added, replaced or
dropped since.
2026-10-09 14:58:16 +02:00
boykopovar 43972e69a1
Merge pull request #2096 from boykopovar/fix/windows-host-import-texture-reuploads
fix(win): windows host import texture reuploads
2026-10-09 12:56:45 +03:00
boykopovar 0e1d25a8a2 fix(agc): avoid redundant transfers for untracked imported textures 2026-10-09 10:50:49 +03:00
Dean Galvin ac2d172e0b perf(agc): bind misaligned draw buffer regions in place through the view adjustment
A draw's guest buffer region inside a host import at an offset off
minStorageBufferOffsetAlignment was copied per build (a new buffer, an
input snapshot, a vkCmdCopyBuffer that ends the open render pass), and
DirectRegions refused such builds as templates.

Descriptor already binds any DWORD-aligned view from the aligned offset
below it and passes the remainder through the shader's memory offset
slot. A draw build that is not address-based and whose every guest buffer
element has such a slot (a push constant byte, or a shader data byte
inside its data buffer) now binds a region whose offset in its import is
DWORD aligned in place, like an aligned one: its read-only views are
snapshotted per draw by PrepareDrawBindings at address - adjustment, the
import serial keys the template, and Revalidate proves it per use.
Dispatches keep the copy (they read in-place inputs at execution, not at
record).

agc_driver_recorder_tests misalignedRegionTests: a misaligned read-only
draw region is read in place, the build is reusable, the push constant
carries the adjustment, and the per-draw snapshot starts at the aligned
offset below the view.
2026-10-09 20:36:07 +13:00
Celegans12 97b9439d4f perf(agc): size the storage and sampled texture caches to the device
The storage image and sampled texture caches each let go of their least
recently used entries past a fixed 2 GiB, and a sampled view of a
storage image counted that image a second time.

The storage image cache keeps a quarter of the largest device-local
heap, at least the 2 GiB of before (TextureCacheBudget). The sampled
cache gets what VK_EXT_memory_budget leaves on that heap after the
memory in use outside sampled textures and cached storage images, the
storage cache's budget and an eighth of the heap budget, read at most
once a second and at least 2 GiB; without the extension it keeps the
storage cache's rule. A snapshot counts its image allocation, a texture
still bound after leaving the cache counts as sampled memory, and a
change of more than 10% is logged at most every 10 s. A nonzero
APS5_TEXTURE_CACHE_MIB sets both budgets; a view of a cached storage
image counts nothing and leaves the cache when its image does.
2026-10-08 20:24:03 +02:00
alfalfa-star a2b049d455 feat(agc): accept 64-bit atomics in graphics shaders when the device enables them
The recompiler emits OpCapability Int64Atomics for 64-bit buffer atomics
in any stage, and the device enables shaderBufferInt64Atomics when it
has it, but graphics shader validation only accepted its fixed list of
capabilities, so every draw whose shaders use one was rejected with
"SPIR-V requires unsupported device capability 12". Compute dispatches
are not validated this way and already ran them.

The device records the feature (bufferInt64Atomics in the device state
and the graphics Context) and ValidateShaders accepts Int64Atomics when
it is enabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:16:01 +02:00
alfalfa-star 45541350bb feat(agc): accept UINT16_ABGR color exports into unsigned integer targets
SPI_SHADER_COL_FORMAT 7 (UINT16_ABGR) was rejected by DecodeState,
though the recompiler already handles it: a pixel shader's MRT output
under mode 7 is a uvec4, and a compressed export's 16-bit halves are
taken with OpBitFieldUExtract. The format is now accepted when the
target's CB_COLOR_INFO number type is UINT; into any other target it
still throws, as does SINT16_ABGR (8), whose halves would need sign
extension.

The target records the export (ColorTarget::uintExport). Shader
validation then requires a uint4 output at its location instead of a
float4 one, and blending into it is refused (Vulkan has no blending of
integer attachments).

PPSA14632 (LEGO Horizon Adventures) writes a 2848x1600 R8_UINT target
this way; those draws were dropped.

agc_driver_pixel_uint16_export draws compressed MRT0 exports under mode
7 into a linear 16_16_16_16 UINT target, one row per pair of packed
words (0x0000ffff/0xffff0000, 0x00010002/0xffffffff and four distinct
halves), and reads every 16-bit component back under the identity,
STD_REV and ALT_REV export mappings. agc_driver_graphics covers the
decode and the blend refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:46:09 +02:00
Michon 7208d7d314 fix(agc): a key fill over other images stays inside the image's DCC key extent; test the fill cover
When another live image overlaps the fill, a fill at a live image's dccAddress is a key fill
only while it stays within DccKeyCount (the pipe-aligned key count); with nothing overlapping
the length rule is unchanged. ClassifyFill, NoteKeysFill and ClearByKeysFill share the match.
agc_driver_fill_cover_keys pins Keys, Inside and Several for fills at and beside the keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 18:06:37 +02:00
boykopovar 2ec144d4d3 perf(shader): avoid redundant resource validation + eliminate dead spirv computations 2026-10-08 17:29:48 +03:00
boykopovar 05fa426112 perf(shader): eliminate prepared-path overhead in data, descriptors, dispatch, bda 2026-10-08 17:29:17 +03:00
boykopovar 7431e5a6e1 perf(shader): restore prepared vertex inputs + harden buffer specialization 2026-10-08 17:28:55 +03:00
boykopovar 7f56e04157 fix(shader): validate and serialize pipeline specialization constants (wip) 2026-10-08 17:28:35 +03:00
boykopovar 73816838dc perf(shader): add pipeline specialization and direct buffer access (wip) 2026-10-08 17:28:34 +03:00
boykopovar f524bbedc3 refactor(shader): separate artifact preparation from draw and dispatch 2026-10-08 17:26:40 +03:00
boykopovar ab0f9985fa feat(shader): resolve bindless resources through runtime heap metadata 2026-10-08 17:26:36 +03:00
boykopovar dccfa08de9 feat(shader): add fixed runtime abi + typed descriptor heaps 2026-10-08 17:26:04 +03:00
Celegans12 1816aea91c fix(agc): store and read DCC keys over the console's metadata extent
The console's DCC of a single-level 4-byte SW_64KB_R_X surface is
ceil(W/512) * ceil(H/512) * 4096 bytes, 49152 for 1920x1080, but the
driver stored and read one key per 256 surface bytes (34560).
PPSA26344 retiles its render DCC into the displayable copy it
registers (cs_dcc_retile_32bpp); a retile of the stale tail gives the
mixed keys PPSA12544 stops on.

DccKeyCount gives that extent. Color target and storage image key
stores cover it when the DCC is pipe-aligned (CB_COLOR_ATTRIB3 bit 30,
T# word 6 bit 19), whose CB keys reach its last meta block, and throw
where it is not writable; unaligned DCC keeps one key per 256 bytes,
as do texture and color target key reads. DisplayBufferKeys reads the
display DCC over the extent, presents only when every key agrees,
names the first differing key's pixels and checks a pending image
against those keys.
2026-10-08 15:24:43 +02:00
Adrià 07c2405c35
Merge pull request #1371 from TibixDev/pr/depth-maintenance-precheck
fix(agc): reject depth maintenance before shader compilation
2026-10-08 14:37:01 +02:00
Adrià 072804fd33
Merge pull request #1288 from Celegans12/fix/agc-dcc-filled-keys-refresh
fix(agc): forget a DCC key fill once a refresh sees other keys
2026-10-08 14:35:47 +02:00
Adrià cba8d86da8
Merge pull request #1270 from Celegans12/fix/agc-unaligned-buffer-views
fix(agc): bind guest buffer views that start off a DWORD boundary
2026-10-08 14:34:45 +02:00
Adrià 0b3cc73e1c
Merge pull request #1112 from Celegans12/feat/agc-conservative-rasterization
feat(agc): implement overestimating conservative rasterization
2026-10-08 14:31:38 +02:00
Adrià d393c3e754
Merge pull request #1346 from TibixDev/pr/disabled-color-targets
fix(agc): honor disabled color targets and their reset state
2026-10-08 13:36:03 +02:00
Celegans12 29c22442dc feat(agc): implement overestimating conservative rasterization
A draw whose PA_SC_CONSERVATIVE_RASTERIZATION_CNTL (context 0x313) was
not the default 0x6000 threw in DecodeState and the draw precheck.
0x6001 sets OVER_RAST_ENABLE and now decodes to Vulkan's overestimation
mode, chained to the pipeline's rasterization state and its key.

The device enables VK_EXT_conservative_rasterization only when its
primitiveOverestimationSize is at most 1/256 pixel and it rasterizes
degenerate triangles; elsewhere the pipeline throws. Overestimation is
accepted only when triangles reach the rasterizer: VGT_GS_OUT_PRIM_TYPE
behind a geometry shader, VGT_TF_PARAM's output topology behind
tessellation, VGT_PRIMITIVE_TYPE otherwise. Other 0x313 values and
centroid interpolation still throw.

Adds the agc_driver_conservative_rasterization GPU test and extends
agc_driver_graphics.
2026-10-08 13:20:22 +02:00
Celegans12 38e89df1a5 fix(agc): bind guest buffer views that start off a DWORD boundary
A V# whose base is not a multiple of 4 bytes from the start of its GPU
owner threw in GuestBufferMemory::Descriptor, because the shader added
the offset below the view only in whole dwords.

Descriptor now binds from the offset alignment below the view and
passes the whole remainder. Such a view's range covers the dwords
around it, and its descriptor region starts and ends on dword
boundaries, so a lone view copied to its own buffer binds the same way.

The buffer specialization records the V# base's low two bits. Raw
vector loads through such a V# join two dwords, glc dwordx2 loads
included, stores merge their bytes into both with compare-exchange
loops, and bounds checks include the second dword. s_buffer_load
ignores the low two bits, as SrtEvaluator does. Formatted accesses
whose element alignment (min(element bytes, 4)) the base breaks throw,
as they fault the wave on RDNA2, and so do atomics.
2026-10-08 13:01:27 +02:00
Celegans12 ccddd4f89b fix(agc): forget a DCC key fill once a refresh sees other keys
StorageTexture::MarkDirty skips the first write's uncompressed key
store while the image's filledKeys holds a clear code, and only an
upload or clearByKeysFill reset that fill. After a 0001 key fill, a
kernel storing 0000 over the keys and a storage write, the refresh of
write-watched memory read 0000, the keys the image was uploaded under,
so it did not upload again and kept the stale 0001. The write then
left the 0000 keys in memory, and a kernel reading them saw the clear
colour.

StorageTexture::ProvedKeys, the key read of Refresh and the fast
revalidation, now forgets the fill when it reads other keys while the
image has no results pending. An image with pending results keeps it,
since its write-backs treat those results as killed by that fill.
2026-10-08 12:55:45 +02:00
Adrià 30e89cc6a0
Merge pull request #1266 from Celegans12/fix/agc-oversized-descriptor-sets
fix(agc): allocate oversized descriptor sets from a dedicated pool
2026-10-08 12:09:59 +02:00
Adrià 96614df544
Merge pull request #1239 from awake-devel/fix/agc-release-host-imports
fix(agc): release host imports before the device is destroyed
2026-10-08 11:27:40 +02:00
Adrià 3ce729fe86
Merge pull request #1182 from MichonGoddijn231849/feat/compute-scratch
feat(agc): compute dispatches with scratch memory
2026-10-08 11:15:45 +02:00
Adrià a5df1a874d
Merge pull request #1177 from MichonGoddijn231849/feat/standard-64k-color-targets
feat(agc): 64 KiB standard color targets
2026-10-08 10:44:52 +02:00
Michon 20e055c244 feat(agc): compute dispatches with scratch memory
A compute program with COMPUTE_PGM_RSRC2.SCRATCH_EN takes its per-lane private size from the AGC
shader header (scratch_size_dw_per_thread) instead of being refused. The size travels in
ShaderComputeStageInfo (cache key, request serialization version 10) to the translator, whose
scratch accesses already lower to a per-invocation Function array of that many dwords.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 10:22:40 +02:00
Adrià e705d430d6
Merge pull request #1139 from alfalfa-star/fix/agc-inert-pixel-stage
fix(agc): run draws whose pixel stage cannot run without its program
2026-10-08 10:20:09 +02:00
Michon 6aa8e58de7 feat(agc): 64 KiB standard color targets
Color targets with the SW_64KB_S swizzle (CB_COLOR_ATTRIB3 tile mode 9) use the standard element
order of the 4 KiB mode extended by the texture detiler's 64 KiB bits, and are resident like the
other tiled targets. The standard blocks are now wider than tall for 2- and 8-byte elements, as the
standard swizzle and the texture layout have them (they were transposed, aliasing texels).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 10:16:22 +02:00
Adrià 8e22498c20
Merge pull request #1134 from alfalfa-star/fix/agc-mesh-unindexed-index-vsharp
fix(agc): bind a null index buffer to non-indexed mesh draws
2026-10-08 10:15:09 +02:00
Adrià 72bcc33606
Merge pull request #1113 from Celegans12/fix/agc-batch-kept-bytes
fix(agc): bound the upload buffers that recorder batches keep alive
2026-10-08 09:39:56 +02:00
TibixDev 1841f3c6e7 fix(agc): honor disabled color-buffer formats
Exclude COLOR_INVALID attachments from the effective write mask while preserving later MRT export indices and depth-only rendering. Validated with the graphics tests and Skyrim menu draws.

AI-assisted implementation and testing by OpenAI Codex.
2026-10-08 10:22:13 +03:00
Chad c17337b6d9 fix(agc): size CMASK by whole 1024x512 metablocks
A CMASK holds 4 KiB per 1024x512-pixel metablock, not one nibble per 8x8
tile of the target: 1920x1080 spans 0x6000 bytes, as titles clear it,
not 16200. The swizzled nibbles of the lower-right tiles lie past the
packed size, so the fast-clear check missed them and the expanded store
left them cleared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:53:02 +13:00
alfalfa-star 61a61016d8 feat(agc): render into CMASK fast-clear color targets
Draws into a color target with CB_COLOR_INFO FAST_CLEAR (bit 13) were
rejected. The CMASK keeps one nibble per 8x8 tile: 0 means the tile is
fast-cleared and reads as CB_COLOR_CLEAR_WORD, 0xF means expanded (the
texels hold the color). The texture units and display scanout do not read
it, so a title runs a fast-clear eliminate pass before sampling or
flipping such a target.

DecodeColorBuffer now takes the CMASK address (CB_COLOR0_CMASK and
CB_COLOR0_CMASK_BASE_EXT) and the bytes one nibble per 8x8 tile spans.
Before a draw renders into the target, and in a fast-clear eliminate
pass, a CMASK whose nibbles are all 0 is materialized: the target is
filled with the clear texel (FillClear on its resident image, else
guest memory on the CPU) and the CMASK bytes are stored as expanded,
through the same GPU-ordered store as the DCC "uncompressed" keys
(0xFF either way). The result equals the draw followed by the eliminate
pass. An all-expanded CMASK changes nothing; a mixed one throws, as do
fast clears of DCC, mipmapped, 3D and array targets.

PPSA14632 (LEGO Horizon Adventures) fast-clears its two 3840x2160
display buffers through CMASK, so its final composite draw was dropped
on every frame and only black was presented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:58:31 +02:00
Adrià 058dead176
Merge pull request #1058 from Celegans12/feat/agc-r8-srgb-color-target
feat(agc): implement 8 srgb color targets through rgba8 srgb proxies
2026-10-08 07:52:45 +02:00
Dean 5afffae1e0
Merge pull request #1235 from CnRJay/fix/agc-host-import-remapped-range
fix(agc): retire host imports of ranges mapped again
2026-10-08 15:17:35 +13:00
TibixDev f2fe3f7165 fix(agc): reject depth maintenance before shader compilation 2026-10-08 03:39:05 +03:00