Skip to content

feat(shader): implement s_memtime and s_memrealtime - #324

Merged
boykopovar merged 3 commits into
boykopovar:mainfrom
adriadam10:feat/shader-memtime
Oct 3, 2026
Merged

boykopovar merged 3 commits into
boykopovar:mainfrom
adriadam10:feat/shader-memtime

Conversation

@adriadam10

Copy link
Copy Markdown
Collaborator

What

s_memtime (SMEM 0x24) and s_memrealtime (SMEM 0x25) were rejected by the decoder (SMEM opcode is not supported). Each one reads a 64-bit counter into an SGPR pair. Shaders use them for timing and for cheap per-frame seeds.

  • Decoder: both decode with their SDST pair and no memory operands.
  • IR: ShaderClock / RealtimeClock (U64). The translation writes the low dword to sdst and the high dword to sdst+1.
  • SPIR-V: OpReadClockKHR. s_memtime uses Subgroup scope (the per-wave shader clock) and s_memrealtime uses Device scope (the constant real-time clock). The emitter adds ShaderClockKHR / SPV_KHR_shader_clock only when used. If the target lacks them it fails with reads the shader clock, which needs the device's VK_KHR_shader_clock, the same way MinLod does. It does not return a constant.
  • VulkanDevice enables VK_KHR_shader_clock when the device has both shaderSubgroupClock and shaderDeviceClock (RADV, lavapipe, NVIDIA and Intel all do).

References: shadPS4 lowers S_MEMTIME to OpReadClockKHR with subgroup scope and returns the constant 1 when the device has no shader clock. KytyPS5 leaves both opcodes unimplemented.

Test agc_driver_shader_clock: each clock is read before and after a 2000-iteration loop. The test checks that both 64-bit values are non-zero and never go backwards, that the loop result is right, and that the values are uniform over the wave. On lavapipe (subgroup size 8) the wave32 spans several host subgroups, so subgroup-scope reads can differ between groups of 8 lanes. The uniformity check is per group of 8 for that reason.

Tested

Linux, full ctest (100) passes.

  • RADV (Radeon 660M) and lavapipe: the test passes (5/5 runs on RADV).
  • Without the decoder change: SMEM opcode is not supported. Without the device change: opcode=ShaderClock reason=reads the shader clock, which needs the device's VK_KHR_shader_clock.

Checklist

adriadam10 and others added 3 commits October 1, 2026 22:45
MixPrecision and SdwaDestination dispatch hand-assembled RDNA through the
recompiler and compare every lane with a CPU model, but were never in ctest.
Move them to tests/execution/, which is globbed into one test per file with
the same target names, so new execution tests add a file and no CMake lines.
They exit 77 (skipped) when the host has no Vulkan device; the Linux runner
installs lavapipe and sets ANYPS5_REQUIRE_VULKAN=1 so they cannot skip there.

Co-Authored-By: Claude <noreply@anthropic.com>
s_icache_inv, s_incperflevel, s_decperflevel, s_ttracedata_imm, s_wait_idle,
s_gl1_inv, s_dcache_inv, s_dcache_wb, buffer_gl0_inv and buffer_gl1_inv threw
in the decoder. SPIR-V has no cache control, so they translate like s_clause
and s_waitcnt, which already emit nothing. The SMEM and MUBUF forms carry no
operands, so no pass sees a phantom base or destination register.

Co-Authored-By: Claude <noreply@anthropic.com>
Both SMEM opcodes read a 64-bit counter into an SGPR pair. They now
lower to OpReadClockKHR: s_memtime with subgroup scope (the shader
clock) and s_memrealtime with device scope (the constant real-time
clock). The device enables VK_KHR_shader_clock when it has both clocks
and the backend refuses the opcodes with a clear reason otherwise.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

Progress report (709d7fe → 7d90b1d)

📈 GPU shader instructions: 53.52% (+0.86%, +10 implemented instructions)

✅ 10 implemented
Encoding Name
MUBUF BUFFER_GL0_INV
MUBUF BUFFER_GL1_INV
SMEM S_DCACHE_INV
SMEM S_GL1_INV
SMEM S_MEMREALTIME
SMEM S_MEMTIME
SOPP S_DECPERFLEVEL
SOPP S_ICACHE_INV
SOPP S_INCPERFLEVEL
SOPP S_WAIT_IDLE

