Skip to content

feat(shader): implement s_movrels/s_movreld (b32, b64) and s_movrelsd_2_b32 - #326

Merged
boykopovar merged 3 commits into
boykopovar:mainfrom
adriadam10:feat/scalar-relative-indexing
Oct 3, 2026
Merged

boykopovar merged 3 commits into
boykopovar:mainfrom
adriadam10:feat/scalar-relative-indexing

Conversation

@adriadam10

Copy link
Copy Markdown
Collaborator

What

The scalar relative moves threw unsupported SOP1 opcode. The ISA sweep found them. This PR implements them:

Opcode Semantics (measured on an RDNA2 GPU)
s_movrels_b32 (0x2e) D = SGPR[S0 + M0]
s_movrels_b64 (0x2f) D[0:1] = SGPR[S0 + (M0 & ~1)] pair
s_movreld_b32 (0x30) SGPR[D + M0] = S0
s_movreld_b64 (0x31) SGPR[D + (M0 & ~1)] pair = S0[0:1]
s_movrelsd_2_b32 (0x49) SGPR[D + M0[25:16]] = SGPR[S0 + M0[9:0]]

The 64-bit forms keep the pair aligned: with M0 = 3, s_movrels_b64 s[40:41], s[20:21] reads s[22:23]. A full-M0 write out of range writes nothing.

The lowering follows v_movrels/v_movreld: a select over every SGPR from the base up to s105 (readRelativeScalar/writeRelativeScalar). These shaders used to fail at decode, so the extra selects only affect shaders that could not compile before. The embedded-vertex-fetch scan clears every tracked SGPR on a relative write, and clears the destination on a relative read.

Out-of-range relative reads are left as they are: the hardware returns an unrelated value there.

Test agc_driver_scalar_relative_indexing: 16 results, captured on the RDNA2 GPU (ROCm HSA, raw kernels). It covers each opcode, the b64 alignment for reads and writes, the split M0 fields with high bits set, an out-of-range write, and the neighbours that must not change.

Note: this stacks on #255, which already conflicts with #311 in ScalarInstructions.cpp (both add SOP1 cases in the same place). This PR doesn't add a conflict of its own.

Tested

Linux, full ctest (101) passes.

  • RADV (Radeon 660M) and lavapipe: the test passes.
  • Without the b64 alignment: movrels_b64_lo is 0x00002023, expected 0x00002022.

Checklist

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Progress report (01eaae0 → 3033e5e)

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

✅ 10 implemented
Encoding Name
SOP1 S_BCNT0_I32_B64
SOP1 S_FF0_I32_B64
SOP1 S_FLBIT_I32
SOP1 S_FLBIT_I32_I64
SOP1 S_MOVRELD_B32
SOP1 S_MOVRELD_B64
SOP1 S_MOVRELSD_2_B32
SOP1 S_MOVRELS_B32
SOP1 S_MOVRELS_B64
SOP1 S_QUADMASK_B32

This was referenced Oct 2, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 2, 2026
The WriteLane IR takes {value, lane, previous}, as the translation and the
read-lane eliminator use it, but the SPIR-V emitter compared the lane id with
the previous value and selected between the lane index and the value. Every
v_writelane therefore wrote its value to all lanes (or the lane index to the
lane whose old value happened to equal its id).

Co-Authored-By: Claude <noreply@anthropic.com>
adriadam10 and others added 2 commits October 2, 2026 09:59
…i64), s_quadmask_b32

The decoder threw for these SOP1 opcodes. The 64-bit find-first-zero and
signed leading-bit counts reuse the existing 64-bit helpers with a flag;
s_quadmask_b32 is the 32-bit half of s_quadmask_b64. s_bcnt0 and s_quadmask
set SCC to result != 0; the find and leading-bit forms leave it.

Co-Authored-By: Claude <noreply@anthropic.com>
…_2_b32

s_movrels reads SGPR[src + M0] and s_movreld writes SGPR[dst + M0].
The 64-bit forms align the offset down to even (M0 & ~1), and
s_movrelsd_2_b32 takes the source offset from M0[9:0] and the
destination offset from M0[25:16], as measured on hardware. They use
the same select-over-registers lowering as the vector forms, over the
106 SGPRs. The embedded vertex-fetch scan forgets every tracked SGPR on
a relative write.

Co-Authored-By: Claude <noreply@anthropic.com>
@adriadam10
adriadam10 force-pushed the feat/scalar-relative-indexing branch from 560dcb3 to 3033e5e Compare October 2, 2026 08:05
@github-actions github-actions Bot added shader core/shader agc libSceAgc* and removed needs rebase Conflicts with main, rebase needed labels Oct 2, 2026
@boykopovar
boykopovar merged commit b457162 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/scalar-relative-indexing 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* shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants