Commit Graph
12 Commits
Author SHA1 Message Date
Mac 491dd71b2a graphics: account for device memory the way VMA sees it
The caches decided when to collect from the driver's process-wide usage
estimate, which varied by about 4x between reads of the same moment on this
setup and is not what the allocator is holding. Read VMA's own accounting
instead, and let the collector stand down on the same figure it stood up on
rather than a stale tally.

Adds a small deferral guard so a completion callback cannot re-enter the
resource caches while the caller still holds their state.
2026-08-31 23:41:16 +05:30
Mac e77041b6f5 graphics: size the buffer and page-table constants explicitly
Names the upload/stream/download/device-local buffer sizes instead of repeating
literals, and makes the BDA page-table address width explicit.

Two of these are behaviour changes and are the ones to look at:

- DOWNLOAD_BUFFER_SIZE is raised from 32 MiB to 128 MiB. Marvel's Spider-Man:
  Miles Morales asks for a single 80 MiB download allocation, which 32 MiB
  cannot serve; the run dies with 'failed to map reusable download buffer,
  size=0x5000000'. This costs every title the larger reservation.
- CACHING_ADDRESS_BITS is 39, where the table previously covered 40 bits. That
  halves the BDA page table from 512 MiB to 256 MiB, at the cost of covering
  guest addresses only to 512 GiB. 38 bits was tried first and was too narrow -
  it produced an intermittent DMA barrier on an address just past 2^38.

The address-width reduction in particular is tuned against one title; if the
1 TiB window is load-bearing for something else, take the naming and leave the
value at 40.
2026-08-31 23:41:14 +05:30
Mac 3cd6ff0a3f graphics: pass the real patch control point count for tessellation
Tessellation draws were created with a hardcoded 3 control points per patch.
Take the count from VGT_LS_HS_CONFIG.HS_NUM_INPUT_CP instead, and key the
pipeline cache on it so patches of different sizes do not share a pipeline.
2026-08-31 23:40:51 +05:30
Mac ce782ef77f recompiler: allow a shader to be refused instead of aborting
A shader the recompiler cannot translate is a gap in emulation, not a reason to
take the process down: skipping the draw or dispatch that wanted it costs some
rendering, while aborting costs the title.

CompileOptions gains non_fatal and CompileResult gains unsupported. With
non_fatal set, the three places the recompile path gives up - an opcode with no
IR translation, a CFG that will not build, and resource tracking that cannot
resolve a descriptor - record the failure and unwind rather than calling EXIT,
and Recompile returns a result marked unsupported. The caller skips that draw or
dispatch. Nothing changes when non_fatal is clear.

Marvel's Spider-Man: Miles Morales meets an untranslatable compute shader on its
third frame, so a strict build cannot pass the opening logo. Astro's Playroom is
also stopped by a shader today and reaches a later, different failure with this
in place.
2026-08-31 23:40:50 +05:30
Mac a2cafb2f2c shader: resolve and inline S_SWAPPC_B64 indirect calls
The callee of an indirect call is not in the shader binary. It lives elsewhere
in guest memory and is never dispatched, so it is never compiled - the scan
finding zero S_SETPC_B64 across every compiled shader is the same fact seen from
the other side.

The target arrives through a descriptor chain rooted in user data. Resolving
that chain inside the recompiler would need the SRT walk, which needs the shader
to translate, which is what the unhandled S_SWAPPC_B64 prevents. Resolving it
from the dispatch side, where the user data is already in hand, avoids that
circle: find each call site, fetch the callee, and splice it in before
recompiling.

Each table entry is a {function, context} pair; the caller moves the first half
into the call-target registers and the second into the next pair as an argument,
so inlining at the call site needs no argument marshalling.
2026-08-31 23:40:33 +05:30
Mac c944a2f7ad shader: structurize loops whose selection merge escapes
A conditional inside a loop where exactly one arm stays in the loop body has its
real merge at the arm that stays, not at the block the generic search finds.
Without this the CFG is rejected as unstructured and the shader falls back to
the dispatcher.

Also splits selection merges shared between a break and its continuation, which
the same shaders rely on.
2026-08-31 23:40:32 +05:30
Mac f14fb8c9df shader: resolve typed phis and ReadFirstLane in the SRT walker
Two descriptor chains this title uses could not be resolved:

- A descriptor whose address arrives through a phi. Walk the phi to its leaves
  and accept the result when they agree, or when exactly one is a real address
  and the rest are null/sentinel.
- A descriptor read through ReadFirstLane. This is safe for non-image
  descriptors, where every lane holds the same handle, so accept it there. Image
  descriptors keep the old restriction, gated by the dword count.
2026-08-31 23:40:30 +05:30
Mac 02aadec124 shader: preserve inactive lanes in buffer loads
A buffer load wrote its destination unconditionally, clobbering lanes the exec
mask had masked off. Select against the previous value so inactive lanes keep
what they held.
2026-08-31 23:40:12 +05:30
Mac d6d7b81099 shader: emit a real ballot for S_CMP on an exec mask
S_CMP_{EQ,LG}_U64 against a mask operand and zero is the idiom for 'are any
lanes live'. Treating it as a scalar compare loses the per-lane information, so
emit an actual ballot for that shape.
2026-08-31 23:40:11 +05:30
Mac 727e7d1930 shader: lower wave64 subgroup broadcast workgroup-wide
OpGroupNonUniformShuffle with Subgroup scope only reaches 32 lanes on this
hardware, but GCN wave64 code expects all 64. A decoupled-lookback prefix scan
broadcasts its ticket across the whole wave, so the subgroup-scoped lowering
silently read the wrong lane. Lower the broadcast across the workgroup instead.

DS_BPERMUTE and DS_SWIZZLE keep the raw subgroup id: they are defined on
independent 32-lane halves and must not be widened.
2026-08-31 23:40:09 +05:30
Mac 758bfe1513 shader: decode V_CMP_LT_U64
The 64-bit unsigned less-than compare was missing from the VOPC table, so any
shader using it failed to decode.
2026-08-31 23:40:08 +05:30
Mac c8f34f94d3 build: fix clang-cl compile of ResourceTracking
Tracker::IndirectImagePlan lives in an anonymous namespace, so std::projected
cannot be formed for it and the three std::ranges algorithms over
m_indirect_images fail to compile under clang-cl with the MSVC STL:

  error: function 'std::projected<..., std::identity>::operator*' is used but
  not defined in this translation unit, and cannot be defined in any other
  translation unit because its type does not have linkage

Using the iterator-pair overloads compiles and is otherwise identical.

Seen with clang-cl and MSVC 14.29 (VS2019) STL. CI does not catch this because
its build targets are launcher and the smaller test binaries; kyty_emulator,
which is what pulls in this file, is never built there.
2026-08-31 23:39:50 +05:30