-
Notifications
You must be signed in to change notification settings - Fork 304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wgsl] Explicit layout needs more than Offset: ArrayStride and matrix attributes #773
Comments
Discussed at the 2020-05-19 meeting. |
Related to #561 |
D3D's packing rules: Everything is aligned to the maximum of per-component natural alignment or 4. "per-component" here means the scalar component - so for a There's an additional nuance here with constant buffers. The above describes the "new" layout, but constant buffers may also use a "legacy". "legacy" packing rules are documented here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules. fxc only supports legacy layout (this is relevant to any WebGPU-compat mode goals), so any pipeline that relies on fxc (eg D3D11) will need to work within those constraints. |
To be explicit about it, Chrome definitely wants to support D3D11 targets. |
But we may take additional restrictions to do so. |
Vulkan's rules are here: https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html#interfaces-resources-layout I adapted them for WebGPU here (when SPIR-V was our proposal): I think that's a clear set of rules. It has different rules for UBOs and SSBOs; UBOs have additional requirements that the base alignment of structure members, and of array strides be a multiple of 16. I've mentioned in meetings that, in order to help port D3D content to Vulkan, Vulkan has added extensions to relax rules over time. These have produced "relaxed" block layout, and then later "scalar" block layout. |
The feature flag is now core, but can't the feature itself can still be unavailable? |
Does that mean it would be impossible to add an array to a uniform block without making a dummy type alias? 😕 |
Yes, you understood correctly. The reasoning is that you want the array layout to be part of the type, so that with a type-correct program address calculations (called sub-indexing in the draft) can be done correctly, even if you break up the sub-indexing into intermediate steps Example, where I've added an unusual stride:
The stride is an intrinsic part of the array type. The benefit is you don't have to go decorating all the intervening address calculations with the stride. Having to decorate the intermediate calculations is tedious and error prone. |
It's unfortunate to require typedefs for all host sharable arrays. How about new syntax instead? Like...
Pick your favorite :) |
@litherum pretty much all of these variants rely on syntax that is not consistent with the current grammar. I.e. Saying that, it seems to me that the original PR is most consistent with the grammar, and would make our lives easier. |
Do we know how common host shareable arrays are in existing corpora? |
Any bulk data in a uniform buffer or in a storage buffer is going to be array-based. It's either going to be an array or an unspecified-sized array (what SPIR-V calls a runtime array). e.g. in GLSL: // storage buffer
layout(set=0,binding=0) buffer BufferName {
int count;
vec4 u[2]; // sized array
vec4 v[]; // unsized array; can only be last element in a storage buffer's struct.
} buffer_var;
void main() {
buffer_var.u[0] = vec4(0.0);
buffer_var.v[i] = vec4(1.0);
} |
I'm with @kvark on this one. Of @litherum's suggestions, the most regular one and least-deviating from existing WGSL syntax is:
But type names appear all over the place in WGSL, so the burden is on @litherum to argue that there are no weird cases introduced. For example, from the interactions with other attributes that might be at play. Does this restrict further growth? I think for MVP the original suggestion of using the type alias is the winner here. |
Array stride is an attribute that can be declared on an alias declaration of an array type. Fixes gpuweb#773
Discussed in WGSL meeting 2020-07-21 Action: @dj2 will change the grammar to allow |
It is not possible today to give an explicit stride in MSL or explicitly change the majorness (row-major or column-major) of a standard MSL matrix. |
Hm, that means for MSL we'll need to change the element type to match the stride value, possibly turning it into a struct with padding at the end? |
* [wgsl] Add stride array decoration. This CL adds the stride decoration to type alias'd arrays. Issue #773 * review feedback * Move stride into type
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:
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:
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:
Spell out matrix layouts. I'm happy to attack this separately, but it's still needed for MVP.
The text was updated successfully, but these errors were encountered: