Making it easier to work with shaders

Overview

Slang

Linux Build Status Windows Build Status

Slang is a shading language that makes it easier to build and maintain large shader codebases in a modular and extensible fashion, while also maintaining the highest possible performance on modern GPUs and graphics APIs. Slang is based on years of collaboration between researchers at NVIDIA, Carnegie Mellon University, and Stanford.

Key Features

The Slang system is designed to provide developers of real-time graphics applications with the services they need when working with shader code.

  • Slang is backwards-compatible with most existing HLSL code. It is possible to start taking advantage of Slang's benefits without rewriting or porting your shader codebase.

  • The Slang compiler can generate code for a wide variety of targets and APIs: D3D12, Vulkan, D3D11, OpenGL, CUDA, and CPU. Slang code can be broadly portable, but still take advantage of the unique features of each platform.

  • Parameter blocks (exposed as ParameterBlock<T>) provide a first-class language feature for grouping related shader parameters and specifying that they should be passed to the GPU as a coherent block. Parameter blocks make it easy for applications to use the most efficient parameter-binding model of each API, such as descriptor tables/sets in D3D12/Vulkan.

  • Generics and interfaces allow shader specialization to be expressed cleanly without resort to preprocessor techniques or string-pasting. Unlike C++ templates, Slang's generics are checked ahead of time and don't produce cascading error messages that are difficult to diagnose. The same generic shader can be specialized for a variety of different types to produce specialized code ahead of time, or on the fly, completely under application control.

  • Slang provides a module system that can be used to logically organize code and benefit from separate compilation. Slang modules can be compiled offline to a custom IR (with optional obfuscation) and then linked at runtime to generate DXIL, SPIR-V etc.

  • Rather than require tedious explicit register and layout specifications on each shader parameter, Slang supports completely automate and deterministic assignment of binding locations to parameter. You can write simple and clean code and still get the deterministic layout your application wants.

  • For applications that want it, Slang provides full reflection information about the parameters of your shader code, with a consistent API across all target platforms and graphics APIs. Unlike some other compilers, Slang does not reorder or drop shader parameters based on how they are used, so you can always see the full picture.

Getting Started

If you want to try out the Slang language without installing anything, a fast and simple way is to use the Shader Playground.

The fastest way to get started using Slang in your own development is to use a pre-built binary package, available through GitHub releases. There are packages built for 32- and 64-bit Windows, as well as 64-bit Ubuntu. Each binary release includes the command-line slangc compiler, a shared library for the compiler, and the slang.h header.

If you would like to build Slang from source, please consult the build instructions.

Documentation

The Slang project provides a variety of different documentation, but most users would be well served starting with the User's Guide.

We also provide a few examples of how to integrate Slang into a rendering application.

Contributing

If you'd like to contribute to the project, we are excited to have your input. The following guidelines should be observed by contributors:

  • Please follow the contributor Code of Conduct.
  • Bugs reports and feature requests should go through the GitHub issue tracker
  • Changes should ideally come in as small pull requests on top of master, coming from your own personal fork of the project
  • Large features that will involve multiple contributors or a long development time should be discussed in issues, and broken down into smaller pieces that can be implemented and checked in in stages

Limitations

The Slang project has been used for production applications and large shader codebases, but it is still under active development. Support is currently focused on the platforms (Windows, Linux) and target APIs (Direct3D 12, Vulkan) where Slang is used most heavily. Users who are looking for support on other platforms or APIs should coordinate with the development team via the issue tracker to make sure that their use case(s) can be supported.

License

The Slang code itself is under the MIT license (see LICENSE).

Builds of the core Slang tools depend on the following projects, either automatically or optionally, which may have their own licenses:

Slang releases may include slang-llvm which includes LLVM under the license:

  • llvm (Apache 2.0 License with LLVM exceptions)

Some of the tests and example programs that build with Slang use the following projects, which may have their own licenses:

  • glm (MIT)
  • stb_image and stb_image_write from the stb collection of single-file libraries (Public Domain)
  • tinyobjloader (MIT)
Issues
  • Fix ARM64 detection for MSVC

    Fix ARM64 detection for MSVC

    Small one to fix ARM64 not being detected correctly for MSVC building for windows ARM64.

    Would be awesome to see windows arm64 binaries attached to releases as well, but I wasn't sure what needed to change to make that happen.

    opened by englercj 14
  • Poor performance when reading float4x4 uniform with dynamic array index

    Poor performance when reading float4x4 uniform with dynamic array index

    This may or may not be an issue of Slang, but I have observed a strange performance issue in my shader that is probably worth noting here.

    On Vulkan, I defined a uniform float4x4 array in my shader code (in this case, the lightMatrix for cascaded shadow maps), and as long as I am accessing the array in a loop, the performance drops dramatically (from ~200fps to 20fps), even after I changed loop to do nothing else but accessing the data.

    The performance issue is solved by manually unrolling the loop, and make sure the shader is only using constants as indices into the array. I also tried to just define float4 arrays, and construct a float4x4 by manually loading 4 float4s, but that doesn't seem to work either. However, the same issue does not exist for float4x3 arrays.

    Note that it does not matter whether the code is actually executed or not, the existence of such code causes the slow down of entire pixel shader execution, even if the access is in a branch that is never executed.

    I feel that this may have something to do with row_major, and if that is the case, then we definitely should generate code to handle all input fetching ourselves (as we discussed last time).

    kind:performance 
    opened by csyonghe 13
  • Do uniforms have incorrect

    Do uniforms have incorrect "set" index in Spirv?

    Hi,

    I was trying slang for a while and noticed for SPIRV (and GLSL) the ParameterBlock is converted to a uniform with set=1 decorator. Shouldn't that be set=0?

    Input: shader.slang:

    struct UBOData {
        float4x4 model;
        float4x4 view;
        float4x4 proj;
    };
    
    ParameterBlock<UBOData> ubo;
    

    GLSL output:

    layout(binding = 0, set = 1)
    layout(std140) uniform _S1
    {
        UBOData_0 ubo_0;
    };
    

    Shouldn't set be 0? Same with SPIRV's disassembly: OpDecorate %_ DescriptorSet 1

    I am trying to run some vulkan code, and my pipeline layout has only 1 descriptor set which is set 0. Is there any specific reason to go with set 1?

    Ran on Slang binary: v0.10.32

    kind:bug scenario:cross compilation area:reflection 
    opened by vasumahesh1 13
  • Hitting

    The issue reproduces with the compute shader from Falcor on the latest:

    https://github.com/NVIDIAGameWorks/Falcor/blob/55f943ef35ee752f368fc14fbc6352818af48367/Samples/Core/ComputeShader/Data/compute.hlsl

    Any write to a UAV of the pattern:

    uavTexture[coord] = foo;

    fails with this error.

    kind:bug area:semantic checking 
    opened by zbethel 13
  • API for compiling entry point sets

    API for compiling entry point sets

    Proposing the following API:

    struct Value
    {
        int valueType;
        char * stringValue;
        int intValue;
        float floatValue;
    };
    struct EntryPointSet
    {
         const char * name;
         SlangProfileID vsProfile, psProfile, hsProfile, gsProfile, dsProfile;
         int specializationArgumentCount;
         Value ** arguments;
    };
    int spAddEntryPointSet(compileRequest, EntryPointSet entryPointSet);
    
    SLANG_API char const* spGetEntryPointSetSource(
            SlangCompileRequest*    request,
            int                     entryPointSetIndex,
            SlangStage       stage);
    
    SLANG_API char const* spGetEntryPointSetCode(
            SlangCompileRequest*    request,
            int                     entryPointSetIndex,
            SlangStage       stage);
    

    When a compile request gets executed, it will compile the entry points defined in an entry point set using the corresponding profiles. The compiled code can be retrieved via spGetEntryPointSetSource and spGetEntryPointSetCode functions. spGetEntryPointSetSource returns null if the corresponding stage is not defined by the entry point set.

    kind:enhancement kind:design area:API 
    opened by csyonghe 10
  • Vector comparison returns wrong type

    Vector comparison returns wrong type

    Vector comparison operators such as operator ==(float3, float3) should return bool3, which shouldn't be allowed directly as if condition or in branching(x?y:z) expressions.

    Currently Slang does not issue any diagnostic message when source code does this, and generates invalid HLSL/GLSL that fails downstream compilation.

    opened by csyonghe 9
  • Float operation is in 16 bit precision?

    Float operation is in 16 bit precision?

    Hi, In slang shader I write:

    float computeRoot(float b, float c, int2 uv)
    {
        float d = b * b - 4 * c;
        gDebugTexture[uv] = float4(b*b,4*c,d,0);
        return d;
    }
    

    upon inspecting in renderdoc, the input of b = 0.016f; c = 0.00006f; I would expect b*b = 0.000256f, 4 * c = 0.00024, and d = 0.000016f; But in renderdoc it actually shows that gDebugTexture[uv] = ( 0.00026, 0.00026, 0, 0). Which means that b*b is calculated into 0.00026 with the same value as 4 * c becoming 0.00026. In turns the d becomes 0.

    This doesn't seems to be executing at 32 bit floating point precision. Looks more like half floating point precision. If I look at the spir-v code in renderdoc, i don't see any converting into half floating point.

    Any idea why this is happening?

    thanks.

    kind:question target:glsl scenario:cross compilation 
    opened by KaChen-Dex 8
  • Using associatedtypes from global generic type parameter does not work

    Using associatedtypes from global generic type parameter does not work

    //TEST(compute):COMPARE_COMPUTE:-xslang -use-ir
    //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
    //TEST_INPUT:type AssocImpl
    
    
    RWStructuredBuffer<float> outputBuffer;
    
    interface IBase
    {
        float getVal();
    };
    
    interface IAssoc
    {
        associatedtype TBase : IBase;
    };
    
    struct BaseImpl : IBase
    {
        float getVal() { return 1.0; }
    };
    
    struct AssocImpl : IAssoc
    {
        typedef BaseImpl TBase;
    };
    
    __generic_param T : IAssoc;
    
    
    [numthreads(4, 1, 1)]
    void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
    {
        uint tid = dispatchThreadID.x;
        T.TBase base;
        float rs = base.getVal();
        outputBuffer[tid] = rs;
    }
    

    Output HLSL contains FuncType = /*unhandled case*/

    opened by csyonghe 8
  • Support `static` methods

    Support `static` methods

    To express entry point functions in a entry-point-set struct, we need to be able to define the entry point functions as static methods of a struct type.

    For example, we should be able to compile:

    struct EPS
    {
          static VSOut vsMain(VSIn vsIn) {}
          static FSOut fsMain(VSOut vsOut) {}
    };
    
    kind:enhancement area:ir area:semantic checking 
    opened by csyonghe 8
  • Generate GLSL bindings for separate texture/sampler objects

    Generate GLSL bindings for separate texture/sampler objects

    To support OpenGL applications, Slang needs to have a story for generating GLSL bindings of separate texture / sampler objects.

    While it is relatively easier to just add support for combined texture/sampler objects for all targets, it feels limiting since it forces developers who wish to target OpenGL to author shader code using only combined texture/samplers.

    Ideally, I should be able to write the following code:

    Texture2D tex1;
    Texture2D tex2;
    SamplerState samplerState;
    
    void func()
    {
        vec4 v1 = tex1.Sample(samplerState, uv);
        vec4 v2 = tex2.Sample(samplerState, uv);
    }
    

    Slang should generate the following GLSL:

    layout(binding = 0) sampler2D tex1;
    layout(binding = 1) sampler2D tex2;
    ...
    

    And provide the following reflection data:

    tex1: type = texture2D,  binding = 0
    tex2: type = texture2D, binding = 1
    samplerState: type = sampler, binding = {0, 1} // this sampler is used at texture unit 0 and 1
    

    There is one case that we cannot easily handle: when the shader code samples one Texture2D object with two different sampler objects, it actually needs two different sampler2D declarations in GLSL, and need to tell the host to setup two different combined texture/samplers and bind them to the pipeline. I don't see a easy way to do this without adding complexity to the reflection API and the host logic. So it might be helpful for the compiler to just emit error message when this happens.

    kind:enhancement target:glsl scenario:cross compilation 
    opened by csyonghe 8
  • [Vulkan] Incorrect descriptor set when compiling from single slang shader?

    [Vulkan] Incorrect descriptor set when compiling from single slang shader?

    Hi,

    It seems I have another descriptor set issue. And a doubt too.

    Say if I have:

    ParameterBlock<UBOData> ubo;
    SamplerState     textureSampler;
    Texture2D        textureSource;
    

    And I have both my pixel shader and vertex shader functions in the same file. But ubo is not used in PS and vice versa for the texture & sampler.

    Do I expect ubo to be assigned to set 0 and texture sampler to set 1 when I get my compiled output? Or Do I expect both of them to be set 0 (Because the unused variables get compiled out)?

    Because I have neither the case and ubo gets assigned to set 1 and the texture+sampler gets set 0 (and correct bindings). Here is the source I used

    Output for GLSL:

    // Vertex Shader
    #line 25
    layout(binding = 0, set = 1)
    layout(std140) uniform _S1
    {
        UBOData_0 ubo_0;
    };
    
    // Pixel Shader
    #line 27 0
    layout(binding = 1)
    uniform texture2D textureSource_0;
    
    
    #line 26
    layout(binding = 0)
    uniform sampler textureSampler_0;
    

    Tested on 0.11.1

    kind:question scenario:cross compilation 
    opened by vasumahesh1 7
  • Split debug-layer into smaller files

    Split debug-layer into smaller files

    Changes:

    • In the same vein as D3D/Vulkan/CUDA/cpu, debug-layer.h/cpp has been split into multiple smaller files organized around individual classes.
    • Added a new debug-layer folder containing the post-split files and updated premake to account for it
    opened by lucy96chen 0
  • Added a new differential type system and various improvements

    Added a new differential type system and various improvements

    Added IDifferentiable interface and logic to check that types conform to this interface Added custom IR to make and access differential pairs along with a struct definition that the user can use to pass inputs. Changed some variable naming Moved derivative related definitions into diff.meta.slang and set up appropriate commands to include it into the stdlib. Rewrote tests to conform to new typing system.

    There's still quite some cleanup to do and some hacky code to rewrite, but the tests now pass again, and I wanted to make a PR before the changes get too large.

    opened by saipraveenb25 0
  • Basic pointer usages.

    Basic pointer usages.

    This PR adds parsing, checking and basic operators for pointer types.

    Now it is valid to use * in c-style declarator to define pointer-typed variables.

    Pointers can be compared, cast explicitly to and from uint64/int64 and implicitly to bool.

    Pointers can be dereferenced with the * operator which results in a RefType<T> that can be "opened" to an l-value T at assignments and calls.

    The & operator can be used on l-values to return a pointer.

    opened by csyonghe 0
  • Problems using `main` as an entry point for CPU based targets

    Problems using `main` as an entry point for CPU based targets

    Having an entry point called main can be a problem when compilation goes through a C/C++ backend, because it at least some C++ compilers require main conform to the normal C++ usage.

    This behavior can be seen when using slang-llvm (and presumably) LLVM, with a shader

    RWStructuredBuffer<float> outputBuffer;
    
    [numthreads(4, 1, 1)]
    void main(uint3 dispatchThreadID : SV_DispatchThreadID)
    {
        outputBuffer[dispatchThreadID.x] = float(dispatchThreadID.x);
    }
    

    Outputs...

    // [numthreads(4, 1, 1)]
    SLANG_PRELUDE_EXPORT
    void main(ComputeVaryingInput* varyingInput, void* entryPointParams, void* globalParams)
    {
        ComputeVaryingInput vi = *varyingInput;
        ComputeVaryingInput groupVaryingInput = {};
        for (uint32_t z = vi.startGroupID.z; z < vi.endGroupID.z; ++z)
        {
            groupVaryingInput.startGroupID.z = z;
            for (uint32_t y = vi.startGroupID.y; y < vi.endGroupID.y; ++y)
            {
                groupVaryingInput.startGroupID.y = y;
                for (uint32_t x = vi.startGroupID.x; x < vi.endGroupID.x; ++x)
                {
                    groupVaryingInput.startGroupID.x = x;
                    main_Group(&groupVaryingInput, entryPointParams, globalParams);
                }
            }
        }
    }
    

    Which leads to LLVM outputting

    LLVM/Clang 14.0: (72): error : 'main' must return 'int'
    LLVM/Clang 14.0: (72): error : first parameter of 'main' (argument count) must be of type 'int'
    LLVM/Clang 14.0: (72): error : second parameter of 'main' (argument array) must be of type 'char **'
    LLVM/Clang 14.0: (72): error : third parameter of 'main' (environment) must be of type 'char **'
    
    opened by jsmall-nvidia 0
  • Optimization level ignored in TargetDesc

    Optimization level ignored in TargetDesc

    The optimization level set in TargetDescs defined in slang.h appears to be ignored.

    TargetDesc can be passed in as part of the SessionDesc as part of global session construction. Some fields are honored from TargetDesc such as the floating point mode. But the optimization level appears to not be used (it's taken from the linkage in slang-compiler.cpp), which can be set by another API call (EndToEndCompileRequest::setOptimizationLevel)

    opened by jsmall-nvidia 0
  • Multiple -entry options in single slangc invocation does not work

    Multiple -entry options in single slangc invocation does not work

    Hello!

    I'm trying to use the slangc commandline utility to output multiple .spv outputs, one per entry point. However, this doesn't seem to work...

    According to the help,

    -entry : Specify the name of an entry-point function. Multiple -entry options may be used in a single invocation. If no -entry options are given, compiler will use [shader(...)] attributes to detect entry points.

    I have a simple slang file here:

    StructuredBuffer<float> buffer0;
    StructuredBuffer<float> buffer1;
    RWStructuredBuffer<float> result;
    
    [shader("compute")]
    [numthreads(1,1,1)]
    void hello(uint3 threadId : SV_DispatchThreadID)
    {
        uint index = threadId.x;
        result[index] = buffer0[index] + buffer1[index] + 1337.f;
    }
    
    [shader("compute")]
    [numthreads(1,1,1)]
    void world(uint3 threadId : SV_DispatchThreadID)
    {
        uint index = threadId.x;
        result[index] = buffer0[index] + buffer1[index] + 42.f;
    }
    

    This command works: slangc.exe hello-world.slang -entry hello -o test2.spv And this one works too: slangc.exe hello-world.slang -entry world -o test2.spv But multiple -entry result in errors: slangc.exe hello-world.slang -entry hello -o test1.spv -entry world -o test2.spv:

    (0): error 70: the output path 'test1.spv' is not associated with any entry point; a '-o' option for a compiled kernel must follow the '-entry' option for its corresponding entry point (0): error 70: the output path 'test2.spv' is not associated with any entry point; a '-o' option for a compiled kernel must follow the '-entry' option for its corresponding entry point

    Perhaps I'm using the compiler incorrectly here, but I would have expected the above to work given the help text generated by the compiler.

    opened by natevm 5
Releases(v0.24.11)
A modern-day Boss Key software tool. Switch instantly from work to play & play to work with Bosky.

Bosky By: Seanpm2001, Bosky-dev Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af Afrika

Sean P. Myrick V19.1.7.2 1 Nov 11, 2021
ApeX is a static library for C++ software. Originally it was created to make C++ studying easier,

ApeX is a static library for C++ software. Originally it was created to make C++ studying easier, so it has functions to complete common tasks with just one line of code. But who knows, maybe this library will get bigger some day

null 0 Jan 18, 2022
A single file, single function, header to make notifications on the PS4 easier

Notifi Synopsis Adds a single function notifi(). It functions like printf however the first arg is the image to use (NULL and any invalid input should

Al Azif 7 Mar 24, 2022
Seam is a pin-based node editor for OpenFrameworks that makes prototyping visual systems easier and faster.

seam Seam is a pin-based node editor for openFrameworks built using: openFrameworks Dear ImGui the node editor extension for ImGui It is heavily WIP,

Austin Clifton 2 Jan 2, 2022
A simple program to make your life a little easier when you evaluate the Rush exercises at 42.

Rush exercise number A simple program to make your life a little easier when you evaluate the Rush exercises at 42. Usage Run make to generate the exe

Edmar Paulino 3 Feb 7, 2022
This is the source code for for the Plugin GAS Associate, that is supposed to make your life easier while using Unreal's Gameplay Ability System.

GASAssociate Description: This is the source code for for the Plugin GAS Associate, that is supposed to make your life easier while using Unreal's Gam

Malik Sahab 10 Jul 24, 2022
SKSE plugin for replacing Skyrim SE shaders at launch.

Plugin for SSE Parallax Shader Fix. Requirements CMake Add this to your PATH PowerShell Vcpkg Add the environment variable VCPKG_ROOT with the value a

null 6 Jun 10, 2022
Hydrogen is a tiny GDI Malware, with some bytebeat music, many payloads and some shaders

Hydrogen is a tiny GDI Malware, with some bytebeat music, many payloads and some shaders

Leo Lezury 16 Jul 28, 2022
LLVM IR and optimizer for shaders, including front-end adapters for GLSL and SPIR-V and back-end adapter for GLSL

Licensing LunarGLASS is available via a three clause BSD-style open source license. Goals The primary goals of the LunarGLASS project are: Reduce the

LunarG, Inc. 151 Jun 18, 2022
A collection of post-processing shaders written for ReShade.

ReShade FX shaders This repository aims to collect post-processing shaders written in the ReShade FX shader language. Installation Download this repos

null 737 Jul 29, 2022
yariv.h is a single C/C++ header to encode and decode SPIR-V shaders into a more compressed form I've called YARI-V.

YARI-V yariv.h is a single C/C++ header to encode and decode SPIR-V shaders into a more compressed form I've called YARI-V. YARI-V is an alternative e

Neil Henning 32 May 3, 2022
⚔️ A tool for cross compiling shaders. Convert between GLSL, HLSL, Metal Shader Language, or older versions of GLSL.

A cross compiler for shader languages. Convert between SPIR-V, GLSL / GLSL ES, HLSL, Metal Shader Language, or older versions of a given language. Cross Shader wraps glslang and SPIRV-Cross, exposing a simpler interface to transpile shaders.

Alain Galvan 161 Aug 2, 2022
A collection of osl shaders

This is a collection of osl shaders that I have found. This collection is intended for use with a version of blender that has been compiled with osl

Shane Ambler 292 Aug 7, 2022
Step-by-step guide through the abstract and complex universe of Fragment Shaders.

The Book of Shaders by Patricio Gonzalez Vivo and Jen Lowe This is a gentle step-by-step guide through the abstract and complex universe of Fragment S

Patricio Gonzalez Vivo 4.6k Aug 7, 2022
dump and replace shaders of any OpenGL or Vulkan application

deshade deshade is a library that allows you to dump and replace the shaders of any OpenGL or Vulkan application, which includes: GL2 + extensions, GL

Dale Weiler 24 Jul 2, 2022
making dwm as beautiful as possible

chadwm (Initial look) (empty workspaces have their color greyed out) NOTE: This is vanilla dwm bar (status2d patch for setting colors) not dwmblocks o

null 824 Aug 6, 2022
✨ Your best friend when it comes to making your output beautiful ✨

?? Fadey ✨ Your best friend when it comes to making your output beautiful ✨ ?? Content: About Requirements Installation Features Performance Shoutout

Fluffy 3 Nov 29, 2021
This repository is for my coding practice, making a text editor from scratch in C.

text-editor-practice This repository will contain my coding practice, making a text editor from scratch. I based this practice from this wonderful res

null 2 Dec 13, 2021
Making dwm as beautiful as possible!

chadwm (Initial look) (empty workspaces have their color greyed out) NOTE: This is vanilla dwm bar (status2d patch for setting colors) not dwmblocks o

null 824 Aug 6, 2022