-
Notifications
You must be signed in to change notification settings - Fork 345
Description
This issue is a blocker for meaningful support of compute shaders.
We have agreed that buffer resource data needs to be explicitly laid out.
That was resolved in the discussion of #561 where we talked about the Offset attribute.
However, Offset alone is not enough to explictly lay out data.
Explicit layout in SPIR-V shaders (for graphics APIs) also uses:
- ArrayStride
- RowMajor, ColMajor: for matrices
- MatrixStride: for matrices
See [https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_shadervalidation_a_validation_rules_for_shader_a_href_capability_capabilities_a](validation rules for Shader modules) for the requirement that structured data passing between host and device must be explicitly laid out. Start at "Composite objects in the StorageBuffer,..."
The ArrayStride is the most pressing one to have and which is missing from the main text of the current WGSL draft. There is an example in 3.16 Type Aliases showing an example usage:
type RTArr = [[stride 16]] array<vec4<f32>>;
type S = [[block]] struct {
[[offset 0]] a : f32;
[[offset 4]] b : f32;
[[offset 16]] data : RTArr;
};
ArrayStride is the number of bytes between two adjacent elements in the array.
E.g. This attribute is required to capture the difference between the natural layouts for a std140 and a std430 buffer. (In std140, array stride must be a multiple of 16; std430 doesn't have that rule.)
Matrix stuff:
Vulkan supports both row-major and column-major matrices. So we need to apply RowMajor or ColMajor on each thing that ends up being a matrix in the structured data interface.
Additionally, for a row-major matrix the matrix-stride is the number of bytes between adjacent rows; for a column-major matrix the matrix-stride is the number of bytes between adjacent columns. Vulkan supports multiple matrix-strides, i.e. more than the minimum natural stride.
Now, where to apply these. SPIR-V has the rule that effectively you don't decorate a type with attributes (there at most one type definition of a matrix with a given number of rows, columns, and scalar component type). So instead the matrix-related layout attributes are applied to the struct member of matrix type or struct member of any level of nested-array-of-matrix type.
This is sufficient for several reasons, including the fact that a single descriptor binding maps to a block-decorated struct.
So the proposal is:
-
ArrayStride:
- 1a. Add (some spelling of) ArrayStride as a possible attribute of an array type, applied via a type-alias, as in the example currently in 3.16.
- 1b. Spell out the rules of when it's needed: on any array type used as the member of a struct that describes the content of a single buffer-like binding.
-
Spell out matrix layouts. I'm happy to attack this separately, but it's still needed for MVP.