Repository navigation
feat(agc): look up table images at run time through a device image table on the GPU heap (APS5_GPU_PATH) - #7642
EagleBearerYS wants to merge 174 commits into
Conversation
|
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.
|
|
Rebase handoff for the 82-commit GPU-path series — the full series is rebased onto
Verified on Linux (CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, To pick it up: |
|
@EagleBearerYS here's Astro's Playroom (PPSA01325) on this head (05502ba), Linux, RTX 5080 (driver 615.78.08), one run each into the first level with Cross pressed, and a 10 s trace window in the same gameplay scene. Both runs had With the switch on, the log has no The 12 captured frames of each run show the same intro and gameplay scene, with no black or missing textures in either. The trace window had 135 frames with the switch and 124 without. The GPU ran at P0 for most of both runs, median graphics clock 2812 MHz in each. That's one round each, and the two are within 10%, so I wouldn't read the gap as a speedup. |
|
@fma-rc Thanks for the Astro's Playroom (PPSA01325) run. No @blawesom Thanks for rebasing the series and for the notes. We won't take the rebased copy into this PR. It carries the 31 commits of Raghav314's #6947, which this draft is stacked on, and rebasing those is his call on his PR. This PR follows #6947 when it moves, with a merge of main of its own if needed. Your resolution notes (the finisher threading, |
… uploads agc_driver_sampled_cache_budget_heap_view set APS5_SYNC_TEXTURE_UPLOAD=1 so that its recovery check could free exactly one of two textures. With asynchronous uploads the active recorder keeps each texture's image until its batch completes, and a finished batch's kept objects are destroyed on the release thread only after the GpuMutex hold ends. The recovery, which counts bytes actually freed since boykopovar#10472, then freed nothing on the test's thread and evicted both textures. The check now syncs the active recorder before the recovery, and the test runs with APS5_RELEASE_UNDER_LOCK=1, so the synced batches' images are freed inside Sync(). Uploads stay asynchronous, the default path. Without the sync, or without the switch, the check fails as before.
In descriptor-heap mode the driver's internal passes recorded classic descriptor binds or push constants. Each one put the command buffer back in classic mode, so the next heap draw or dispatch bound the heaps again. Like vkd3d-proton's meta shaders, each pass now has a heap twin pipeline: the same SPIR-V with a null layout and the descriptor-heap flag, buffers mapped to pushed addresses, and images mapped to heap slots indexed from push data. The pass's push constants stay at push-data offset 0, with the addresses and slot indices after them. The classic pipeline is still used outside heap mode, and when no slot is free or the twin cannot be created. Passes: color transfer, multisample readback and upload, staged merge, depth to storage, first-sample copy (its sampler embedded in the mapping), sample order (storage and depth halves), and the detiler's buffer detile and repack. A buffer detile that the descriptor shader would run through its word path (elements under 4 bytes) keeps the addressed shader, which reads the same push layout: on RADV the word path costs 71 instructions against 40. Slot owners release their slots before they destroy the views; a staged write keeps the merge target that owns its slot. Tests: the sample order and multisample readback tests give their passes a slot owner and require, in heap mode, that recording a pass does not make the heaps bind again. The first-sample check now requires the same. The heap slot tests set APS5_HEAP_SLOT_CAP before opening the device, since the twins create the heap while it opens.
Since address-based draws became reusable over their cached space, PrepareDrawBindings gives them per-draw copies of guest memory: a snapshot of every read-only input on a build, and a copy of every read-only buffer that moved on a reused hit. Heap stages bind those copies through their ring descriptors, so a draw reads memory as the CPU saw it at record time instead of at execution, and Minecraft Dungeons II shows flickering shadows. Heap stages of an address draw now read guest memory in place, as the BDA table and the hardware do. No snapshot is taken, and a moved buffer is viewed at its new address through the build's own memory (GuestBufferMemory::TryDescriptor, a non-throwing Descriptor). A hit whose moved buffer the build's memory cannot view with the alignment offset the build baked into the shader data is built again. The heap variant of the address draw reuse test never built heap stages; --heap-stages compiles both stages for the heap and checks that a CPU write and a buffer moved inside the space are read in place, with no copies taken (DrawInputCopies), and that a move off the build's alignment is refused. Heap stages report no BDA fault per use, so that case is skipped there and listed in the debt file.
…ignature Descriptor-heap stages read their root (ring, pagetable, fault and GDS addresses, stencil reference, and each stage's data offset, SRT index, SRT size and table map) and their shader data (heap slot indices, image first elements, user data, memory offsets, image metadata) from push data, as vkd3d-proton maps a root signature and PS5 delivers user SGPRs. Like a root signature, a graphics pipeline gets one layout for all its stages: nothing is reserved; the driver packs only the root items its stages read and each stage's wanted shader-data dwords into the 64 push dwords (the pixel stage from the top, pre-rasterization stages from the bottom, the mesh, tessellation, depth-remap and compute words kept clear only when used, pushed data shared evenly when short) and passes the positions as specialization constants. A pixel stage that fits is placed as it is alone, so its fragment library stays shared. Shader data that does not fit stays in the ring. APS5_NO_HEAP_PUSHED_DATA reads all shader data from the ring.
The heap branch encodes new artifact (gpuResolvedImages, sampler slot and buffer address dwords, pushed data, push items, data-address push, BDA stores), invocation (heap slot words) and binding-layout fields (data address, slot and address dword counts, pushed data, heap storage images, GPU-resolved images), so its entries need their own format number above main's.
… device A nearly full GPU heap used to send every draw down the per-draw path until owners released slots. Like vkd3d-proton, which leaves descriptor lifetime to the heap's owner, the heap now frees the image slots no draw has used for two submissions. An evicted slot moves its generation, so templates holding it take fresh slots on their next draw, and it is handed out again only after the submission that followed the eviction completes. Draws that keep using a slot refresh it on every heap stage write. APS5_NO_HEAP_EVICTION turns it off. The image heap length is now the HeapImageSlots specialization constant instead of a constant in the module, the way vkd3d-proton sizes its heap arrays at pipeline creation. Pipelines set it to the device heap's slot count, which grows past the ABI's 233472 into resource heap space the shader data ring leaves unused, up to 524288 slots. Shader disk cache format 58. The 10 s [gpu-heap] line adds the slot count, evictions and their waits, and ring waits, the largest bytes one batch wrote into the ring and the largest span.
…ers them Review of the eviction found that the margin counted evicted slots before any submission had a serial for them, so a busy batch could drain the free list without refusing the heap and fail a draw with "the global image heap is full". The margin now counts only evicted slots a submission covers, eviction starts at twice the margin, scans at most once per submission, needs the recorder timeline, and reclaims once per submit instead of per taken slot. A blocking reclaim waits only on submitted serials, heap stages refresh their slots once per submission, and the validator checks the image table alias is an array before reading its length. The [gpu-heap] line adds ring MiB written per 10 s and image slots held.
A draw that reuses a ring span it wrote earlier reopens the span's chunk, so the chunk takes the serial of the newest batch, and when the ring came round to it later it waited for a batch the GPU had only just started: every ring wait in a MCD2 run was of that kind. Like vkd3d-proton, which takes another scratch buffer instead of waiting for one the GPU still reads, the ring now skips such a chunk. Only when every chunk is taken or busy does it wait, and then on the chunk whose batch is oldest. APS5_HEAP_RING_MIB sets the ring size between 4 and 64 MiB (default 64, less when it sits in a smaller resource heap). MCD2 writes up to ~10 MiB in one batch and stops with "one batch's shader data exceeds its ring" at 8 MiB, so the default stays as large as the heap allows.
Shader data, flattened SRT data and table maps lived in the descriptor ring inside the resource heap. A batch writing more than the ring held aborted the run, and the ring took heap room from images. They now go into a pool of 2 MiB blocks, the way vkd3d-proton's uniform upload pool works. A batch takes new blocks instead of waiting, a span larger than a block gets a block of its own, a block is reused once the GPU has finished the batches that read it, and idle blocks over 32 MiB are freed. Shaders read the data through 64-bit addresses pushed per draw (shader data, table map, addressed flattened SRT), so the shared ring address push item is gone; the push-data size stays about the same. The ring inside the heap now holds only per-draw buffer descriptors and defaults to 16 MiB. The shader cache format moves to 59.
…ptor ring A batch writing more per-draw buffer descriptors than the ring holds aborted the run. Before each draw and dispatch the recorder now submits once the open batch holds half the ring's chunks, and one draw may take at most a quarter of the ring, so a batch always fits.
SpirvBufferAccess.hpp: boykopovar#9508's five RootItem declarations plus boykopovar#7642's EmitAddressWordPointer; the old field-based root declarations go, as boykopovar#9508 drops them. SpirvBufferAccess.cpp: boykopovar#7642's EmitAddressWordPointer kept, followed by boykopovar#9508's RootItem EmitRootAddressWordPointer, EmitRootAddressReadOnlyWordPointer, EmitRootAddress and EmitStageRingWordPointer. ShaderDiskCache.hpp: FormatVersion 62 (boykopovar#7642). ShaderDiskCache.cpp: encode and decode take pushedData and pushItems, then deviceImageTables, after bufferAddressCount; sizes 328/288/712/424/256 and field counts ImageResource 51, SampledResourcePair 4, DeviceImageUse 4. PipelineSpecialization.hpp: MirrorUnnormalizedBase, MinLodBase and VolumeGatherBase from boykopovar#9508, then DeviceSamplerClassBase = 58368u. CacheKey.hpp: hostInterpolationFirst and shaderImageMinLod from boykopovar#9508, then deviceImageTables. IrMetadata/Resources.hpp: boykopovar#9508's MirrorsIfUnnormalized, then boykopovar#7642's NoSampler and DeviceImageUse. Recompiler.hpp: hostInterpolationFirst and shaderImageMinLod from boykopovar#9508, then deviceImageTables. Recompiler.cpp: materializeResult takes pushedData, pushItems and deviceImageTables; RecompileImpl builds each result as a value, sets deviceImagePlan when deviceImageTables, then returns make_shared<const> of it, keeping boykopovar#9508's CountedCompile. ResourceMaterializer.cpp: boykopovar#7642's !deviceTable guard on boykopovar#9508's new fill(fill, ..., tables.tables.at(...), Abi::TableHeader(...)) call. ShaderResources.cpp: boykopovar#9508's SampledLookupKeyProofs and DrawInputCopies, then boykopovar#7642's LookupDeviceTableTexture and DeviceTableTextureCurrent. tests/BindlessHeapSlots.cpp: boykopovar#9508's side, which already sets APS5_HEAP_SLOT_CAP before opening the device and adds the busy-chunk and large-span cases. tests/ShaderDiskCache.cpp: both comparisons and both setters, windowLaneGuards then the device image fields. tests/ShaderMemory.cpp: boykopovar#7642's device image table and trailer checks, then boykopovar#9508's verifyPointerTableUnwrittenReuse, and both dispatch entries.
…till reads them Prepare swept the table's slots and then waited in chunkFor for a free miss-ring chunk, and that wait can submit the open batch. boykopovar#9508's eviction at that submission retires slots the table never touched after taking them, so the next batch read a slot the heap had retired and could reuse through the uploaded table. Prepare now sweeps again and uploads after chunkFor, the last point at which it can submit, so the batch that reads the table never sees an entry whose slot moved. It also touches every live entry's slot once per heap epoch through a new Slots::touch, which the GPU heap maps to TouchSlots, so eviction no longer counts slots the table still serves as idle.
tests/ShaderMemory.cpp: the --device-image-tables and --table-trailer dispatch branches, then main's --registered-view-churn branch, each closed as its side had it. IrMetadata/Resources.hpp: NoSampler and DeviceImageUse, then main's AppliesLodBiasInShader; each is defined once. PipelineSpecialization.hpp: main's SamplerLodBiasBase = 57728u and SamplerLodBiasShaderThreshold = 15.0f, then DeviceSamplerClassBase = 58368u.
What
Shaders that load a T# from an image table at a key they compute (bindless tables, V#-addressed T# arrays) can only be bound today if the CPU snapshots and resolves every table record for every draw: the CPU table path. With large tables that's most of a draw's cost. On a Village-shaped lavapipe bench (a 32,768-record V# table, 256 textures, 850 indirect draws per frame), the CPU table path spends 14.7–16.5 ms per draw in
descriptorsalone, and runs out of memory within 30 s. Lavapipe's 256-byte descriptors make that larger than a GPU driver would, so the title measurement under Pending is the number that counts.With
APS5_GPU_HEAP=1 APS5_GPU_PATH=1, such a T# is looked up on the GPU instead.BindlessHeap::TextureSlot), and the shader samples through that slot.ExpectedDeviceImages) and inserts those keys first. A per-thread memo keeps that at about 4 µs per draw in steady state on the bench.BindlessHeap::TextureSlotand itsNearlyFullmargin as they are. The table takes no slot whileNearlyFullholds and reserves none. Each entry holds its texture, and eachPreparemarks the live entries' slots used in the heap's epoch (92c6dab397), so perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's idle-slot eviction doesn't take a slot the table serves. The table drops every key whoseSlotGenerationmoved, after the last point inPreparethat can submit and before it uploads.map[HeaderElementBase]in the heap table map, the bucket buffer's device address and the open batch's miss-ring chunk address. They're all zero when no device table is attached, so maps without a table behave as now.ImageTableAbi::Versiongoes 2 → 3, and every heap map carries the trailer, which adds 16 bytes per stage map. A column served by the device table writes no per-element slot parts. Raghav314 agreed to the trailer and the version bump (reply).APS5_GPU_PATH=1turns it on. WithoutAPS5_GPU_HEAP=1and a device withVK_EXT_descriptor_heap, it stays off and says why;APS5_NO_DEVICE_IMAGE_EXPECT=1leaves first uses to the miss ring;[device-images]lines underAPS5_PROFILE_DRAW=1.Credit:
wip/new-gpu-path.Pending
APS5_GPU_HEAP=1 APS5_GPU_PATH=1the Vulkan device was lost in 3 of 3 runs before the title menu stood. With neither switch, the menu stood in both runs.APS5_GPU_HEAP=1alone, and 1,096 with both. SoAPS5_GPU_PATHadds about 70 MB/min, within run-to-run spread. Both runs with both switches stopped at the 2.5 GB commit floor; the run withAPS5_GPU_HEAP=1alone reached menu + 12 min without stopping. A later run on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 5645b5b with two heap counters on top (counts) found the heap's holds flat from 2 minutes after the menu appeared: 1,907 slots, 1,490 textures (667 MiB) and 49 storage images (526 MiB), none held only by the heap. Memory still grew 1,149 MB/min. So the growth comes withAPS5_GPU_HEAP=1but isn't the heap's holds; its cause is pending a comparison of where the memory goes with the heap on and off.Limitations
VulkanDevice::Drawoutside the driver with device-table results isn't served, soagc_driver_image_table's graphics part fails with the switch on. Only tests and tools draw that way.agc_driver_bindless_imagesasserts CPU table behaviour, so it fails with the switch on./dev/udmabuf), a draw copies its V# table and rebuilds its resources every draw.Tested
NVIDIA GeForce RTX 3070 Laptop GPU at edc6108 (driver 617.42, Windows 11, WinLibs GCC 15.2.0, Release,
ANYPS5_REQUIRE_VULKAN=1; GPU clocks weren't held, pass/fail only). perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's heap is live there: every run logs "Vulkan descriptor heap: GPU-mode draws and dispatches bind from VK_EXT_descriptor_heap".agc_driver_device_image_table_heap, which checks that perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's sweep keeps the slots the table holds, andagc_driver_device_image_path_gpu_pathpass 5 runs in a row.agc_driver_device_image_table,agc_driver_device_image_pathandagc_driver_device_image_path_without_heappass 3.agc_driver_device_image_table_heapandagc_driver_device_image_tablepass 5 runs in a row.device.reset(), so its buffer pool freed memory on a destroyed device. The test now scopes that context, and the product code is unchanged.Linux (lavapipe, CI's flags), per commit: each of the 8 commits builds, registers with nothing new left unrun, and passes
ctest -R 'table_trailer|device_image'5 runs in a row. lavapipe has noVK_EXT_descriptor_heap, so the two GPU-heap tests skip 77 there with "the device lacks VK_EXT_descriptor_heap…".Eight reds, each with the code under test broken and the named test kept:
agc_shader_table_traileragc_shader_table_traileragc_driver_device_image_tableOwnWriteSerialdroppedagc_driver_device_image_tableagc_driver_device_image_tableagc_shader_device_image_tablesagc_shader_device_image_tablesAPS5_GPU_PATHAPS5_GPU_HEAPagc_driver_device_image_tableCI's Linux job, mirrored, on the head before the teardown fix (66b470c, which differs from this head only in that test): 1,919 of 1,930.
agc_driver_image_table_atomicstests.agc_driver_pipelined_fill_gpu_heap, a perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 test none of these commits touch, under the run's load. It passes 10 of 10 alone.check_skips.pyflags onlyguest_sce_net, as on every branch on that machine.agc_driver_pipelined_fill_gpu_heapunder load: a perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 test, run on cloud Linux machines with lavapipe, its ctest environment and 6 concurrent loops, at the rebase 9e843c1 on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 5547aa1.main) cherry-picked onto both trees, both pass 360 of 360. So it's a race in the test, which test(agc): share the pipelined fill blocker with its lambda and end each case on an empty pipeline #9697 fixes, and this PR doesn't change its rate.MinGW (
x86_64-w64-mingw32-g++-posix,-fsyntax-only -Wall -Wextra) on the 27 changed sources, against the same files at 23b2a3f: no new diagnostics.GitHub's runners at 67c1aea, this PR's 9 commits on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's head 5645b5b (run):
git range-diffagainst the previous head 4e3a10d shows 7 commits unchanged. Commit 1 takes perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508'sFormatVersion49 as its base and keeps perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's new slot sentence indocs/dev/ARCHITECTURE.mdwith this PR's trailer line. Commit 4 calls perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508'sSlotGeneration(slot), since its slots became one shared pool: in the table's heap slots and in its heap test, three lines.agc_driver_device_image_*tests,agc_device_image_keysand the shader tests built from the changed files, 10 runs in a row. Linux: 24 run, 22 pass, 2 skip (agc_driver_device_image_path_gpu_pathandagc_driver_device_image_table_heap, which needVK_EXT_descriptor_heap), 0 fail. Windows: 26 run, 21 pass, 5 skip (the fiveagc_driver_device_image_*tests; the runner has no Vulkan device), 0 fail.agc_driver_image_table_vouched_lookups). Commit 4 (run) on Linux 21 run, 20 pass, 1 skip, and on Windows 23 run, 20 pass, 3 skip. Commit 6 (run) on Linux 22 run, 21 pass, 1 skip, and on Windows 24 run, 21 pass, 3 skip. None failed. The skips are the GPU-heap test on Linux, and on Windows the Vulkan tests.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.Validation, perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 5645b5b against 67c1aea (CONTRIBUTING's AGC rule), on one GitHub Linux runner (run), with
VK_LAYER_KHRONOS_validation,ANYPS5_NO_SHADER_CACHE=1,ANYPS5_REQUIRE_VULKAN=1andctest -Von llvmpipe: the loader inserted the layer 2 times on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's tree and 9 times with this PR, neither log haswas not found, and both report onlyVUID-VkDeviceCreateInfo-pNext-pNext, so this PR adds noVUID-message.GitHub's runners at 594b346, this PR's 8 commits rebased onto perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's head 1b09774 (run):
mainand gained one commit, 1b09774 ("keep GPU heap pipelines in their own journal"). Its other 36 commits carry over: 34 unchanged, and 2 adjusted wheremainchanged the same pipeline-library lines.git range-diffagainst the previous head 0aaf2b9: 6 commits unchanged, and 2 whose only changes are context lines frommain. Those are aGuestMemory.cpphunk header, aftermainsplitMarkWritten, and an include line inResourceMaterializer.cpp. Against the rebase the load runs below used (9e843c1, on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 5547aa1), all 8 are unchanged.agc_driver_device_image_*tests,agc_device_image_keysand the shader tests built from the changed files pass 10 runs in a row on Linux, with the two GPU-heap tests skipping there. On Windows they build and pass, with 5 Vulkan tests skipping.guest_raise_in_system_callfailed in the job's first attempt, and the job's second attempt passed both suites (144, 208). That test also timed out twice onmain's own Windows Build today (run, run), and this PR changes nothing in libkernel.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.Validation, perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 against this head (CONTRIBUTING's AGC rule), on one GitHub Linux runner (run):
VK_LAYER_KHRONOS_validation,ANYPS5_NO_SHADER_CACHE=1,ANYPS5_REQUIRE_VULKAN=1andctest -V, on llvmpipe.agc_driver_image_table_vouched_lookupsand the shader tests it has; this head ran those and this PR's tests.was not found.VUID-VkDeviceCreateInfo-pNext-pNext, so this PR adds noVUID-message.Earlier heads on GitHub's runners:
git range-diff: all 8=). The fiveagc_driver_device_image_*tests and the shader tests built from the changed files pass 10 runs in a row on Linux, with the two GPU-heap tests skipping there. On Windows they build and pass, with the Vulkan tests skipping. The libkernel suite passes on both and libc's on Windows. On Linux libc's one failure isprecise_wait, a timing test this PR doesn't touch, which also failed withmain's implementation in another run today (run).On perf(agc): GPU descriptor heap (APS5_GPU_HEAP) #6947 (the previous base, up to 05502ba): the CI Linux mirror with the switch unset changed no test's status,
^(agc|shader|recompiler)with it on passed 749 of 751 (the two test limitations above), the device image harness passed in 8 configurations with a red per case, and the fork's full Windows build passed 1,572 tests.Astro's Playroom (PPSA01325), by @fma-rc (comment), on the previous head (05502ba, on perf(agc): GPU descriptor heap (APS5_GPU_HEAP) #6947), as the no-change check: Linux, RTX 5080 (driver 615.78.08), one run each into the first level, with and without
APS5_GPU_PATH=1. No program in that scene read an image table this path serves, the 12 captured frames of each run show the same scenes with no black or missing textures, and one round each within 10% is not a speedup, as they read it.Not tested: the watched-import half of
agc_storage_clear_hand_over. On lavapipe it runs the unwatched hand-over, which passes 10 of 10 on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 and with this PR, then skips the watched case, since lavapipe's host imports are compared rather than write-watched.check_conventions.pypasses at 594b346 against 1b09774, with no comment lines added. It passed at 0aaf2b9 against f85d0b3, and at 66b470c against 23b2a3f and againstmain.88ad9e8, a merge of
main2b1ae87, which brings milescoviello's perf(shader): allocate a program's use lists from an arena #12039 (run).ShaderDiskCache.cpp. perf(shader): allocate a program's use lists from an arena #12039 growsIrValueto 144 bytes, and this PR'sIrResourcePlanis 752. Each side changed only its own struct, so the merge keeps both values, and the build compiles both asserts. The merge commit's message says so.ShaderInfo25,ImageResource47,DeviceImageUse4) stay this PR's; no struct gained fields from both sides.FormatVersionstays 62. This PR's own diff is unchanged.agc_shader_device_image_tablesand every^agc_driver_bda_test.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_EXT_descriptor_heap).ctest -R '^(agc|shader)': 1,246 passed, 0 failed, 98 skipped.0f3e74a: 6407d56, a merge of perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's head dd7120c, and a heap-slot test fix on top.
main, the last of 6a691f6.docs/dev/ENVIRONMENT.md's rows, nowAPS5_GPU_HEAP,APS5_GPU_HEAP_EXCLUDEandAPS5_GPU_PATHin name order; the WIN32 PATHset_tests_propertieslist inCMakeLists.txt; andVulkanDevice::Target(), which takes both assignments.ShaderResources.cppmerged on its own and keeps perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's resolution of perf(agc): expand an HTILE on the GPU behind a pending mask clear kernel #8105, so a build with an HTILE mask clear is never reusable, address-space reuse included.APS5_HEAP_SLOT_CAPwithAPS5_GPU_HEAPinBindlessHeapSlots.cpp, before the test opens its device. WithAPS5_GPU_PATH=1the device creates the device image table at open, and that builds the device's heap.BindlessHeapreads the cap once, in its constructor, so the heap kept its full slot count and none of the test's refusals at 1 or 8 slots happened.ANYPS5_REQUIRE_VULKAN=1; GPU clocks weren't held, pass/fail only). perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's heap is live there: every run logs "Vulkan descriptor heap: GPU-mode draws and dispatches bind from VK_EXT_descriptor_heap".APS5_GPU_HEAP=1 APS5_GPU_PATH=1, the sixagc_driver_heap_slots*tests fail 6 of 6 with the test file before this commit, for example "bindless heap slot reuse tests failed: one free slot of eight refuses the heap". With it, they pass 3 runs of 3.agc_driver_device_image_*tests,agc_driver_device_image_table_heapandagc_driver_device_image_path_gpu_pathincluded, pass 3 runs of 3 with the switches and without them.^agc_driver_heap_slotsand^agc_driver_image_tabletest.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.^agc|^shaderonce (run):agc_driver_pipeline_journaltimed out at 120 s, the cold-compile timeout perf(agc): reuse read-only address-based draw builds over their cached address space #13858's sweep also hit. Alone ×5 (run) it passes 5 of 5 on Linux: 83.60 s for the first run, and 6.10 to 6.14 s for each after.VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validationand the runner's layer 1.3.275 (run). It ranagc_driver_depth_clear_hletwice, with the tests the verify adds for the files this head changes over perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508: 25 tests.was not found.VUID-VkDeviceCreateInfo-pNext-pNext,VUID-vkCmdCopyImage-srcImage-01548andVUID-vkCmdCopyImage-srcImage-01551, so this head adds none.agc_driver_depth_clear_hlealso passes 30 runs of 30 under layer 1.4.363, with no validation message.VK_EXT_descriptor_heap);^agc_driver_heap_slots|^agc_driver_image_table: 12 pass, 7 skip;ctest -R '^(agc|shader)'withoutGALLIUM_OVERRIDE_CPU_CAPS=avx: 1,176 passed, 99 skipped, 0 failed.22cead4: 525408a, a merge of
main5fb1747, then a merge of perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 0ab5f15.ShaderResources.cpp, where JJenkx's perf(agc): clear a fast-cleared sampled texture on the GPU #13648 addsSampledTexturesCleared()and this PR addsLookupDeviceTableTextureandDeviceTableTextureCurrent. Both are kept, with no other edit.DeviceTableTextureCurrentreturn false, so the table looks it up again, as it did for every DCC-keyed entry before.SHADER_READ_ONLY_OPTIMAL) are those of an uploaded one.main, which brings chitters2004's perf(agc): run first the library prebuilds of programs a submission binds #13667. perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's own resolution of perf(agc): run first the library prebuilds of programs a submission binds #13667's newPrebuildStageLibraryargument comes with it unchanged. Clean.+/-lines over perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 andmain.^agc_driver_heap_slotsand^agc_driver_image_tabletest,agc_driver_sampled_clear_keysandagc_driver_depth_clear_hle.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation(layer 1.3.275) (run).VUID-VkDeviceCreateInfo-pNext-pNext,VUID-vkCmdCopyImage-srcImage-01548andVUID-vkCmdCopyImage-srcImage-01551, so this head adds none. The loader inserted the layer 28 times on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 and 35 times with this head.agc_driver_image_tablefails its ctest check for validation messages. ItsFAIL_REGULAR_EXPRESSIONmatches theVUID-VkDeviceCreateInfo-pNext-pNextline that layer 1.3.275 logs forVkPhysicalDeviceMaintenance8FeaturesKHRin the device's feature chain. Both the check and that feature chain aremain's.VK_EXT_descriptor_heap, or no uint storage view);agc_driver_sampled_clear_keyspasses 10 of 10;^(agc|shader): 1,278 run, 1,178 pass, 99 skip, 1 fail. The failure isagc_driver_idle_store_yields, from fix(agc): yield the queue-idle storage write-back to new work #13621, which failed 14 of 30 runs onmain5fb1747 alone there.06eba99: every field the device image interface's duplicate check compares is in its id, for @mrfelek's Death Stranding 2 (PPSA02015) stop on feat(agc): serve lane-keyed, pointer and runtime image-table columns #10193 (comment):
device image interface: two image interfaces share the id.RegisterDeviceImageInterfacecompares entries withImageResource's defaultedoperator==, butmixImageInterfacedidn't mix five of its fields, anddeviceInterfaceImagedidn't clear them. Two device-table images, or mode lists, that differed only in one of those fields got one id, and the second registration threw.ResourceMaterializer.cpp, decides each field by whether the interface depends on it:dimensionQueryOnlyandsampledOnly:inspectImageDescriptorreads both on the stored interface image whenDeviceImageTable::lookupKeypicks a mode throughTryRuntimeImageMode;targetMerge: it changes the modes and the SPIR-V declarations.adjustedSample: it only decides which modesRuntimeImageModesadds, and the modes are already part of the id;optionalDescriptor: only the per-draw snapshot reads it, on the program's own copy.deviceTableimages, so nothing else changes.FormatVersionandSourceVersion()both match (ShaderDiskCache.cpp1478 and 1491), and its directory and key are named afterSourceVersion()(1514, 1950-1951).SourceVersion()is a SHA-256 over the recompiler's sources (ShaderCacheVersion.cmake),ResourceMaterializer.cppincluded. So no entry with an old id can be read, and the layout is unchanged.agc_driver_device_image_table's interface case now registers, for each of the five fields, an image that differs from the base only in that field.sampledOnlygets its own id.ImageResource::volumeGather. Whichever of fix(shader): gather a 3D image's image_gather4_lz from one slice as measured #9183 and this PR merges second gives it a mixed-or-cleared call, with a test case.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VUID-VkDeviceCreateInfo-pNext-pNext,VUID-vkCmdCopyImage-srcImage-01548andVUID-vkCmdCopyImage-srcImage-01551, so this head adds none.agc_driver_image_tablefails its validation-message check on both arms, as above. The only "was not found" in either log is that check's own regex, echoed in its failure line.^(agc|shader): 1,279 run, 1,180 pass, 99 skip, 0 fail. A first run had 6 failures: five frame-capture tests stopping on that machine's full disk ("less than 4 GiB free on the capture volume"), andagc_driver_idle_store_yields,main's flaky test. All 6 passed alone, and the rerun after freeing space is the one above.715097e: b5065a1 and 715097e, merges of perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 31f5d0e and 09cc865, which bring Raghav314's commits since 0ab5f15 and perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's merges of
main, with build(agc): register each AGC test executable in its own CMake fragment #12862's test split.DeviceImageTable::HeapSlotspassestexture.get()to perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508'sTextureSlot(Texture*)(dd83293). That's the change milescoviello named in their Ghost of Tsushima run on feat(agc): serve lane-keyed, pointer and runtime image-table columns #10193 (below).docs/dev/ARCHITECTURE.md'sAPS5_GPU_HEAPbullet keeps perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's sentences and this PR's trailer words.CMakeLists.txtis resolved withtools/agc_test_split.py resolve, which moves this PR's registrations intotests/cmake/. perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 already registers the_gpu_heapvariants throughagc_add_gpu_heap_test().ShaderDiskCache.cpp: perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 866bd70 drops the seconduserDataRegisterReads, and this PR's two lists followimageTableFaultsin both directions;Dispatch.cppandDrawCapture.cpp;ShaderResources.cpp's includes;tests/BindlessHeapSlots.cpp: perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's helpers, with both settings made before the device opens;PATHline inagc_shader_memory_tests.cmake.LoadTableMap,TableHeap(),TableMapAddressed(),context.localDevice,graphicsContext()), so this PR's lines follow.BufferSpecializationFields) comes in through perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's own merge ofmain, which adds it to the binding-plan key and the snapshot hash. This PR'sRecompiler.cpplines don't touch those functions.-DBUILD_TESTING=ON,ctest -Ngives 3,227 tests: perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 3,219 plus this PR's 8, each listed once, with all 22_gpu_heapvariants.LoadTableMap'sTableMapAddressed()branch, never the table-map buffer branch.agc_shader_device_image_tablescompiles and validates it. The GPU tests that run it,agc_driver_device_image_table_heapandagc_driver_device_image_path_gpu_path, skip on lavapipe, which has noVK_EXT_descriptor_heap.^agc_driver_heap_slotsand^agc_driver_image_table.VK_EXT_descriptor_heap.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.main3103478 against this head, the same tests, on GitHub's Linux runner (run).VUID-VkDeviceCreateInfo-pNext-pNext,VUID-vkCmdCopyImage-srcImage-01548andVUID-vkCmdCopyImage-srcImage-01551, so this head adds none.mainand 35 times with this head.agc_driver_image_tablefails its validation-message check on both arms, as above.^(agc|shader): 1,292 run, 1,121 pass, 171 skip, 0 fail. The skips rise from 104 at b5065a1 because perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's 09cc865 makes its GPU heap variants skip, instead of passing on the per-draw path, when the device has no descriptor heap (95 of the 171).APS5_GPU_HEAP=1 APS5_GPU_PATH=1. On the CPU table path it creates ~17,000 sampled textures and spends ~85 ms per draw, until memory runs out. On the GPU path it creates 800 sampled textures, at ~2.8-15 ms per draw, until the interface id stop that 06eba99 fixes. With 06eba99 merged into the same stack, mrfelek reports the id stop gone in 2 of 2 runs (comment); the next limit there is 20 programs on the CPU table path and host memory.APS5_GPU_HEAP=1 APS5_GPU_PATH=1 APS5_KEEP_UNEXPECTED_DEVICE_IMAGES=1, an RTX 4070 Ti, Linux.APS5_NO_HEAP_DATA_UNIFORM=1, the 20-minute session runs to the end. Its interface id clash at 101 s is the one 06eba99 fixes.67420fb: 7e88d62 and 67420fb, merges of perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's de1bbf1 and fbab1c1, with 92c6dab, a fix for the device image table's eviction window, between them.
main. Among the commits:RecompileImplbuilds the result as a value, setsdeviceImagePlan, then makes itshared_ptr<const>;ResourceMaterializer's!deviceTableguard goes on perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's newfill(...)call.fix(agc): keep device image table slots from retiring while a batch still reads them.DeviceImageTable::Prepareswept its keys (retainSlots) and uploaded, then took a miss-ring chunk withchunkFor(recorder, true), which canSyncand submit.Preparenow sweeps again and uploads once, afterchunkFor, so nothing that can submit sits between the last sweep and the upload. That also covers a flush insideresolve's texture lookup.Expectnever uploads, so it needs no change.Slots::touchmember, mapped toBindlessHeap::TouchSlots, marks every live entry's slot used once per heap epoch. perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508'sevictLockedtakes only slots withuse + 2 <= epoch, so it no longer takes one the table serves.agc_driver_device_image_table:SweptWhileWaitingForAChunkholds all 16 miss-ring chunks and moves a live key's slot insidechunkFor's wait. On the merge without the fix it fails with "a prepare serves no key whose heap slot moved while it waited for a miss-ring chunk (slot 2, 0 swept)", and with the fix it passes.LiveSlotsTouchedchecks the touch once per epoch.main87448b3 into perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508. Three conflicts, each resolved by keeping both sides:tests/ShaderMemory.cpp: the--device-image-tablesand--table-trailerdispatch, thenmain's--registered-view-churn;IrMetadata/Resources.hpp:NoSamplerandDeviceImageUse, thenmain'sAppliesLodBiasInShader;PipelineSpecialization.hpp:main'sSamplerLodBiasBase57728 andSamplerLodBiasShaderThreshold, thenDeviceSamplerClassBase58368.git diff de1bbf1af3 92c6dab397andgit diff fbab1c1619 67420fb18bboth give 59 files, +4,252/-30.FormatVersionstays 62.3rdparty/SDL2move and the new3rdparty/sqlitearemain's, through perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508.main, the bases from 57344 to 57791 are contiguous. The device sampler classes take 58368 to 58431, after 576 unused IDs.info.samplersstops atShaderInfo::MaxSamplers(ResourceTracker.cpp:2461-2464).SpirvImageEmitter.cpp:2371).main's shader-side bias (AppliesLodBiasInShader,SamplerLodBiasBaseplus the sampler index).^agc_shader_memory,^agc_shader_registered_view_churn,^agc_driver_image_sample_lod_bias,^agc_shader_sampler_limitsand^agc_shader_disk_cache.VK_EXT_descriptor_heap.agc_driver_device_image_tablepasses 10 of 10.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.main87448b3 against this head, the same tests, on GitHub's Linux runner (run).main's arm ran 15 tests and this head's arm 36, all passing, with 15 skipped on this head.VUID-VkDeviceCreateInfo-pNext-pNext, so this head adds none.mainand 27 times with this head, and neither log haswas not found.^(agc|shader): 1,482 run, 1,289 pass, 193 skip, 0 fail.^(agc|shader): 1,494 run, 1,301 pass, 193 skip, 0 fail. 106 of the skips needVK_EXT_descriptor_heap.agc_driver_device_image_table_heapandagc_driver_device_image_path_gpu_pathneedVK_EXT_descriptor_heap, which lavapipe and GitHub's runners lack, and the RTX 3070 above wasn't rerun at this head.Checklist
mainthrough perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 (Raghav314, fbab1c1, which this head merges); perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508's image tables are CPU-resolved into heap slots, and fable-void's branch is not an open PR. feat(shader): resolve nested image tables through runtime pointers #7223, feat(shader): read samplers through nested and pointer-keyed descriptor tables #7395 and fix(shader): answer image_get_resinfo on any T# dimension #7550 extend the CPU table path in the same recompiler files (ResourceMaterializer.cpp,ResourceTracker.cpp); they compose with this. No other open PR implements these 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)