Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

slang-java

CI Release Maven Central

Java bindings for the Slang shading-language compiler. Compile Slang source to SPIR-V, DXIL, HLSL, GLSL, WGSL, or Metal from the JVM, inspect the result with Slang's full reflection API, and resolve imports through your own code — pack files, classpath resources, in-memory maps. Java on the FFM API (java.lang.foreign): no JNI, no native glue of its own — it binds the official Khronos-signed Slang binaries directly. Windows, macOS, and Linux, on x86_64 and aarch64. Requires JDK 25+.

Coordinates

Artifact Purpose
io.github.refux:slang-java:0.0.11 The library: compiler API, reflection, Java file systems
io.github.refux:slang-java-natives:0.0.11:<os>-<arch> The official Slang binaries, as one classifier per platform: windows, linux, or macos × x86_64 or aarch64

The library version tracks slang-java's own API, not Slang's. To see which Slang release a jar binds, read its manifest — no resolving, no running:

unzip -p slang-java-0.0.11.jar META-INF/MANIFEST.MF

Slang-Version there is a floor, not a lockstep: it names the release the bindings were generated against, and any newer Slang works, because Slang's public ABI is append-only. The same value is available at runtime as SlangLibrary.PINNED_SLANG_VERSION, alongside GlobalSession.buildTagString() for the library actually loaded.

Serialized modules (Module.serialize()) are versioned separately and more narrowly: each Slang release reads only a small range of module versions, so treat them as a cache tied to the release that wrote them. Session.loadModuleFromIr throws a SlangCompileException for anything the loaded Slang cannot read, and Session.moduleInfo tells you up front which version a blob is.

Getting started

Add the library and the natives classifier for your machine — compute it from the host so you never hardcode a platform:

// build.gradle.kts
val slangNatives = "${
    when {
        org.gradle.internal.os.OperatingSystem.current().isWindows -> "windows"
        org.gradle.internal.os.OperatingSystem.current().isMacOsX -> "macos"
        else -> "linux"
    }
}-${if (System.getProperty("os.arch") in listOf("aarch64", "arm64")) "aarch64" else "x86_64"}"

dependencies {
    implementation("io.github.refux:slang-java:0.0.11")
    runtimeOnly("io.github.refux:slang-java-natives:0.0.11:$slangNatives")
}

tasks.withType<JavaExec> {
    jvmArgs("--enable-native-access=ALL-UNNAMED") // FFM restricted methods, JEP 472
}

Shipping one build that runs on every OS? List the classifiers instead — they sit on the classpath together and the loader picks the host's at runtime (LWJGL-style):

dependencies {
    implementation("io.github.refux:slang-java:0.0.11")
    runtimeOnly("io.github.refux:slang-java-natives:0.0.11:macos-aarch64")
    runtimeOnly("io.github.refux:slang-java-natives:0.0.11:windows-x86_64")
    runtimeOnly("io.github.refux:slang-java-natives:0.0.11:linux-x86_64")
}

Then compile a shader and reflect on it:

import io.github.refux.slang.*;
import io.github.refux.slang.Module; // disambiguates from java.lang.Module

try (GlobalSession global = Slang.createGlobalSession();
     Session session = global.newSession()
         .target(CompileTarget.SPIRV, t -> t.profile("spirv_1_5"))
         .create()) {

    Module module = session.loadModuleFromSource("hello", """
        RWStructuredBuffer<float> result;

        [shader("compute")] [numthreads(8,8,1)]
        void main(uint3 tid : SV_DispatchThreadID)
        {
            result[tid.x] = float(tid.x) * 2.0;
        }
        """);

    try (ComponentType linked = session.composite(module, module.entryPoint("main")).link()) {
        byte[] spirv = linked.entryPointCode(0, 0); // hand to Vulkan, cache to disk, ...

        ShaderReflection reflection = linked.layout(0);
        for (var parameter : reflection.parameters()) {
            System.out.println(parameter.name() + " : " + parameter.category());
        }
    }
}

Compile errors throw SlangCompileException carrying the compiler's diagnostics text; warnings go to an optional onDiagnostics consumer on the session builder. Imports can be served from Java instead of the OS file system:

Session session = global.newSession()
    .target(CompileTarget.SPIRV)
    .fileSystem(SlangFileSystem.ofMap(Map.of(
        "common.slang", "public static const float kScale = 2.0;")))
    .create();

Matrices follow SessionDesc's row-major default, which is not what the slangc command line uses — compile the same shader offline with slangc and at run time through this library and every matrix comes out transposed relative to the other build, with nothing to diagnose it. matrixLayout(MatrixLayout.COLUMN_MAJOR) on the session builder matches slangc.

Everything is AutoCloseable with try-with-resources as the idiom; anything left unclosed is released by a Cleaner when unreachable, and -Dio.github.refux.slang.debug=true traces leaks to their allocation site and asserts session thread confinement.

To use a different Slang build than the bundled one (say, a local checkout), set -Dio.github.refux.slang.libraryPath=<dir> or SLANG_JAVA_LIBRARY_PATH to any directory holding the Slang libraries — it takes precedence over the natives artifacts.

How it works

  • The low-level layer is generated from slang.h itself: COM vtable dispatch, structs with clang-verified offsets, all enums, and the complete reflection C ABI — validated byte-identical across all six OS/architecture ABIs, with an append-only lockfile guarding against upstream ABI drift.
  • Java-implemented Slang interfaces (file systems, blobs) are real refcounted COM objects backed by FFM upcall stubs.
  • The native binaries are the unmodified official Slang releases — nothing is rebuilt or patched.

Development

Architecture, decisions, and status: DESIGN.md. Contributor commands: CLAUDE.md.

Licensed under the Apache License 2.0.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages