yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
785548a49
master
layout: user-guide permalink: /user-guide/get-started
Getting Started with Slang
Slang enables you to do many powerful things with shader code, including compiling shader code to many different platforms, obtaining reflection information, organizing your shader library in a modern modular fashion, controlling specialization and more. The following sections help you get started with the basics of Slang in a simple example. We will assume Windows as the operating system, but the steps performed here are similar for other platforms.
Installation
The easiest way to start using Slang is to download a binary release from the GitHub repository. Once you have downloaded and extracted the files from a release package, you can find the slangc.exe or slangc executable under /bin. In this tutorial we will use the slangc standalone Slang compiler included in a release package.
Note: Required Dependencies
For Windows,
slang.dllandslang-glslang.dllmust be placed in the same directory asslangc.exeas they are required by the standalone executable.
Note: Multiple Slang Installations
If you have multiple versions of Slang installed on your system (such as Slang from the Vulkan SDK), ensure that the correct dynamic libraries are being loaded. On Linux, the
LD_LIBRARY_PATHenvironment variable will override theRUNPATHembedded in theslangcexecutable, causing it to loadlibslang.sofrom the path specified inLD_LIBRARY_PATHfirst. This can lead to version mismatches and unexpected behavior.
If you are interested in building from source, please refer to the documentation on building Slang.
Your first Slang shader
In this section we demonstrate how to write a simple compute shader in Slang that adds numbers from two buffers and writes the results into a third buffer. To start, create a text file named hello-world.slang in any directory, and paste the following content in the newly created file:
// hello-world.slang StructuredBuffer < float > buffer0 ; StructuredBuffer < float > buffer1 ; RWStructuredBuffer < float > result ; [ shader ( "compute" )] [ numthreads ( 1 , 1 , 1 )] void computeMain ( uint3 threadId : SV_DispatchThreadID ) { uint index = threadId . x ; result [ index ] = buffer0 [ index ] + buffer1 [ index ]; }
Note
Slang has official language extension support for both Visual Studio and Visual Studio Code. The extensions are powered by the Slang compiler to support a wide range of assisting features including auto-completion, function signature hinting, semantic highlighting and more.
As you can see, hello-world.slang is no different from a normal HLSL shader file. In fact, Slang is compatible with most HLSL code you would write. On top of HLSL, Slang has added many new language and compiler features that simplifies various tasks with shader code, which we will cover in future chapters. For now we will demonstrate one key feature of Slang: cross-compiling to different platforms.
Slang supports compiling shaders into many different targets including Direct3D 11, Direct3D 12, Vulkan, CUDA and C++ (for execution on CPU). You can run slangc with the following command line to compile hello-world.slang into Vulkan SPIRV:
.\slangc .exe hello -world .slang -profile glsl_450 -target spirv -o hello -world .spv -entry computeMain
If you would like to see the equivalent GLSL of the generated SPIRV code, simply change the -target argument to glsl:
.\slangc .exe hello -world .slang -profile glsl_450 -target glsl -o hello -world .glsl -entry computeMain
The resulting hello-world.glsl generated by slangc is shown below:
// hello-world.glsl (generated by slangc) #version 450layout (row_major )uniform ;layout (row_major )buffer ;#line 2 0 layout (std430 ,binding = 0 )readonly buffer _S1 {float _data []; }buffer0_0 ;#line 3layout (std430 ,binding = 1 )readonly buffer _S2 {float _data []; }buffer1_0 ;#line 4layout (std430 ,binding = 2 )buffer _S3 {float _data []; }result_0 ;layout (local_size_x = 1 ,local_size_y = 1 ,local_size_z = 1 )in ;void main () {#line 10uint index_0 = gl_GlobalInvocationID .x ;float _S4 = ((buffer0_0 )._data [(index_0 )]);#line 11float _S5 = ((buffer1_0 )._data [(index_0 )]);#line 11float _S6 = _S4 + _S5 ;#line 11 ((result_0 )._data [(index_0 )])= _S6 ;#line 8return ; }
As you can see, things are being translated just as expected to GLSL: the HLSL StructuredBuffer and RWStructuredBuffer types are mapped to shader storage objects and the [numthreads] attribute are translated into proper layout(...) in qualifier on the main entry-point.
Note that in the generated GLSL code, all shader parameters are qualified with explicit binding layouts. This is because Slang provides a guarantee that all parameters will have fixed bindings regardless of shader optimization. Without generating explicit binding layout qualifiers, the downstream compiler in the driver may change the binding of a parameter depending on whether any preceding parameters are eliminated during optimization passes. In practice this causes a pain in application code, where developers will need to rely on run-time reflection to determine the binding location of a compiled shader kernel. The issue gets harder to manage when the application also needs to deal with shader specializations. Since Slang will always generate explicit binding locations in its output on all targets as if no parameters are eliminated, the user is assured that parameters always gets a deterministic binding location without having to write any manual binding qualifiers in the Slang code themselves. In fact, we strongly encourage users not to qualify their Slang code with explicit binding qualifiers and let the Slang compiler do its work to properly lay out parameters. This is best practice to maintain code modularity and avoid potential binding location conflicts between different shader modules.
The full example
The full Vulkan example that sets up and runs the hello-world.slang shader is located in the /examples/hello-world directory of the Slang repository. The example code initializes a Vulkan context and runs the compiled SPIRV code. The example code demonstrates how to use the Slang API to load and compile shaders.
1--- 2layout : user-guide 3permalink : /user-guide/get-started 4--- 5 6# Getting Started with Slang 7 8Slang enables you to do many powerful things with shader code, including compiling shader code to many different platforms, obtaining reflection information, organizing your shader library in a modern modular fashion, controlling specialization and more. The following sections help you get started with the basics of Slang in a simple example. We will assume Windows as the operating system, but the steps performed here are similar for other platforms. 9 10## Installation 11 12The easiest way to start using Slang is to download a [binary release](https://github.com/shader-slang/slang/releases/) from the GitHub repository. Once you have downloaded and extracted the files from a release package, you can find the `slangc.exe` or `slangc` executable under `/bin`. In this tutorial we will use the `slangc` standalone Slang compiler included in a release package. 13 14> #### Note: Required Dependencies #### 15> For Windows, `slang.dll` and `slang-glslang.dll` must be placed in the same directory as `slangc.exe` as they are required by the standalone executable. 16 17> #### Note: Multiple Slang Installations #### 18> If you have multiple versions of Slang installed on your system (such as Slang from the Vulkan SDK), ensure that the correct dynamic libraries are being loaded. On Linux, the `LD_LIBRARY_PATH` environment variable will override the `RUNPATH` embedded in the `slangc` executable, causing it to load `libslang.so` from the path specified in `LD_LIBRARY_PATH` first. This can lead to version mismatches and unexpected behavior. 19 20If you are interested in building from source, please refer to the [documentation on building Slang](../building.md). 21 22## Your first Slang shader 23 24In this section we demonstrate how to write a simple compute shader in Slang that adds numbers from two buffers and writes the results into a third buffer. To start, create a text file named `hello-world.slang` in any directory, and paste the following content in the newly created file: 25 26``` hlsl 27// hello-world.slang 28StructuredBuffer < float > buffer0 ; 29StructuredBuffer < float > buffer1 ; 30RWStructuredBuffer < float > result ; 31 32[ shader ( "compute" )] 33[ numthreads ( 1 , 1 , 1 )] 34void computeMain ( uint3 threadId : SV_DispatchThreadID ) 35{ 36uint index = threadId . x ; 37result [ index ] = buffer0 [ index ] + buffer1 [ index ]; 38} 39``` 40 41> #### Note #### 42> Slang has official language extension support for both [Visual Studio](https://marketplace.visualstudio.com/items?itemName=shader-slang.slang-vs-extension) and [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=shader-slang.slang-language-extension). The extensions are powered by the Slang compiler to support a wide range of 43> assisting features including auto-completion, function signature hinting, semantic highlighting and more. 44 45As you can see, `hello-world.slang` is no different from a normal HLSL shader file. In fact, Slang is compatible with most HLSL code you would write. On top of HLSL, Slang has added many new language and compiler features that simplifies various tasks with shader code, which we will cover in future chapters. For now we will demonstrate one key feature of Slang: cross-compiling to different platforms. 46 47Slang supports compiling shaders into many different targets including Direct3D 11, Direct3D 12, Vulkan, CUDA and C++ (for execution on CPU). You can run `slangc` with the following command line to compile `hello-world.slang` into Vulkan SPIRV: 48 49``` bat 50.\slangc.exe hello-world.slang -profile glsl_450 -target spirv -o hello-world.spv -entry computeMain 51``` 52 53If you would like to see the equivalent GLSL of the generated SPIRV code, simply change the `-target` argument to `glsl`: 54``` bat 55.\slangc.exe hello-world.slang -profile glsl_450 -target glsl -o hello-world.glsl -entry computeMain 56``` 57 58The resulting `hello-world.glsl` generated by `slangc` is shown below: 59``` glsl 60// hello-world.glsl (generated by slangc) 61#version 450 62layout( row_major ) uniform ; 63layout( row_major ) buffer ; 64 65#line 2 0 66layout( std430 , binding = 0 ) readonly buffer _S1 { 67float _data []; 68} buffer0_0 ; 69 70#line 3 71layout( std430 , binding = 1 ) readonly buffer _S2 { 72float _data []; 73} buffer1_0 ; 74 75#line 4 76layout( std430 , binding = 2 ) buffer _S3 { 77float _data []; 78} result_0 ; 79 80layout( local_size_x = 1 , local_size_y = 1 , local_size_z = 1 ) in ; 81void main () 82{ 83 84#line 10 85uint index_0 = gl_GlobalInvocationID . x ; 86float _S4 = (( buffer0_0 ). _data [( index_0 )]); 87 88#line 11 89float _S5 = (( buffer1_0 ). _data [( index_0 )]); 90 91#line 11 92float _S6 = _S4 + _S5 ; 93 94#line 11 95(( result_0 ). _data [( index_0 )]) = _S6 ; 96 97#line 8 98return ; 99} 100``` 101 102As you can see, things are being translated just as expected to GLSL: the HLSL `StructuredBuffer` and `RWStructuredBuffer` types are mapped to shader storage objects and the `[numthreads]` attribute are translated into proper `layout(...) in` qualifier on the `main` entry-point. 103 104Note that in the generated GLSL code, all shader parameters are qualified with explicit binding layouts. This is because Slang provides a guarantee that all parameters will have fixed bindings regardless of shader optimization. Without generating explicit binding layout qualifiers, the downstream compiler in the driver may change the binding of a parameter depending on whether any preceding parameters are eliminated during optimization passes. In practice this causes a pain in application code, where developers will need to rely on run-time reflection to determine the binding location of a compiled shader kernel. The issue gets harder to manage when the application also needs to deal with shader specializations. Since Slang will always generate explicit binding locations in its output on all targets as if no parameters are eliminated, the user is assured that parameters always gets a deterministic binding location without having to write any manual binding qualifiers in the Slang code themselves. In fact, we strongly encourage users not to qualify their Slang code with explicit binding qualifiers and let the Slang compiler do its work to properly lay out parameters. This is best practice to maintain code modularity and avoid potential binding location conflicts between different shader modules. 105 106## The full example 107 108The full Vulkan example that sets up and runs the `hello-world.slang` shader is located in the [/examples/hello-world](https://github.com/shader-slang/slang/tree/master/examples/hello-world) directory of the Slang repository. The example code initializes a Vulkan context and runs the compiled SPIRV code. The example code demonstrates how to use the Slang API to load and compile shaders.