Commit Graph

8695 Commits

Author SHA1 Message Date
Sylpheed RE agent
c1b57f93bb [RE] threading_posix: fix a lost resume that left CREATE_SUSPENDED threads dead
A thread created suspended publishes its state and its suspend count in TWO
separate lock scopes:

    { lock; state_ = kSuspended; notify_all(); }        // lock released here
    if (create_suspended) { lock; suspend_count_ = 1; wait(count == 0); }

and Resume() does WaitStarted() - which waits only for state_ != kUninitialized -
followed by `if (suspend_count_ == 0) return false;`. So a resumer can slip into
the gap: it sees the thread started, sees suspend_count_ still 0, drops the
resume and returns false. The new thread then sets the count to 1 and waits on it
forever. A textbook lost wakeup.

Measured in Project Sylpheed. Pressing (A) on the title makes the game do
XamUserGetXUID -> NtCreateEvent -> ExCreateThread(entry=821748F0,
CREATE_SUSPENDED) -> NtResumeThread, and the loader thread then never ran: zero
kernel calls of its own (it appeared in the log only as an argument) and 00:00:00
host CPU time, while the emulator sat at 546% CPU. Boots reached the main menu
1 time in 6.

Fixed by publishing state_ and suspend_count_ under one lock and waiting without
releasing it, so a resumer past WaitStarted() always observes 1.

On the first clean boot after the fix the same loader thread is the CALLER on 20
kernel-call lines and issues 4 ResolvePath asset reads. Every failed boot before
it had exactly zero of both.

Also logs when the host resume is refused. XThread::Resume's Linux path
discarded that bool - the Windows path turns it into X_STATUS_UNSUCCESSFUL - so a
dropped resume was invisible from both sides. Note the log is not by itself a
defect: resuming a thread that is not suspended legitimately returns false, and
it fires ~7 times in a normal boot.

(cherry picked from commit a60fe7d11c)
2026-08-19 18:24:44 +00:00
91200ca993 [HID] file-pad: implement GetKeystroke -- menus do not read GetState
The pad looked correct and did nothing. Its own log showed A arriving, the
emulator sat on "PRESS (A) BUTTON", and the title never advanced.

Cause: 360 front-ends poll XamInputGetKeystrokeEx, not XamInputGetState. This
title imports both, and its menus use the keystroke path; the driver returned
X_ERROR_EMPTY there, so every scripted press went into the void while GetState
faithfully reported a button nobody asked about.

Implement it edge-triggered, one event per call: KEYUPs for everything released
first, then KEYDOWNs, matching the SDL driver's ordering (so a thumb transition
clears before it sets). Deliberately NO auto-repeat -- scripted input wants
exactly one event per press, and repeat is precisely what makes menu steps
overshoot. Bits without a virtual key (guide, unused) are swallowed rather than
re-offered forever.

Verified on the real game: title -> main menu -> EXTRAS driven entirely from the
pad file, with `[file-pad] keystroke vk=5800 down/up` in the log for each press.

(cherry picked from commit 15fe11d5d9)
2026-08-19 18:07:57 +00:00
47209a1cbd [HID] file-pad: nanosecond change detection, and log every state change
Two things that only show up once you actually script this pad.

st_mtime is whole seconds. Combined with size it looked like enough and is not:
a script stepping a menu writes several same-length states per second
(`press=A` then `press=B`, both 8 bytes), and every one after the first was
silently dropped -- the emulator simply did not react, with nothing in any log
to say why. Compare st_mtim.tv_nsec as well, and track whether the file existed
at all so a delete is registered once rather than every frame.

Also log one line per state change (not per frame, so it stays quiet). Driving
the emulator headless means there is nothing to watch; this line is the only
proof that a scripted press was picked up, which turns "did my input land?" from
a guess into a grep.

(cherry picked from commit e3e17e4951)
2026-08-19 18:07:57 +00:00
cbfad1ab36 [HID] file-pad: a controller driven by a text file, for scripted RE
The scripted-input tool this project uses for reverse engineering created its
pad through /dev/uinput. Input devices are NOT namespaced by the kernel, so a
uinput device created inside a container registers with the HOST's input stack:
every trigger hold and button press is delivered to whatever on the host reads
gamepads, not just to the emulator. That was noticed the hard way, and it made
every runtime experiment -- booting, menu navigation, unit harvesting, flight
measurement -- unusable from inside the box.

