diff --git a/docs/spirv-ptr-ref.md b/docs/spirv-ptr-ref.md new file mode 100644 index 0000000000..615e12c4c1 --- /dev/null +++ b/docs/spirv-ptr-ref.md @@ -0,0 +1,115 @@ +# 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.