Skip to content

perf(agc): reuse address-based dispatch builds with a fault record per use - #8971

Closed
EagleBearerYS wants to merge 28 commits into
boykopovar:mainfrom
EagleBearerYS:perf/agc-reuse-address-dispatch-builds-v3-8104
Closed

EagleBearerYS wants to merge 28 commits into
boykopovar:mainfrom
EagleBearerYS:perf/agc-reuse-address-dispatch-builds-v3-8104

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

A dispatch whose program reaches guest memory through the BDA table (an address-based dispatch) builds its resources again every time: the lease of the registered memory, the upload, the page table and its fault buffer, the image table and the descriptor set. noteReusable gives up on any address-based build that isn't a draw, and #6636, which this PR stacks on, makes only draws reusable.

The change. Dispatch builds take #6636's rules for draws. A build whose stages are address-based is reusable, and a hit runs Revalidate's address branch:

  • the snapshots, compared after the recorded GPU writes over their ranges are completed (perf(agc): reuse address-based draw builds whose inputs are unchanged #6636);
  • the cached address space, refused when it was replaced, or when its device, registry generation or import epoch moved, or a mirror could not be refreshed;
  • the build's image and buffer proof, then the space's imports.

Each dispatch takes the space for its batch and suspends it after recording. Between dispatches the build pins no guest allocation, so a guest free doesn't wait for it.

One difference from draws. A dispatch isn't refused while an earlier dispatch of its build is in flight, because several dispatches of one program per batch are common.

  • The build's fault buffer holds the fault report and the written-page record of one use. The first use in flight takes it. Every other concurrent use takes a spare from the build's pool: a fault buffer of its own, and a descriptor set that repeats the build's writes with that buffer in the fault binding.
  • Each use's completion checks its own record. A fault is reported by the dispatch that made it, and each dispatch marks the pages it wrote.
  • A spare goes back to the pool when its use ends, when its completion ran or its batch was discarded. The build's descriptors don't change after the build, so a pooled set stays valid.
  • A fault makes the build non-reusable, as for draws. So does an unaligned BDA access: the use's writes are marked first, as main does since c0588d2.

Main's template path. main's 89d255c serves a compute dispatch from its cached template when only read-only buffers moved. Non-address hits keep that path exactly. Address-based hits skip its proof, which always refuses them. Both then run Revalidate(shaders, nullptr, snapshots), and a dispatch binds either main's moved-buffer set or its use's record set, never both.

Overflowing written-page records (first commit).

  • A use overflows its record when its stores through the BDA table touch more than 2,048 chunks of 32 pages, or when its shader finds no free slot for a chunk within 8 probes. Its completion then threw "more than 2048 chunks ... are not implemented". The pages the record held weren't marked as written, the write-back was reported as failed, and the build stopped being reusable.
  • The completion now marks the chunks the record holds, then every writable range of the build's page table. That's a superset of what the GPU stored, because a store outside those ranges faults instead.
  • The guest-memory caches over those ranges revalidate once. This applies to every address-based build, reused or not.

Prior art. The record per use follows fable-void's 26ff0b4 on wip/new-gpu-path ("take each dispatch's BDA table and fault record from pooled slabs"), in place of his shared batch record (a7015cd). The overflow handling follows his 3b1372e. Both commit bodies name the source commits.

Profile counters. Reuses and refusals go to #6636's address reuse counters, and its [rescache] line now reads "address-based draws and dispatches". APS5_NO_ADDRESS_DISPATCH_REUSE=1 builds every dispatch as before, separately from #6636's APS5_NO_ADDRESS_DRAW_REUSE=1. Both are in docs/dev/ENVIRONMENT.md.

What it leaves out (also in the debt file):

  • Dispatch recipes still need a build without completion work, so an address-based build never gets one: a recipe's validation proves neither the space nor the snapshots.
  • Builds with copied writes are still never reusable.
  • Stores through the BDA table aren't recorded as pending writes, so a snapshot-backed region that a BDA store writes would still be compared against the old bytes. No test covers that.
  • A spare record's descriptor set is sized to the device's image-table capacity rather than to the build's table, and a build's spares are bounded only by its uses in flight.

Cost. A dispatch binding harness on lavapipe, one wave per dispatch. The driver's time per address-based dispatch, as the median of five 10-s windows, on #6636's head fc9c541 and with this PR:

textures one dispatch per submission eight per submission
1 295.7 → 51.6 µs 275.4 → 25.8 µs
16 355.1 → 58.4 µs 307.4 → 30.4 µs
128 705.9 → 99.2 µs 408.5 → 63.1 µs
2,000 7,325.8 → 1,044.7 µs 2,637.6 → 909.5 µs

#6636's head has no resource-cache hit on any row. This PR has one miss per run, and reuses the build for the rest, eight concurrent uses per batch included.

These runs cap the image table at 4,096 entries on both sides (APS5_IMAGE_TABLE_CAPACITY=4096, 3640795's cap applied by hand; main has no such cap). Without it, each spare record's descriptor set is allocated at the device's full image-table capacity (16 MiB on lavapipe, about 100 ms to create), and a build keeps its spares until its uses are reaped. That is fixed before this leaves draft.

Pending: Resident Evil Village (PPSA01556)'s first scene, where dispatches bound the frame. The comparison is the default against APS5_NO_ADDRESS_DISPATCH_REUSE=1, with fps over 5 minutes at control and the [rescache] address-based line. It will be added here before this leaves draft.

Overlap. Checked with git merge-tree against every open PR on the same files, on main 9be6ccf. Beyond #6636's own list, which this PR inherits:

The commits:

  1. fix(agc): mark a BDA written-page record's writable ranges when it overflows.
  2. perf(agc): reuse address-based dispatch builds with a fault record per use. This includes AddressDispatchReuse.cpp, the debt entries, the ENVIRONMENT.md row and the agc_driver_graphics expectation.
  3. fix(agc): keep address-based builds with a staged overlay reusable (for perf(agc): stage the written elements of address-based compute builds in device memory #8104, above).

Tested

  • New agc_driver_address_dispatch_reuse (tests/execution/AddressDispatchReuse.cpp, lavapipe). Each case is red with the second commit's non-test hunks reverted, and green here:
    • repeated: four repeated dispatches with unchanged inputs are reused and counted, including four in one batch over two blocks. Red: "4 of 4 repeated address-based dispatches with unchanged inputs built their resources again".
    • snapshot: a changed word of the program snapshot rebuilds and counts one snapshots refusal.
    • faults: of two reused dispatches in one batch, only the one storing into read-only memory reports its fault, once, and the other's store lands. The next dispatch counts one "not reusable" and rebuilds, and two faulting dispatches in one batch each report their own address.
    • srt: a dispatch that stores a new pointer into the SRT through the BDA table is seen by a reused reader later in the batch. A FillBuffer recorded over a captured SRT refuses the reuse as a changed snapshot.
    • free: a guest free while a reused build is cached, and while a reused dispatch is in flight, returns at once, and later dispatches are correct.
    • overflow: 1,024 threads × 3 stores into 3,072 distinct 128 KiB chunks overflow the record without failing. Every store lands, and the build is reused afterwards.
    • unaligned: a reused dispatch whose global_atomic_add is 2 bytes off marks its writes and stops the build's reuse.
  • The first commit's own red: with its fix reverted, "more than 2048 chunks of 32 pages stored to through the BDA table in one use are not implemented".
  • Mutation checks: with the spare records disabled, faults reports a fault twice. With the pre-proof sync removed, srt reuses the dispatch after the recorded fill.
  • Repeats: agc_driver_address_dispatch_reuse --repeat until-fail:20: 20 of 20. perf(agc): reuse address-based draw builds whose inputs are unchanged #6636's agc_driver_address_draw_reuse and _watched_imports pass.
  • With the third commit (Linux, lavapipe): the three reuse tests pass 20 of 20 each with --repeat until-fail:20. ^agc gives 850 of 851, the same agc_driver_sgpr_pattern_fill_keys failure under load (5 of 5 alone).
  • ^agc (Linux, lavapipe, CI configuration): 851 of 851 with the reuse on, and 850 of 851 with APS5_NO_ADDRESS_DISPATCH_REUSE=1. perf(agc): reuse address-based draw builds whose inputs are unchanged #6636's head gives 849 of 850. The one failure in both of the last two is agc_driver_sgpr_pattern_fill_keys under load, which passes 5 of 5 alone on both trees.
  • Merged with perf(agc): reuse address-based draw builds whose inputs are unchanged #6636's head 7cef9bc (8555d56, the head; perf(agc): reuse address-based draw builds whose inputs are unchanged #6636 merges main with fix(agc): bind a strided buffer's last record only up to the render target it runs into #8224 and cuts its debt entry, so this PR's entry keeps that shorter form with its dispatches added), on GitHub's runners (run): agc_driver_address_dispatch_reuse, both draw-reuse registrations, agc_driver_graphics and the tests tied to the changed files pass 5 runs in a row on Linux (31 tests). On Windows 27 pass and 2 skip without Vulkan. The suites pass on both.
  • GitHub's runners on 8b4e909, against perf(agc): reuse address-based draw builds whose inputs are unchanged #6636's head fc9c541 (run):
  • GitHub's runners on the first two commits, against the same head (run):
  • CI's Linux job, mirrored (Ubuntu 24.04, gcc 13.3, lavapipe): 1,766 of 1,774 on this head and 1,766 of 1,773 on perf(agc): reuse address-based draw builds whose inputs are unchanged #6636's head.
  • check_conventions.py passes, with no comment lines added.

Checklist

…gistered

An address-based build takes the cached address space when it is the
device's, of the registry generation read before any lease, and no import
was retired since; it then stamps the space's imports as used and brings
the space's sparse, writable and heap mirrors up to date. Those steps now
live in helpers of their own (spaceMiss, stampSpaceImports,
refreshSparseMirrors, appendWritableMirrors), so a later use of an
existing build can make the same proof and the same refresh as a build
that takes the space. No behaviour change.
A draw whose stages reach guest memory through the BDA table built its
resources on every draw: the lease of the registered memory, the upload,
the page table and its fault buffer, the descriptor set and the image
lookups. boykopovar#2657 skipped the resource cache for such draws because the
build was never kept: its completion checked the faults, marked the pages
the shader stored to, wrote the written ranges back and released the
lease, once.

A draw build over the cached address space is now kept when everything it
depends on can be proved again cheaply: the space it was built over must
be the one a build would take now (the device's, of the current registry
generation, with no import retired since), its own regions must be imports
or read-only image mirrors with unchanged serials, or snapshot copies whose
bytes the draw's snapshots repeat in the same order; the images are proved
as for any cached build. The read-only buffers and data words the content
key leaves out must equal the build's: a hit with other ones rebinds them
per draw, which an address-based build cannot. A reused draw takes the
space again and refreshes its mirrors as a build does, and the imports are
checked once more after the image proofs. Each draw keeps its own
completion: its batch holds the space until then, and its completion
checks the faults, marks the written pages and the written ranges served
in place. Between draws the build pins no guest allocation, so a guest
unmap never waits for the resource cache.

The fault buffer, which holds the fault and written-page records, belongs
to the build, so one draw at a time uses a build: a draw that repeats it
before the previous draw's completion ran builds anew. A build whose draw
faulted is not reused. Dispatches and draw recipes do not reuse
address-based builds. APS5_NO_ADDRESS_DRAW_REUSE=1 builds every one as
before.
The reuse of address-based draw builds rests on choices that are not
measured on titles: one draw at a time per build (the fault buffer holds
one draw's records), the snapshot list repeated in the same order, and no
reuse for dispatches or draw recipes. Recorded as technical debt so they
can be revisited with title measurements.
…ation

A guest buffer descriptor can describe more than its build binds. Past
the device's range limit the build cuts the size at the registered end,
or binds an empty buffer when nothing is registered there, and it trims
a stride overhang that reaches past the allocation. A reuse compared each
descriptor's raw size with what the build had bound, so such a buffer
always looked moved: an address-based draw built its resources again on
every draw, and a cached build of another draw rebound a trimmed buffer
at its raw size, past its allocation.

The moved-buffer check and the alias checks a reuse repeats now both
take the size from the build's own computation. The alias checks need
it as well: with only the moved-buffer check changed, the reused draw
failed with "shader buffer aliases the render target", which fails the
driver.

agc_driver_address_draw_reuse draws twice with a vertex buffer
descriptor of 0xffffffff records whose render target lies above its
64 KiB allocation. The second draw must reuse the first one's build;
without the fix it built again.
Both walks of the reuse proof skip a rejected image-table element, so
it is never proved again. Two rejections are transient (a surface that
is not mapped, a texture lookup that throws), and pages committed in a
registered reserved range leave the registry generation alone: an
address-based build could be reused with the element still rejected
after its surface became valid. Such a build is now not reusable.

The address-based proof could also throw out of Revalidate and fail
the draw, where a fresh build would reject the element or report the
error itself. Anything the proof throws now refuses the reuse.
A batch whose end or submit fails is discarded without running its
completions. The use count BeginUse took was only dropped by
CompleteUse, so the build stayed in use and was never reused again.

The count now goes with the token BeginUse returns, which the
completion owns: it drops when the completion runs or is discarded.
The mock's queue submit can now fail for the test.
A fresh capture lists a draw's snapshot regions sorted by address
(ShaderMemory::Regions). A decode-cache hit lists the stages' code
and their matched regions in stage order instead. SameSnapshots
compares the two lists entry by entry, so the first hit after a decode
miss failed the address-based reuse and built the draw again whenever
the orders differed, as they do when the pixel shader's code lies
below the vertex shader's.

The draw now sorts its snapshots by address before it hands them on.
…rofile

A tester of address-based draw reuse could not tell how often a draw
reused its build: the driver counted no reuse, and two runs averaged 4.4
and 10.2 ms per address-based draw where others took about 1 ms. A
refused reuse pays for its proof and then for the build, so the refusals
and their reasons are what tell such runs apart.

The resource cache now counts, for address-based draw builds, the proofs
Revalidate runs, the reuses, and the refusals by reason: in use (the
build's previous draw has not completed; refused before any proof), not
reusable (its draw faulted), snapshots differ, the space did not resume
(by its state, a replaced space, the device, the registry generation, the
import epoch, or a sparse mirror that could not be refreshed), the image
or buffer proof failed, the imports changed, the proof threw, and
read-only buffers that moved after the proof passed. The time of refused
proofs is summed under APS5_PROFILE_DRAW. A reused draw's hold of its
space is counted until its use ends, and host import refusals, over the
budget or of an import that would replace a held one, are counted with
how many came while such a hold was live.

The reused flag travels in the use token BeginUse returns, so the hold
is released with the use count when the token goes, also when a batch
is discarded without running its completions. A proof that throws is
counted on its own, as "threw": the throw can come from resuming the
space, from the proof or from the imports check, and counting it under
any of those would hide an error among ordinary refusals.

APS5_PROFILE_DRAW prints them every 10 s right after the [rescache] draws
line, beside the pin-contention waits of the same window (the
[address-sync] leases line prints those cumulatively on its own timer):
"[rescache] address-based draws: P proofs, R reused; refused: in use N,
..., threw N, moved buffers N; ...; host import refusals: budget B (H
while a reused draw held its space), held import ...; pin-contention
waits W (T ms)".

agc_driver_address_draw_reuse reads the counters: repeated unchanged
draws count as reuses, a draw repeated before the previous one completed
counts one refusal in use, a draw after the guest rewrote its pixel
program counts one refusal for a changed snapshot, a draw after a guest
write into memory it reads in place counts a reuse, the draw after a
fault counts one refusal of a build that is no longer reusable, and a
proof that throws counts one refusal that threw. The BDA resource tests
check that a reused draw's hold is counted while its batch is pending
and released when the batch fails to submit.
…ss reuse proof

The reuse proof of an address-based draw build compares the draw's
snapshots with guest memory for live regions and with the build's
copies for the others. A write that earlier work in the batch recorded
over a snapshot's range (a fill, a copy, a dispatch storing through a
descriptor) may still be pending when the proof runs: memory then still
holds the bytes the capture saw, the proof passes, and the draw runs
after the write on a program the decoder specialized on the old bytes.

Revalidate now syncs the recorder through every snapshot range that a
recorded write overlaps before it compares the snapshots, so the
comparison sees the memory the earlier work leaves, and a capture made
before that write is refused as a changed snapshot. A range with no
pending write costs one overlap test. Stores through the BDA table are
not recorded as pending writes; a later use reads them in place.

agc_driver_address_draw_reuse gains the case: a draw whose snapshots
include the guest pointer its pixel shader reads, reused once, then a
FillBuffer recorded over that pointer and the same draw with the old
capture in the same batch. The draw is refused for its snapshots,
builds again and reads the new pointer; without the sync it was reused
("1 reuses, 0 builds").
Main's boykopovar#7044 gives the build and the dispatch move proof one size
function for a guest buffer, ShaderResources::guestBufferBytes, as this
branch's GuestBufferBytes does for the build, the draw move check and
the address reuse proof. Keep main's clamping in the static
GuestBufferBytes, have guestBufferBytes call it, and drop this branch's
two helpers. Main's depth guard counter and debt entry stay beside this
branch's.
Keeps this branch's configurable mock submit result next to main's mockCmdCopyBuffer in the graphics tests.
Keeps this branch's guestBufferBytes next to main's longer addGuestBuffer signature in ShaderResources.cpp.
importAllocation takes main's step-down for a held or over-budget import
and its pinned byte count; a refusal is counted only where the import is
refused, not where it steps down. A cached space is reused only when every
heap and sparse mirror is still watched or cannot be imported now (main's
check, spaceMirrorsKept), at acquisition and at ResumeSpace, and stamping
its imports follows main's once-per-space use stamps. The BDA test access
keeps both new hooks, submitResult and limitImports.
…th watched imports

jotitadev's macOS run of agc_driver_address_draw_reuse failed at its
ThrowingProof case while imports stay watched: the fast proof found the
sampled image's memory unchanged after MultisampleTargetView took it
over, and the build was reused. Main's 67575aa, merged in the parent,
checks every ordinary sampled and storage range against the multisampled
color targets before either proof, so the case is refused before the
fast proof runs; no Linux test forced watched imports.

agc_driver_address_draw_reuse_watched_imports runs the test with
APS5_WRITE_WATCH_IMPORTS=watch where the switch exists (not on Windows),
and the throwing proof also runs on a draw build without the address
table, whose proof throws as its fresh build does. Without that check,
the watched run fails at "an address-based draw build whose sampled
image's memory became a multisampled target was reused", and both runs
fail at the build without the address table.
…erflows

A use whose stores through the BDA table touch more than 2,048 chunks
of 32 pages, or whose shader finds no free slot for a chunk within its
8 linear probes, sets the record's overflow word. Its completion then
threw "more than 2048 chunks ... are not implemented": the pages the
record did hold were not marked as written, the write-back was
reported as failed, and an address-based build stopped being reusable.

The completion now marks the chunks the record holds, then every
writable range of the build's page table, and clears the overflow
word. That is a superset of what the GPU stored, since a store outside
those ranges faults instead; the guest memory caches over them
revalidate once. The first overflow of a process is reported on stderr.

The handling follows fable-void's 3b1372e on wip/new-gpu-path
("attribute faults in shared records by access ranges and survive
their overflow"), which applies the chunks a shared batch record holds
and then marks the write ranges of every build sharing it. A record
here belongs to one build, whose stores can reach any writable range
of its table, so those ranges are the superset.

Rebased onto boykopovar#6636's head fc9c541: the only conflict was the
debt list, where main's new entries and this one are both kept.
…r use

An address-based compute object was never reusable: noteReusable gave
up on any build with usesBda that was not a draw, so every dispatch of
a program that reaches guest memory through the BDA table rebuilt its
resources, its page table and image table included.

Dispatch builds now take boykopovar#6636's rules for draws. A build whose stages
are address-based is reusable (APS5_NO_ADDRESS_DISPATCH_REUSE=1 builds
each dispatch), and a hit runs Revalidate's address branch: the
snapshots, the cached address space (refused when it was replaced or
its device, registry generation or import epoch moved, or a mirror
could not be refreshed), the build's image and buffer proof and the
space's imports. Each dispatch takes the space for its batch and
suspends it after recording, so between dispatches the build pins no
guest allocation and a guest free does not wait for it. Reuses and
refusals go to the address reuse counters, whose [rescache] line now
reads "address-based draws and dispatches".

Unlike a draw, a dispatch is not refused while an earlier dispatch of
its build is in flight, since several dispatches of one program per
batch are common. The build's fault buffer holds the fault report and
written-page record of one use, so the first use in flight takes it
and every other concurrent use takes a spare: a fault buffer of its
own and a descriptor set that repeats the build's writes with that
buffer in the fault binding. The use's completion checks its own
record, so a fault is reported by the dispatch that made it and each
dispatch marks its own written pages. The spare returns to the build's
pool when the use ends and serves a later concurrent use; the build's
descriptors do not change after the build, so a pooled set stays
valid. A fault makes the build non-reusable, as for draws.

Dispatch recipes still require a build without completion work, so an
address-based build never gets one: a recipe's validation proves
neither the space nor the snapshots.

A record per use follows fable-void's 26ff0b4 on wip/new-gpu-path
("take each dispatch's BDA table and fault record from pooled slabs").
It replaces the shared batch record of his a7015cd ("share one
fault record among the address-based builds of a batch"), whose faults
needed 3b1372e's attribution by access ranges; a record that one use
owns needs no attribution.

In BF-033's dispatch binding harness on lavapipe (one wave per
dispatch, APS5_IMAGE_TABLE_CAPACITY=4096, APS5_LOOKUP_LOG_BOUND=8192
at 2,000 textures), the driver's time per address-based dispatch, as
the median of five 10 s windows, on boykopovar#6636's head and with this change:

  textures   one dispatch per submission   eight per submission
  1          374 -> 77 us                  1,684 -> 24 us
  16         519 -> 76 us                  1,600 -> 28 us
  128        798 -> 123 us                 1,845 -> 57 us
  2,000      5,032 -> 699 us               2,232 -> 647 us

The head builds on every dispatch (no cache hit); with the change each
run builds once and reuses the build for the rest, eight concurrent
uses per batch included.

agc_driver_address_dispatch_reuse covers the cases, each red on
boykopovar#6636's head (89ab0ea) and green here:
- repeated dispatches with unchanged inputs are reused and counted,
  four in one batch over two blocks too;
- a changed word of the program snapshot rebuilds and counts one
  snapshot refusal;
- of two reused dispatches in one batch, only the faulting one reports
  a fault, and two faulting ones each report their own address;
- a dispatch rewriting the SRT that a later reused dispatch of the
  batch reads is seen by it, and a fill recorded over a captured SRT
  refuses the reuse as a changed snapshot;
- a guest free while a reused build is cached, and while a reused
  dispatch is in flight, returns at once;
- a dispatch storing to 3,072 chunks overflows its written-page record
  without failing and is reused after it.

The BDA resource unit test (agc_driver_graphics) expected an
address-based dispatch build not to be reusable; it now expects one to
be reusable unless APS5_NO_ADDRESS_DISPATCH_REUSE=1 is set.

Rebased onto boykopovar#6636's head fc9c541, which carries main's 89d255c
(compute templates served with moved read-only buffers) and the SRT
guard word in the fault buffer. Main's moved-buffer proof refuses
address-based builds, so an address-based hit skips it, in
PrepareDispatch and in the dispatch; every other hit takes main's path
unchanged, and a dispatch binds either main's moved-buffer set or its
use's fault-record set. A use's own fault record clears the SRT guard
word as the build's does, and the guard is read from that record. As
WriteBackBuffers does since main's c0588d2, a use that reports an
unaligned BDA access marks its writes before the report; the new
unaligned case runs such a use.
With Celegans12's change 8104, an address-based compute build stages a
written element in device memory as an overlay region of its import: the
region is a GPU copy (gpuCopy, deviceLocal) with no direct pointer.
SpaceRegions refused every region that was neither direct nor a fixed
mirror, so noteReusable never marked such a build reusable and each
dispatch of it rebuilt.

A staged region is safe to reuse. proveBuild records its copy-in from the
import anew for each reuse (RecordStagingCopies), MarkGpuWrites records
the copy-back of its written ranges after each use (RecordCopyBacks), and
its range is held to the serial of the import it lies in like a direct
region. Count it as a space region.

Address-based builds do not stage before that change, so on its own this
changes nothing.
@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line labels Oct 21, 2026
@github-actions

Copy link
Copy Markdown

This pull request is labeled perf, so it needs the summary line of a capture on main and one with the change, from the same title, scene and machine, as the Performance report form asks. Please paste both aps5-summary.jsonl lines, attach the two traces and add the output of tools/trace_digest.py.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6273 docs/dev/debt/libSceAgcDriver.md L228
PR 6804 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp L488, L625-626
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L2497-2499
PR 6959 docs/dev/debt/libSceAgcDriver.md L228
PR 7233 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4928
PR 7261 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L2497, L2502-2503, L2520-2521
PR 7371 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4928
PR 7618 docs/dev/debt/libSceAgcDriver.md L228
PR 7647 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp L493
PR 8099 docs/dev/debt/libSceAgcDriver.md L228

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.

Pull request Shared files not compared
PR 1191 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 1896 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 4448 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4449 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5372 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5404 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 5431 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 5441 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5499 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5609 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6044 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/ENVIRONMENT.md
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6197 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6290 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6501 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6539 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6548 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6628 core/libs/prx/libSceAgcDriver/Graphics/include/BdaResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BdaResources.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
PR 6747 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6788 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6868 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6879 docs/dev/ENVIRONMENT.md
PR 6887 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6918 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
PR 6924 docs/dev/ENVIRONMENT.md
PR 6946 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 6947 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/BdaResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BdaResources.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 6960 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6965 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6973 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6987 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6989 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6995 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7002 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/BdaResources.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7484 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/ENVIRONMENT.md
PR 7505 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7514 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7800 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7803 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7883 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7893 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7910 docs/dev/debt/libSceAgcDriver.md
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 8014 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8077 docs/dev/ENVIRONMENT.md
PR 8105 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8212 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8278 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8339 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 8538 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8552 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8564 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 8612 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8881 core/libs/prx/libSceAgcDriver/Graphics/src/BdaResources.cpp
PR 8992 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9020 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9077 docs/dev/debt/libSceAgcDriver.md

main brings boykopovar#8224, which cuts a read-only strided buffer that runs less
than one stride into the render target at the target, in addGuestBuffer
and in CheckBufferAliases. CheckBufferAliases keeps this branch's
GuestBufferBytes size and applies main's cut to it, as addGuestBuffer
does after guestBufferBytes.
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
…uild does

Since boykopovar#8224, a read-only strided buffer that runs less than one stride
into the render target is bound only up to the target, and the cached
build keeps that size. MovedReadOnlyBuffers compared it with the size
without that cut, so a hit with the same words took the buffer as moved
and rebound all of it, over the render target, and an address-based
build holding such a buffer was never reused.

GuestBufferBytes takes the target and applies the cut. The build,
CheckBufferAliases and MovedReadOnlyBuffers pass the draw's target for
read-only buffers, so all three size a buffer the same way.

agc_driver_graphics checks a cached build whose read-only stride-60,
4-record buffer runs 8 bytes into the target: the same words list
nothing moved, a buffer moved to run 4 bytes in is listed at 236 bytes,
and one moved to run a whole stride in keeps its 240.
The entry described each proof the reuse makes. It now names where they
are (ShaderResources::Revalidate) and keeps what stays open: one draw at
a time per build, no reuse for dispatches and draw recipes, and no
measurement in a title. It goes from 1,537 to 871 characters.
boykopovar#6636 merges main (with boykopovar#8224), sizes a moved read-only buffer at the
render target as its build does, and cuts its debt entry to the gaps.
The entry here keeps that shorter form and adds this branch's
dispatches: the dispatch switch, a dispatch's own fault buffer and
descriptor set for a repeat in one batch, and recipes for both.
@github-actions github-actions Bot added build docs agc libSceAgc* needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 21, 2026
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

Closing this together with #6636. It reuses address-based dispatch builds through the same proof, and #6636's Resident Evil Village (PPSA01556) runs show that proof refusing every draw build at the menu, because the reads' addresses move with each draw (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs perf numbers missing perf pull request without a before and after summary line perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant