Filled rectangles (VGT_PRIMITIVE_TYPE 7 and 17) use the same single-sample MSAA_ENABLE path as triangles; PPSA03541 stops on a rect-list draw otherwise.
Co-authored-by: Cursor <[email protected]>
RADV initializes and fast-clears DCC keys with its fill_memory compute
kernel, which stores through a global address. Run as an ordinary
dispatch, its stores name no range. The DCC key tracking therefore saw
a key fill only once it had landed in guest memory, which could be
after later writes to the surface had already been recorded.
vkQuake (PPSA99010) hits this on every item pickup:
- the scene renders into a second color buffer;
- RADV's UNDEFINED -> GENERAL barrier fills color buffer 0's keys with
DCC_CLEAR_0000;
- a screen-effects compute pass writes color buffer 0;
- the UI pass draws on color buffer 0.
The keys landed while the UI pass was being recorded. The refresh took
them for a clear made after the compute pass, dropped its results and
cleared the image to black. For the length of the pickup flash the
scene was black, with only the HUD drawn.
The fill HLE now matches the 16-byte variant of the kernel as a fill of
min(threads * 16, user[4] + 16) bytes. The kernel takes its address in
user[2..3], its largest store offset in user[4] and its value in
user[5]. A key fill through it is handled where it is in the command
stream.
Primitive type 19 (DI_PT_QUADLIST, 0x13) is used by Unity and other engines for UI quads, sprites and font glyphs. Because Vulkan lacks native quad-list primitive topology, quad draws are expanded on the CPU into indexed triangle lists with 6 indices per 4-vertex quad, respecting the first/last provoking vertex configuration and discarding incomplete trailing vertices. Adds unit tests and documents the functional debt.
main took FormatVersion 40 with #6486, so this branch moves to 41. The grid-reference test's skip now reads as a device that does not keep depth at custom sample locations, the wording tools/check_skips.py accepts as a device limitation. The sample-location debt entry describes the 2x checkerboard without naming titles.
#4650 took request serialization version 35 for its depth remap flag, so this branch's sample order moves to 36. The serialization tests drop #4650's trailing byte from every older version they build, as main's do, along with the iteration fields and the sample order.
A dispatch over maxComputeWorkGroupCount was split into vkCmdDispatchBase
chunks whose base reached the limit, which VUID-vkCmdDispatchBase-baseGroupX-00421
forbids, and NVIDIA refused the split outright.
Compute modules now declare WorkgroupOffset specialization constants (default 0)
that the recompiler adds to WorkgroupId and GlobalInvocationId and keeps
unmaterialized. Each chunk is recorded with vkCmdDispatch from group 0, bound to
a pipeline variant specialized with the chunk's base. The NVIDIA throw is gone;
device-memory LDS splits still throw.
Fixes#7375
importBudget keeps this branch's configuredBudget split and takes #6472's HostImportBudget for the default; the host-import debt entry takes #6472's budget sentence next to this branch's report and refusal sentences.
PPSA08270 (Eternights) stopped after its story intro with "AGC graphics:
CB resolve from a target whose sample count differs from the
rasterizer's". It resolves a 4x 512x512 target into a single-sample one
with PA_SC_MODE_CNTL_0.MSAA_ENABLE off while PA_SC_AA_CONFIG still holds
2x from earlier draws. Without MSAA_ENABLE the scan converter does not
use PA_SC_AA_CONFIG's sample count, so the resolve takes its sample
count from CB0 as it already does when PA_SC_AA_CONFIG is single-sample.
Main's sameRange for a failed import now takes the import budget, as the HostImport overload does, so a recorded failure is compared against the run the budget would import again.
Main's sameRange for a failed import now takes the import budget, as the HostImport overload does, so a recorded failure is compared against the run the budget would import again.
Main's sameRange for a failed import now takes this branch's import budget, as the HostImport overload does, so a recorded failure is compared against the run the budget would import again.
Imports, type-3 mirrors and the buffers and textures placed in host memory share the driver's system memory heap. On Windows that heap is half the physical memory, so on a 16 GiB machine the old budget (the heap less 2 GiB) let imports hold about 6 of its 8 GiB, and host buffer allocations then overflowed into the 256 MiB device-local host-visible heap and failed. The budget now reserves the larger of 2 GiB and half the largest host heap.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Each depth surface stores its plane through a storage image of its own,
kept for the surface's life. A title that switches output resolution
binds new depth targets over memory where the previous targets' planes
were, and the old images stayed live there. Storage images over the same
memory lend each other pending results, so a later store of the new
plane did not reach guest memory and buffer reads kept seeing the old
depth. A bind now drops the images and the pending store of older
surfaces whose planes overlap its plane over another range. A
same-range surface (another stencil or HTILE address) keeps its image.
The scan runs only when a surface or plane image was created since the
surface's last scan.
AI-assisted: yes
A depth surface lives in its Vulkan image, so a buffer read of its depth
plane saw guest memory the surface never wrote, and a buffer write into the
plane never reached the surface: binding the target again kept the old
depth.
- A single-sample 32-bit depth surface with the 64 KiB Z swizzle
(DB_Z_INFO SW_MODE 24) keeps a storage image in that swizzle over its
plane. A bind that writes or fast clears depth marks the plane stale;
FlushDepthPlanes copies the depth into the storage image and stores it
into guest memory. It runs from StorageTexture::FlushPending, when a
buffer upload finishes (over its regions and address space), and before
a dispatch for each GuestBuffers V# it binds (a cached dispatch reads
them without an upload). A reused build flushes its in-place buffer
regions, and an image lookup flushes the range it reads, as do the
write-stamp proofs that let a cached image or a reused build skip that
lookup: a stale plane's memory looks unchanged to them.
- Stale planes are kept as ranges under their own lock with an atomic
hull; a flush that overlaps none returns without the GPU and surface
locks.
- Every bind of such a surface, and every flush of its stale plane,
collects the plane's writes. Written by someone else since the surface's
previous bind, store or reload, the plane is reloaded from memory
instead of stored, so a guest write after a depth draw is not
overwritten by that draw's late store. A pending HTILE fast clear wins
over the reload.
- A color target flushes the stale planes under it before it retires their
surfaces, so a target that loads or blends reads the stored depth. A
retired surface's plane is no longer stale: a later flush never stores
its old depth over what the new owner of the memory wrote.
- The depth surfaces lock is recursive: a store reached from a flush under
DepthSurfaceTexture re-enters it.
- Draws pass whether they write depth, so read-only binds do not mark the
plane stale.
PPSA05684 copies its main depth plane into two ping-pong planes with a
buffer compute, draws the cage's depth into them and fogs its menu from the
result; without this the copy carried nothing and the fog covered the
cliff and the cage.
agc_driver_depth_plane_buffer_memory draws depth 0.5 into such a plane,
fetches vertices from it (the plane must hold 0.5), writes 0.75 into the
memory and draws at 0.5 under LESS (must pass), then checks the depth
written after the reload reaches memory again. On a new plane it writes
memory after a depth draw and before any store: a buffer read must keep
the guest bytes and the next bind must reload them; a guest write before a
depth draw must then lose to that draw. A linear texture at an offset into
a plane must read what memory holds after a flush, also when it is viewed
through its cached storage image after another depth draw. On a plane with
HTILE, an HTILE fast clear after a guest write must win. A color target
that blends ZERO/ONE over a plane just drawn at 0.5 must write back the 0.5
it loaded.
AI-assisted: yes
Combines this branch's sample order with #6470's once-per-pixel and once-per-sample inputs. The pixel request keeps both sides' fields: #6470's iteration, position location and sample locations are serialized at version 34, and the sample order after them at version 35. The serialization tests move the sample-order bytes after the iteration fields and drop both from older versions. The pixel info collector adds sample order to the SampleLocationsVary inputs, and the draw keys compare and hash both. EmitSampleOffset's iterated index already goes through GuestSampleIndex, since the SampleId builtin does. The shader cache stays at FormatVersion 40, and the sample-location debt entry takes #6470's sentence on the position inputs.
The custom MSAA sample-location debt entry keeps this branch's grid stand-in text and takes main's sentence on ANCILLARY and the position inputs of a once-per-pixel shader.
Write the INDEX_ATTRIBUTES_INDIRECT packet the console's builder writes,
as measured by the prosper console oracle, with OpenAGC's signature, and
report its measured size of 16 bytes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Takes #6215's framebuffer owners and target-owned sampled textures, keeping this branch's sample-order steps after the framebuffer and the sampled-only usage next to the storage order view.
Resolves the shader debt file bullet by bullet: main's EmitSetAttribute entry, and this branch's PERSP_SAMPLE/LINEAR_SAMPLE and pixel-position entries.