| # 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. |