librashader

repository·master·Indexed 41 days ago

https://github.com/snowflakepowered/librashader

A high-performance preprocessor, compiler, and runtime for RetroArch 'slang' shaders implemented in Rust. Version 0.12.0 provides a Rust crate and a C API to integrate advanced shader effects into graphics applications. It supports multiple render APIs including OpenGL 3.3+, Vulkan, Direct3D 9, 11, 12, Metal, and wgpu. Features include a CLI for shader manipulation, HDR support for SRGB, HDR10, and scRGB color spaces, and a pluggable pipeline architecture.

Tokens
60.8K
Snippets
198
Records
264
Agent score
51%

What's inside librashader

  1. Understand librashader C API versioning (API vs ABI)

    master

    The C API uses two separate monotonically increasing version numbers exported via headers to manage compatibility:

    • LIBRASHADER_CURRENT_VERSION (API Version): Specifies the API version. An increase in this value is guaranteed to be backwards compatible for the same LIBRASHADER_CURRENT_ABI. New features in option structs require the version to be $\ge$ the version where the feature was introduced; otherwise, a default value is passed.
    • LIBRASHADER_CURRENT_ABI (ABI Version): Specifies the ABI version. Any change to this value is a breaking change.

    Safety Mechanism: The librashader_ld loader checks if LIBRASHADER_CURRENT_ABI matches the loaded binary. If they do not match, the library will not load. A value of 0 indicates a 'null' instance where all operations are no-ops (occurring when no compatible implementation is found).

  2. Comply with librashader licensing and distribution

    master

    The licensing model depends on how you link to the library:

    • Core Components (Preprocessor, Parser, Runtimes, etc.): Licensed under Mozilla Public License 2.0 (MPL-2.0).
    • C API (Headers/Definitions): More permissively licensed.
    • Using librashader_ld: If your project is not MPL-2.0 compatible, you can link against librashader_ld. This loader thunks calls to any librashader.so, librashader.dll, or librashader.dylib found in the load path.

    Critical Distribution Rule: If your project cannot comply with MPL-2.0, you cannot distribute the implementation files (librashader.so, librashader.dll, or librashader.dylib) alongside your project. The end user must obtain the implementation themselves. Alternatively, you may choose to distribute librashader under GPLv3.

  3. Understand `libra_viewport_t` semantics in ABI 2

    master

    In ABI 2, all viewport parameters for libra_*_filter_chain_frame functions take a pointer to a libra_viewport_t struct.

    Behavior based on pointer value:

    • If viewport is NULL: The render viewport is set to be equal to the width and height of the output texture (matching the default behavior of ABI 1).
    • If viewport is NOT NULL:
      • The width and height of the output quad's viewport rectangle are set to viewport.width and viewport.height.
      • The origin point (x, y) is set in the native coordinate system of the runtime.
      • The scissor rectangle is automatically set to the same size and origin as the viewport rectangle.
  4. Understand librashader compatibility and pipeline behavior

    master

    librashader implements the RetroArch shader pipeline and is highly compatible with existing shaders, but has key architectural differences:

    • Pluggable Pipeline: Unlike RetroArch, filter chains do not terminate at a backbuffer. They terminate at a caller-provided output surface and viewport. The caller is responsible for blitting the surface back to the backbuffer.
    • Parallel Compilation: Shaders are compiled in parallel to decrease preset compile times (except for OpenGL).
    • No Input Mipmaps: For performance, mipmaps are never generated for the input texture. Presets using mipmap_input0 = "true" will not receive a mipmapped input.
    • Strict Parsing: The preset parser is stricter than RetroArch's; some presets may require workarounds.
    • SPIR-V Pre-linking: Shaders are pre-linked at the SPIR-V level. Unused inputs in the fragment shader are removed, and corresponding vertex shader inputs are downgraded to global variables.
  5. Thread safety in librashader

    master

    Thread safety rules vary by runtime:

    • General Rule: It is safe to create a filter chain instance from a different thread, but drawing frames requires external synchronization of the filter chain object.
    • Direct3D 11: The immediate context is considered the graphics device queue. Loading LUTs requires command submission to the GPU.
    • OpenGL: Creating a filter chain in a different thread is safe only if the thread-local OpenGL context is initialized to the same context as the drawing thread. OpenGL does not support deferred GPU resource initialization.
    • Metal: The Metal runtime is not thread safe. However, you can still use filter_chain_create_deferred to defer submission of GPU resource initialization.
    • Direct3D 9: Not thread safe unless D3DCREATE_MULTITHREADED is enabled at device creation.
  6. Quad vertices and rotations

    master

    All runtimes render intermediate passes using an identity matrix MVP and a VBO with range [-1, 1].

    The final pass uses a Quad VBO with range [0, 1]. By default, the following projection matrix is used:

    static DEFAULT_MVP: &[f32; 16] = &[ 
      2.0, 0.0, 0.0, 0.0, 
      0.0, 2.0, 0.0, 0.0, 
      0.0, 0.0, 0.0, 0.0, 
      -1.0, -1.0, 0.0, 1.0, 
    ];

    To pass orientation information to shaders, apply a rotation to this MVP; this rotation will only be applied on the final pass.

  7. Migrate D3D11 runtime to ABI 2

    master

    If LIBRA_RUNTIME_D3D11 is defined, apply the following changes:

    • Image Handling: libra_source_image_d3d11_t has been removed. The image parameter of libra_d3d11_filter_chain_frame now expects an ID3D11ShaderResourceView *. Pass the value that was previously in the .handle field of libra_source_image_d3d11_t directly.
    • Filter Chain Frame: In libra_d3d11_filter_chain_frame, the viewport parameter has moved to follow the out parameter. Its type is now libra_viewport_t * (can be NULL).
    • Thread Safety: Calling libra_d3d11_filter_chain_set_param is always thread-safe.
  8. Build the C compatible dynamic library

    master

    To build the dynamic library (librashader.dll or librashader.so), use the build script via cargo xtask or by running the librashader-build-script package directly.

    Supported profiles: debug, release, or optimized (enables full LTO).

    Building with Nightly Rust: To enable minor optimizations (impl_trait_in_assoc_type) and C header generation, use the nightly feature. When using a nightly toolchain, pass the --nightly flag.

    Note: Using nightly to generate C headers is no longer encouraged. Use the provided librashader.h in the include folder instead.

    # Using xtask
    $ cargo xtask build --profile optimized
    
    # Using the build script directly
    $ cargo run -p librashader-build-script -- --profile optimized
    
    # Building with nightly features
    $ cargo xtask build --profile optimized --nightly
  9. Migrate to librashader ABI 2

    master

    Librashader version 0.5.0 introduced a breaking change to the C ABI. This migration is only relevant to consumers of the librashader C ABI. Rust users should refer to the official documentation on docs.rs.

    Key global changes:

    • LIBRASHADER_CURRENT_ABI has changed from 1 to 2.
    • LIBRASHADER_CURRENT_API remains unchanged; continue using it to access the latest feature set.
    • On Linux, the SONAME for librashader.so has changed from librashader.so.1 to librashader.so.2. This affects consumers linking via the linkage table (e.g., using -lrashader) rather than through libashader_ld.h.
  10. Serialize a shader preset pack to a single file

    master

    The pack command creates a "preset pack" (slangpkg). This format stores an entire shader preset, including its files and preprocessed source code, into a single JSON or MessagePack representation. This allows the preset to be loaded into memory without requiring filesystem access, making it ideal for environments like the web.

    Warning:

    • The .slangpkg file format is unstable.
    • Packs are only supported by the librashader Rust API and are not portable to other implementations of "slang" shaders.
    • The librashader C API is unlikely to support loading shader packs.
  11. Migrate D3D9 and Metal runtimes to ABI 2

    master

    For both LIBRA_RUNTIME_D3D9 and LIBRA_RUNTIME_METAL:

    • Filter Chain Frame: In libra_d3d9_filter_chain_frame and libra_mtl_filter_chain_frame, the viewport parameter has moved to follow the out parameter. Its type is now libra_viewport_t * (can be NULL).
    • Thread Safety: Calling libra_d3d9_filter_chain_set_param and libra_mtl_filter_chain_set_param is always thread-safe.
  12. Migrate OpenGL runtime to ABI 2

    master

    If LIBRA_RUNTIME_OPENGL is defined, apply the following changes:

    • Initialization: libra_gl_init_context has been removed. Instead, libra_gl_filter_chain_create now accepts a loader parameter of type libra_gl_loader_t. The filter chain is created against the current OpenGL context.
    • Image Structs: libra_output_framebuffer_gl_t and libra_source_image_gl_t are replaced by libra_image_gl_t.
      • For output images: Set .width and .height using the values previously found in libra_viewport_t. The fbo field is no longer required as librashader manages the framebuffer object internally.
      • For source images: libra_image_gl_t has the same layout and semantics as the old libra_source_image_gl_t.
    • Filter Chain Frame: In libra_gl_filter_chain_frame, the viewport parameter has moved to follow the out parameter. Its type is now libra_viewport_t * (can be NULL).
    • Thread Safety: Calling libra_gl_filter_chain_set_param is always thread-safe.