From 85b996a75683b5364456d731a9cb4aee5c3fada2 Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Wed, 18 Sep 2024 18:36:33 +0300 Subject: Add WGSL pack/unpack, constructor, derivatives & misc intrinsics (#5102) * Add WGSL pack/unpack intrinsics This addresses issue #5080. * Add WGSL constructor intrinsics This addresses issue #5081. * Add WGSL derivative and miscellaneous intrinsics This addresses issue #5083. * Add some missing WGSL intrinsics - degrees - faceforward --- source/slang/hlsl.meta.slang | 117 ++++++++++++++++++++++----------- source/slang/slang-capabilities.capdef | 9 +++ source/slang/slang-emit-wgsl.cpp | 18 +++++ source/slang/slang-emit-wgsl.h | 7 ++ 4 files changed, 113 insertions(+), 38 deletions(-) (limited to 'source') diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 2df66c1f7..0fd40b9d8 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -5710,7 +5710,7 @@ bool all(T x) __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl)] bool all(vector x) { if(N == 1) @@ -5747,6 +5747,8 @@ bool all(vector x) OpAll $$bool result %castResult }; } + case wgsl: + __intrinsic_asm "all"; default: bool result = true; for(int i = 0; i < N; ++i) @@ -5849,7 +5851,7 @@ bool any(T x) __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl)] bool any(vector x) { if(N == 1) @@ -5886,6 +5888,8 @@ bool any(vector x) OpAny $$bool result %castResult }; } + case wgsl: + __intrinsic_asm "any"; default: bool result = false; for(int i = 0; i < N; ++i) @@ -5948,7 +5952,7 @@ double2 asdouble(uint2 lowbits, uint2 highbits) // Reinterpret bits as a float (HLSL SM 4.0) [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] float asfloat(int x) { __target_switch @@ -5961,11 +5965,12 @@ float asfloat(int x) case spirv: return spirv_asm { OpBitcast $$float result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; } } [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] float asfloat(uint x) { __target_switch @@ -5978,12 +5983,13 @@ float asfloat(uint x) case spirv: return spirv_asm { OpBitcast $$float result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asfloat(vector< int, N> x) { __target_switch @@ -5994,6 +6000,7 @@ vector asfloat(vector< int, N> x) case spirv: return spirv_asm { OpBitcast $$vector result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; default: VECTOR_MAP_UNARY(float, N, asfloat, x); } @@ -6001,7 +6008,7 @@ vector asfloat(vector< int, N> x) __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asfloat(vector x) { __target_switch @@ -6012,6 +6019,7 @@ vector asfloat(vector x) case spirv: return spirv_asm { OpBitcast $$vector result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; default: VECTOR_MAP_UNARY(float, N, asfloat, x); } @@ -6176,7 +6184,7 @@ int asint(float x) } [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] int asint(uint x) { __target_switch @@ -6189,12 +6197,13 @@ int asint(uint x) case spirv: return spirv_asm { OpBitcast $$int result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asint(vector x) { __target_switch @@ -6205,6 +6214,7 @@ vector asint(vector x) case spirv: return spirv_asm { OpBitcast $$vector result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; default: VECTOR_MAP_UNARY(int, N, asint, x); } @@ -6212,7 +6222,7 @@ vector asint(vector x) __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asint(vector x) { if(N == 1) @@ -6225,6 +6235,7 @@ vector asint(vector x) case spirv: return spirv_asm { OpBitcast $$vector result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; default: VECTOR_MAP_UNARY(int, N, asint, x); } @@ -6320,7 +6331,7 @@ uint asuint(float x) } [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] uint asuint(int x) { __target_switch @@ -6333,12 +6344,13 @@ uint asuint(int x) case spirv: return spirv_asm { OpBitcast $$uint result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asuint(vector x) { __target_switch @@ -6351,12 +6363,13 @@ vector asuint(vector x) }; default: VECTOR_MAP_UNARY(uint, N, asuint, x); + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_4_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)] vector asuint(vector x) { if(N == 1) @@ -6369,6 +6382,7 @@ vector asuint(vector x) case spirv: return spirv_asm { OpBitcast $$vector result $x }; + case wgsl: __intrinsic_asm "bitcast<$TR>($0)"; default: VECTOR_MAP_UNARY(uint, N, asuint, x); } @@ -7188,7 +7202,7 @@ vector cospi(vector x) // Population count [__readNone] [ForceInline] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] uint countbits(uint value) { __target_switch @@ -7204,13 +7218,15 @@ uint countbits(uint value) __intrinsic_asm "$P_countbits($0)"; case spirv: return spirv_asm {OpBitCount $$uint result $value}; + case wgsl: + __intrinsic_asm "countOneBits"; } } __generic [__readNone] [ForceInline] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector countbits(vector value) { __target_switch @@ -7223,6 +7239,8 @@ vector countbits(vector value) __intrinsic_asm "popcount"; case spirv: return spirv_asm {OpBitCount $$vector result $value}; + case wgsl: + __intrinsic_asm "countOneBits"; default: VECTOR_MAP_UNARY(uint, N, countbits, value); } @@ -7275,12 +7293,13 @@ vector cross(vector left, vector right) // Convert encoded color [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)] int4 D3DCOLORtoUBYTE4(float4 color) { __target_switch { case hlsl: __intrinsic_asm "D3DCOLORtoUBYTE4"; + case wgsl: __intrinsic_asm "bitcast(pack4x8unorm($0)).zyxw"; default: let scaled = color.zyxw * 255.001999f; return int4(scaled); @@ -7294,7 +7313,7 @@ for (auto xOrY : diffDimensions) { }}}} __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, fragmentprocessing)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)] T dd$(xOrY)(T x) { __requireComputeDerivative(); @@ -7310,12 +7329,14 @@ T dd$(xOrY)(T x) __intrinsic_asm "dfd$(xOrY)"; case spirv: return spirv_asm {OpDPd$(xOrY) $$T result $x}; + case wgsl: + __intrinsic_asm "dpd$(xOrY)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, fragmentprocessing)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)] vector dd$(xOrY)(vector x) { __requireComputeDerivative(); @@ -7331,12 +7352,14 @@ vector dd$(xOrY)(vector x) __intrinsic_asm "dfd$(xOrY)"; case spirv: return spirv_asm {OpDPd$(xOrY) $$vector result $x}; + case wgsl: + __intrinsic_asm "dpd$(xOrY)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, fragmentprocessing)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)] matrix dd$(xOrY)(matrix x) { __requireComputeDerivative(); @@ -7448,7 +7471,7 @@ ${{{{ __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl)] T degrees(T x) { __target_switch @@ -7458,6 +7481,7 @@ T degrees(T x) case spirv: return spirv_asm { OpExtInst $$T result glsl450 Degrees $x }; + case wgsl: __intrinsic_asm "degrees"; default: return x * (T(180) / T.getPi()); } @@ -8030,7 +8054,7 @@ vector exp10(vector x) __glsl_version(420) __cuda_sm_version(6.0) [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] float f16tof32(uint value) { __target_switch @@ -8048,12 +8072,13 @@ float f16tof32(uint value) result:$$float = OpFConvert %half }; } + case wgsl: __intrinsic_asm "unpack2x16float($0).x"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector f16tof32(vector value) { __target_switch @@ -8078,7 +8103,7 @@ vector f16tof32(vector value) __glsl_version(420) __cuda_sm_version(6.0) [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] uint f32tof16(float value) { __target_switch @@ -8096,12 +8121,13 @@ uint f32tof16(float value) result:$$uint = OpUConvert %lowBits }; } + case wgsl: __intrinsic_asm "pack2x16float(vec2f($0,0.0))"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector f32tof16(vector value) { __target_switch @@ -8127,7 +8153,7 @@ vector f32tof16(vector value) __glsl_version(420) [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] float f16tof32(float16_t value) { __target_switch @@ -8143,12 +8169,13 @@ float f16tof32(float16_t value) result:$$float = OpFConvert $value }; } + case wgsl: __intrinsic_asm "f32($0)"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector f16tof32(vector value) { __target_switch @@ -8167,7 +8194,7 @@ vector f16tof32(vector value) // Convert to float16_t __glsl_version(420) [__readNone] -[require(cuda_glsl_metal_spirv, shader5_sm_5_0)] +[require(cuda_glsl_metal_spirv_wgsl, shader5_sm_5_0)] float16_t f32tof16_(float value) { __target_switch @@ -8178,12 +8205,13 @@ float16_t f32tof16_(float value) case spirv: return spirv_asm { OpFConvert $$float16_t result $value }; + case wgsl: __intrinsic_asm "f16($0)"; } } __generic [__readNone] -[require(cuda_glsl_metal_spirv, shader5_sm_5_0)] +[require(cuda_glsl_metal_spirv_wgsl, shader5_sm_5_0)] vector f32tof16_(vector value) { __target_switch @@ -8203,7 +8231,7 @@ vector f32tof16_(vector value) // Flip surface normal to face forward, if needed __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)] vector faceforward(vector n, vector i, vector ng) { __target_switch @@ -8214,6 +8242,7 @@ vector faceforward(vector n, vector i, vector ng) case spirv: return spirv_asm { OpExtInst $$vector result glsl450 FaceForward $n $i $ng }; + case wgsl: __intrinsic_asm "faceForward"; default: return dot(ng, i) < T(0.0f) ? n : -n; } @@ -8221,7 +8250,7 @@ vector faceforward(vector n, vector i, vector ng) // Find first set bit starting at high bit and working down [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] int firstbithigh(int value) { __target_switch @@ -8234,12 +8263,13 @@ int firstbithigh(int value) case spirv: return spirv_asm { OpExtInst $$int result glsl450 FindSMsb $value }; + case wgsl: __intrinsic_asm "firstLeadingBit"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector firstbithigh(vector value) { __target_switch @@ -8250,13 +8280,14 @@ vector firstbithigh(vector value) case spirv: return spirv_asm { OpExtInst $$vector result glsl450 FindSMsb $value }; + case wgsl: __intrinsic_asm "firstLeadingBit"; default: VECTOR_MAP_UNARY(int, N, firstbithigh, value); } } [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] uint firstbithigh(uint value) { __target_switch @@ -8269,12 +8300,13 @@ uint firstbithigh(uint value) case spirv: return spirv_asm { OpExtInst $$uint result glsl450 FindUMsb $value }; + case wgsl: __intrinsic_asm "firstLeadingBit"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector firstbithigh(vector value) { __target_switch @@ -8285,6 +8317,7 @@ vector firstbithigh(vector value) case spirv: return spirv_asm { OpExtInst $$vector result glsl450 FindUMsb $value }; + case wgsl: __intrinsic_asm "firstLeadingBit"; default: VECTOR_MAP_UNARY(uint, N, firstbithigh, value); } @@ -8292,7 +8325,7 @@ vector firstbithigh(vector value) // Find first set bit starting at low bit and working up [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] int firstbitlow(int value) { __target_switch @@ -8305,12 +8338,13 @@ int firstbitlow(int value) case spirv: return spirv_asm { OpExtInst $$int result glsl450 FindILsb $value }; + case wgsl: __intrinsic_asm "firstTrailingBit"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector firstbitlow(vector value) { __target_switch @@ -8321,13 +8355,14 @@ vector firstbitlow(vector value) case spirv: return spirv_asm { OpExtInst $$vector result glsl450 FindILsb $value }; + case wgsl: __intrinsic_asm "firstTrailingBit"; default: VECTOR_MAP_UNARY(int, N, firstbitlow, value); } } [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] uint firstbitlow(uint value) { __target_switch @@ -8340,12 +8375,13 @@ uint firstbitlow(uint value) case spirv: return spirv_asm { OpExtInst $$uint result glsl450 FindILsb $value }; + case wgsl: __intrinsic_asm "firstTrailingBit"; } } __generic [__readNone] -[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)] +[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)] vector firstbitlow(vector value) { __target_switch @@ -8356,6 +8392,7 @@ vector firstbitlow(vector value) case spirv: return spirv_asm { OpExtInst $$vector result glsl450 FindILsb $value }; + case wgsl: __intrinsic_asm "firstTrailingBit"; default: VECTOR_MAP_UNARY(uint, N, firstbitlow, value); } @@ -8707,7 +8744,7 @@ matrix frexp(matrix x, out matrix exp) // Texture filter width __generic [__readNone] -[require(glsl_hlsl_metal_spirv, fragmentprocessing)] +[require(glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)] T fwidth(T x) { __requireComputeDerivative(); @@ -8724,12 +8761,14 @@ T fwidth(T x) { OpFwidth $$T result $x; }; + case wgsl: + __intrinsic_asm "fwidth($0)"; } } __generic [__readNone] -[require(glsl_hlsl_spirv, fragmentprocessing)] +[require(glsl_hlsl_spirv_wgsl, fragmentprocessing)] vector fwidth(vector x) { __requireComputeDerivative(); @@ -8744,6 +8783,8 @@ vector fwidth(vector x) { OpFwidth $$vector result $x; }; + case wgsl: + __intrinsic_asm "fwidth($0)"; } } diff --git a/source/slang/slang-capabilities.capdef b/source/slang/slang-capabilities.capdef index 3e17b3d19..96f5996a0 100644 --- a/source/slang/slang-capabilities.capdef +++ b/source/slang/slang-capabilities.capdef @@ -330,6 +330,10 @@ alias cuda_glsl_spirv = cuda | glsl | spirv; /// [Compound] alias cuda_glsl_metal_spirv = cuda | glsl | metal | spirv; +/// CUDA, GLSL, Metal, SPIRV and WGSL code-gen targets +/// [Compound] +alias cuda_glsl_metal_spirv_wgsl = cuda | glsl | metal | spirv | wgsl; + /// CUDA, and HLSL code-gen targets /// [Compound] alias cuda_hlsl = cuda | hlsl; @@ -342,6 +346,10 @@ alias cuda_hlsl_spirv = cuda | hlsl | spirv; /// [Compound] alias glsl_hlsl_spirv = glsl | hlsl | spirv; +/// GLSL, HLSL, SPIRV and WGSL code-gen targets +/// [Compound] +alias glsl_hlsl_spirv_wgsl = glsl | hlsl | spirv | wgsl; + /// GLSL, HLSL, Metal, and SPIRV code-gen targets /// [Compound] alias glsl_hlsl_metal_spirv = glsl | hlsl | metal | spirv; @@ -1705,6 +1713,7 @@ alias fragmentprocessing = fragment + _sm_5_0 | fragment + metal | fragment + cpp | fragment + cuda + | fragment + wgsl ; /// Capabilities required to use fragment derivative operations (with GLSL derivativecontrol) /// [Compound] diff --git a/source/slang/slang-emit-wgsl.cpp b/source/slang/slang-emit-wgsl.cpp index 0a4cca407..40d8ace91 100644 --- a/source/slang/slang-emit-wgsl.cpp +++ b/source/slang/slang-emit-wgsl.cpp @@ -1002,4 +1002,22 @@ void WGSLSourceEmitter::emitFrontMatterImpl(TargetRequest* /* targetReq */) } } +void WGSLSourceEmitter::emitIntrinsicCallExprImpl( + IRCall* inst, + UnownedStringSlice intrinsicDefinition, + IRInst* intrinsicInst, + EmitOpInfo const& inOuterPrec + ) +{ + // The f16 constructor is generated for f32tof16 + if (intrinsicDefinition.startsWith("f16")) + { + m_f16ExtensionEnabled = true; + } + + CLikeSourceEmitter::emitIntrinsicCallExprImpl( + inst, intrinsicDefinition, intrinsicInst, inOuterPrec + ); +} + } // namespace Slang diff --git a/source/slang/slang-emit-wgsl.h b/source/slang/slang-emit-wgsl.h index dacd11c3d..d3cf19d91 100644 --- a/source/slang/slang-emit-wgsl.h +++ b/source/slang/slang-emit-wgsl.h @@ -53,6 +53,13 @@ public: IRInst* inst, const EmitOpInfo& outerPrec ) SLANG_OVERRIDE; + virtual void emitIntrinsicCallExprImpl( + IRCall* inst, + UnownedStringSlice intrinsicDefinition, + IRInst* intrinsicInst, + EmitOpInfo const& inOuterPrec + ) SLANG_OVERRIDE; + void emit(const AddressSpace addressSpace); private: -- cgit v1.2.3