Commit Graph

760 Commits

Author SHA1 Message Date
ParantezTech 81dfcb3bd7 Merge remote-tracking branch 'origin/main' into perf_computed_shaders 2026-10-03 04:25:31 +03:00
Mathias e01198a147
Fix/gen5 shader resource handling (GTA 5) (#1015)
* fix(gpu): upload complete dirty pages for cached image sources

* perf(shader): hoist single-block loop entry guards

* fix(shader): support scalar quad masks in resource analysis

* fix(gpu): use native Vulkan fill for three-vertex rectangles

* test(stdio): wait directly for concurrency workers
2026-10-03 04:00:32 +03:00
ParantezTech a2dbecb26f [Docs] Document the pipeline cache modes and the shader prewarm list
Adds SHARPEMU_SHADER_PREWARM, SHARPEMU_VK_PIPELINE_CACHE_SHARDS and
SHARPEMU_VK_PIPELINE_CACHE_LEGACY_SHARDS, and describes the new cache
file default.
2026-10-03 02:33:41 +03:00
ParantezTech ed70f697a3 [Vulkan] Keep the pipeline cache in memory on Windows
The GPU driver keeps its own shader cache on disk, and the shader prewarm
list rebuilds it after an update, so Windows no longer writes the driver
cache file by default. SHARPEMU_VK_PIPELINE_CACHE=file keeps one; Linux
keeps the file and macOS keeps its shards.
2026-10-03 02:33:41 +03:00
ParantezTech 3ba3650f59 [Vulkan] Prewarm the recorded compute pipelines after a translator or driver change
A first run after a translator change compiled every compute pipeline
one at a time while the render thread waited (Demon's Souls: 282
pipelines, 144 s). When the translator assemblies or the driver differ
from shader-prewarm.stamp, background threads at below-normal priority
translate the listed programs again and create their pipelines, so the
driver has them before the game asks. With the same build and driver the
launch does no prewarm work. The log reports the prewarm result and how
many runtime compute modules it produced.
2026-10-03 02:33:41 +03:00
ParantezTech 0cd7cf10ff [Gpu] Record compiled compute programs in a shader prewarm list
When the pipeline host gives a list, each compute permutation the game
compiles is appended at once to shader-prewarm.bin: the guest code the
decoder read (once per program), the fused parts, the compute input, the
system registers, the resource specialization and the push data start.
Records carry a checksum, so a cut tail is dropped at the next open.
TryCompilePrewarm rebuilds the compile request from a record through the
same layout and request code as the runtime, so it produces the same
SPIR-V.
2026-10-03 02:33:41 +03:00
ParantezTech d88c14ef71 [Vulkan] Remove the single-file cache once the shard mode takes over
The shard mode never reads the single cache file of the default path, so
it is deleted instead of staying on disk.
2026-10-03 02:33:41 +03:00
ParantezTech cfcebc4cd9 [Vulkan] Write only the cache shards that gained pipelines
A shard remembers the driver size it was loaded or saved with and is not
written again while that size holds. Shard saves are logged as one
summary line, and a shard load only when it is slow.
2026-10-03 02:33:41 +03:00
ParantezTech 825d72f0fa [Vulkan] Keep saving a pipeline cache that outgrows its limit
A driver cache over 256 MiB was refused on every save, so it was never
written again and every launch compiled the same pipelines. Such a cache
is now written as an empty file once, and the next launch starts a fresh
one. A save is skipped when the driver reports the size that was loaded
or last saved, and a failed or deferred save waits for the next interval
instead of running again on every new pipeline.
2026-10-03 02:33:41 +03:00
ParantezTech 5516f4d3d1 [ShaderCompiler] Return the entry header address of a registered fused program
An overload of TryGetFusedProgramParts also gives the entry header, so a
caller can register the same fused program on another memory.
2026-10-03 02:33:40 +03:00
Mathias 6cac2b5f47
fix(agc): patch indirect-buffer continuation links (#1012) 2026-10-03 00:51:09 +03:00
ParantezTech 90b1cafe6d Merge remote-tracking branch 'origin/main' into perf_computed_shaders
# Conflicts:
#	tests/SharpEmu.Libs.Tests/Agc/Gen5WaveMaskSpirvTests.cs
2026-10-02 20:07:35 +03:00
ParantezTech 027e421271 [PhtreadSpecificSemanticsTests] Fixes for computed shaders 2026-10-02 19:55:12 +03:00
ParantezTech 7041911bb3 [AudioIn] Answer sceAudioInGetSilentState without an input backend
No AudioIn port can be opened until an input backend exists, so the export
returns an AudioIn error code (0x80260101) instead of being an unresolved
import.
2026-10-02 19:16:45 +03:00
ParantezTech 20e8a18009 [Font] Implement sceFontTextSourceInit
Fills the 0x60-byte text source with the text range, the cursor, the parser
callback and its object, and the text size, and leaves the memory after it
untouched.
2026-10-02 19:16:45 +03:00
ParantezTech 67f11e78ea [Json] Add the sce::Json::Value copy constructor and keep shadow values on copies
The copy constructor (fSb2oQTNrgA) shares the assignment path. Assignment
and reads now carry the value a constructor or setter recorded in the object
heap, so a copy keeps it after the source is destroyed.
2026-10-02 19:16:45 +03:00
ParantezTech 542786420e [Gpu] Merge the stencil replacement references of a face
Vulkan has one stencil reference per face for the comparison and every
replace operation. Replacements with the test value and with the operation
value are now merged into that reference over the written bits, and refused
only when they conflict on bits the comparison also reads. A replacement
with an operation value of zero over the written bits becomes a zero
operation, which ASTRO's PLAYROOM uses to clear one stencil bit.
2026-10-02 19:16:45 +03:00
ParantezTech 9148c5e184 [ShaderCompiler] Decode S_CMOV_B64 as a conditional select
S_CMOV_B64 is decoded as S_CSELECT_B64 with the old destination pair as the
false source, so it reuses the SCC, register-pair and EXEC handling of the
translators and of the scalar value graph.
2026-10-02 19:16:45 +03:00
ParantezTech 78a24f24b5 [Agc] Implement the legacy sceAgcFuseShaderHalves export
The older NID (nApJjpKNBl4) shares the fusing path but keeps the front half's
user data pointer, takes the larger value of the resource allocation fields
of both halves, takes the user SGPR count and the ES component flag from the
front half, and copies the checksum register of the matching stage.
2026-10-02 19:16:45 +03:00
ParantezTech 02e3040acf [ShaderCompiler] Key fused programs by the underlying guest memory
Each native guest thread wraps the guest memory in its own tracking wrapper,
so a fused program registered while one thread created the shader was not
found by the render context. The registry now unwraps ICpuMemoryWrapper
before it looks up the per-memory table.
2026-10-02 19:16:45 +03:00
ParantezTech 4eea0075f8 [GpuCommands] Let a wait see its own queue's preceding label store
A memory wait that directly follows a 4- or 8-byte store of its queue to the
same address, with only waits or inert NOPs and markers between them, compares
against the stored value when guest memory no longer holds it. Dead Cells
writes a label and waits for it while the CPU already rewrites it for the next
frame. The forwarded value lives only within one slice, and any draw, dispatch
or transfer in between drops it.
2026-10-02 19:16:45 +03:00
ParantezTech 72eb9dbfd9 [GpuCommands] Write the 64-bit label of a compute-done release with an interrupt
RELEASE_MEM with event 0x2F and a 64-bit data selection was accepted only
without an interrupt. It is now handled like the other end-of-pipe events:
the label is written and the interrupt is raised after it.
2026-10-02 19:16:45 +03:00
ParantezTech ae94230c8b [Docs] Document the new environment variables
Adds SHARPEMU_ASYNC_GUEST_READBACK, SHARPEMU_GPU_WAIT_SPIN_US,
SHARPEMU_IMAGE_LOOKUP_MEMO, SHARPEMU_RESOURCE_PREFETCH,
SHARPEMU_SUSPEND_POINTS_IN_FLIGHT, SHARPEMU_RENDER_CORE,
SHARPEMU_TRACE_DCC_WRITERS, SHARPEMU_TRACE_GPU_READS,
SHARPEMU_TRACE_WRITER_ADDRESS and SHARPEMU_PROFILE_GPU_DRAWS, and corrects the
group counts to the rows the tables hold.
2026-10-02 19:16:37 +03:00
ParantezTech 166a340950 [Gpu] Throttle the device-address fault and 3D slice range logs
Little Nightmares wrote 195 thousand "Accessed non-GPU cached memory" lines in
one session and Silent Hill 6800 slice range lines. Both now print the first
occurrences and then only at power-of-two counts, with the count.
2026-10-02 19:16:37 +03:00
ParantezTech 6283b7a802 [Agc] Make the number of suspend points in flight configurable
CommandStreamQueue takes the number of frame boundaries that may wait behind
the graphics commands. The default stays one, so the guest CPU can run one
frame ahead, and SHARPEMU_SUSPEND_POINTS_IN_FLIGHT=0 makes a suspend point
wait until its own boundary is processed, for diagnosis. Tests cover both
modes, including a label that the CPU rewrites after the suspend point.
2026-10-02 19:16:29 +03:00
ParantezTech 825f0085cc [Tests] Cover the deferred global barrier of an attachment-only scope
A global barrier still ends a scope whose draws store to memory. In a scope
whose draws only write attachments it waits for the scope to end, and a later
memory-writing draw ends the scope and records it.
2026-10-02 19:03:44 +03:00
ParantezTech 901548fcbb [Gpu] Collect an image only once it is old enough in frames
Since images age by frame, clamping the age to the current frame made every
image of the first frame collectable during the first 16 frames, and a
submission that ended no frame could delete a texture the frame still used.
Without memory pressure nothing is collected until the full age has passed;
under pressure the clamp still lets collection relieve memory early.
2026-10-02 19:03:44 +03:00
ParantezTech 1b3c380137 [ShaderCompiler] Decode fused programs whose halves are far apart
The fused decoder joined the continuation at its address distance from the
entry and refused halves more than 4 GiB apart or in the wrong order, which
Poppy Playtime now hits for a vertex shader (invalid-fused-layout). Such a
continuation is placed right after the entry instead, and each of its
instructions keeps its real offset from the program address in AddressOffset;
S_GETPC_B64 in the scalar graph, the SPIR-V and the MSL translators uses that
offset, and the persisted scalar analysis key includes it.
2026-10-02 19:03:43 +03:00
ParantezTech 521360f04b [ShaderCompiler] Look up fused programs without the registry lock
Every shader header lookup and decode asked the fused-program registry under
its lock. The registry now publishes an immutable dictionary that readers
take with a volatile read, and a registration copies it under the lock.
2026-10-02 19:03:43 +03:00
ParantezTech 2a42567bcf [Gpu] Reuse image lookups that found the same backing
FindImage remembers, in a 256-slot table, each request that resolved to an
image with the same backing, keyed by the request bytes and a generation
that every index registration or removal advances. A repeated request
touches the image and returns the remembered result without walking the page
owner index. SHARPEMU_IMAGE_LOOKUP_MEMO=0 turns it off; [PERF][IMAGE_LOOKUP]
reports hits and misses.
2026-10-02 19:03:43 +03:00
ParantezTech f125d17510 [ShaderCompiler] Prefetch contiguous resource words in one resident read
Resource materialization read every descriptor and flattened-table word
through its own guarded TryReadGuestWord call, about 2.6 million per five
seconds in Demon's Souls. The raw reads of each plan are grouped once; at run
time their addresses are resolved, sorted and read as contiguous runs through
the resident guest reader, and the values seed the evaluator cache. A run the
GPU may still own, or one out of bounds or through a null base, falls back to
the word reads. The cache recorder records the prefetched words, and
SHARPEMU_RESOURCE_PREFETCH=0 turns the prefetch off.
2026-10-02 19:03:43 +03:00
ParantezTech 6277441eb3 [Gpu] Read GPU-written guest memory back asynchronously and ahead of time
VulkanAsyncReadback keeps eight slots: slot zero serves synchronous reads and
the others carry asynchronous downloads. A guest thread that reads GPU-written
memory lets the render thread start the copy and waits for it on its own
thread, then the render thread applies it if the range is unchanged; a
foreign read keeps the source buffer alive until it completes.

Windows the render thread had to read synchronously become hot. When a batch
writes into a hot window, the window is downloaded right after the batch is
submitted, and the next read uses that copy if it is still current. A pending
write to a hot window ends the open batch early. SHARPEMU_ASYNC_GUEST_READBACK=0
keeps the synchronous path; [PERF][ASYNC_READBACK] reports the counts.
2026-10-02 19:03:37 +03:00
ParantezTech 46a9dd223d [VideoOut] Read resource words through cached clean pages and the backing alias
TryReadGuestWord and TryReadResidentGuestBytes remember the last 64 pages
found free of GPU-dirty bytes, keyed by the GPU-modified version, and read
them through the backing alias inside the alias access window that each
command stream slice now holds. GPU-dirty checks are byte-precise, and a
resident read refuses unreadable ranges before it asks the page tracker.
2026-10-02 19:03:37 +03:00
ParantezTech afa7018e13 [ShaderCompiler] Keep recent materialization variants per draw key
A cache key now holds up to four materializations in most-recently-used order,
so alternating descriptor contents reuse their earlier result instead of
re-materializing. The cache report counts stale and unreadable entries and
table refreshes, and ReadingTable tells a reader when the flattened table is
being evaluated.
2026-10-02 19:03:37 +03:00
ParantezTech 64d885981a [Diagnostics] Trace shader resource reads that wait for GPU-written memory
SHARPEMU_TRACE_GPU_READS=1 writes the shader, stage, address and table phase
of a resource read that has to synchronize GPU-written memory, once per shader
and page.
2026-10-02 19:03:21 +03:00
ParantezTech 8324faed84 [HLE] Resolve backing aliases for readers that hold an access window
SharedBackingViews publishes its view snapshot as an alias identity, and a
reader can enter an alias access window once and resolve guest pages to their
backing alias without the views lock until the snapshot changes.
2026-10-02 18:48:24 +03:00
ParantezTech e47798a854 [Gpu] Turn AGC fill compute shaders into buffer fills
BoundedFillDetector recognizes the AGC range-fill and pattern-fill compute
programs, including thread-dimension dispatches, and a dispatch of one that
targets DCC metadata becomes a DCC fill instead of a compute dispatch.
Refused conversions are reported by the DCC writer trace.
2026-10-02 18:48:12 +03:00
ParantezTech 73eace56b0 [Gpu] Fill DCC metadata on the GPU and in guest memory at once
A fill that targets DCC metadata which no GPU write owns is recorded as a GPU
fill and also written to the guest backing directly, so the range never
becomes GPU-dirty and later CPU reads need no readback. Ranges the GPU still
owns or that overlap an image keep the plain buffer fill.
2026-10-02 18:48:11 +03:00
ParantezTech 42182ebcb8 [Diagnostics] Trace the GPU writers of DCC metadata and of a chosen address
SHARPEMU_TRACE_DCC_WRITERS=1 writes the shader program and a call stack for
GPU buffer writes that overlap DCC metadata; SHARPEMU_TRACE_WRITER_ADDRESS
does the same for writes that cover one guest address.
2026-10-02 18:48:02 +03:00
ParantezTech 792953c90b [Gpu] Track the extent of DCC metadata and answer overlap queries
A color target records the size of its DCC metadata, and the image cache can
tell whether a guest range overlaps registered DCC metadata.
2026-10-02 18:48:02 +03:00
ParantezTech 7085532257 [Gpu] Version the GPU-modified buffer ranges
A written range bumps GpuModifiedVersion only when it adds bytes to the
GPU-modified set, so readers can cache a clean verdict for a page until the
GPU writes something new.
2026-10-02 18:47:46 +03:00
ParantezTech 50bd6a9e11 [Gpu] Skip syncing a written buffer range that is already GPU-owned
SynchronizeBuffer returns early when a written range lies entirely in the
GPU-modified ranges, uses the lock-free CPU-dirty query for reads, and the
render profile splits buffer sync time into written, texel and upload parts.
2026-10-02 18:47:22 +03:00
ParantezTech f2d55afe69 [GpuMemory] Scan possibly CPU-dirty blocks 64 at a time
ForEachPossiblyCpuDirtyRange combined a region lookup and a summary read for
every 4 MiB block of mapped memory on each device-address sweep. A bitset of
blocks that have a region and the dirty summary words are now scanned a word
at a time, with the same runs as before.
2026-10-02 18:47:22 +03:00
ParantezTech 87c5195ba3 [Gpu] Skip the device-address sweep while no page became CPU-dirty
PrepareBda remembers the CPU-dirty epoch and the mapping it swept last and
skips the full sweep of mapped memory until either changes.
2026-10-02 18:47:15 +03:00
ParantezTech defa313acc [GpuMemory] Answer CPU-dirty range queries without the tracker lock
MayHaveCpuDirtyPages reads the per-block summary and the region masks without
taking the region lock; a true answer still goes through the locked path.
Regions also bump a CPU-dirty epoch whenever a page becomes CPU-dirty.
2026-10-02 18:47:15 +03:00
ParantezTech 9fa858a82a [Vk] Spin briefly before blocking on a GPU wait
A GPU wait polls the timeline for SHARPEMU_GPU_WAIT_SPIN_US microseconds
(150 by default) before it sleeps, which saves the wake-up latency when the
work completes soon.
2026-10-02 18:47:06 +03:00
ParantezTech 6fad30011b [HLE] Reserve a host core for the render thread
On Windows hosts with 8 to 64 logical processors the render thread gets the
last physical core of the fastest efficiency class at the highest priority,
and guest threads are kept off that core so spinning job workers cannot take
the renderer's SMT sibling. SHARPEMU_RENDER_CORE=0 turns it off.
2026-10-02 18:47:06 +03:00
ParantezTech 82be3a52bf [Vk] Measure GPU busy time from per-submission timestamps
Per-draw timestamps are written only with SHARPEMU_PROFILE_GPU_DRAWS=1; by
default each submission gets two timestamps and the overlapping intervals
are merged into a [PERF][GPU_BUSY] line with the busy share and the longest
submission.
2026-10-02 18:46:58 +03:00
Mathias 6cebf7ec56
Fix/vulkan wave64 ballot masks (#1011)
* fix(shader): preserve wave64 ballot masks on Vulkan

* test(shader): cover subgroup lane bits in wave mask predicates
2026-10-02 15:10:39 +03:00
kuba 6d138afb13 [Vulkan] Forget driver cache identities of destroyed shader modules
The remaining change of the updated #1006 head (e6659681) that the integration branch did not carry.
2026-10-02 14:22:25 +03:00