Commit Graph

513 Commits

Author SHA1 Message Date
Mathias 0a461f8d69
fix: improve Direct Execution guest runtime and AGC compatibility (#880)
* test(cpu): verify VEH thunk preserves nonvolatile registers

* fix(memory): commit complete native guest mappings

* fix(cpu): treat time polling as import-loop progress

* fix(cli): preserve DLL path in mitigation relaunch

* refactor(cpu): remove obsolete inflate recovery hack

* fix(agc): accept shaders without embedded program registers
2026-09-11 13:37:31 +03:00
Berk ca90d17541
[aerolib-catalog] Add support for multiple Aerolib catalogs (#867) 2026-09-08 18:25:48 +03:00
Berk 6d4e5b4f65
chore: bump version to 0.0.3-release.4 (#866) 2026-09-08 16:04:47 +03:00
Berk d93ecaafa3
[CPU] Fixes a Windows VEH synchronization regression (#865) 2026-09-08 15:56:54 +03:00
Berk 33f590b381
chore: bump version to 0.0.3-release.3-patch.1 (#864) 2026-09-07 14:08:50 +03:00
Mathias b8f24219ae
fix VEH trampoline REX prefix and TLS patch boundaries (#859)
Fixes the REX.B prefix on the VEH entry spinlock's lock cmpxchg, which was
compare-exchanging on [rcx] instead of [r9] and therefore never guarding
anything.

Matches TLS and stack-canary patterns at instruction boundaries instead of
byte by byte. Without it GTA V dies at ~5s on a write through a register the
patcher had left unloaded; with it the title reaches its pause menu.

Co-authored-by: Foued Attar <attar.foued@gmail.com>
2026-09-04 21:07:58 +02:00
Berk 3831f3c407
Fix debugger frontend (#858)
* [security] harden debugger frontend API

* [docs] document debugger frontend security boundaries
2026-09-03 05:24:41 +03:00
frangametv b226dca3df
feat(hle): prefer loaded guest exports for selected registrations (#844)
Co-authored-by: Acelogic <miguelc4600@gmail.com>
2026-08-25 22:32:57 +02:00
Foued Attar 51e5480049
fix(cpu): preserve TLS instruction boundaries after rel8 branches (#846) 2026-08-24 22:52:30 +02:00
frangametv 600fcde637
fix(memory): expand the HLE guest-allocation arena (#843)
Co-authored-by: Foued Attar <foued.attar@lyceeastier.com>
2026-08-24 19:23:43 +03:00
frangametv 807aad18b3
tools(shader): inspect raw Gen5 shader dumps (#842)
Co-authored-by: Acelogic <miguelc4600@gmail.com>
2026-08-24 19:23:18 +03:00
frangametv f4f36b558f
fix(agc): refine vertex layouts without rebasing captured inputs (#841) 2026-08-24 14:49:36 +02:00
frangametv 2b8ef7d8fa
shader: add compact f16 arithmetic and compare lowering (#840)
Co-authored-by: Foued Attar <attar.foued@gmail.com>
2026-08-24 13:59:51 +02:00
angleyanalbedo f8a826ec1b
fix(agc,video): CMASK/DCC metadata state machine , remove heavy heavy motion trails in DeadCell (#836)
* fix(agc): add support for CMASK fast clear in rendering process

* fix(agc): prevent stale cross-frame label writes from bypassing WAIT_REG_MEM

Add frame-ID tracking to GpuWaitRegistry so that WAIT_REG_MEM in frame N+1
is not satisfied by a label written in frame N. Previously, a label that
persisted in guest memory from the previous frame could satisfy a new
WAIT_REG_MEM immediately, causing the waiting DCB to bypass its fence and
execute out of order.

Changes:
- GpuWaitRegistry: add _labelFrameIds, _currentFrameId, AdvanceFrame(),
  IsLabelFresh(); RecordProduced now stamps the frame ID on each write
- AgcExports: call AdvanceFrame() at RFlip (frame boundary);
  HandleSubmittedWaitRegMem checks IsLabelFresh before bypassing

This is one piece of the Dead Cells character visibility fix (issue #833).
The cross-frame label reuse could cause composite passes to execute before
character-layer passes, resulting in invisible characters.

* fix(video): simulate CMASK 'all clear' at frame boundary to prevent trails

On real PS5, CMASK is reset to 'all clear' at each frame boundary,
so render targets are effectively cleared. SharpEmu did not implement
this behavior, causing GBuffer targets to LOAD stale data from the
previous frame, resulting in visible trails/ghosting.

Reset Initialized=false for all offscreen guest images at the present
boundary (when _currentFrameSlot changes). This ensures every render
target starts each frame with LoadOp.Clear, matching the hardware's
CMASK behavior.

This is the trail fix for Dead Cells (issue #833), complementing the
cross-frame label staleness fix in GpuWaitRegistry.

* fix(video): only reset render targets (not textures) for CMASK simulation

Previous commit 89b4610 reset Initialized for ALL guest images, including
textures and storage images, causing a completely black screen. Only images
with a RenderPass (actual color render targets) should be reset, as CMASK
'all clear' only applies to color render targets, not sampled textures.

* Revert "fix(video): simulate CMASK 'all clear' at frame boundary to prevent trails"

This reverts commit 89b4610a015619848e4000372822dca1c08051ff.

* fix(agc): implement CMASK state machine for render target clearing

Implement CMASK (Color Mask) hardware behavior based on shadPS4's approach:

1. Track CMASK addresses from CB_COLORn_CMASK registers
2. Detect compute shaders that write to CMASK addresses (IsComputeMetaClear
   heuristic: no bitwise XOR in shader = clear shader)
3. Mark CMASK as 'all clear' when compute shader writes to it
4. EliminateFastClear mode now checks CMASK state before clearing

This addresses the trail/ghosting issue in Dead Cells (issue #833) where
642x362 GBuffer targets were never cleared after first use, causing stale
data from previous frames to persist.

Reference: shadPS4's IsComputeMetaClear + EliminateFastClear implementation.

* fix(agc): implement CMASK state machine for render target clearing

Based on shadPS4's PM4 implementation, add CMASK (Color Mask) hardware
behavior tracking:

1. TrackCmaskAddresses: Read CB_COLORn_CMASK registers to get CMASK addresses
2. CheckCmaskWrite: When DMA fill targets CMASK address with value 0,
   mark CMASK as 'all clear' (shadPS4's FillBuffer logic)
3. EliminateFastClear: Check CMASK state before clearing - only clear
   if CMASK is 'all clear', then mark as 'dirty'
4. DMA fill: Call TrackCmaskAddresses before processing to ensure
   CMASK addresses are registered when DMA fills happen

This addresses the trail/ghosting issue in Dead Cells (issue #833) where
642x362 GBuffer targets were never cleared after first use.

Reference: shadPS4's IsComputeMetaClear + EliminateFastClear + FillBuffer.

* refactor(agc): remove diagnostic CMASK traces from hot path

Remove 4 diagnostic TraceAgcShader calls that were added during CMASK
investigation:
- agc.cb_regs=[...] - allocated List<string> + string.Join on every draw
- agc.cmask_track - per-slot interpolated string on every draw
- agc.cmask_write - per-DMA-fill interpolated string
- agc.eliminate_fast_clear - per-draw interpolated string

These were debugging probes and are no longer needed.

* fix(agc): sync constant-fill zero writes to Vulkan render targets

Dead Cells GBuffer trails: the constant-fill compute kernel
(TrySubmitConstantFillKernel) wrote zeros to guest memory but never
invalided the host Vulkan GuestImageResource that backs the render
target, so the GBuffer pass kept LoadOp.Load stale previous-frame pixels.

After the guest write, request a guest color clear尷 ... clear for the
destination address (RequestAgentColorClear projection (clear)) so the next render pass
uses LoadOp.Clear. The pending clearandray mechanism already exists; the
fill kernel was simply bypassing it.

* Remove AGC lifecycle debug probes

Remove transient render-target lifecycle and indirect draw debug instrumentation from AgcExports. The change strips the noisy console probing while keeping the active render-target tracking logic intact for draw sequencing and validation.

* fix(video): clear frame-stale MRT groups at guest flip boundary

On hardware a colour surface whose fast-clear metadata is in reset
state reads back as the CB clear value instead of stale memory, so
games can leave per-frame MRT groups uncleaned and rely on that
implicit initialization. With no metadata layer, such a target keeps
whatever touched it last; when the group shares addresses with the
compositor's output, the entire finished previous frame bleeds
through every region the new frame does not repaint (Dead Cells
dungeon trails / ghosted characters).

Arm a reset at the guest's own flip command - the authoritative
frame boundary inside the submission stream - and let the first
multi-attachment colour group of the fresh frame consume it,
starting from LoadOp.Clear. One arm per flip yields exactly one
reset per guest frame regardless of CPU/GPU pipelining; later
groups keep load semantics so intra-frame pass chaining is
untouched. CPU-backed images are never touched.

Mirrors shadPS4's meta-state-driven attachment.is_clear at
render-pass begin (vk_rasterizer.cpp BeginRendering).

* fix(agc): correct CbColor0Cmask register offset and add EXT support

CbColor0Cmask was 0x320 (CMASK_SLICE, tile_max:14) instead of 0x31F
(CMASK_BASE_ADDRESS). TrackCmaskAddresses read the slice count instead
of the base address, so CMASK registration always produced garbage or
zero — the entire meta-state chain starved for every game.

Fix: 0x320 → 0x31F. Add CbColor0CmaskBaseExt (0x398) and decode the
full 48-bit address: ((ext & 0xFF) << 40) | ((low & 0x1FFFFFFF) << 8).

Phase 0 probe confirmed Dead Cells programs neither CMASK nor DCC
registers (all zeros) — it relies on unified memory semantics where
unwritten surfaces read as zero. The register offset fix is still
needed for games that do use CMASK metadata.

* feat(agc,video): CMASK/DCC meta-state machine with CLEAR WORD support

Replace the flat _cmaskClearedState dictionary with a proper meta-state
ledger that separates registration, clearing, and dirtying:

- MetaSurfaceInfo keyed by colour-buffer address (not meta address)
- Reverse map _cmaskToColorBuffer for fill/compute write detection
- TrackCmaskAddresses reads both CMASK (0x31F) and DCC (0x325) with
  EXT high-bit decoding; prefers CMASK, falls back to DCC
- CLEAR_WORD captured at registration time, passed through to
  BeginTranslatedRenderPass as VkClearValue
- EFC checks specific surface (not 'any cleared → clear slot0'),
  dirties only that surface (not entire table)
- CheckCmaskWrite uses reverse map for O(1) lookup
- Presenter bind loop queries IsMetaClearedForSurface → LoadOp.Clear
- _metaStateOverridesFlipArm flag gates flip-arm for gradual retirement

Phase 0 probe confirmed Dead Cells programs neither CMASK nor DCC
(all registers zero) — flip-arm remains the correct fix for that game.
The meta-state machine serves games that do use CMASK/DCC metadata.

* fix(agc,video): implement surface clearing at guest flip boundary

* refactor(video): remove flip-arm heuristic, meta-state machine fully replaces it

The flip-arm (_frameColorResetArmed) was a heuristic that cleared the
first multi-attachment colour group at guest flip boundary.  The
CMASK/DCC meta-state machine now handles all clearing: at flip time
MarkAllSurfacesCleared() marks every registered surface as cleared;
at bind time IsMetaClearedForSurface() triggers LoadOp.Clear and
consumes the state.  This replaces the flip-arm with a per-surface
state machine that correctly handles both explicit clears (DMA fill,
compute, EFC) and implicit frame-boundary resets.

Also fixed a bug where TrackCmaskAddresses overwrote IsCleared to
false on every call, defeating the frame-boundary reset.  Now
preserves existing IsCleared state when re-registering.

* Thread-safe meta-surface state & meta-clear decode

Add synchronization for metadata state: introduce _metaSurfaceGate and guard accesses to _metaSurfaces and _cmaskToColorBuffer in AgcExports to avoid concurrent-dictionary corruption and ensure small critical sections. Preserve cleared state only when metadata binding matches during re-registration. Make Gen5 texture format constants internal. Update logic to set/consume IsCleared under lock and check CMASK nearby windows safely.

Decode meta clear values in VulkanVideoPresenter: skip CPU-backed targets for meta clears, add UnpackMetaClearValue and HalfToFloat to convert CLEAR_WORD0/1 into proper ClearColorValue for R8G8B8A8_UNORM and R16G16B16A16_FLOAT formats (with an 8_8_8_8 fallback). This ensures correct clear colours and thread-safe metadata handling.
2026-08-24 13:56:44 +03:00
Foued Attar 4a7a45d1b3
Fix TLS-load patcher corrupting short jumps immediately before FS:[0] reads (#838)
The linear scanner consumed leading 0x66 bytes without checking that the
candidate starts on an instruction boundary. A short jump whose disp8 is
0x66 (EB 66) directly followed by a 66-prefixed FS:[0] load made the
patcher treat the displacement as a prefix and write its call opcode over
it, rewriting 'jmp forward past the TLS access' into 'jmp backward' -- an
infinite loop. GTA V's AGC resource destructors hit exactly this shape and
leaked the entire heap inside a container drain before any frame was
presented.

Reject candidates whose preceding byte is 0xEB: a bare EB can never be the
last byte of a valid instruction, so such a position is provably
mid-instruction. The outer byte scan then retries at the next offset,
which is the true boundary, and the patch lands correctly.
2026-08-23 14:52:44 +02:00
angleyanalbedo 3a744c991e
fix(agc): record write_data produced labels so WAIT_REG_MEM can resume (#834)
ApplySubmittedWriteData wrote label values to guest memory but never called
GpuWaitRegistry.RecordProduced, unlike ApplySubmittedReleaseMem. A suspended
WAIT_REG_MEM on a write_data label (e.g. Dead Cells frame fence 0x10243CFD8)
then could never be latched or deadlock-broken: guest memory is reset to 0 for
frame reuse before the next re-check, and _lastProduced had no value to replay.
Record each written dword and, for increment count2, the combined 64-bit value
so 32/64-bit waits latch like ReleaseMem dataSel=2.
2026-08-21 20:18:30 +03:00
urmoit 35a28f0143
[GUI] Estonian language (#835)
* [GUI] Estonian language

Implements Estonian language support for the SharpEmu's GUI.

* [GUI] Update and refine Estonian translations

Correct grammatical errors, refine technical UI terminology (e.g., view layout descriptions), and improve overall phrasing for better consistency across the launcher UI.
2026-08-21 20:18:07 +03:00
Marcin Mitura e79a1cc70a
[GUI] Polish language (#832) 2026-08-20 19:34:52 +02:00
Mathias a2241d0e83
Fix/agc zero dim and storage (#828)
* fix(videoout): promote guest images to storage usage

* fix(agc): treat zero-dimension indirect compute dispatches as valid no-ops
2026-08-18 21:20:54 +02:00
Foued Attar fe6521f617
Fix unaligned BufferLoad/GlobalLoad dword access
BufferLoadDword/x2/x3/x4, BufferStoreDword/x2/x3/x4, and their GLOBAL
counterparts were routed through LoadUnalignedBufferWord /
StoreBufferBytes, which reconstruct every dword one byte at a time
(4 bounds-checked buffer accesses per dword, each with its own
OpArrayLength + OpSelect + OpAccessChain + OpLoad/OpStore, plus
shift/mask/or reassembly on top).

The GCN ISA guarantees these opcodes are always dword-aligned - only
the byte/short/D16 variants legitimately need unaligned access, and
those already have their own dedicated path
(LoadSubdwordBufferValue / StoreBufferBytes with an explicit byte
count). The generic dword-count loop reached by every other
BufferLoad*/BufferStore*/GlobalLoad*/GlobalStore* opcode was paying
the same per-byte cost for no reason.

Route the dword-granularity path straight through the existing
LoadBufferWord / StoreBufferWord helpers (one bounds check and one
load/store per dword) instead. Measured on a compute shader with 6
BufferLoadDwordx4 instructions in its hottest basic block, this drops
GPU dispatch time for that shader from ~430-448ms to ~86-92ms (~5x)
with no change in output correctness - it is a pure translation
inefficiency fix, independent of any specific title.
2026-08-18 12:20:24 +02:00
Mathias 034ddcc092
fix(vmem): use ConcurrentDictionary for _pageProtections to prevent race corruption (#823) 2026-08-18 12:13:32 +02:00
Berk d9b599a1fd
chore: bump version to 0.0.3-release.3 (#826) 2026-08-18 00:19:31 +03:00
Astell ad115ddcbc
VMovrelsB32 opcode fix (#825) 2026-08-18 00:00:28 +03:00
Foued Attar 7521295ee1
[Codec/Native] Real H.264 decode for sceVideodec2, fix TLS loader missing the main module (#824)
* [Codec/Native] Real H.264 decode for sceVideodec2, fix TLS loader missing the main module

sceVideodec2 was a capability-only stub: the game's video pipeline
worked end-to-end but never produced a picture, so intro/cinematic
videos stayed black even though playback "completed" without errors
(confirmed on Ghost of Yotei's intro cinematic).

- Videodec2Decoder: owns an FFmpeg H.264 session per decoder handle,
  running decode and presentation pacing on their own threads (never
  the guest thread) so a whole clip isn't decoded faster than it can
  be displayed. Converts to BGRA and submits straight to
  VulkanVideoPresenter, bypassing guest memory the same way the
  existing Bink2 path does.
- Videodec2Exports: wires the real decoder into
  sceVideodec2CreateDecoder/Decode/Flush/Reset/DeleteDecoder, falling
  back to the original no-picture stub whenever FFmpeg is unavailable
  or a given decoder failed to open.
- VulkanVideoPresenter: decoded frames were being dropped under a
  single "latest wins" slot the render loop didn't always poll in
  time before the next frame overwrote it. Queues pending video
  presentations the same way guest-image flips already are.
- DirectExecutionBackend: the TLS load patcher's one-shot scan missed
  the main game module when the entry point resolves to a separate
  bootstrap allocation, and never re-scanned lazily-committed pages
  patched in afterward -- both left FS:[0] TLS loads unpatched,
  causing an early mutex-spin boot stall (reproduced on Demon's
  Souls: stuck at import #256). Now scans both the entry point's own
  allocation and the standard PS5/PS4 image base, and re-scans each
  newly committed executable range as it's touched.

* [GUI] Add a toggle for SHARPEMU_FORCE_SUBMIT_ORPHAN_PREAMBLES

This flag already existed as an AGC workaround (forces queued GPU
command-buffer preambles through when their target queue never picks
them up, unblocking titles stuck on a WAIT_REG_MEM that never
signals) but was only reachable by setting the environment variable
by hand. Expose it as a checkbox next to the other env toggles, in
both the global Options panel and the per-game settings panel, so it
can be turned on for a specific title without touching a shell.

* [GUI] Add remaining language translations for the new env toggle

The previous commit only added the new key to en.json/fr.json,
relying on Localization's runtime fallback to English -- but
LocalizationTests.EmbeddedLanguages_ContainEveryEnglishOptionsKey
requires every Options.* key to exist in every embedded language
file, which broke CI on all three build jobs. Fills in the
remaining 13 languages.
2026-08-18 00:00:01 +03:00
Astell 1660111189
A vplayer fix (#821)
* Astrobot-video-fix

* Astrobot-video-fix with updated files

* Astrobot-video-fix with tests files
2026-08-17 00:57:42 +03:00
Atson Melo 7caf430aa9
test(cpu): cover Gen5 native return smoke path (#818) 2026-08-11 04:52:49 +03:00
Astell 1e96eca316
Astrobot - Canonicalize fix and ffmpeg library on build (#817) 2026-08-11 00:36:12 +03:00
Foued Attar 498d402577
[HLE] Fix AGC OOB, kevent coalescing, and VideoOut flip/buffer-registration bugs (#808)
sceAgcAddPrimStateRegisters (NID unconfirmed, resolved from the decrypted
eboot's call site) reads 32 register pairs from a buffer that
sceAgcCreatePrimState only partially fills, treating the unfilled part as
guest-stack garbage -- an out-of-bounds probe index sourced from that
garbage was the AV. Zero the unfilled part instead.

GPU interrupt kevents were being coalesced when several arrived close
together, but the AGC driver's interrupt thread expects exactly one
completion per delivered kevent -- coalescing silently dropped completions
and wedged its dependency counters. Deliver one kevent per trigger instead,
with a cap so an undrained queue can't grow unbounded.

sceVideoOutGetFlipStatus left an extended region of its output struct
un-zeroed; some titles poll a flag past the classic struct layout and spin
forever on garbage that never clears. Zero the whole region -- flips
already complete synchronously in this emulator, so it should read as
not-pending anyway.

sceVideoOutRegisterBuffers2 rejected any nonzero category/option, which
some titles use, making them unable to ever register display buffers or
flip. Treat unknown categories as the standard layout instead of failing
the registration.

Tested on Ghost of Yotei (PPSA26344): combined with the separate
ajm-acm-audio change, gets past its audio-init stall and renders/presents a
real GPU frame; neither change alone reaches that point.

Tested on Cult of the Lamb: calls sceAgcAddPrimStateRegisters 39 times, 0
crashes (previously an unresolved import on this exact NID).

Regression-checked on Demon's Souls (both with and without the separate
native-tls-fix change, to reach further into boot), Astro Bot, Outer Wilds,
Ghost of Tsushima, GTA, Minecraft, Quake: no change in behavior on any of
them.
2026-08-09 18:52:23 +03:00
Foued Attar 4b8d45520e
[HLE] Fix AJM/ACM no-op stubs and accept Gen5 AudioOut2 mastering/batch calls (#807)
AjmModuleUnregister/AjmFinalize were pure no-ops (always returned success
without touching state); they now validate the context and actually remove
the codec registration / context entry, returning a real error when the
context is unknown. AjmModuleUnregister traces whether the codec was
actually registered, to help spot a title unregistering something it never
registered.

MaxCodecType was hardcoded to 25 based on known Sony codec ids, incorrectly
rejecting valid Gen5 codec types (e.g. 24). Registration is pure bookkeeping
(HashSet.Add); the only real constraint is that codecType must not overflow
the 32-bit instanceId it gets packed into, i.e. codecType < 2^18. Named the
instanceId bit-packing constants (InstanceIdSlotBits/InstanceIdSlotMask) so
the four call sites that used to hardcode 14/0x3FFF independently can't
drift out of sync, and MaxCodecType's formula is self-evident.

Accept sceAcmBatchInitialize/InitializeLite/Start/StartMultiple/Process as
successful no-ops -- the emulator runs no ACM DSP jobs, but Scream's workers
trap on int 0x41/0x42 asserts whenever a submission call reports failure.

Accept sceAudioOut2MasteringInit/Set3DLatency as no-ops -- the host mixer
has no mastering/object pipeline to tune, but returning failure makes
titles tear down their whole ACM context and abort audio arena bring-up.

Tested on Ghost of Yotei (PPSA26344): sceAudioOut2MasteringInit/Set3DLatency
unresolved-import warnings go from 2 to 0, unblocking 5 audio-related guest
threads that never spawned before (MovieDecoder, snd_stream_parsing_thread,
snd_stream_reader_thread, Psn, NCA::PumpThread), watchdog stall errors from
1 to 0. This alone gets the title past its Scream audio-init stall into
further boot, but it still hits an unrelated infinite retry loop in
sceVideoOutGetFlipStatus shortly after -- fixed by the separate
videoout-agc-hle-misc change; combined, the title renders and presents a
real GPU frame.

Regression-checked on Demon's Souls, Astro Bot, Outer Wilds, Cult of the
Lamb, Ghost of Tsushima, GTA, Minecraft, Quake: 0 calls to any export
touched by this change on any of them, byte-for-byte identical to
upstream/main.
2026-08-09 18:52:15 +03:00
Foued Attar 62c3852556
[AGC] Fix arena/fence tracking stalls and recover lost GPU progress (#770)
* [AGC] Fix arena/fence tracking stalls and recover lost GPU progress

Fix several AGC synchronization issues that could leave GPU work
unsubmitted or fences permanently unsatisfied:

- Recover fence writes missed during arena transitions by tracking
  closed arena tails and resweeping unresolved fence locations.
- Fix chunk submission accounting so only actually parsed ranges are
  considered submitted, avoiding missed orphan recovery.
- Extend arena sweeps to follow chained command ranges without
  duplicate submissions.
- Preserve GPU state tracking across native worker memory wrappers by
  using canonical guest memory identity.
- Fix builder-ring orphan submissions and stale ring-tail waits.
- Improve frame cycling by handling arena reuse, cursor regression,
  and transiently unavailable builder headers.
- Record conditional DCB execution (IT_COND_EXEC) instead of
  silently dropping the packet.

These changes improve AGC progress tracking and prevent GPU fence
starvation/deadlocks on titles relying on builder arenas and indirect
command chains.

* chore: trigger CI
2026-08-07 14:37:09 +03:00
Fa1dz 418eb7ecea
fix(audioout2): wire skipped-submit trace counter (#761) 2026-08-04 03:22:39 +03:00
Foued Attar c086e32f3d
Fix GuestDataPool lease leak on non-GPU compute dispatch paths (#759)
ObserveComputeDispatch only returned evaluation's pooled arrays when
evaluationHandledByCpu was set. Dispatches rejected before submission
(empty resource tables, oversized workgroup, compile failure) or a
compute submit that got dropped instead of enqueued (workSequence == 0)
never handed those buffers to a consumer that would return them,
leaking one lease per occurrence and growing GuestDataPool.Shared
without bound over a long session.

Adds GuestDataPool.DiagnosticStats() (outstanding lease count, idle
cached bytes) surfaced in the periodic [LOADER][PERF] line, to catch
this class of regression going forward.

Verified on Ghost of Yotei and Demon's Souls: pool_leases grew
unbounded before the fix (525 in 5 min on Demon's Souls, 1114 in 180s
on Yotei) and stays flat/bounded after (0-6 and 2-18 respectively),
with no behavioral regression observed.
2026-08-03 21:18:23 +03:00
shpeenut22 9e10d7c44a
Functions exports in kernel and NpTrophy2 (#749)
* sceNpTrophy2GetTrophyInfoArray export

* sceNpTrophy2GetTrophyInfoArray comment changed

* sceKernelIsTrinityMode & sceKernelGetOpenPsId exports

* deleted console log in KernelIsTrinityMode

* sceKernelGetOpenPsId: fix ORBIS_GEN2_ERROR_INVALID_ARGUMENT casts with uint.
2026-08-03 12:54:07 +03:00
ParantezTech 207441ca95 [asset] upload transparent logo image 2026-08-03 10:43:43 +03:00
ParantezTech 6b8f11a468 [asset] Add logo.psd file for future edits and modifications 2026-08-03 10:37:44 +03:00
Berk da0de5cf92
chore: bump version to 0.0.3-release.2 (#756) 2026-08-03 10:15:53 +03:00
Berk 26bda041fa
[videoout] guard degenerate guest buffer ranges (#755) 2026-08-03 10:09:07 +03:00
Berk 8eb2c1e9cb
Renderdoc (#753)
* [videoout] added renderdoc in-app capture

* [gui] added renderdoc toggle and debug group

* [gui] added renderdoc strings to all languages
2026-08-03 10:01:41 +03:00
Foued Attar f3d9439952
Fix Vulkan presenter synchronization and frame handling issues (#747)
* [VideoOut/Vulkan] Fix boot deadlock, writeback stall, and presentation bugs

- Presenter thread now starts on the compute dispatch path too, fixing
  a boot deadlock when a title's first GPU work is compute (Ghost of
  Yotei G-Buffer clear).
- Guest render-target format swaps between sibling pixel formats now
  reinterpret in place instead of recreating blank, preserving
  GPU-written content.
- Vectorized the guest-buffer writeback scan (equal-byte skip + coarse
  per-page pre-check), fixing multi-second stalls on fragmented buffers
  that starved JobWorker completion signals.
- _presentedSequence now advances on every Render() early-return path,
  fixing an unthrottled busy loop on stale/dropped presentations.

* Remove unnecessary Silk.NET.Windowing dependency
2026-08-03 00:36:33 +03:00
999sian 8df4039ca4
Ampr: fix path case on Linux (#750) 2026-08-03 00:36:00 +03:00
Foued Attar f36ce4084a
[Memory/Kernel] Fix Windows allocation-granularity and mutex-resolution bugs (#748)
- Fixed guest mappings now go through a granule-aware allocator so
  adjacent PS5 16 KiB pages sharing a 64 KiB Windows allocation
  granule no longer collide and fail.
- TryBackFixedRange routes free/reserved gaps through the same
  granule-safe path, fixing strays that stranded the rest of a granule.
- NORMAL pthread mutex self-relock reverted to real EDEADLK instead of
  silent compatibility recursion, which was starving other threads.
- TryResolveMutexState now checks the handle-keyed lookup before
  falling through to "not found" on a fresh, never-cached address.
2026-08-03 00:15:42 +03:00
Arseny Yankovsky 4b5ea6a793
AGC: honour DCC fast clears instead of drawing the clear quad (#738)
On GFX10 a colour clear is not a packet. The driver programs
CB_COLORn_CLEAR_WORD0/1 and draws a covering quad which the colour block
turns into DCC clear codes, discarding whatever the pixel shader
exported. We executed that quad as an ordinary draw, so the shaded output
landed in the surface instead of a clear.

That alone would be a wrong-pixels bug, but the blend those quads use
makes it compound. Every draw into the target blends src=ONE,
dst=ONE_MINUS_SRC_ALPHA, so alpha follows a <- a_src + a_dst*(1 - a_src),
whose fixed point is 1. A guest colour attachment is cleared once on
first use and loaded on every pass after, so nothing ever resets it and
the channel climbs until it saturates. Where such a surface is a
compositing layer, the final image is ui.rgb + scene.rgb*(1 - ui.a) and a
saturated alpha multiplies the scene away entirely - the scene renders
correctly the whole time and is then masked to black.

Recognise the clear and perform it: the attachment is reset and the quad
is dropped, which reproduces the observable effect without modelling DCC
block state. The reset drops the image's Initialized flag so the next
render pass clears via AttachmentLoadOp.Clear, rather than enqueuing a
CmdClearColorImage - the latter lands outside the following render pass,
and a target cleared that way was still observed reading back its
previous contents.

Restricted to clear-to-zero: the reset clears to zero, so a nonzero
CLEAR_WORD would be cleared to the wrong colour and is left to be drawn.
Zero is zero under every encoding the register pair can carry, so the
test needs no format handling.

The clip-space span test is load-bearing rather than defensive. Fills
sharing the vertex count, topology and blend outnumber the clears by two
orders of magnitude and sit well outside the frame; treating those as
clears erases the UI and blanks video surfaces.
2026-08-02 16:39:25 +03:00
Astell cf3bd0b4f2
Astrobot - Vulkan fix : 0x8A (#736) 2026-08-02 13:28:41 +03:00
AlexC 5ee7cd1dfa
Icons in about section (#735) 2026-08-01 18:01:38 +03:00
Arseny Yankovsky ea9be7484f
AGC: correct GS program registers, stop dropping rect-list draws, add a missing size export (#734)
Three defects found while bringing up a PS5 title. None are title-specific.

SPI_SHADER_PGM_LO_GS / HI_GS were 0x8A/0x8B, which are actually
SPI_SHADER_PGM_RSRC1/RSRC2_GS. Reading them as an address produced a
58-bit value (observed live: 0x30004622C008300). The correct offsets are
0x88/0x89, consistent with SPI_SHADER_PGM_CHKSUM_GS = 0x80 and
SPI_SHADER_PGM_LO_ES = 0xC8 already in the table.

Draw translation dropped any RECT_LIST draw whose vertex program exported
no parameters while the pixel shader had interpolated inputs. A
disposition census over a real run measured this deleting ~620 of every
5000 draws (12%). Rect lists are what AMD drivers emit for clears, blits
and resolves, so the guard was deleting clears and leaving previous frame
contents on screen as trails. Rendering a draw whose interpolants are
undefined is strictly better than deleting it.

sceAgcDcbDrawIndexIndirectMultiGetSize was unimplemented while
sceAgcDcbDrawIndexIndirectMulti emits an eight-dword packet. A title that
sizes its command buffer from the missing export under-reserves by three
dwords. NID derived with Ps5Nid.Compute, which reproduces the committed
NIDs of the neighbouring exports.

Tests: AgcContextRegisterTests and AgcShaderStageRegisterTests drive real
PM4 packets through sceAgcDriverSubmitDcb and assert what the parser
retained for the context and SH register dictionaries, via two new
internal accessors; neither dictionary had any test surface, which is why
register questions previously cost five-minute game runs.
2026-08-01 17:30:02 +03:00
Astell a8fa9c96dc
Astrobot - Vulkan fix (#733)
* log and vulkan fix

* Astrobot - Vulkan fix : OpControlBarrier
2026-08-01 17:17:45 +03:00
Berk c387b969e1
[GUI] few stability patches for GUI (#732) 2026-08-01 15:05:13 +03:00
Berk 7c9740fee8
[GUI] Add grid settings to GUI and implement grid snapping (#729) 2026-07-31 13:27:43 +03:00
Emil 544f588cfd
Required imports for Astro Bot (#710)
* Required imports for Astro Bot

* Add missing clone to match ValueIndexCString
2026-07-31 12:31:14 +03:00
kuba ecd657006a
AGC: retain label producers and report failed release writes (#719)
* AGC: retain active label producer records

Ported from the archived silent-hill-minimal branch (274ccfdf).

RegisterLabelProducer bounded its history with RemoveRange(0, 1024) once it
reached 4096 entries, which evicts the oldest records regardless of whether
their label write has completed. Those records are not a diagnostic cache:
a suspended DCB resolves its wait_reg_mem by finding the producer that will
write the watched label. Dropping an active record hides an earlier
same-submission label write, so a legitimate in-stream fence suspends
forever and the graphics queue stops.

Compact only completed history, and let the list exceed the soft bound when
every record is still active — correctness over a diagnostic limit.

Two hardening changes over the ported version, because a suspended queue is
exactly when every record is active:
- compaction is a single order-preserving pass instead of repeated RemoveAt,
  which would shift the tail per eviction (quadratic) while the label gate is
  held;
- when a pass frees nothing the bound is raised to twice the current count, so
  registration does not rescan the whole list on every subsequent add, and it
  is reset once compaction can make progress again.

Tests: 664 pass, 0 fail (SharpEmu.Libs.Tests 598 -> 600).

* AGC: keep produced label values a suspended wait still needs

GpuWaitRegistry.RecordProduced dropped the entire produced-value table once it
reached 8192 entries:

    if (_lastProduced.Count >= 8192) { _lastProduced.Clear(); }

Those entries are release state, not a cache. CollectDeadlockBroken is the only
way out for a DCB suspended on a WAIT_REG_MEM whose label the guest has since
recycled for other data: it replays the value a real producer already wrote to
that label. Clearing the table wholesale erases exactly the records live waiters
depend on, so every such waiter is stranded permanently — the suspended graphics
queue never resumes, and with it the render thread and the whole engine thread
graph park.

That is what Silent Hill (PPSA10112) hits. Its final unsatisfied waits watch
labels holding guest allocator metadata (each reads a pointer into its own
region rather than the expected 1), i.e. recycled memory, which is precisely
the case the deadlock breaker exists to handle — yet agc.deadlock_break fires 0
times across a run with 490 wait suspensions and 1068 successful release_mem
writes, because the producing values had already been cleared.

Prune only values no registered waiter is watching, and let the table exceed the
soft bound while they are all watched. Same reasoning as the label-producer
history in the preceding commit: correctness of synchronization state takes
precedence over a diagnostic bound.

Tests: 666 pass, 0 fail. The regression test fails against the previous
wholesale Clear() and passes with the prune, verified by reverting the fix.

* AGC: report release-label writes that never reach guest memory

Both release_mem handlers recorded the produced label value only on success:

    if (wroteData && dataSelection is 1 or 2) GpuWaitRegistry.RecordProduced(...)

with no else. A failed write is not benign here. That packet is the producer a
suspended WAIT_REG_MEM is waiting for, so when it fails the label is neither
written nor recorded, CollectDeadlockBroken has no value to replay, and the
graphics queue stays suspended forever — the render thread and the engine
thread graph park behind it with nothing in the log to say why.

Measured on Silent Hill (PPSA10112): the fatal AccessViolation lands exactly
here, on the presenter thread, in ApplySubmittedReleaseMem's label write into a
protected guest page. The faulting variant kills the process; the
returns-false variant wedges the GPU silently. Only the first was ever visible.

Report the failure (rate-limited: first 16, then powers of two) instead of
dropping it. This does not fix the underlying write failure — it makes a
permanently suspended queue diagnosable rather than silent.

Tests: 666 pass, 0 fail.
2026-07-31 12:14:38 +03:00