This driver takes the kernel out of the loop. Pad state lives in an ordinary
text file only the container can see; GetState re-reads it when it changes.
Nothing is registered with the host and no X server is involved. A bonus for RE:
analogue values are exact rather than whatever a virtual stick quantises to.

    press=A,START     buttons by name, comma separated
    buttons=0x1010    or the raw XINPUT mask
    lt=0 rt=255       triggers, 0..255
    lx=0 ly=0         thumbs, -32768..32767

Absent keys are neutral, so `press=A` alone is a valid file, and a missing or
empty file means no input -- the safe default if it is deleted mid-run.

Selected with --hid=file, path from --pad_file (default /tmp/xenia_pad.txt).
Deliberately NOT part of "any": this pad has to be asked for. Header-only, so it
adds no build target and no cost to anyone not using it.

(cherry picked from commit d15c8cfab6)
2026-08-19 18:07:57 +00:00
Gliniak
a5a18f5c75 [Misc] Random optimizations.
- Seems like it improves performance in debug, not sure about release

- Stuff suggested by AI
2026-08-18 11:43:52 +02:00
Clippy95
4cc584f47d [D3D12] Fix constant-alpha blending in the RTV path 2026-08-18 09:16:57 +02:00
goldislead
7cd47947b0 [GPU] Select promoted tfetch1D layouts at runtime
This keeps 545407D4's 2D use working while fixing wide 1D bindings in 555308CE.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
95545f8e76 [D3D12] Fix over-invalidation of bulk fetch register writes
Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
197929d967 [D3D12] Fall back to point sampling for non-filterable formats
Matches Vulkan.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
61a8aa3607 [Vulkan] Add spirv_disable_rounding_mode_rte
RenderDoc's shader debugger doesn't support RoundingModeRTE and crashes.

Co-Authored-By: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
31168682b0 [Vulkan] Fix draw_resolution_scaled_texture_offsets cancelling itself out
The offset was being multiplied by the scale and divided by the host scaled size, which collapsed back to guest step, so the cvar changed nothing on Vulkan while D3D12 stepped host texels. Since the size is already in host texels, dividing the offset by it gives the proper step.

Unnormalized coordinates convert to host texels before the offset add so the offset isn't multiplied along with the coordinate. Folds in the fix for 5841095A.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
3eab2b8b39 [GPU] Handle tessellated triangle strip and fan draws
Strips and fans normalize to triangle list host draws instead of being rejected. The conversion buffer is built at runtime when the backend did not bake one at init.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
Co-authored-by: Reality <reality@xenios.jp>
2026-08-18 08:32:23 +02:00
goldislead
77597d62ae [Vulkan] Select back-face stencil ref/mask when culling only front faces
They were picked whenever front faces were culled, even with both faces culled. Matches D3D12.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
53061c63fe [Vulkan] Use dedicated alpha blend factor map for alpha srcb/dest blend
Matches D3D12.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
2d5b41080c [Vulkan] Clamp stacked-texture layer index for Inf/NaN coords
Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
9e9d3cdd3f [GPU] Clamp out-of-bounds vertex fetch words to 0
Words at or past the size in the fetch constant read as 0 now instead of whatever sits in shared memory, matching real hardware.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
e6bdb0fdf7 [Vulkan] Skip draws with surface_pitch==0 to match D3D12
Realistically only affects memexport draws.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
654a8cacf5 [Vulkan] Fix FSI 2x-as-4x sample mask reading host sample 2 instead of 3
Guest sample 1 lives in host sample 3 when 2x-as-4x. This might have originally just been a typo or oversight.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
0d38781760 [Vulkan] Apply float controls to geometry shaders to match VS/PS
Mainly for NaN preservation. GS discards primitives by checking positions for NaN, mostly for vertex kill, and without the controls drivers might fold those checks away.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
f25003c0ea [GPU] Load guest-resolved mips from scaled resolve memory
Mips were always regenerated by blitting down from base, even when guest resolved real data into scaled memory.

The upload footprint is the guest mip reduced then scaled while the subresource is the base scaled then reduced, so the deepest mips of scaled textures can disagree by a row or column per axis. Compressed formats round up to the block and absorb it, uncompressed copies now clamp per axis so they never overrun the host image.

