116 lines
5.0 KiB
Markdown
116 lines
5.0 KiB
Markdown
|
# 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](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#LogicalPointerType).
|
||
|
The [SPIR-V Universal Validation Rules](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_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.
|
||
|
* [Gpuweb issue 1530](https://github.com/gpuweb/gpuweb/issues/1530)
|
||
|
is filed to allow those operations to work on pointers.
|
||
|
* 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.
|