Repository navigation
fix(agc): give pooled buffers a VkBuffer of exactly the requested size - #2233
Conversation
|
Linux run: Linux 7.2 (x86_64), Intel(R) Graphics (RPL-S) (Mesa 26.3.0-devel, Vulkan 1.4.363), GCC 16.2.1, Release,
Tested on Linux to cover the platform noted in the description ("Not run: Linux"). |
adriadam10
left a comment
There was a problem hiding this comment.
Thanks. The test passes here on the PR head alone, and fails with the three non-test files reverted, so it pins the fix. Needs a rebase before it can land:
- Conflicts with
mainincore/libs/prx/libSceAgcDriver/Graphics/src/Resources.cppsince "perf(agc): pool device staging buffers by size class" (28345b0).mainnow hasBufferPool::Usage(usage, properties),Capacity(size, properties)and setscapacity = allocation->bytesafterTake. - After the rebase,
BindExactBuffer(Resources.cpp:18, called at :55 and :143) must receive the pool-adjustedthis->usage, not the constructor argument, or a pooled buffer re-created at the exact size gets different usage flags than the pooled memory was keyed on. - Device buffers now use finer size classes (
deviceClassBits), soClassBytes/the "4096-byte class" expectations inPooledBufferRange.cpp(:25, :311) need rechecking againstBufferPool::Capacity(size, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); better to derive them from it than hardcode. - Rerun
agc_driver_pooled_buffer_rangeand the otheragc_drivertests on the rebased tree.
Buffer and DeviceBuffer created their VkBuffer at the pool's size class, so a robust read past the requested size stayed in bounds and returned the bytes an earlier user of the pooled memory left there instead of an out-of-range result. Each VkBuffer now has the requested size, created with the pool's usage, over memory of its class (or its slab slot); one taken from the pool for a different size is recreated over the same memory at the same offset. agc_buffer_pool follows a pooled buffer by its memory, so its class and reuse cases hold with the exact-size buffers.
12da51f to
aa9ee1b
Compare
|
Rebased onto
One more change to flag:
|
|
Checked
Not checked here: a game, or a hardware driver. AI-assisted: yes (Claude Code). |
|
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.
|
adriadam10
left a comment
There was a problem hiding this comment.
Checked the PR merged onto current main on Linux : agc_buffer_pool and agc_driver_pooled_buffer_range pass, and both fail with the three non-test files reverted, so they pin the fix. Slab slots are bounded by the slot size and the rebind checks size and alignment; no conflicts with main. Also confirmed by @Kikoarl (Intel), @orishamir (llvmpipe) and @Mouhand-Kaddo (Windows). Merging.
What
BufferandDeviceBuffercreated theirVkBufferat the pool's size class (BufferPool::Capacity: power-of-two classes below 1 MiB, finer device classes above), not at the size the caller asked for. WithrobustBufferAccess, a shader read past the requested size therefore stayed inside theVkBufferand returned whatever an earlier user of the pooled memory left there, instead of an out-of-range result (zero or a value inside the buffer).Each
VkBuffernow has exactly the requested size, created with the pool's usage (BufferPool::Usage) and bound to memory sized for its class, or to its slab slot, so the allocation stays reusable.BufferAllocationrecords the size itsVkBufferwas created with (bufferBytes). A buffer taken from the pool for a different size gets a newVkBufferover the same memory at the same offset; a same-size reuse keeps the existing one.tests/BufferPool.cppfollowed a pooled buffer by itsVkBufferhandle and checked a class by theVkBuffer's size. With exact-size buffers the class is held by the memory, so those checks now follow the bound memory (MemoryOf/ClassOf); the cases are unchanged, and the first one also checks that theVkBufferis created at the requested size.Open PRs #1896, #1201 and #290 also change
BufferPool.cpp/.hpp, but only eviction and retained-byte bookkeeping; none touches theBuffer/DeviceBufferconstructors orBufferAllocation.Tested
Windows 11, RTX 5070 (driver 595.x), MinGW-w64 GCC, Release,
BUILD_TESTING=ON, onmain5edae353.agc_driver_pooled_buffer_range:0xababababand released. A 100-byte buffer then takes the same pooled memory, and a compute shader reads word 28 (byte 112) through aVK_WHOLE_SIZEstorage descriptor withrobustBufferAccessenabled. Onmainthis returns0xabababab, the earlier user's bytes; with the fix it returns zero or a value inside the buffer.vkCreateBuffer(fresh, pooled-at-another-size and same-size-reusedBufferandDeviceBuffer), with the classes taken fromBufferPool::Capacity.main(5edae353), passes with this change.ctest -R "^agc_driver|^agc_buffer_pool": 255/255 pass. Fullctest: 710/710 pass (display-dependent video-out tests skipped).python tools/check_conventions.py --base origin/mainpasses.Not run: Linux (tested there on the earlier revision by @Kikoarl), AMD.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)