Matches D3D12 fix for the same problem.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
7101021150 [Vulkan] Bind shared memory persistently for texture loads and resolves
Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
cb240560df [Vulkan] Fix 2x MSAA alpha-to-coverage sample layout
Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
4aeb518c9c [Vulkan] Clamp scalar maxas/maxasf address register to [0, 255]
Matches DXBC.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
3ff230d23b [GPU] Emulate extended-range float16 in render target pack/unpack
Exp 31 is a large finite value up to 131,008 on the guest, not Inf or NaN.
Packing used to clamp colors at 65504 and unpacking returned Inf for extended encodings.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
2b071d9b09 [Vulkan] Invalidate user clip plane constants on source registers change
Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
66779fb873 [Vulkan] Fix adaptive tessellation issues
The domain shader reads the patch index from the hull shader output instead of gl_PrimitiveID, which bypassed the endian swap, offset, wrap and clamp already applied upstream.

The tessellator winds clockwise now. Clip space Y is not flipped on Vulkan, so counterclockwise winding inverted the facing and guest backface culling removed whole surfaces.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
goldislead
aed81ca93a [Memory] Rework guest access resolution and unwatched invalidation
This is a combination of three different Edge commits.

Guest page access is resolved with system page granularity so that anything deciding on protection now takes permissive access of every guest page a system page covers, which matters when the host is larger than the guest.

Access violations: Write faults on pages with no watch armed are only reported handled if guest mapping allows the write.

Invalidation of unwatched ranges when made writable or freed: Decommit, Release and Protect-to-writable (including write-combine) raise invalidation callbacks even with no watch armed.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-18 08:32:23 +02:00
Adrian
59c08cd462 [Kernel] Replaced X_DISPATCHER_FLAGS with X_OBJECT_TYPES 2026-08-18 08:00:29 +02:00
The-Little-Wolf
cdd60494d7 [XEX] - Add support for dash 1746
- Add support for dash 1746
2026-08-18 07:26:06 +02:00
Gliniak
5cf409d6e5 [Misc] C++20'ify Part 1
- Use ranges
2026-08-17 18:23:52 +02:00
AurisDSP
8ffe24e372 [CPU] Publish JIT entry results under the entry table lock
GetOrCreate reads entry->status while holding the global critical region,
but ResolveFunction published compile results by writing entry->function,
end_address and status directly, with no lock held. Nothing establishes a
happens-before edge between the two, so a thread that observes
STATUS_READY can still read a stale entry->function -- which it does
unlocked, right after GetOrCreate returns.

Benign on x86's TSO in practice; reachable on AArch64.

Add MarkReady/MarkFailed, which publish under that same lock, and route
Processor through them.

ThreadSanitizer against the real EntryTable: 2 data races before, 0 after.
The race is undefined behaviour by definition; no torn pointer was
actually observed in those runs.
2026-08-17 14:23:12 +02:00
goldislead
0d395ce9ab [GPU] Move debug cvars to a new TOML block, misc cleanup
native_2x_msaa is now debug_msaa_4x_as_2x, hopefully clearing up any user ambiguity.
2026-08-17 13:55:01 +02:00
Adrian
907d92bf8c [XAM] Fixed potential OOB memory write in copy utils 2026-08-13 21:54:31 +02:00
Michael Oliver
92ada8ebc0 [GPU] Fix scalar ALU swizzles with three-source vector ops 2026-08-13 20:24:57 +02:00
WawWeFix
ec5c875122 [CPU/X64] Optimize VMX dot products, vrsqrtefp, partial stores, and permutes 2026-08-13 07:25:39 +02:00
Gliniak
e31142bd79 [Linux/XSocket] Added error ID mapping for error 11. 2026-08-12 16:44:33 +02:00
bomabomabomaboma
fc48d37cdc [GPU] Remove num_format/decode cvars and dead shader code
Both of these have been around long enough to be probably prove safe and correct.

As a reminder, color resolves only take the full shader path if the destination number format matches EDRAM encoding && full 8_8_8_8_GAMMA resolves always decode PWL to linear before MSAA sample averaging.

Keeping decode_pwl_gamma bit for testing, but it's probably superfluous.
2026-08-12 09:24:36 +02:00
Adrian
8c98ef0280 [XAM] Cleanup XamUserCreateTitlesPlayedEnumerator 2026-08-11 19:27:27 +02:00
The-Little-Wolf
367d22d269 [XBOXKNRL/MISC] - Stub MicDeviceRequest
- Stub MicDeviceRequest
- Games:
  - Rock Band 2 now exits game instead of being stuck on boot when mic set to false
  - Guitar Hero World Tour now properly responds when you tell it mic is connected
