# Translations This document attempts to document how WGSL translates into the various backends for the cases where the translation is not a direct mapping. # Access Control ## HLSL * ReadOnly -> `ByteAddressBuffer` * ReadWrite -> `RWByteAddressBuffer` ## MSL * ReadOnly -> `const` ## SPIR-V There are two ways this can be achieved in SPIR-V. Either the variable can be decorated with `NonWritable` or each member of the struct can be decorated with `NonWritable`. We chose to go the struct member route. * The read-only becomes part of the type in this case. Otherwise, you are treating the readonly type information as part of the variable which is confusing. * Treating the readonly as part of the variable means we should be deduplicating the types behind the access control, which causes confusing with the type_names and various tracking systems within Tint. # Builtin Decorations | Name | SPIR-V | MSL | HLSL | |------|--------|-----|------| | position | SpvBuiltInPosition |position | SV_Position | | vertex_index | SpvBuiltInVertexIndex |vertex_id | SV_VertexID | | instance_index | SpvBuiltInInstanceIndex | instance_id| SV_InstanceID | | front_facing | SpvBuiltInFrontFacing | front_facing | SV_IsFrontFacing | | frag_coord | SpvBuiltInFragCoord | position | SV_Position | | frag_depth | SpvBuiltInFragDepth | depth(any) | SV_Depth | | local_invocation_id | SpvBuiltInLocalInvocationId | thread_position_in_threadgroup | SV_GroupThreadID | | local_invocation_index | SpvBuiltInLocalInvocationIndex | thread_index_in_threadgroup | SV_GroupIndex | | global_invocation_id | SpvBuiltInGlobalInvocationId | thread_position_in_grid | SV_DispatchThreadID | # Builtins Methods | Name | SPIR-V | MSL | HLSL | | ------|--------|-----|------ | | abs | GLSLstd450FAbs or GLSLstd450SAbs| fabs or abs | abs | | acos | GLSLstd450Acos | acos | acos | | all | SpvOpAll | all | all | | any | SpvOpAny | any | any | | arrayLength | SpvOpArrayLength | | | | asin | GLSLstd450Asin | asin | asin | | atan | GLSLstd450Atan | atan | atan | | atan2 | GLSLstd450Atan2| atan2 | atan2 | | ceil | GLSLstd450Ceil| ceil | ceil | | clamp | GLSLstd450NClamp or GLSLstd450UClamp or GLSLstd450SClamp| clamp | clamp | | cos | GLSLstd450Cos | cos | cos | | cosh | GLSLstd450Cosh | cosh | cosh | | countOneBits | SpvOpBitCount | popcount | countbits | | cross | GLSLstd450Cross | cross | cross | | determinant | GLSLstd450Determinant | determinant | determinant | | distance | GLSLstd450Distance | distance | distance | | dot | SpOpDot | dot | dot | | dpdx | SpvOpDPdx | dpdx | ddx | | dpdxCoarse | SpvOpDPdxCoarse | dpdx | ddx_coarse | | dpdxFine | SpvOpDPdxFine | dpdx | ddx_fine | | dpdy | SpvOpDPdy | dpdy | ddy | | dpdyCoarse | SpvOpDPdyCoarse | dpdy | ddy_coarse | | dpdyFine | SpvOpDPdyFine | dpdy | ddy_fine | | exp | GLSLstd450Exp | exp | exp | | exp2 | GLSLstd450Exp2 | exp2 | exp2 | | faceForward | GLSLstd450FaceForward | faceforward | faceforward | | floor | GLSLstd450Floor | floor | floor | | fma | GLSLstd450Fma | fma | fma | | fract | GLSLstd450Fract | fract | frac | | frexp | GLSLstd450Frexp | | | | fwidth | SpvOpFwidth | fwidth | fwidth | | fwidthCoarse | SpvOpFwidthCoarse | fwidth | fwidth | | fwidthFine | SpvOpFwidthFine | fwidth | fwidth | | inverseSqrt | GLSLstd450InverseSqrt | rsqrt | rsqrt | | isFinite | | isfinite | isfinite | | isInf | SpvOpIsInf | isinf | isinf | | isNan | SpvOpIsNan | isnan | isnan | | isNormal | | isnormal | | | ldexp | GLSLstd450Ldexp | | | | length | GLSLstd450Length | length | length | | log | GLSLstd450Log | log | log | | log2 | GLSLstd450Log2 | log2 | log2 | | max | GLSLstd450NMax or GLSLstd450SMax or GLSLstd450UMax | fmax or max | max | | min | GLSLstd450NMin or GLSLstd450SMin or GLSLstd450UMin | fmin or min | min | | mix | GLSLstd450FMix | mix | mix | | modf | GLSLstd450Modf | | | | normalize | GLSLstd450Normalize | normalize | normalize | | pow | GLSLstd450Pow | pow | pow | | reflect | GLSLstd450Reflect | reflect | reflect | | reverseBits | SpvOpBitReverse | reverse_bits | reversebits | | round | GLSLstd450Round | round | round | | select | SpvOpSelect | select | | | sign | GLSLstd450FSign | sign | sign | | sin | GLSLstd450Sin | sin | sin | | sinh | GLSLstd450Sinh | sinh | sinh | | smoothStep | GLSLstd450SmoothStep | smoothstep | smoothstep | | sqrt | GLSLstd450Sqrt | sqrt | sqrt | | step | GLSLstd450Step | step | step | | tan | GLSLstd450Tan | tan | tan | | tanh | GLSLstd450Tanh | tanh | tanh | | trunc | GLSLstd450Trunc | trunc | trunc | # Types ## Sampler Types | WGSL | SPIR-V | MSL | HLSL | |------|--------|-----|------| | sampler | OpTypeSampler | sampler | SamplerState | | sampler_comparison | OpTypeSampler | sampler | SamplerComparisonState | ## Texture Types | WGSL | SPIR-V | MSL | HLSL | |------|--------|-----|------| | texture_1d<type> | OpTypeImage 1D Sampled=1 | texture1d<type, access::sample> | Texture1D | | texture_2d<type> | OpTypeImage 2D Sampled=1 | texture2d<type, access::sample> | Texture2D | | texture_2d_array<type> | OpTypeImage 2D Arrayed=1 Sampled=1 | texture2d_array<type, access::sample> | Texture2DArray | | texture_3d<type> | OpTypeImage 3D Sampled=1 | texture3d<type, access::sample> | Texture3D | | texture_cube<type> | OpTypeImage Cube Sampled=1 | texturecube<type, access::sample> | TextureCube | | texture_cube_array<type> | OpTypeImage Cube Arrayed=1 Sampled=1 | texturecube_array<type, access::sample> | TextureCubeArray | | | | | | texture_multisampled_2d<type> | OpTypeImage 2D MS=1 Sampled=1 | texture2d_ms<type, access::sample> | Texture2D | | | | | | texture_depth_2d | OpTypeImage 2D Depth=1 Sampled=1 | depth2d<float, access::sample>| Texture2D | | texture_depth_2d_array | OpTypeImage 2D Depth=1 Arrayed=1 Sampled=1 | depth2d_array<float, access::sample> | Texture2DArray | | texture_depth_cube | OpTypeImage Cube Depth=1 Sampled=1 | depthcube<float, access::sample> | TextureCube | | texture_depth_cube_array | OpTypeImage Cube Depth=1 Arrayed=1 Sampled=1 | depthcube_array<float, access::sample> | TextureCubeArray | | | | | | texture_storage_1d<image_storage_type> | OpTypeImage 1D Sampled=2| texture1d<type, access::read> | RWTexture1D | | texture_storage_2d<image_storage_type> | OpTypeImage 2D Sampled=2 | texture2d<type, access::read> | RWTexture2D | | texture_storage_2d_array<image_storage_type> | OpTypeImage 2D Arrayed=1 Sampled=2 | texture2d_array<type, access::read> | RWTexture2DArray | | texture_storage_3d<image_storage_type> | OpTypeImage 3D Sampled=2 | texture3d<type, access::read> | RWTexture3D | | | | | | texture_storage_1d<image_storage_type> | OpTypeImage 1D Sampled=2 | texture1d<type, access::write> | RWTexture1D | | texture_storage_2d<image_storage_type> | OpTypeImage 2D Sampled=1 | texture2d<type, access::write> | RWTexture2D | | texture_storage_2d_array<image_storage_type> | OpTypeImage 2D Arrayed=1 Sampled=2 | texture2d_array<type, access::write> | RWTexture2DArray | | texture_storage_3d<image_storage_type> | OpTypeImage 3D Sampled=2 | texture3d<type, access::write> | RWTexture3D| # Short-circuting ## HLSL TODO(dsinclair): Nested if's ## SPIR-V TODO(dsinclair): Nested if's # Storage classes TODO(dsinclair): do ... # Storage buffers ## HLSL TODO(dsinclair): Rewriting of accessors to loads # Loop blocks ## HLSL TODO(dsinclair): Rewrite with bools ## MSL TODO(dsinclair): Rewrite with bools # Input / Output storage class ## HLSL TODO(dsinclair): Structs and params ## MSL TODO(dsinclair): Structs and params # Discard ## HLSL * `discard` ## MSL * `discard_fragment()` # Specialization constants ## HLSL ``` #ifndef WGSL_SPEC_CONSTANT_<id> -- if default provided #define WGSL_SPEC_CONSTANT_<id> default value -- else #error spec constant required for constant id -- #endif static const <type> <name> = WGSL_SPEC_CONSTANT_<id> ``` ## MSL `[[function_constant(<id>)]]`