SPIR-V translation of WGSL pointers and references
WGSL was updated to have two kinds of memory views: pointers and references. See https://github.com/gpuweb/gpuweb/pull/1569
In summary:
- Reference types are never explicitly mentioned in WGSL source.
- A use of a variable is a value of reference type corresponding to the reference memory view of the storage allocated for the variable.
- Let-declared constants can be of pointer type, but not reference type.
- Function parameter can be of pointer type, but not reference type.
- A variable's store type is never a pointer type, and never a reference type.
- The “Load Rule” allows a reference to decay to the underlying store type, by issuing a load of the value in the underlying memory.
- For an assignment:
- The right-hand side evaluates to a non-reference type (atomic-free plain type).
- The left-hand side evaluates to a reference type, whose store type is the same as the result of evaluating the right hand side.
- The address-of (unary
&
) operator converts a reference to a pointer. - The dereference (unary
*
) operator converts a pointer to a reference.
TODO: Passing textures and samplers to helper functions might be done by “handler value”, or by pointer-to-handle.
Writing SPIR-V from WGSL
The distinction in WGSL between reference and pointer disappears at the SPIR-V level. Both types map into pointer types in SPIR-V.
To translate a valid WGSL program to SPIR-V:
- The dereference operator (unary
*
) is the identity operation. - The address-of operator (unary
&
) is the identity operation. - Assignment maps to OpStore.
- The Load Rule translates to OpLoad.
Reading SPIR-V to create WGSL
The main changes to the SPIR-V reader are:
- When translating a SPIR-V pointer expression, track whether the corresponding WGSL expression is of corresponding WGSL pointer type or correspoinding WGSL type.
- Insert dereference (unary-
*
) or address-of (unary-&
) operators as needed to generate valid WGSL expressions.
The choices can be made deterministic, as described below.
The SPIR-V reader only supports baseline functionality in Vulkan. Therefore we assume no VariablePointers or VariablePointersStorageBuffer capabilities. All pointers are SPIR-V logical pointers. The SPIR-V Universal Validation Rules specify where logical pointers can appear as results of instructions or operands of instructions.
Each SPIR-V pointer result expression is a logical pointer, and therefore is one of:
- OpVariable: map to the reference type.
- OpFunctionParameter: map to the pointer type.
- OpCopyObject:
- When these only have one use, then these often fold away. Otherwise, they map to a a let-declared constant.
- Map to the pointer type.
- OpAccessChain, OpInBoundsAccessChain:
- This could map to either pointer or reference, and adjustments in other areas could make it work. However, we recommend mapping this to the reference type.
- OpImageTexelPointer is not supported in WGSL. It is used to get a pointer into a storage texture, for use with atomic instructions. But image atomics is not supported in WebGPU/WGSL.
Each SPIR-V pointer operand is also a logical pointer, and is an operand to one of:
- OpLoad Pointer operand:
- Map to reference, inserting a dereference operator if needed.
- OpStore Pointer operand:
- Map to reference, inserting a dereference operator if needed.
- OpStore Pointer operand:
- OpAccessChain, OpInBoundsAccessChain Base operand:
- WGSL array-access and subfield access only works on references.
- Map to reference, inserting a dereference operator if needed.
- OpFunctionCall function argument pointer operands
- Function operands can't be references.
- Map to pointer, inserting an address-of operator if needed.
- OpAtomic instruction Pointer operand
- These map to WGSL atomic builtins.
- Map to pointer, inserting an address-of operator if needed.
- Note: As of this writing, the atomic instructions are not supported by the SPIR-V reader.
- OpCopyObject source operand
- This could have been mapped either way, but it's easiest to map to pointer, to match the choice for OpCopyObject result type.
- Map to pointer, inserting an address-of operator if needed.
- OpCopyMemory, source and destination operands
- This acts as an assignment.
- Map both source and destination to reference, inserting dereference operators if needed.
- Note: As of this writing, OpCopyMemory is not supported by the SPIR-V reader.
- Extended instruction set instructions Modf and Frexp
- These map to builtins.
- Map the pointer operand to pointer, inserting an address-of operator if needed.