Skip to content

rslc: initialize local constants at their use sites - #19934

Closed
finalpatch wants to merge 1 commit into
libretro:masterfrom
finalpatch:fix/rslc-local-constant-init
Closed

finalpatch wants to merge 1 commit into
libretro:masterfrom
finalpatch:fix/rslc-local-constant-init

Conversation

@finalpatch

@finalpatch finalpatch commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fix a severe shader performance regression with rslc on Adreno GPUs. On a Samsung Galaxy Z Fold7 (Adreno 830), presets/crt-hyllian-sinc-smartblur-sgenpt.slangp runs at normal speed with glslang but becomes very slow with rslc. The final pass contains constant mask arrays in mutually exclusive branches.

rslc emits these local arrays as initialized Function OpVariables, which initializes them at function entry even when their branches are not taken. On this GPU, the resulting shader uses 1,168 bytes of scratch memory per shader instance and 216 memory-write instructions.

Emit local storage without an initializer and store the constant at each dynamic access instead. This keeps initialization inside the branches that use it and ensures each access has an initialized value. The driver then reports zero scratch memory and zero memory-write instructions for this shader.

Validation

  • Built two ARM64 Release APKs from the same historical revision (fcfd5bf4eb), selecting glslang or rslc: glslang was fast; rslc was slow.
  • Tested the fixed rslc APK on the same Fold7 with a cleared shader cache: the original six-pass preset now holds 60 FPS.
  • In an isolated Vulkan workload on the same device at 1920×1080, the final pass takes approximately 64 ms per draw with unmodified rslc and less than 1 ms with the fix. The compared fragment modules differ only in the placement of the 12 array initializers; both pass spirv-val --target-env vulkan1.0.
  • Existing rslc_test, rslc_remap_test (GL=0), shader_chain_test, and slang_hlsl_backend_test pass in Android/Termux.
  • Full desktop Linux/Windows CI and Mesa rendering checks have not been run locally.

Related Issues

[Any issues this pull request may be addressing]

Related Pull Requests

[Any other PRs from related repositories that might be needed for this pull request to work]

Reviewers

[If possible @mention all the people that should review your pull request]

Keep constant-array stores inside the branches that use them instead of initializing every array at function entry. This avoids excessive scratch-memory traffic in Hyllian shaders on Adreno GPUs.
@LibretroAdmin

LibretroAdmin commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Thanks, great find! Merged into master with your authorship kept.

I added a small follow-up on top: instead of reusing one variable for every read of the same constant, each read now gets its own fresh variable, exactly like glslang's "indexable" temporaries. With one shared variable, a constant read in two places gets written again after it has already been read. Mesa's large-constant pass then stops promoting it to a constant table on RADV/ANV/Turnip/NVK, so the slowdown would have moved to Mesa drivers. With one variable per read, both your Adreno fix and the Mesa fast path hold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants