Repository navigation
fix(shader): index a pointer-loaded V#'s T# array by a word read from the same buffer - #9969
EagleBearerYS wants to merge 36 commits into
Conversation
…mers A T# read from a nested child table stayed a runtime read when one of its words also fed another instruction. That read goes through a V# that exists only in the snapshot, so the dispatch read a garbage address; lavapipe crashed in the shader. The nested branch now refuses a child whose descriptor words are used by anything but equal handles, as it already does for a V# with another consumer. (cherry picked from commit 0df7d32)
An S# read from a V# that a scalar record selects through a pointer was refused, so recompiling failed with "GetSamplerResource dword 0 is not a valid runtime value". The nested branch now takes sampler columns: they get child tables per distinct V# like nested T#s, share equal children, count against the nested key budget and the S# entry budget, and fault on an unmapped, non-buffer or uncaptured parent. The plan decoder accepts a nested sampler column; the plan encoding is unchanged.
An S# or T# loaded through a pointer that a scalar record holds was refused when a Phi merged the pointer's low word with constants, so recompiling failed with "GetSamplerResource dword 0 is not a valid runtime value". Such a column is now pointer-keyed: the snapshot captures every record's pointer and the descriptor behind it, the map holds boykopovar#7223's sorted pointer dictionary with descriptor records as its codes, and the GPU looks up the actual 64-bit pointer. A pointer that was not captured faults as outside the snapshot, and a null one as unmapped. The plan gains TableColumn::pointerKeyed and the snapshot gains ImageTableColumnSnapshot::pointerKeyed, so the disk-cache format moves to 43 and the image-table ABI to 4.
A T# loaded through a record pointer whose low word passes nested Phis was refused when one Phi arm held a word of a Ballot lane mask, as in a waterfall loop that reuses the pointer's SGPR for an s_and_saveexec or v_cmp mask, so recompiling failed with "GetImageResource dword 0 is not a valid runtime value". A pointer-keyed column now accepts such a word as an arm that is not a record pointer, as it does for constants, and still refuses any other foreign arm. At run time a pointer built from a lane mask is not a captured pointer and faults as outside the snapshot. A pointer-keyed column also accepts low-word reads, and a high-word read, of the same record word under different keys: same table, record offset, stride and addend. The GPU looks the pointer up by its value, so the key does not matter there. The column takes its table and record offset from the high-word read, which dominates the descriptor load. A shader that planned before plans the same way, so the disk-cache format stays at 43.
…ed record pointer A T# loaded through a record pointer was still refused with "GetImageResource dword 0 is not a valid runtime value" when the pointer's low word passed ANDs with lane masks, as a waterfall loop that copies EXEC into the pointer's SGPR builds them, or when its high word was a Phi of the record's high word read under several keys. For a pointer-keyed column, the walk of the low word now takes an AND with a lane-mask operand (a Ballot word, or an AND or Phi of only Ballot words and immediates) and keeps walking its other operand, so its record reads must still match the column and anything else still refuses. The high word is walked the same way: its record reads must be the record word at the low word's offset plus 4. A high word that is one read still gives the column its table and record offset, as before. Otherwise the table comes from a record read whose V# words are defined before the descriptor load, and the record offset from the high word, which the GPU does not read for a pointer-keyed column. A high-word arm read from another buffer, such as one whose V# is loaded through a pointer, stays refused. A shader that planned before plans the same way, so the disk-cache format does not change.
… a pointer-keyed record pointer A T# loaded through a record pointer was still refused with "GetImageResource dword 0 is not a valid runtime value" when a Phi of the pointer's low word merged the record read, a zero, and the waterfall's lane mask with the handled lane's bit cleared, BitwiseAnd32(CompositeExtractU32x4(Ballot(...), 0), BitwiseNot32(ShiftLeftLogical32(1, index))), as s_ff1, s_lshl and s_not with s_and, or s_andn2, build it in the SGPR the pointer reuses. The walk took only Ballot words and ANDs of them as lane masks, so it walked into the NOT and refused. A lane-mask operand is now a Ballot word or the loop's lane bit, a shift of 1 by an index from FindILsb32, FindUMsb32 or ReadFirstLane (through the AND, add, subtract and select that s_ff1_i32_b64, s_bitset0 and the shift's own mask put around it), or an AND, OR, NOT or Phi of only those and immediates. An arm of the pointer that is entirely such an operand is skipped. An AND with a record read in it still has the read matched against the column, and anything else still refuses. agc_driver_pointer_phi_lane_not_table builds that shape in a wave64 waterfall: the low word's Phis merge the record read at +0, a zero and the lane mask without the handled lane's bit, cleared by s_not and s_and and by s_andn2, and the high word is one read at +4. Each lane samples the T# of its record, and every masked word faults outside the snapshot. agc_driver_pointer_vsharp_select_table reads a record keyed by ReadFirstLane(SelectU32(LogicalAnd, IAdd32, Phi)), a pointer from it, a V# through the pointer and the T# through the V#; it passes without this change and keeps that chain checked, including a record pointer moved to the other V# without a recompile. Shaders that planned before plan the same way, and a refusal is never cached, so the disk-cache format does not change.
…keyed records A pointer-keyed record pointer now also takes lane-mask ANDs, the waterfall loop's lane bit and its OR and NOT forms, and a high word merged from the record's next word. A high word read from a second buffer stays refused.
The low and high words of a pointer-keyed record pointer were walked separately, so a high-word arm on a path whose low word is a lane mask refused the plan even though that pair is no pointer. Ratchet & Clank: Rift Apart (PPSA01474) stops this way at LoadAddressU32@pc=0x9a30: one high-word arm reads a second buffer, and on that edge the low word is a lane mask, the waterfall loop reusing the SGPR pair. Walk the two words together. Where both are Phis of one block, each low-word edge takes the high word of the same predecessor. An edge whose low word is a constant or a lane mask is skipped with its high word. A record low word still needs every high word it can meet to be a constant, a lane mask or the same record column at offset + 4, so a second-buffer high word paired with the record word stays refused. agc_driver_pointer_phi_high_second_lane_table adds the lane-mask low word to the second-buffer arm: it plans, each group samples the T# its record selects, and that arm faults outside the snapshot.
…nter The two words of the pointer are now walked edge by edge, and an edge whose low word is a constant or a lane mask is skipped with its high word. A high word read from a second buffer stays refused on an edge whose low word is the record word.
Brings boykopovar#8991 (match image-table T# halves offset before and after readfirstlane). ResourceTracker.cpp: main's FirstLaneOffset, ParseFirstLaneOffset and SameFirstLaneOffset go before TryMakeTableColumn, which keeps this branch's signature with the buffer parameter. Main's first-lane base check in the column loop merged on its own.
…ane-masks Brings boykopovar#7395's merge of main bd4d801, with boykopovar#8991. It merged without conflicts.
TryMakeIndirectColumn refused every pointer hop once the record's pointer words were merged, so a T# read through a pointer loaded from a pointer-keyed record pointer stayed unplanned (Gran Turismo 7's World Map compute shaders, issue boykopovar#6191). Only buffer handles still refuse hops: the materializer keys the records by the innermost pointer before it follows the hops, and the plan's parent pointer is that innermost one.
…one-key child From hugodearaujo's change on boykopovar#8939 (Marvel's Spider-Man 2, PPSA03016).
Spider-Man 2's shape: a record keyed by a first-lane read, its dwords 2-3 a pointer, a V# loaded at that pointer plus 0xa0, and the T# read at offset 0 or 0x40 of that V#'s buffer with no second key. Two records point at V#s of different T#s; a moved record pointer and a moved V# must change the result without recompiling.
…andles as nested children Marvel's Spider-Man 2 (PPSA03016) stops at 131 s on boykopovar#9457 in a compute shader whose record pointer, at dwords 2-3 of a waterfall-keyed record with its low word merged by a Phi with a constant, leads to a V# that two GetBufferResource handles read: a T# at offset 0 and a T# at 0x4c0, each sampled. The nested branch of TryMakeTableColumn refused the first T# because the V#'s words also fed the second handle, whose reads belong to the other T#. A parent V# whose word reads feed several GetBufferResource handles is now accepted when every other handle has the same words and its uses are only reads whose users are T# or S# descriptor handles. Each descriptor plans its child column from its own handle; both walks reach the same reads, so the parent interns to one source, the materializer reads its records once (NestedColumn takes them from Column()), and each child keeps its own offset. A handle with any other use still refuses, and a sibling descriptor that cannot be planned still refuses the shader, as its words are not runtime values. T# or S# words that have other users stay refused. Planning keeps those reads in the program: PlanTableColumnPass marks a read planning-only only when every user is a planned handle (ResourceTracker.cpp:1770-1781). But they read through the V# handle, whose arguments Run() replaces with the column offset and the parent pointer words (:154-160), and whose own word loads become planning-only once every handle over them is planned, so LoadAddress emits nothing for them (SpirvMemoryInstructions.cpp:599-601). The kept read would address a V# that only the snapshot holds. Allowing those uses in this shape, where the second T#'s dwords 0 and 1 reach the pointer registers on one edge before a later s_load, crashes lavapipe in the dispatch. Taking it needs that V# kept alive for those reads: an unrewritten copy of the handle and real loads of its words through the record pointer. Shape from hugodearaujo's IR on boykopovar#8939 (issuecomment-6340144242).
…d other instructions Marvel's Spider-Man 2 (PPSA03016) still stops at pc 0x8fa0 with the shared-V# planning alone: its shader moves dwords 0 and 1 of the second T# read through the pointer-loaded V# into the record pointer's registers, so those reads have Phi users. The nested branch of TryMakeTableColumn refused that T#, and the first T# with it, because the sibling handle's reads were not only descriptor words. d132754 added the refusal after such a read crashed lavapipe: the read stayed in the program but went through the V# handle that Run() rewrites to the column offset and parent pointer words, while the V#'s own word loads became planning-only and were not emitted, so it read a garbage address. A planned nested child's T# or S# read with other users now goes through an unrewritten copy of the V# GetBufferResource. PlanTableColumnPass keeps a read real while any planned handle using it has a use that stays real, so the V#'s four loads through the record pointer are emitted for the copy, and the descriptor handles still take the snapshot. No kept read goes through a rewritten handle, so the other users read the guest's V# and descriptor words at dispatch. The copy needs the V#'s words to be loads through the record pointer that the program emits. Any other V#, and a data read through a handle on the V#'s words, remain refused. The shared-V# reuse test now checks both T#s per group and the word the later s_load reads behind T#2's dwords 0 and 1, which the test backs with a snapshot at that address. The T# and S# consumer cases that d132754 refused now check the real descriptor word. A data read through a third handle and a T# consumer whose V# comes from a keyed table record stay refused. Shape from hugodearaujo's IR on boykopovar#8939 (issuecomment-6340144242).
… the same buffer Marvel's Spider-Man 2 (PPSA03016) on boykopovar#9790 stops at 135 s in compute 0x11e2b40f00 at ReadConstBuffer@pc=0x9a50, a T# read through a pointer-loaded V# at (word >> 16) * 32, where the word is a data read through the same V#, next to an S# read through that V#. hugodearaujo's run: boykopovar#9790 (comment) On boykopovar#9790 the T# plans as a nested child with an unkeyed domain, but the S# is refused: the key read's handle shares the V#'s words with the S#'s handle, and DescriptorWordReads takes only descriptor words, so the S# falls to GetHandle and its dword 0 is not a valid runtime value. A sibling read is now taken as a child key word when it is a scalar read at an immediate offset through a rereadable V# and its uses only reach the offsets of T# or S# reads through the same V#, as scale * ((word >> s) & m) + c. The key read keeps its handle and the V#'s loads, so the dispatch reads the guest's word. The T# or S# column gets a child key domain (offset, shift, mask): the snapshot reads that word from each child buffer and maps only the entry it selects. possibleU32Bits follows a right shift by a constant, so the child table spans at most min(num_records / stride, the key's range), 65,536 entries for a 16-bit field. A key the dispatch reads differently from the snapshot faults outside the key domain, and a key past num_records reads a null T#, as s_buffer_load_dwordx8 does past num_records. A store through a handle on the V#'s words, keys from two words or from a word at a runtime offset, and other data reads through the V# stay refused. KeyDomain gains child, shift and mask, so the shader disk cache format moves to 50. The test reads a key word at 0x14 and an S# at 0x20 of each child buffer and checks keys 2, 5, 17, 30 and 47 (the last of the V#'s 48 T#s), both S#s, a moved record pointer, null T#s for keys 48 and 65535, a fault for a key the dispatch reads differently from the snapshot, and the refusals above. This does not make the title pass: the same IR also merges the 0x4c0 T#'s dwords 0 and 1 into the record pointer, which stays refused here.
…ed V#'s record pointer In hugodearaujo's IR for Marvel's Spider-Man 2 (PPSA03016), compute 0x11e2b40f00 reloads the V# at pc 0x9a3c through a record pointer whose two words are Phis: record dwords 2 and 3 on most edges, and dwords 0 and 1 of the T# read at 0x4c0 through the same V# on the edge from $353. boykopovar#9790 (comment) The T# read at ReadConstBuffer@pc=0x9a50 through that V# is refused with "GetImageResource dword 0 is not a valid runtime value", whatever its offset: TryMakeIndirectColumn walked a merged V# pointer with PointerRecordReads, which takes only the record read and constants on the low word, and it needed the high word to be the record read itself. A merged V# pointer now goes through PointerRecordPairs, the edge-paired walk that a pointer-keyed T# already uses, and a word read as part of a T# or S# is a pointer-free arm there, like a constant or a lane mask. The child is looked up by the actual 64-bit pointer, so that arm, which the snapshot never captures, faults outside the snapshot when a lane takes it instead of reading a T#. The record reads on every edge must still be one read per word for a V#. The test samples the T# at 0x4c0, moves its dwords 0 and 1 into the record pointer under a condition, reloads the V# behind that Phi, and reads the key word, the T# at the key and the S# through it, as the IR does. It checks the three reads per lane with the arm not taken, and a group that takes the arm faulting outside the snapshot. That last run replaces the key read with a constant: a data read through a V# loaded from an unmapped pointer crashes lavapipe on boykopovar#9790 as well, as its shared-V# reuse shader does with an unmapped record pointer. On boykopovar#9790, and with the previous commit alone, the test is refused with the text above. This does not claim the title passes.
|
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.
|
|
One integration point to coordinate before merge: this branch is based on #9790’s cache version 46 and advances it to 50, while open #10000 independently advances current main from 44 to 49. The changes can be sequenced, but the cache format number must remain monotonic and unique after rebasing the later branch (if #10000 lands first, #9790 and this stack need cumulative version bumps; if this stack lands first, #10000 must bump beyond 50). Please include #10000 in the version-order plan and validate the resulting format number against the merged base. This is sequencing feedback, not a request to close or drop either PR. |
MarcZX10
left a comment
There was a problem hiding this comment.
I found a cache-budget accounting gap in the new nested snapshot path. NestedColumn copies the parent descriptor readRanges and appends a range for each distinct child buffer; the indirect-buffer path also records a descriptor range per captured pointer. CopyRecords retains those ranges in ImageTableColumnSnapshot, and ResolutionMemoEntry stores the table snapshots. However, resolutionFootprint() counts map words, codes, descriptor words, and pointer words, but not table.readRanges.
These are 16-byte pairs, so omitting them undercounts by four 32-bit words per range. With up to 524,288 parent keys and up to 524,288 child buffers, the retained ranges can add roughly 16 MiB to an entry beyond the ResolutionMemoWords estimate. The LRU can therefore retain more than its declared 8M-word budget, especially across its four variants per shader. Please either include retained read-range storage in the footprint (and add a boundary regression) or avoid retaining ranges in resolution memo entries if they are not part of the cache key/result. This is a memory-bound issue introduced by the new nested-table path, not a queue-size concern.
I also checked pointer-map construction/search ordering, nested-key limits, decode validation, snapshot hashing, cache serialization and the SPIR-V lower-bound lookup; I found no additional confirmed issue. Current-main diff and conventions checks pass. Hosted eligibility, intake, conventions, labels and report pass, while native product jobs are skipped. I could not run the image-table runtime tests locally because this workspace has no matching build/test executable; the PR's reported Linux/Windows and validation-layer results remain author-reported.
|
@MarcZX10 Thanks, the order is already set so that either one can land first. #10000 moves
Both PRs' Depends on and Overlap lines will say this. The |
Keeps this branch's FormatVersion above main's 45 (boykopovar#7831's barycentric bump).
…ution memo footprint ImageTableColumnSnapshot keeps its read ranges, four words each, and ColumnRecords::Footprint already counts them. resolutionFootprint did not, so a resolution memo entry could hold more than ResolutionMemoWords. Count them for the tables and the nested tables. The plan round trip now resolves a nested fixture's snapshot twice with 2^21 read ranges on a table, then on a nested table: four words each fill the memo budget, so the entry must not be kept.
|
Windows run on NVIDIA and Intel. Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0 r7, Release. NVIDIA GeForce RTX 3060 Ti (driver 617.42) and Intel Arc Graphics (Meteor Lake, Xe-LPG, driver 101.9150), selected with Tests: the 1260 that
The two new tests that fail on Intel Arc are the sampler ones from #7395's commits:
These are the same two lines as on the UHD 770 with ANV in #7395, which Capmare traced to Gfx12 EU fusion (Mesa issue 16622, fixed in Mesa 25.3). Intel's Windows driver shows it too; details on #7395. Nothing else in this PR differs from AI-assisted: yes (Claude Code) |
|
Thanks, @BKlaasWerkman, a per-test comparison with |
|
@BKlaasWerkman thanks for both runs. One small follow-up on the two Intel Arc failures, if you have a minute: could you rerun just those two on the same build and GPU, with On ANV that switch made both pass (Capmare's runs on #7395), so the result tells us whether Intel's Windows driver fails for the same reason. |
|
@EagleBearerYS rerun done on this PR's build: head d01f290 merged into
The switch removes both failures, as it did on ANV. #7395 merged alone into the same AI-assisted: yes (Claude Code) |
adriadam10
left a comment
There was a problem hiding this comment.
Not mergeable as is, and nothing in this PR is blocking by itself:
- The branch conflicts with
main, and so does the root of the stack it sits on (#7223,ResourceTracker.cpp/TryMakeIndirectColumnafter #7880; see oneandonlydean's comment there). The resolution of the two dword reads inTryMakeIndirectColumnis a logic call that has to be settled on #7223 first. - Stacked on #7223, #7395, #8939, #9457, #9633, #9749 and #9790, none merged. Please move the chain onto
mainonce #7223 is resolved, as you said on #7395, and re-request review; the two fix commits and theresolutionFootprintread-range term (d01f290, answers MarcZX10's review) look consistent from the diff. - When rebasing, keep
FormatVersionabovemainand #10000's, as planned. - No new evidence needed on tests: CI on this head only ran Conventions/relinker, the full Build runs when it enters the merge queue.
What
With #9790, Marvel's Spider-Man 2 (PPSA03016) gets past
ReadConstBuffer@pc=0x8fa0. It then stops at 135 s, later in the same compute shader (hugodearaujo's run, RX 9070 XT, RADV):The shape (his IR, block $398):
(word >> 16) * 32is thes_buffer_load_dwordx8offset at 0x9a50.Two refusals, one per commit, both on #9790's head:
fix(shader): index a pointer-loaded V#'s T# array by a word read from the same buffer.TryMakeTableColumn's nested branch,DescriptorWordReads).stride * key + addend, withkeyone of(word >> s) & m,(word & m) >> s,word >> s,word & morword.sandmare constants, and the stride is a constant multiple of 4.num_recordsas the hardware load returns, and maps only that record and key 0. If the word's page is unmapped or has a pending write, it maps the whole child, as other key domains do.min(num_records / stride, maxKey + 1)records, so at most 65,536 for a 16-bit field, within feat(shader): resolve nested image tables through runtime pointers #7223's caps.num_recordsreads a null T#, as the load does.fix(shader): take a T#'s words as an uncaptured arm of a pointer-loaded V#'s record pointer. This is the game's own text.TryMakeIndirectColumn/PointerRecordReads).PointerRecordPairs, the edge-paired walk that pointer-keyed T#s already use. Its new arm kind skips a T# or S# word like a constant.Not claimed: hugodearaujo's dump predates #9907, so it prints every scalar load's immediate as
0x0. The real offsets of the key word and the S# aren't known, and the tests use nonzero ones.Cost:
min(num_records / 32, 65536)T#s.FormatVersion46→50:KeyDomaingains three fields.fix(shader): count an image-table snapshot's read ranges in the resolution memo footprint(d01f290):resolutionFootprintnow adds 4 words per read range (readRanges) of each table and nested table, asColumnRecords::Footprint()does, so a resolution whose read ranges exceed the memo budget isn't memoized.main'sresolutionFootprintleaves out the same term.Tested
agc_driver_pointer_vsharp_child_key_table(new,tests/execution/ImageTable.cpp), commit 1's shape: a record pointer merged by a Phi, a key word at 0x14, the T# at(word >> 16) * 32, an S# at 0x20, then a sample.agc_driver_pointer_vsharp_child_key_arm_table(new), commit 2's shape: it samples the +0x4c0 T#, moves its dwords 0/1 into the record pointer under a condition, reloads the V#, then reads the key word, the T# and the S#.APS5_SKIP_TIMING_TESTS=1.agc_driver_pointer_vsharp_shared_table,…_shared_reuse_tableandagc_driver_nested_image_table.VUID-VkDeviceCreateInfo-pNext-pNext, so the change adds noVUID-message.ctest -R 'image_table|pointer|nested|table|sampler'passes 47/47, including fix(shader): plan several T#s read through one pointer-loaded V#, keeping the V# real for their other uses #9790's, fix(shader): follow pointer hops and fixed-offset V# reads behind a record pointer #9457's and feat(shader): resolve nested image tables through runtime pointers #7223's nested-table tests and fix(shader): plan several T#s read through one pointer-loaded V#, keeping the V# real for their other uses #9790's "data read through a third handle" control.GALLIUM_OVERRIDE_CPU_CAPS=avx.agc_shader_disk_cacheresolves a materialized fixture snapshot twice, then with 2^21 read ranges on a table and on a nested table, exactly the memo's 8M-word budget: memoized without them, not shared with them.agc_shader_disk_cacheand_large_file) pass 10 runs in a row; on Windows, 4 of 4 (with_host_stderrand_long_paths); none skipped or failed. The libc and libkernel suites pass on both, run withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.main938812d (clean), Windows 11 Pro, WinLibs GCC 15.2.0, Release,ANYPS5_NO_SHADER_CACHE=1, with the Khronos validation layer (1.4.363) loaded. The 1,260 teststools/select_tests.pypicks for the PR's files, compared test by test with a full run of thatmainon the same GPU:main(theagc_driver_sample_ordertrio, test(agc): read the sample order tests' depth through a sampled copy #9056). The stack's 20 new nested and pointer tests pass. No newVUID-message.maintoo (AGC (Intel Arc, Windows): agc_storage_write_back fails; buffer-image copies of larger RGBA16F images canonicalize fp16 NaNs #10126, test(agc): skip the MSAA retirement storage promotion without shaderStorageImageMultisample #8604 and AGC (Intel Arc, Windows): agc_driver_alias_copy_label fails about 1 in 3 runs; the label lands before the alias copy's destination store, APS5_STORE_AT_LABEL=1 hides it #10199's intermittent one). The other two are feat(shader): read samplers through nested and pointer-keyed descriptor tables #7395's sampler tests,agc_driver_nested_sampler_tableandagc_driver_pointer_phi_sampler_table, with the lines they fail with on Intel's Linux driver, where the cause is Gfx12 EU fusion (Mesa issue 16622, fixed in Mesa 25.3). @BKlaasWerkman's rerun on the same Intel Arc, of this head (d01f290) merged intomain938812d (comment), and feat(shader): read samplers through nested and pointer-keyed descriptor tables #7395 alone merged into the samemain(comment): both tests fail 3 of 3 by default and pass 3 of 3 withAPS5_SPANNED_WAVE=1, which spans the program over two full 32-lane subgroups. That switch made both pass on ANV too (comment), so this points to the same cause as there. Xe-LPG is Gfx12 as well. Mesa 25.3's fix doesn't reach Intel's Windows driver (101.9150). No newVUID-message.check_conventions.py: passes. No comment lines are added.test/sm2-9790-child-key(ac5f6f8) carries this PR's two commits unchanged on his test branch. With it, Marvel's Spider-Man 2 gets pastReadConstBuffer@pc=0x9a50and runs to 133 s. It then stops on an S# read at 0x9a9c through the V# loaded at 0x9a20, the load that also gives the key word:compute shader 0x11e2b31800: GetSamplerResource dword 0 is not a valid runtime value. This PR doesn't plan that shape; it's for a later change. The branch builds on GitHub's Linux and Windows runners, and its tests pass on Linux (run).main0db47b2. The only conflict wasShaderDiskCache.hpp'sFormatVersionline:mainmoved to 45 (fix(shader): normalize offset perspective barycentrics after interpolation #7831), and this branch keeps its 50. On GitHub's runners (run), the pointer, nested, image-table and disk-cache sets (29 tests) pass 10 runs in a row on Linux. On Windows the set has 31, with two Windows-only disk-cache tests: they build, 5 pass 10 runs in a row, and the other 26, which need a Vulkan device, skip. The libc and libkernel suites pass on both, run withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners. An earlier run linked here didn't run this set, so it's replaced.A limit found on the way, not fixed here: on llvmpipe, a read through a V# whose words come from an unmapped record pointer crashes instead of reporting the fault. llvmpipe does this for any scalar BDA load that misses, and the files that emit those loads are
main's, unchanged by #9790 and by this PR. #9790's limits describe it, with its unmapped-pointer probe faulting through the image table on an NVIDIA GPU instead.Overlap:
FormatVersion: feat(shader): raise the sampler and sampled-pair limits past the 32-bit sampler masks #10000 moves it to 49 and this stack to 50. If feat(shader): raise the sampler and sampled-pair limits past the 32-bit sampler masks #10000 lands first, this stack keeps 50; if this stack lands first, feat(shader): raise the sampler and sampled-pair limits past the 32-bit sampler masks #10000 takes 51 when it mergesmain.PointerRecordPairs(…, chases, chaseDepth)arguments. Take both: call it with their chase arguments.KeyDomaincodec next to theirTableColumnchanges.FormatVersion(take the higher) and the debt lines.main: clean.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)ReadConstBuffer@pc=0x9a50after fix(shader): plan several T#s read through one pointer-loaded V#, keeping the V# real for their other uses #9790, as hugodearaujo's run shows; its next stop is an S# at 0x9a9c (see Tested)