Commit Graph
10 Commits
Author SHA1 Message Date
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