diff options
| -rw-r--r-- | docs/_includes/user-guide-toc.html | 5 | ||||
| -rw-r--r-- | docs/assets/css/style.scss | 10 | ||||
| -rw-r--r-- | docs/user-guide/a1-01-matrix-layout.md | 63 |
3 files changed, 48 insertions, 30 deletions
diff --git a/docs/_includes/user-guide-toc.html b/docs/_includes/user-guide-toc.html index a761fe3fd..b3c1ed39f 100644 --- a/docs/_includes/user-guide-toc.html +++ b/docs/_includes/user-guide-toc.html @@ -1,5 +1,6 @@ + <a href="/slang/user-guide/">Slang User's Guide</a> -<ol style="list-style-type:decimal"> +<ol> <li><a href="/slang/user-guide/00-introduction.html">Introduction</a></li> <li><a href="/slang/user-guide/01-get-started.html">Getting Started</a></li> <li><a href="/slang/user-guide/02-conventional-features.html">Conventional Language Features</a></li> @@ -8,7 +9,7 @@ <li><a href="/slang/user-guide/05-compiling.html">Compiling Code with Slang</a></li> <li><a href="/slang/user-guide/06-targets.html">Supported Compilation Targets</a></li> <li><a href="/slang/user-guide/a1-special-topics.html">Special Topics</a></li> - <ol style="list-style-type:circle"> + <ol> <li><a href="/slang/user-guide/a1-01-matrix-layout.html">Matrix Layout</a></li> </ol> diff --git a/docs/assets/css/style.scss b/docs/assets/css/style.scss index df8ca8272..c8cb75a7c 100644 --- a/docs/assets/css/style.scss +++ b/docs/assets/css/style.scss @@ -6,3 +6,13 @@ blockquote p { font-size: 16px; font-weight: 600; } + +ol { + counter-reset: section; + list-style-type: none; +} + +li:before { + counter-increment: section; + content: counters(section, ".") " "; +}
\ No newline at end of file diff --git a/docs/user-guide/a1-01-matrix-layout.md b/docs/user-guide/a1-01-matrix-layout.md index 347a7cfb1..b24c925df 100644 --- a/docs/user-guide/a1-01-matrix-layout.md +++ b/docs/user-guide/a1-01-matrix-layout.md @@ -7,34 +7,22 @@ Handling Matrix Layout Differences on Different Platforms The differences on default matrix layout or storage conventions between GLSL (OpenGL/Vulkan) and HLSL has been an issue that frequently causes confusion among developers. When writing applications that work on different targets, one important goal that developers frequently seek is to make it possible to pass the same matrix generated by host code to the same shader code, regardless of what graphics API is being used (e.g. Vulkan, OpenGL or Direct3D). As a solution to shader cross-compilation, Slang provides necessary tools for developers navigate around the differences between GLSL and HLSL targets. -Row-major vs Column-major storage layouts +Two conventions of matrix transform math ------------------------- -In this article, the term matrix layouts or storage layouts refers to the order of matrix elements in memory. Specifically, we use the following umambiguous technique to determine whether a matrix is in `row-major` and `column-major` layout: if we have a 4x4 matrix defined as `float m[16]`, and the translation terms are stored at `m[12], m[13], m[14]`, then we say this matrix is in `column-major` layout. If the translation terms are stored at `m[3], m[7], m[11]`, then we say this matrix is in `row-major` layout. +Depending on the platform a developer is used to, a matrix-vector transform can be expressed as either `v*m` (`mul(v, m)` in HLSL), or `m*v` (`mul(m,v)` in HLSL). This convention, together with the matrix layout (column-major or row-major), determines how a matrix should be filled out in host code. One way to make things less ambiguous is to think about where the translation terms should be placed in memory when filling a typical 4x4 transform matrix. -> Note: the term row-major and column-major are heavily overloaded and can mean very different things depending on the context. In this article, we use these terms only as a way to distinguish where the translation terms are placed in a matrix, not anything else. This may contradict with the naming convention that you are used to depending on the platform you are comming from, but the consistent way to make things right stays the same regardless of how it is called. +If the shader code writes `mul(m, v)`, then the last **column** of `m` defines the translation terms. If we use row-major matrix layout, then the host code should make sure the translation terms are filled in at `m + 4, 7, 11` locations in memory. -Using this technique, it should be easy to know the layout that your host math library is using. For example, the `glm` library uses `column-major` layout by default under the definition of this article. +Alternatively, if the shader code writes `mul(v, m)`, then the last **row** of `m` defines the translation terms. When using row-major matrix layout, the host code should make sure the translation terms are filled in at `m + 12, 13, 14` locations in memory. -If the host code generates a `column-major` matrix, then a vertex shader written in GLSL should be like this: -``` -gl_Position = modelViewProjectionMatrix * vertexPosition; -``` -The same vertex shader written in HLSL should be: -``` -float4 result = mul(vertexPosition, modelViewProjectionMatrix); -``` +By default, Slang assumes all matrices to be in **row-major** layout, since this is the most nature layout to work with in CPU code: each row of the matrix occupies contiguous space in memory. A user should stick to one of the above practices to get correct result. Note that this is different from `fxc` which assumes `column_major` layout by default. As an example, if the host code uses `glm` library to generate transform matrices, the translation terms will be stored in `[12], [13], [14]` locations in memory. Therefore, the shader code should stick to the `mul(v,m)` convention to ensure correctness. -If the host code generates a `row-major` matrix, the correct GLSL code should be: -``` -gl_Position = vertexPosition * modelViewProjectionMatrix; -``` -The correct HLSL code should be: -``` -float4 result = mul(modelViewProjectionMatrix, vertexPosition); -``` +Slang automatically handles the convention differences when cross-compiling code to GLSL. For example, a `float3x4` matrix will be translated to `mat4x3` in the resulting GLSL. Correspondingly, `mul(v, m)` will be translated to `m*v` in GLSL. Therefore, as long as the user is sticking to the above practices consistently, they will get correct result with the same matrix value in memory regardless of what graphics API they are actually using. -As you can see, the ordering of matrix multiplication is always reversed between GLSL and HLSL. -Slang will always translate `mul(a, b)` to `b * a` when generating GLSL code. By default, Slang assumes all matrices to be in `row-major` layout, so a shader code written in Slang should be written as `mul(modelViewProjectionMatrix, vertexPosition)`, and the host application should always make sure to pass matrices in row-major layout to shaders. However, the user can always override this behavior with a compiler flag to make Slang compiler assume `column-major` matrix layout by default. This compiler flag can be specified during the creation of a `Session`: +Overriding default matrix layout +-------------------------- + +While we do not recommend so, Slang allows users to override default matrix layout with a compiler flag. This compiler flag can be specified during the creation of a `Session`: ``` slang::IGlobalSession* globalSession; ... @@ -45,18 +33,37 @@ slang::ISession* session; globalSession->createSession(slangSessionDesc, &session); ``` -In summary, to make sure your application works correctly on all platforms, you need to make sure the application does the following things consistently: +This make make Slang treat all matrices as in column-major layout, and emit `column_major` qualifier in resulting code. + +Note that if you choose to use column-major layout, you either need to flip the matrix multiplication order in shader code or fill in the matrix in transpose order in host code. -**Option 1 (translation terms in 12,13,14)** +Summary +------------- -- Make sure the host code fills in matrices in row-major layout, i.e. translation terms are specified in `m[3], m[7], m[11]` elements. +In summary, we put together all options you have to ensure correct result: + +**Option 1: using row-major matrix layout, and `mul(m, v)` math convention** + +- Make sure the host code fills in matrices in the odering so that translation terms are specified in `m[3], m[7], m[11]` elements. +- Leave `defaultMatrixLayoutMode` as default value when creating a Slang session, or specify `SLANG_MATRIX_LAYOUT_ROW_MAJOR`. +- Write `mul(Matrix, Vector)` in shader code to transform `Vector` by `Matrix`. + +**Option 2: using row-major matrix layout, and `mul(v, m)` math convention** + +- Make sure the host code fills in matrices so that translations terms are specified in `m[12], m[13], m[14]` elements. Matrices filled in this way are compatible with typical OpenGL applications. - Leave `defaultMatrixLayoutMode` as default value when creating a Slang session, or specify `SLANG_MATRIX_LAYOUT_ROW_MAJOR`. +- Write `mul(Vector, Matrix)` in shader code. + +**Option 3: using column-major matrix layout, and `mul(m, v)` math convention** + +- Make sure the host code fills in matrices in the odering so that translation terms are specified in `m[12], m[13], m[14]` elements. Matrices filled in this way are compatible with typical OpenGL applications. +- Set `defaultMatrixLayoutMode` to `SLANG_MATRIX_LAYOUT_COLUMN_MAJOR` when creating a Slang session. - Write `mul(Matrix, Vector)` in shader code to transform `Vector` by `Matrix`. -**Option 2 (translation terms in 3,7,11)** +**Option 4: using column-major matrix layout, and `mul(v, m)` math convention** -- Make sure the host code fills in matrices in column-major layout, i.e. translations terms are specified in `m[12], m[13], m[14]` elements. +- Make sure the host code fills in matrices so that translations terms are specified in `m[3], m[7], m[11]` elements. - Set `defaultMatrixLayoutMode` to `SLANG_MATRIX_LAYOUT_COLUMN_MAJOR` when creating a Slang session. - Write `mul(Vector, Matrix)` in shader code. -And that's it! Slang will make sure the remaining details are correctly handled when generating target HLSL/GLSL code. +And that's all you need to pay attention to. Slang will make sure the remaining details are correctly handled when generating target HLSL/GLSL code. |