2026-08-11 11:53:40 +02:00
NicknineTheEagle
12f5084b93 [XAM] Allow deleting titles with achievements earned from profiles 2026-08-11 07:21:55 +02:00
bomabomabomaboma
052cb95f24 [GPU] Give integer scales the channel width that feeds each lane 2026-08-10 22:42:38 +02:00
The-Little-Wolf
7d8db5a2cd [XBOXKRNL] - Replace lpvoid_t with pointer_t
- Replace lpvoid_t with pointer_t
- Use TypedGuestPointer for X_DEVICE_OBJECT struct
2026-08-10 08:54:54 +02:00
goldislead
2b3f0cb456 [GPU] Select alpha for A8 resolves
Treat k_8 + LOW_BLUE as alpha selection. 5451080D uses this to resolve its opacity plane, and 4D530808 does the same for a fog lighting pass. Their blue channels are black, so treating LOW_BLUE as an R/B exchange drops data.

Informed by XGCopySurface decompilation, which combines source and inverse dest swizzle, plus notcing how L8 and A8 share the same texture format.
2026-08-10 07:43:43 +02:00
Gliniak
b98037bed2 [CI] Disable running pipeline for draft PRs
There is no need to run them on main repo, when PR is not ready.
They still should be functional on personal fork.
2026-08-07 17:12:04 +02:00
bomabomabomaboma
6a45452087 [GPU] Walk the guest swizzle for integer scales; update comments
Fixed integer fetches are updated to look widths up through the guest swizzle, so every output channel is scaled by the width it came from.

Previously, host swizzle was being walked, and it was causing some 6 bit channels to be scaled as 5 bits and vice versa.

Co-authored-by: philtimmes <5494151+philtimmes@users.noreply.github.com>
2026-08-06 06:41:21 +02:00
goldislead
25597a5465 [GPU] Allow depth clamping instead of clipping
For now, this adds a depth clamp override to both backends that's kept disabled by default.

494707EE needs this for its setup draws that feed its lighting passes. It could be that guest clipping / host near and flare Z planes aren't cleanly interchangeable at the edge of the clip volume.
2026-08-05 21:52:24 +02:00
Adrian
6ff2a56f6a [XAM] Fixed returning incorrect max property size 2026-08-04 19:37:53 +02:00
bomabomabomaboma
0f2980de44 [GPU] Apply gradient exponent bias during fetch that's per-axis
The fetch constant carries independent signed exponent biases in [-16, 15] for the horizontal and vertical LOD gradients. Scale the H and V gradients by exp2(lod + bias_h) and exp2(lod + bias_v) respectively in the computed LOD sample path. getCompTexLOD keeps returning the raw queried LOD, treating the adjustment like the fetch-constant LOD bias, which is also not folded into it. Zero, the common case, is a no-op.

On the cube implicit-LOD path, where no explicit gradients exist to scale, the greater of the two biases is added to the LOD bias instead - exact when both are equal, erring towards a blurrier mip otherwise.

Co-Authored-By: Herman S. <429230+has207@users.noreply.github.com>
2026-08-04 10:34:42 +02:00
bomabomabomaboma
090cecd1b8 [Vulkan] Implement vertex kill (oPts.z) in the translator
A non-zero value in bits 0:30 of the kill flag kills the vertex, tested on the integer bits rather than as a float comparison so denormal flushing can't affect the result, matching the DXBC translator. With PA_CL_CLIP_CNTL::vtx_kill_or, the position W is set to NaN, killing the whole primitive if any of its vertices requests the kill, with the "and" operator, a dedicated cull distance after the user clip plane cull distances is set to -1, culling the primitive only when all of its vertices request it.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-04 10:34:42 +02:00
bomabomabomaboma
3254ac20f8 [Vulkan] Sample auto-LOD cube fetches with implicit LOD + bias
Explicit gradients of the direction reconstructed from the guest S/T/face coordinates pick the wrong mip on Vulkan, so sample cube fetches that use computed LOD without register gradients with implicit LOD and the accumulated LOD bias (fetch constant + register LOD + instruction bias) as the Bias image operand instead. This also makes tfetchCube consistent with getCompTexLOD, which already queries the implicit LOD. Register-gradient cube fetches keep explicit gradients in cube space, and other dimensions keep explicit gradients, matching the DXBC path. Gradient setup is skipped entirely on the implicit-LOD path.

Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
2026-08-04 10:34:42 +02:00