Expand description
Backend for HLSL (High-Level Shading Language).
§Supported shader model versions:
- 5.0
- 5.1
- 6.0
§Layout of values in uniform
buffers
WGSL’s “Internal Layout of Values” rules specify how each WGSL
type should be stored in uniform
and storage
buffers. The HLSL we
generate must access values in that form, even when it is not what
HLSL would use normally.
Matching the WGSL memory layout is a concern only for uniform
variables. WGSL storage
buffers are translated as HLSL
ByteAddressBuffers
, for which we generate Load
and Store
method
calls with explicit byte offsets. WGSL pipeline inputs must be scalars
or vectors; they cannot be matrices, which is where the interesting
problems arise. However, when an affected type appears in a struct
definition, the transformations described here are applied without
consideration of where the struct is used.
Access to storage buffers is implemented in storage.rs
. Access to
uniform buffers is implemented where applicable in writer.rs
.
§Row- and column-major ordering for matrices
WGSL specifies that matrices in uniform buffers are stored in
column-major order. This matches HLSL’s default, so one might expect
things to be straightforward. Unfortunately, WGSL and HLSL disagree on
what indexing a matrix means: in WGSL, m[i]
retrieves the i
’th
column of m
, whereas in HLSL it retrieves the i
’th row. We
want to avoid translating m[i]
into some complicated reassembly of a
vector from individually fetched components, so this is a problem.
However, with a bit of trickery, it is possible to use HLSL’s m[i]
as the translation of WGSL’s m[i]
:
-
We declare all matrices in uniform buffers in HLSL with the
row_major
qualifier, and transpose the row and column counts: a WGSLmat3x4<f32>
, say, becomes an HLSLrow_major float3x4
. (Note that WGSL and HLSL type names put the row and column in reverse order.) Since the HLSL type is the transpose of how WebGPU directs the user to store the data, HLSL will load all matrices transposed. -
Since matrices are transposed, an HLSL indexing expression retrieves the “columns” of the intended WGSL value, as desired.
-
For vector-matrix multiplication, since
mul(transpose(m), v)
is equivalent tomul(v, m)
(note the reversal of the arguments), andmul(v, transpose(m))
is equivalent tomul(m, v)
, we can translate WGSLm * v
andv * m
to HLSL by simply reversing the arguments tomul
.
§Padding in two-row matrices
An HLSL row_major floatKx2
matrix has padding between its rows that
the WGSL matKx2<f32>
matrix it represents does not. HLSL stores all
matrix rows aligned on 16-byte boundaries, whereas WGSL says
that the columns of a matKx2<f32>
need only be aligned as required
for vec2<f32>
, which is eight-byte alignment.
To compensate for this, any time a matKx2<f32>
appears in a WGSL
uniform
value or as part of a struct/array, we actually emit K
separate float2
members, and assemble/disassemble the matrix from its
columns (in WGSL; rows in HLSL) upon load and store.
For example, the following WGSL struct type:
struct Baz {
m: mat3x2<f32>,
}
is rendered as the HLSL struct type:
struct Baz {
float2 m_0; float2 m_1; float2 m_2;
};
The wrapped_struct_matrix
functions in help.rs
generate HLSL
helper functions to access such members, converting between the stored
form and the HLSL matrix types appropriately. For example, for reading
the member m
of the Baz
struct above, we emit:
float3x2 GetMatmOnBaz(Baz obj) {
return float3x2(obj.m_0, obj.m_1, obj.m_2);
}
We also emit an analogous Set
function, as well as functions for
accessing individual columns by dynamic index.
§Sampler Handling
Due to limitations in how sampler heaps work in D3D12, we need to access samplers through a layer of indirection. Instead of directly binding samplers, we bind the entire sampler heap as both a standard and a comparison sampler heap. We then use a sampler index buffer for each bind group. This buffer is accessed in the shader to get the actual sampler index within the heap. See the wgpu_hal dx12 backend documentation for more information.
Modules§
- conv 🔒
- help 🔒
- Helpers for the hlsl backend
- keywords 🔒
- ray 🔒
- storage 🔒
- Generating accesses to
ByteAddressBuffer
contents. - writer 🔒
Structs§
- Bind
Target - Binding
MapSerialization 🔒 - Dynamic
Storage 🔒Buffer Offset Target Serialization - Fragment
Entry Point - A fragment entry point to be considered when generating HLSL for the output interface of vertex entry points.
- Offsets
Bind Target - BindTarget for dynamic storage buffer offsets
- Options
- Configuration used in the
Writer
. - Pipeline
Options - A subset of options that are meant to be changed per pipeline.
- Reflection
Info - Reflection info for entry point names.
- Sampler
Heap Bind Targets - Sampler
Index 🔒Buffer Binding Serialization - Sampler
Index Buffer Key - Wrapped 🔒
- Writer
Enums§
- Entry
Point Error - Error
- Shader
Model - A HLSL shader model version.
- Wrapped
Type 🔒
Functions§
- deserialize_
binding_ 🔒map - deserialize_
sampler_ 🔒index_ buffer_ bindings - deserialize_
storage_ 🔒buffer_ offsets
Type Aliases§
- Backend
Result 🔒 - Shorthand result used internally by the backend
- Binding
Map - Dynamic
Storage Buffer Offsets Targets - Sampler
Index Buffer Binding Map