Skip to content

[Feature] Use librashader for .slangp (RetroArch) shader support#4678

Open
mr-ke wants to merge 12 commits intoTASEmulators:masterfrom
mr-ke:feature/librashader
Open

[Feature] Use librashader for .slangp (RetroArch) shader support#4678
mr-ke wants to merge 12 commits intoTASEmulators:masterfrom
mr-ke:feature/librashader

Conversation

@mr-ke
Copy link
Copy Markdown

@mr-ke mr-ke commented Apr 12, 2026

dev build for branch | mr-ke:feature/librashader

Summary

This PR integrates librashader as a modern shader filter backend for BizHawk, replacing the legacy Cg/GLSL shader system with support for modern slangp and glslp shader presets.

Changes

New Files

  • BizHawk.Client.Common/DisplayManager/Filters/Librashader.cs - Native bindings for librashader.dll
  • BizHawk.Client.Common/DisplayManager/Filters/LibrashaderFilter.cs - Filter implementation for the display pipeline

Modified Files

  • BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs

    • Added LibrashaderFilter field and RefreshLibrashader() method
    • Integrated librashader into BuildDefaultChain() (TargetDisplayFilter=4)
    • Added disposal of filter resources
  • BizHawk.Client.EmuHawk/config/DisplayConfig.cs

    • Added new RadioButton for librashader selection
    • Split file filters: .cgp for legacy UserFilter, .slangp/.glslp for librashader
    • Auto-select appropriate filter type based on file extension
  • BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs

    • Added UI controls for librashader option
  • BizHawk.Client.EmuHawk/MainForm.Events.cs

    • Added RefreshLibrashader() call after DisplayConfig changes

Features

  • Support for modern slangp and glslp shader presets via librashader
  • Automatic shader chain initialization and management
  • Proper OpenGL context integration
  • Debug logging via Util.DebugWriteLine() (DEBUG builds only)

Requirements

  • librashader.dll must be placed in dll\ directory
  • OpenGL display method must be selected

Testing

Tested with various slangp shader presets (VHS, CRT effects) on NES and other cores.

Check if completed:

@vadosnaprimer
Copy link
Copy Markdown
Contributor

WOW

What's the workflow to use of an arbitrary libretro shader with this? For example https://github.com/libretro/slang-shaders/blob/master/crt/crt-royale.slangp

@mr-ke mr-ke force-pushed the feature/librashader branch from 1f848a4 to 81910d9 Compare April 12, 2026 13:27
@mr-ke
Copy link
Copy Markdown
Author

mr-ke commented Apr 12, 2026

WOW

What's the workflow to use of an arbitrary libretro shader with this? For example https://github.com/libretro/slang-shaders/blob/master/crt/crt-royale.slangp

Hi, good question, I guess you could follow below steps:

  1. git clone https://github.com/libretro/slang-shaders.git
  2. copy crt/crt-royale.slangp (preset file) and its depend *.slang into the Folder you want
  3. In menu of Config->Display->display method tab->OpenGL (have not port direct3D part yet)
  4. In menu of Config->Display->librashader->select, choose your presets you store as upon step
  5. Start to play

@YoshiRulz YoshiRulz added App: EmuHawk Relating to EmuHawk frontend re: Crop/Filter/Pad/Stretch labels Apr 12, 2026
@YoshiRulz YoshiRulz linked an issue Apr 12, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Member

@YoshiRulz YoshiRulz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment thread src/BizHawk.Client.Common/DisplayManager/Filters/Librashader.cs Outdated
Comment thread src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs Outdated
Comment thread src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs
private static uint GetTexID(ITexture2D texture)
{
if (texture == null || TexIDField == null) return 0;
return (uint)TexIDField.GetValue(texture);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is equivalent to return (texture as OpenGLTexture2D)?.TexID ?? default;. Did you use reflection because OpenGLTexture2D is internal?

Copy link
Copy Markdown
Author

@mr-ke mr-ke Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is equivalent to return (texture as OpenGLTexture2D)?.TexID ?? default;. Did you use reflection because OpenGLTexture2D is internal?

If we do not use reflection to access, then InternalsVisibleTo Include="BizHawk.Client.Common" is needed for project BizHawk.Bizware.Graphics, maybe isolate this changeset without change expose charastic of BizHawk.Bizware.Graphics would be a option as better, what do you say?
Same reason apply to drawFbo

Copy link
Copy Markdown
Member

@YoshiRulz YoshiRulz Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

@CasualPokePlayer CasualPokePlayer Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't put this librashader handling in BizHawk.Client.Common in the first place, put it in BizHawk.Bizware.Graphics. This should outright be part of the IGL so it can handle the IGL impl specific details (BizHawk.Client.Common should only be calling IGL APIs, it's not supposed to handle raw OpenGL commands).