This was referenced Oct 2, 2026
@github-actions github-actions Bot added build shader core/shader agc libSceAgc* ci .github labels Oct 2, 2026
@boykopovar
boykopovar merged commit 1043f90 into boykopovar:main Oct 3, 2026
3 checks passed
oneandonlydean added a commit to oneandonlydean/AnyPS5 that referenced this pull request Oct 3, 2026
…oykopovar#304 boykopovar#305 boykopovar#306 boykopovar#322 boykopovar#409 boykopovar#416, boykopovar#276 boykopovar#277 boykopovar#275 boykopovar#307, shader ops boykopovar#226 boykopovar#255 boykopovar#260 boykopovar#280 boykopovar#308 boykopovar#309 boykopovar#311 boykopovar#318 boykopovar#320 boykopovar#324 boykopovar#326 boykopovar#379 boykopovar#384 boykopovar#399, boykopovar#261, kernel boykopovar#335 boykopovar#341 boykopovar#349 boykopovar#355, libs boykopovar#227 boykopovar#244 boykopovar#245 boykopovar#273 boykopovar#274 boykopovar#279 boykopovar#286 boykopovar#287 boykopovar#289 boykopovar#296 boykopovar#300 boykopovar#328 boykopovar#358 boykopovar#402) into astrobot

Where our PR merged in a revised form, main's version is taken; where
astrobot carries the same work plus later local commits, astrobot's code
stays and main's additions appear once.

Conflicts:
- AvPlayer (Export.cpp both libs, include/AvPlayer.hpp, src/Player.cpp,
  src/Source.cpp, AvPlayerLibrary.cmake, CMakeLists.txt, SceTypes.hpp,
  tests/GuestAvPlayer.cpp): main's boykopovar#307 (our reviewed squash, which carries
  9c8e7fd e9ea5c8 adcede3 fb4eeb9 953057c ac456ee). It links the
  shared ffmpeg-core target, so astrobot's second FFmpeg build goes:
  3rdparty/FFmpeg submodule, core/libs/FFmpeg.cmake and src/Exports.cpp.
- libScePngEnc: main's boykopovar#227 (supersedes OverkillLabs' encoder).
- libScePad Export.cpp: main's boykopovar#287 tilt correction (supersedes 49d45f5).
- libSceAudioPropagation Export.cpp: astrobot's object model, which
  defines every function boykopovar#289 declares as a stub.
- libSceSaveData.native Export.cpp: both (SaveDataHoldWrites and boykopovar#289's
  unknown exports).
- VideoOutDriver.cpp: astrobot's (2546bd1 counters around boykopovar#416's
  lastFlipVblank store, same value). tests/Flip.cpp: boykopovar#416's pacing test and
  boykopovar#417's after-GPU test both kept.
- boykopovar#278 files (DisplayFormat, VulkanDevice, GpuColorTransfer,
  ResidentPresent, agc CMakeLists): main's comment-free boykopovar#278 plus
  astrobot's P5 present-direct (b29728d), which removed DetileImage,
  ResidentPresent.hpp and the recorder-test hook; the resident present test
  stays its own executable.
- VulkanDevice.cpp/.hpp: astrobot's GDS, local memory probe, sample dumps
  and P5 code; boykopovar#303/boykopovar#409 comments as main has them; main's shader clock
  (boykopovar#324) and DepthSurface-free includes.
- RequestSerializer.cpp: version stays 8 (6 mesh passthrough, 7
  nonConstantImageOffsets, 8 astrobot's later field). boykopovar#303's auto-merged
  second write and read of nonConstantImageOffsets removed.
- SpirvEmitter.hpp, SpirvEmitterState.hpp, Recompiler.hpp/.cpp, StageIO.hpp,
  SpirvOptimizer.cpp, InstructionTranslator.cpp, ShaderReplay.cpp: local
  fields kept, boykopovar#303/boykopovar#305 comments as main has them.
- SpirvAluEmitterMath.cpp: v_readlane keeps the split-wave path and takes
  boykopovar#322's wrap at the wave size for the others.
- SpirvEmitter.cpp: astrobot's single-lane layout check.
- SpirvFlowEmitter.cpp: boykopovar#304 as merged (the second lane emits a shared
  value itself when the first lane defined nothing).
- SpirvImageEmitter.cpp: main's Offset operand placed before MinLod.
- boykopovar#304: main's WaveUniformValues (SpirvAnalysis.cpp) replaces astrobot's
  copy in SpirvWaveExchange.cpp.
- Recorder.hpp/.cpp, Draw.hpp, Graphics Draw.cpp, ShaderResources.cpp:
  astrobot's boykopovar#276/boykopovar#277 with its later snapshot work (per-use budgets,
  stale-snapshot refresh, profile counters, boykopovar#410, boykopovar#424, fan GS); boykopovar#409/boykopovar#306
  comments as main has them.
- PacketMemory.cpp: boykopovar#409 as merged plus astrobot's two opt-outs.
- tests: ShaderMemory.cpp takes boykopovar#303's and boykopovar#304's new tests; Recorder.cpp
  takes boykopovar#409's afterRecordedWorkTests and drops main's copies of the
  boykopovar#276/boykopovar#277 tests astrobot already has; Structurizer.cpp keeps boykopovar#413's case.

boykopovar#143 (NGG passthrough) stays as on astrobot: upstream did not touch its
files since the boykopovar#258 revert.
@adriadam10
adriadam10 deleted the feat/shader-memtime branch October 5, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build ci .github shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants