Repository navigation
fix(shader): keep a shader's selected image-table records within the image and pair limits - #7527
Merged
oneandonlydean merged 3 commits intoOct 18, 2026
Conversation
…image and pair limits Since boykopovar#6243, each read whose record offset the CPU evaluates gets its own selected table column, so a shader that reads one heap at many such keys plans one image per key. Past 64 keys that is refused with "image resource limit exceeded", or with "sampled image/sampler pair limit exceeded" when each read is sampled twice, where the shader planned within both limits before. After planning the table columns, the tracker now estimates the images and sampled pairs that collecting the program would add, keyed as AddImage and AddSampledPair key them, from the planned column sources and the direct handles. If either is over its limit, it plans again with the columns of one heap unselected, the heap with the most selected columns first, until both fit or no heap is left. Those reads then share one keyed column, as before boykopovar#6243: the union of their key domains and the largest key. A shader within both limits plans exactly as before, from one planning pass. The estimate counts images exactly. A direct sampler is told apart by its handle's words and whether the sample adjusts, before the canonicalization collecting it applies, so the pair count can only be too high and errs toward merging.
…mage and pair limits
…ge limit The selected-records limit tests only read through image tables, so nothing showed that the estimate counts direct images and samplers too. TableManyKeyCode can now also load T#s straight from the SRT and sample them, with the same samplers as the table reads and optionally a third sampler on the last one. agc_shader_selected_records_direct_image_limit: - 63 selected reads and 1 direct image, 64 images: the per-key split is kept (63 selected tables and the direct image). - 63 selected reads and 2 direct images, 65 images: over the limit only because of the direct images. Heap A's reads merge into one unselected table beside the 2 direct images (3 images, 3 pairs), and keys 2, 33 and 64 still bind their records. agc_shader_selected_records_direct_pair_limit: - 31 selected reads and 1 direct image, each with 2 samplers, 64 pairs: the split is kept. - The same with a third sampler on the direct image, 65 pairs: over the pair limit only because of the direct sampler. The reads merge into one table (2 images, 5 pairs), and keys 2, 17 and 32 still bind. With ResourceTracker.cpp as on main 9caecfd, the over-limit cases fail with "image resource limit exceeded" and "sampled image/sampler pair limit exceeded", and the cases within the limits pass.
|
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.
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.
|
adriadam10
pushed a commit
that referenced
this pull request
Oct 19, 2026
#7527's selected-record limit test reads a record's descriptor words through the table snapshot's shared words list; this branch keeps a snapshot's words per column, so the test reads them from its column instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A regression from our #6243. On
main1c523bd, Death Stranding 2: On the Beach (PPSA02015) gets five pixel shaders refused atResolveShaderAbi, before the first frames of its pre-logo scene (TripyFox's A/B):0xc280a65500: "sampled image/sampler pair limit exceeded";0xc280a9e900,0xc282a85000,0xc282ab9f00and0xc282ad0b00: "image resource limit exceeded".TripyFox's build logs a refused shader instead of aborting; plain
mainaborts the guest thread there. With #6243's merge (0e94c5d) reverted, a cold run went past that point and refused nothing. Their replay of the five registration requests gives, without #6243, 2 or 3 images (1 or 2 through image tables, 1 direct), 4-6 samplers and 5-7 pairs. With it, every one stops at 64 images and 64 pairs, all of them sampled only.How it happens (
main9caecfd):TryMakeTableColumn(ResourceTracker.cpp) setsselectedand interns aselectionfrom that read's own offset, andTableColumn::operator==(ControlFlowInfo.hpp) compares both.InternSourcededupes sources by their column, so N reads of one heap at N such keys become N column sources, wheremainbefore perf(shader): select the record of a T# whose offset the CPU evaluates #6243 had one.Collectadds an image for each, andAssignTablesa table. Past 64 images,AddImagerefuses with "image resource limit exceeded"; past 64 image/sampler pairs,AddSampledPairrefuses with "sampled image/sampler pair limit exceeded".The change: #6243's split stays where it fits. Its own tests require two keys of one heap to plan as two one-record tables.
PlanTableColumnsnow estimates the images and sampled pairs the program would add, direct images and samplers included, keyed the wayAddImageandAddSampledPairkey them.mainbefore perf(shader): select the record of a T# whose offset the CPU evaluates #6243 wouldn't have had.AddImage's image key is factored out (ImageKey,SameImageKey), so the estimate andCollectkey images the same way.ARCHITECTURE.mdand theshaderdebt entry say so.What stays as it is:
ShaderDiskCache::StorePlanruns only afterResourceProgramreturns, and the failure memo is per process.Related: #5424 (Death Stranding 2: On the Beach bring-up; the A/B, the replay and the refused shader list are TripyFox's).
Tested
ResourceTracker.cppas onmain. With the fix, they pass 10 of 10, along with the otheragc_shader_memory_testsctests andagc_driver_image_table, which skips on Windows (no Vulkan device).precise_waitfailed once in the suite run with the fix and passed withmain's code. It's a timing test that doesn't link the recompiler, and an earlier run of the first two commits failed it on both sides.check_skipsexpects on a runner with no Vulkan driver or display.main9caecfd. The only differences are the fix's two tests, absent onmainand passing here. The 5 failures on both are that machine's IPv6 tests. The third commit only adds two moreagc_shader_memory_testscases (see Repeats).mainand this branch plan and emit identically.tests/ShaderMemory.cpp. The shader samples a heap of 128 distinct T#s, each read keyed from its own SRT word, and optionally T#s loaded straight from the SRT (direct images):agc_shader_selected_records_image_limit:agc_shader_selected_records_pair_limit: 32 reads with 2 samplers keep 32 tables and 64 pairs. 33 reads plan as one table and 2 pairs.agc_shader_selected_records_direct_image_limit: 63 reads and 1 direct image (64 images) keep the split: 63 selected tables beside the direct image. With 2 direct images (65 images, over the limit only because of them), the 63 reads share one table: 3 images and 3 pairs, in which keys 2, 33 and 64 bind their T#s.agc_shader_selected_records_direct_pair_limit: 31 reads and 1 direct image, each with 2 samplers (64 pairs), keep the split. A third sampler on the direct image (65 pairs) makes the reads share one table: 2 images and 5 pairs, in which keys 2, 17 and 32 bind.ResourceTracker.cppas onmain, the four tests fail, the image ones with "image resource limit exceeded" and the pair ones with "sampled image/sampler pair limit exceeded". The direct tests' cases within the limits pass there too, as boundary cases should; they fail at their case over the limit.agc_shader_memory_testsctests andagc_driver_image_tablepass 10 of 10.Checklist
main9caecfd, and merges cleanly with 9b68377; no other open PR implements the same functions. Overlaps (git merge-tree, each PR merged ontomain9b68377 first):image.volumeArraySampleCompatible = true;toAddImage's new-image branch, which this PR rebuilds aroundImageKey. Whichever merges second keeps that line aftersingleMipPlaneBiasCompatibleand drops theimage.source = source;next to it, sinceImageKeynow sets the source. The flag isn't part of the image key, and fix(shader): sample a 3D T# through DIM 2D_ARRAY as a volume #7381's other hunk, inMerge, merges cleanly.docs/dev/debt/shader.mdright after the image-table bullet this PR edits; whichever merges second keeps this PR's edited bullet and feat(recompiler): support waterfall select conditions and key bounds in pointer image tables #7388's new one.tests/ShaderMemory.cppand feat(shader): read samplers through nested and pointer-keyed descriptor tables #7395 (ours)docs/dev/debt/shader.md: textual only.ResourceTracker.cpp, for nested tables, pointer chains and waterfall loops. None of them changes the selected-record split orAddImage's image key.NotImplemented_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)