This impl using raw OpenGL commands also means the feature is locked to the OpenGL display method, rather than also being available to the (default!) Direct3D11 display method (which librashader can support just fine).

Copy link
Copy Markdown
Author

@mr-ke mr-ke Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't put this librashader handling in BizHawk.Client.Common in the first place, put it in BizHawk.Bizware.Graphics. This should outright be part of the IGL so it can handle the IGL impl specific details (BizHawk.Client.Common should only be calling IGL APIs, it's not supposed to handle raw OpenGL commands).

This impl using raw OpenGL commands also means the feature is locked to the OpenGL display method, rather than also being available to the (default!) Direct3D11 display method (which librashader can support just fine).

Well, you are spot on the view of what should be in BizHawk.Client.Common and what should be in BizHawk.Bizware.Graphics, in the meanwhile, I've made a progress on https://github.com/mr-ke/BizHawk/commits/feature/librashader_d3d11, which I also make librashader works on Bizhawk default d3d11 mode, do you consider it a idea we consist d3d11 together or we need to firstly put these architecture adjustment at first place for OpenGL part then consist d3d11 afterwards.
Looking forward to hear all your ideas in mind.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you got D3D working, you can include that in this PR too.

Copy link
Copy Markdown
Author

@mr-ke mr-ke Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it goes with the joint work d3d & openGL (Also abstract common part into LibrashaderFilterBase.cs).
I've done a instrument on filter_chain_create (shader compile at boot) for both d3d & openGL as below:
Preset: vhs_and_crt_godot.slangp (complex enough)
OpenGL 140ms (Cold start)
OpenGL 55ms (2nd start)

D3D11 1600ms (Cold start)
D3D11 55ms (2nd start) 2026/4/21 updated!!!
That's make sense OpenGL's GLSL is much faster than D3D's HLSL compiler.
Also OpenGL's shader cache works along with D3D's shader cache not work. (You can inspect at %LOCALAPPDATA%\librashader)
I've take a while to check option I set for D3D11, no obvious basis prove we use wrong option for D3D11 but librashader.db.1 can not generated to accelerate D3D11's shader compile.

Updated 2026/4/21 I've identified why shader cache is not generated as expected in D3D11 mode, it is due to a concurrent issue in librashader.dll, after carefull inspect the rust code, the cache issue can be work around by attach D3D11_CREATE_DEVICE_SINGLETHREADED flag to D3D device created.
Please help me check if 0e698fd really matter on other cases.
I understood that EncoreGLTextureProvider and MelonDSGLTextureProvider use GL Interop to share the GL texture to D3D, but it still have fallback methods, do I read it correctly?

@YoshiRulz @CasualPokePlayer

Copy link
Copy Markdown
Member

@CasualPokePlayer CasualPokePlayer Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GL interop is used as a fast method to transfer the GL texture to the display method. The fallback method is slow. This slowness doesn't matter too much at 1x internal resolution, it ends up mattering a lot if you decide to bump up the internal resolution (which I imagine ends up massively overlapping with the userbase that would use these shaders).

Even then, if there's some concurrency occurring within librashader it does not make sense to make the D3D11 device single threaded, if you're saying there's threading in librashader then the single threaded flag should not be set.

Comment thread src/BizHawk.Client.Common/DisplayManager/Filters/LibrashaderFilter.cs Outdated
Comment thread src/BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs Outdated
@YoshiRulz YoshiRulz removed the App: EmuHawk Relating to EmuHawk frontend label Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[F.Rq.] Use librashader for .slangp (RetroArch) shader support

5 participants