diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-02-02 10:38:22 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-02 10:38:22 -0800 |
| commit | 58475a8aa42284722a3763aa3bde49f2fa40366e (patch) | |
| tree | 33149d981bf63dc7583fdadbcc7d54cd319a2057 /docs/language-guide.md | |
| parent | 0360f81b9741ece65768a65731bd23455a3b7a96 (diff) | |
Revamp documentation (#395)
- Remove references to building by embedding source (not recommended at this point)
- Push users more toward binary builds rather than building from source (but include a document that talks about how to build)
- Remove most (all?) references to supporting GLSL input
- Expand the language guide to talk about the new features
- Add a document that talks about the parameter layout algorithm
Diffstat (limited to 'docs/language-guide.md')
| -rw-r--r-- | docs/language-guide.md | 209 |
1 files changed, 182 insertions, 27 deletions
diff --git a/docs/language-guide.md b/docs/language-guide.md index a388e70f3..2cced92aa 100644 --- a/docs/language-guide.md +++ b/docs/language-guide.md @@ -19,19 +19,18 @@ Big-picture stuff that is supported: * The built-in templated resource types like `Texture2D<T>` with their object-oriented syntax for sampling operations * Attributes like `[unroll]` are parsed, and passed along for HLSL/DXBC output, but dropped for other targets * `struct` types that contain textures/samplers as well as ordinary uniform data, both as function parameters and in constant buffers +* The built-in functions up through Shader Model 6.0 (as documented on MSDN) are supported New Features ------------ -Right now the Slang language only has one major feature that is different from existing HLSL (that will change over time). - ### Import Declarations -In order to support better software modularity, and also to deal with the issue of how to integrate shader libraries written in Slang into other langauges, Slang introduces an `__import` declaration construct. +In order to support better software modularity, and also to deal with the issue of how to integrate shader libraries written in Slang into other langauges, Slang introduces an `import` declaration construct. The basic idea is that if you write a file `foo.slang` like this: -``` +```hlsl // foo.slang float4 someFunc(float4 x) { return x; } @@ -39,61 +38,217 @@ float4 someFunc(float4 x) { return x; } you can then import this code into another file in Slang, HLSL, or GLSL: -``` -// bar.glsl +```hlsl +// bar.slang -__import foo; +import foo; -vec4 someOtherFunc(vec4 y) { return someFunc(y); } +float4 someOtherFunc(float4 y) { return someFunc(y); } ``` -The simplest way to think of it is that the `__import foo` declaration instructs the compiler to look for `foo.slang` (in the same search paths it uses for `#include` files), and give an error if it isn't found. +The simplest way to think of it is that the `import foo` declaration instructs the compiler to look for `foo.slang` (in the same search paths it uses for `#include` files), and give an error if it isn't found. If `foo.slang` is found, then the compiler will go ahead and parse and type-check that file, and make any declarations there visible to the original file (`bar.glsl` in this example). -When it comes time to generate output code, Slang will output any declarations from `__import`ed files that were actually used (it skips those that are never referenced), and it will cross-compile them as needed for the chosen target. +When it comes time to generate output code, Slang will output any declarations from `import`ed files that were actually used (it skips those that are never referenced), and it will cross-compile them as needed for the chosen target. -A few other details worth knowing about `__import` declarations: +A few other details worth knowing about `import` declarations: -* The name you use on the `__import` line gets translated into a file name with some very simple rules. An underscore (`_`) in the name turns into a dash (`-`) in the file name, and dot separators (`.`) turn into directory seprators (`/`). After these substitutions, `.slang` is added to the end of the name. +* The name you use on the `import` line gets translated into a file name with some very simple rules. An underscore (`_`) in the name turns into a dash (`-`) in the file name, and dot separators (`.`) turn into directory seprators (`/`). After these substitutions, `.slang` is added to the end of the name. -* If there are multiple `__import` declarations naming the same file, it will only be imported once. This is also true for nested imports. +* If there are multiple `import` declarations naming the same file, it will only be imported once. This is also true for nested imports. * Currently importing does not imply any kind of namespacing; all global declarations still occupy a single namespace, and collisions between different imported files (or between a file and the code it imports) are possible. This is a bug. -* If file `A.slang` imports `B.slang`, and then some other file does `__import A;`, then only the names from `A.slang` are brought into scope, not those from `B.slang`. This behavior can be controlled by having `A.slang` use `__exported __import B;` to also re-export the declarations it imports from `B`. +* If file `A.slang` imports `B.slang`, and then some other file does `import A;`, then only the names from `A.slang` are brought into scope, not those from `B.slang`. This behavior can be controlled by having `A.slang` use `__exported import B;` to also re-export the declarations it imports from `B`. + +* An import is *not* like a `#include`, and so the file that does the `import` can't see preprocessor macros defined in the imported file (and vice versa). Think of `import foo;` as closer to `using namspace foo;` in C++ (perhaps without the same baggage). + +### Explicit Parameter Blocks + +One of the most important new features of modern APIs like Direct3D 12 and Vulkan is an interface for providing shader parameters using efficient *parameter blocks* that can be stored in GPU memory (these are implemented as descritpor tables/sets in D3D12/Vulkan, and "attribute buffers" in Metal). +However, HLSL and GLSL don't support explicit syntax for parmaeter blocks, and so shader programmers are left to manually pack parameters into blocks either using `register`/`layout` modifiers, or with API-based remapping (in the D3D12 case). + +Slang supports a simple and explicit syntax for exploiting parameter blocks: + +```hlsl +struct ViewParams +{ + float3 cameraPos; + float4x4 viewProj; + TextureCube envMap; +}; + +ParameterBlock<ViewParams> gViewParams; +``` + +In this example, the fields of `gViewParams` will be assigned to registers/bindings in a way that supports allocating them into a single parameter block. +For example, when generating GLSL for Vulkan, the Slang compiler will generate a single `uniform` block (for `cameraPos` and `viewProj`) and a global `textureCube` for `envMap`, both decorated with the same `layout(set = ...)`. + + +### Interfaces -* An import is *not* like a `#include`, and so the file that does the `__import` can't see preprocessor macros defined in the imported file (and vice versa). Think inf `__import foo;` as closer to `using namspace foo;` in C++ (perhaps without the same baggage). +Slang supports declaring `interface`s that user-defined `struct` types can implement. +For example, here is a simple interface for light sources: -On that last point, if you really do want something that is like `__import` but interacts with the preprocessor more like `#include` then you can try using `#import`: +```hlsl +// light.slang +struct LightSample { float3 intensity; float3 direction; }; + +interface ILight +{ + LightSample sample(float3 position); +} ``` -#import "foo.slang" -... + +We can now define a simple user type that "conforms to" (implements) the `ILight` interface: + +```hlsl +// point-light.slang + +import light; + +struct PointLight : ILight +{ + float3 position; + float3 intensity; + + LightSample sample(float3 hitPos) + { + float3 delta = hitPos - position; + float distance = length(delta); + + LightSample sample; + sample.direction = delta / distance; + sample.intensity = intensity * falloff(distance); + return sample; + } +} ``` -The `#import` directive is recognized during preprocessing, so macro definitions from the importing file will affect the imported code, and vice versa. -The rules about multiple imports still apply, though, so only the first `#import` encountered will determine the text that is parsed (be careful). -Please think of `#import` as a stopgap for when you want the cross-compilation benefits of `__import`, but need to deal with code that depends on macros in the here and now. +### Generics + +Slang supports *generic* declarations, using the commong angle-brack (`<>`) syntax from languages like C#, Java, etc. +For example, here is a generic function that works with any type of light: + +```hlsl +// diffuse.slang +import light; + +float4 computeDiffuse<L : ILight>( float4 albedo, float3 P, float3 N, L light ) +{ + LightSample sample = light.sample(P); + float nDotL = max(0, dot(N, sample.direction)); + return albedo * nDotL; +} +``` + +The `computeDiffuse` function works with any type `L` that implements the `ILight` interface. +Unlike with C++ templates, the `computeDiffuse` function can be compiled and type-checked once (you won't suddenly get unexpected error messages when plugging in a new type). + +#### Global-Scope Generic Parameters + +Putting generic parameter directly on functions is helpful, but in many cases existing HLSL shaders declare their parameters at global scope. +For example, we might have a shader that uses a global declaration of material parameters: + +```hlsl +Material gMaterial; +``` + +In order to allow such a shader to be converted to use a generic parameter for the material type (to allow for specialization), Slang supports declaring type parameters at the global scope: + +```hlsl +type_param M : IMaterial; +M gMaterial; +``` + +Conceptually, you can think of this syntax as wrapping your entire shader program in a generic with parameter `<M : IMaterial>`. +This isn't beautiful syntax, but it may help when incrementally porting an existing HLSL codebase to use Slang's features. + +### Associated Types + +Sometimes it is difficult to define an interface because each type that implements it might need to make its own choice about some intermediate type. +As a concrete example, suppose we want to define an interface `IMaterial` for material surface shaders, where each material might use its own BRDF. +We want to support evaluating the *pattern* of the surface separate from the reflectance function. + +```hlsl +// A reflectance function +interface IBRDF +{ + float3 eval(float3 wi, float3 wo); +} +struct DisneyBRDF : IBRDF { ... }; +struct KajiyaKay : IBRDF { ... }; + +// a surface pattern +interface IMaterial +{ + ??? evalPattern(float3 position, float2 uv); +} +``` + +What is the type `???` that `evalPattern` should return? We know that it needs to be a type that supports `IBRDF`, but *which* type? +One material might want to use `DisneyBRDF` while another wants to use `KajiyaKay`. + +The solution in Slang, as in modern languages like Swift and Rust, is to use *associated types* to express the depdence of the BRDF type on the material type: + +```hlsl +interface IMaterial +{ + associatedtype B : IBRDF; + B evalPattern(float3 position, float2 uv); +} + +struct MyCoolMaterial : IMaterial +{ + typedef DisneyBRDF B; + DisneyBRDF evalPattern(float3 position, float2 uv) + { ... } +} +``` + +Associated types are an advanced concept, and we only recommend using them when they are needed to define a usable interface. + Future Extensions ----------------- -Longer term we would like to make Slang a much more advanced language, and indeed the implementation already has some of the underpinnings for more powerful things. +### Implicit Generics Syntax + +The syntax for generics and interfaces in Slang is currently explicit, but verbose: + +```hlsl +float4 computeDiffuse<L : ILight>( L light, ... ) +{ ... } +``` + +As a future change, we would like to allow using an interface like `ILight` as an ordinary parameter type: -The most important feature we plan to add is support for "constrained generics" as they appear in C#, Rust, and Swift. -For those of you with a C++ background you could think of this as "templates + concepts", but without many of the rought edges. +```hlsl +float4 computeDiffuse( ILight light, ... ) +{ ... } +``` + +This simpler syntax would act like "syntactic sugar" for the existing explicit generics syntax, so it would retain all of the important performance properties. + +### Returning a Value of Interface Type + +While the above dealt with using an interface as a parameter type, we would eventually like to support using an interface as the *return* type of a function: + +```hlsl +ILight getALightSource(Scene scene) { ... } +``` -Using constrained generics as an underlying mechanism, we then plan to introduce a feature similar in capability to Cg's "interfaces" feature, to allow shaders to express more flexible patterns of composition and dispatch. +Implementing this case efficiently is more challenging. In most cases, an associated type can be used instead when an interface return type would be desired. Not Supported ------------- -Some things are not supported, but probably will be given enough time/resources: +Some features of the current HLSL language are not supported, but probably will be given enough time/resources: * Local variables of texture/sampler type (or that contain these) * Matrix swizzles -* Object-oriented extensions for putting methods inside `struct` types * Explicit `packoffset` annotations on members of `cbuffer`s Some things from HLSL are *not* planned to be supported, unless there is significant outcry from users: |
