From c42b5e24b5b9d6b03352d809e0a49485d361154f Mon Sep 17 00:00:00 2001 From: Jay Kwak <82421531+jkwak-work@users.noreply.github.com> Date: Fri, 20 Sep 2024 19:55:49 -0700 Subject: WGSL implement texture intrinsics except gather and sampler-less (#5123) This commit implements all of the texture intrinsics for WGSL except "Gather" and sampler-less. They will be implemented in a separate PR. A few things to note: - texture sampling functions are available only for the fragment shader stage; not for compute - WGSL doesn't have any functions similar to CalculateLevelOfDetail or CalculateLevelOfDetailUnclamped. - WGSL doesn't have a function overlaoding for textureSample with "clamp" or "status" arguments. - WGSL doesn't support Load operation with offset for texture_multisampled_XX and texture_storage_XX. - WGSL supports only four types of depth textures: 2D, 2D_array, cube and cube_array. - WGSL doesn't support "offset" variants for cube and cube_array. --- source/slang/hlsl.meta.slang | 466 ++++++++++++++++++++++++++++----- source/slang/slang-capabilities.capdef | 8 + source/slang/slang-emit-wgsl.cpp | 46 ++++ source/slang/slang-stdlib-textures.cpp | 41 ++- source/slang/slang-stdlib-textures.h | 5 +- tests/wgsl/texture.slang | 446 +++++++++++++++++++++++++++++++ 6 files changed, 937 insertions(+), 75 deletions(-) create mode 100644 tests/wgsl/texture.slang diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 7b3113fce..b0c1ed450 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -610,7 +610,7 @@ extension __TextureImpl [__readNone] [ForceInline] - [require(cpp_cuda_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T Sample(vector location) { __requireComputeDerivative(); @@ -661,12 +661,14 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().Sample(__getSampler(), location); } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T Sample(vector location, constexpr vector offset) { __requireComputeDerivative(); @@ -689,6 +691,8 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None|ConstOffset $offset; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().Sample(__getSampler(), location, offset); } } @@ -740,7 +744,7 @@ extension __TextureImpl [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T SampleBias(vector location, float bias) { __requireComputeDerivative(); @@ -763,12 +767,14 @@ extension __TextureImpl __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleBias(__getSampler(), location, bias); } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T SampleBias(vector location, float bias, constexpr vector offset) { __requireComputeDerivative(); @@ -790,12 +796,14 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None|Bias|ConstOffset $bias $offset; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleBias(__getSampler(), location, bias, offset); } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmp(vector location, float compareValue) { __requireComputeDerivative(); @@ -826,12 +834,14 @@ extension __TextureImpl { result:$$float = OpImageSampleDrefImplicitLod $this $location $compareValue; }; + case wgsl: + return __getTexture().SampleCmp(__getComparisonSampler(), location, compareValue); } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmpLevelZero(vector location, float compareValue) { __target_switch @@ -858,12 +868,14 @@ extension __TextureImpl { result:$$float = OpImageSampleDrefExplicitLod $this $location $compareValue Lod $zeroFloat; }; + case wgsl: + return __getTexture().SampleCmpLevelZero(__getComparisonSampler(), location, compareValue); } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmp(vector location, float compareValue, constexpr vector offset) { __requireComputeDerivative(); @@ -890,12 +902,14 @@ extension __TextureImpl { result:$$float = OpImageSampleDrefImplicitLod $this $location $compareValue ConstOffset $offset; }; + case wgsl: + return __getTexture().SampleCmp(__getComparisonSampler(), location, compareValue, offset); } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmpLevelZero(vector location, float compareValue, constexpr vector offset) { __target_switch @@ -922,12 +936,14 @@ extension __TextureImpl { result:$$float = OpImageSampleDrefExplicitLod $this $location $compareValue Lod|ConstOffset $zeroFloat $offset; }; + case wgsl: + return __getTexture().SampleCmpLevelZero(__getComparisonSampler(), location, compareValue, offset); } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleGrad(vector location, vector gradX, vector gradY) { __target_switch @@ -940,21 +956,22 @@ extension __TextureImpl case cpp: case metal: return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY); - case glsl: - __intrinsic_asm "$ctextureGrad($0, $1, $2, $3)$z"; + __intrinsic_asm "$ctextureGrad($0, $1, $2, $3)$z"; case spirv: return spirv_asm { %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Grad $gradX $gradY; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY); } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleGrad(vector location, vector gradX, vector gradY, constexpr vector offset) { __target_switch @@ -968,13 +985,15 @@ extension __TextureImpl case metal: return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY, offset); case glsl: - __intrinsic_asm "$ctextureGradOffset($0, $1, $2, $3, $4)$z"; + __intrinsic_asm "$ctextureGradOffset($0, $1, $2, $3, $4)$z"; case spirv: return spirv_asm { %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Grad|ConstOffset $gradX $gradY $offset; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY, offset); } } @@ -1008,7 +1027,7 @@ extension __TextureImpl [__readNone] [ForceInline] - [require(cpp_cuda_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleLevel(vector location, float level) { __target_switch @@ -1060,12 +1079,14 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Lod $level; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleLevel(__getSampler(), location, level); } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleLevel(vector location, float level, constexpr vector offset) { __target_switch @@ -1078,7 +1099,6 @@ extension __TextureImpl case cpp: case metal: return __getTexture().SampleLevel(__getSampler(), location, level, offset); - case glsl: __intrinsic_asm "$ctextureLodOffset($0, $1, $2, $3)$z"; case spirv: @@ -1087,6 +1107,8 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Lod|ConstOffset $level $offset; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + return __getTexture().SampleLevel(__getSampler(), location, level, offset); } } } @@ -1147,7 +1169,7 @@ extension __TextureImpl { [__readNone] [ForceInline] - [require(cpp_cuda_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T Sample(SamplerState s, vector location) { __requireComputeDerivative(); @@ -1226,12 +1248,29 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSample($0, $1, ($2).x, i32(($2).y))$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSample($0, $1, ($2).xy, i32(($2).z))$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSample($0, $1, ($2).xyz, i32(($2).w))$z"; + } + } + __intrinsic_asm "textureSample($0, $1, $2)$z"; } } + [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T Sample(SamplerState s, vector location, constexpr vector offset) { __requireComputeDerivative(); @@ -1267,12 +1306,28 @@ extension __TextureImpl case glsl: __intrinsic_asm "$ctextureOffset($p, $2, $3)$z"; case spirv: - return spirv_asm - { - %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; - %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|ConstOffset $offset; - __truncate $$T result __sampledType(T) %sampled; - }; + return spirv_asm + { + %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; + %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|ConstOffset $offset; + __truncate $$T result __sampledType(T) %sampled; + }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSample($0, $1, ($2).x, i32(($2).y), $3)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSample($0, $1, ($2).xy, i32(($2).z), $3)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSample($0, $1, ($2).xyz, i32(($2).w), $3)$z"; + } + } + __intrinsic_asm "textureSample($0, $1, $2, $3)$z"; } } @@ -1344,7 +1399,7 @@ extension __TextureImpl [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T SampleBias(SamplerState s, vector location, float bias) { __requireComputeDerivative(); @@ -1381,20 +1436,36 @@ extension __TextureImpl // TODO: This needs to be handled by the capability system __intrinsic_asm ""; case glsl: - __intrinsic_asm "$ctexture($p, $2, $3)$z"; + __intrinsic_asm "$ctexture($p, $2, $3)$z"; case spirv: - return spirv_asm - { - %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; - %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias $bias; - __truncate $$T result __sampledType(T) %sampled; - }; + return spirv_asm + { + %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; + %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias $bias; + __truncate $$T result __sampledType(T) %sampled; + }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleBias($0, $1, ($2).x, i32(($2).y), $3)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleBias($0, $1, ($2).xy, i32(($2).z), $3)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleBias($0, $1, ($2).xyz, i32(($2).w), $3)$z"; + } + } + __intrinsic_asm "textureSampleBias($0, $1, $2, $3)$z"; } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0_fragment)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] T SampleBias(SamplerState s, vector location, float bias, constexpr vector offset) { __requireComputeDerivative(); @@ -1428,20 +1499,36 @@ extension __TextureImpl // TODO: This needs to be handled by the capability system __intrinsic_asm ""; case glsl: - __intrinsic_asm "$ctextureOffset($p, $2, $4, $3)$z"; + __intrinsic_asm "$ctextureOffset($p, $2, $4, $3)$z"; case spirv: - return spirv_asm - { - %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; - %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias|ConstOffset $bias $offset; - __truncate $$T result __sampledType(T) %sampled; - }; + return spirv_asm + { + %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; + %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias|ConstOffset $bias $offset; + __truncate $$T result __sampledType(T) %sampled; + }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleBias($0, $1, ($2).x, i32(($2).y), $3, $4)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleBias($0, $1, ($2).xy, i32(($2).z), $3, $4)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleBias($0, $1, ($2).xyz, i32(($2).w), $3, $4)$z"; + } + } + __intrinsic_asm "textureSampleBias($0, $1, $2, $3, $4)$z"; } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmp(SamplerComparisonState s, vector location, float compareValue) { __requireComputeDerivative(); @@ -1492,12 +1579,28 @@ extension __TextureImpl %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; result:$$float = OpImageSampleDrefImplicitLod %sampledImage $location $compareValue; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).x, i32(($2).y), $3)"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).xy, i32(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).xyz, i32(($2).w), $3)"; + } + } + __intrinsic_asm "textureSampleCompare($0, $1, $2, $3)"; } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmpLevelZero(SamplerComparisonState s, vector location, float compareValue) { __target_switch @@ -1544,12 +1647,28 @@ extension __TextureImpl %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; result:$$float = OpImageSampleDrefExplicitLod %sampledImage $location $compareValue Lod $zeroFloat; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).x, i32(($2).y), $3)"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).xy, i32(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).xyz, i32(($2).w), $3)"; + } + } + __intrinsic_asm "textureSampleCompareLevel($0, $1, $2, $3)"; } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmp(SamplerComparisonState s, vector location, float compareValue, constexpr vector offset) { __requireComputeDerivative(); @@ -1593,12 +1712,28 @@ extension __TextureImpl %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; result:$$float = OpImageSampleDrefImplicitLod %sampledImage $location $compareValue ConstOffset $offset; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).x, i32(($2).y), $3, $4)"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).xy, i32(($2).z), $3, $4)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleCompare($0, $1, ($2).xyz, i32(($2).w), $3, $4)"; + } + } + __intrinsic_asm "textureSampleCompare($0, $1, $2, $3, $4)"; } } [__readNone] [ForceInline] - [require(glsl_hlsl_metal_spirv, texture_shadowlod)] + [require(glsl_hlsl_metal_spirv_wgsl, texture_shadowlod)] float SampleCmpLevelZero(SamplerComparisonState s, vector location, float compareValue, constexpr vector offset) { __target_switch @@ -1644,12 +1779,28 @@ extension __TextureImpl %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; result:$$float = OpImageSampleDrefExplicitLod %sampledImage $location $compareValue Lod|ConstOffset $zeroFloat $offset; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).x, i32(($2).y), $3, $4)"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).xy, i32(($2).z), $3, $4)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleCompareLevel($0, $1, ($2).xyz, i32(($2).w), $3, $4)"; + } + } + __intrinsic_asm "textureSampleCompareLevel($0, $1, $2, $3, $4)"; } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleGrad(SamplerState s, vector location, vector gradX, vector gradY) { __target_switch @@ -1695,12 +1846,28 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Grad $gradX $gradY; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).x, i32(($2).y), $3, $4)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).xy, i32(($2).z), $3, $4)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).xyz, i32(($2).w), $3, $4)$z"; + } + } + __intrinsic_asm "textureSampleGrad($0, $1, $2, $3, $4)$z"; } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleGrad(SamplerState s, vector location, vector gradX, vector gradY, constexpr vector offset) { __target_switch @@ -1743,6 +1910,22 @@ extension __TextureImpl __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).x, i32(($2).y), $3, $4, $5)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).xy, i32(($2).z), $3, $4, $5)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleGrad($0, $1, ($2).xyz, i32(($2).w), $3, $4, $5)$z"; + } + } + __intrinsic_asm "textureSampleGrad($0, $1, $2, $3, $4, $5)$z"; } } @@ -1797,7 +1980,7 @@ extension __TextureImpl [__readNone] [ForceInline] - [require(cpp_cuda_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleLevel(SamplerState s, vector location, float level) { __target_switch @@ -1870,19 +2053,35 @@ extension __TextureImpl } } case spirv: - return spirv_asm - { - %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; - %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Lod $level; - __truncate $$T result __sampledType(T) %sampled; - }; + return spirv_asm + { + %sampledImage : __sampledImageType(this) = OpSampledImage $this $s; + %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Lod $level; + __truncate $$T result __sampledType(T) %sampled; + }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).x, i32(($2).y), $3)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).xy, i32(($2).z), $3)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).xyz, i32(($2).w), $3)$z"; + } + } + __intrinsic_asm "textureSampleLevel($0, $1, $2, $3)$z"; } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_0)] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)] T SampleLevel(SamplerState s, vector location, float level, constexpr vector offset) { __target_switch @@ -1925,6 +2124,22 @@ extension __TextureImpl %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Lod|ConstOffset $level $offset; __truncate $$T result __sampledType(T) %sampled; }; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).x, i32(($2).y), $3, $4)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).xy, i32(($2).z), $3, $4)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureSampleLevel($0, $1, ($2).xyz, i32(($2).w), $3, $4)$z"; + } + } + __intrinsic_asm "textureSampleLevel($0, $1, $2, $3, $4)$z"; } } } @@ -2433,7 +2648,7 @@ extension __TextureImpl location) { __target_switch @@ -2525,13 +2740,38 @@ extension __TextureImpl || T is vector || T is vector + , "WGSL supports only f32 type textures"); + static_assert(Shape.flavor == $(SLANG_TEXTURE_1D) + || Shape.flavor == $(SLANG_TEXTURE_2D) + || Shape.flavor == $(SLANG_TEXTURE_3D) + , "WGSL supports textureLoad only for 1D, 2D and 3D textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z), ($1).w)$z"; + } + } + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureLoad($0, ($1).x, ($1).y)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, ($1).z)$z"; + case $(SLANG_TEXTURE_3D): + __intrinsic_asm "textureLoad($0, ($1).xyz, ($1).w)$z"; + } + return T(); } } __glsl_extension(GL_EXT_samplerless_texture_functions) [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)] + [require(cpp_glsl_hlsl_spirv_wgsl, texture_sm_4_1_samplerless)] T Load(vector location, constexpr vector offset) { __target_switch @@ -2562,6 +2802,22 @@ extension __TextureImpl || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y), $2)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z), $2)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w), $2)$z"; + } + } + __intrinsic_asm "textureLoad($0, $1, $2)$z"; } } @@ -2584,7 +2840,7 @@ extension __TextureImpl location, int sampleIndex) { __target_switch @@ -2686,12 +2944,28 @@ extension __TextureImpl || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y), $2)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z), $2)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w), $2)$z"; + } + } + __intrinsic_asm "textureLoad($0, $1, $2)$z"; } } [__readNone] [ForceInline] - [require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)] + [require(cpp_glsl_hlsl_spirv_wgsl, texture_sm_4_1_samplerless)] T Load(vector locationAndSampleIndex) { return Load(__vectorReshape(locationAndSampleIndex), locationAndSampleIndex[Shape.dimensions + isArray]); @@ -2707,9 +2981,9 @@ extension __TextureImpl location) { __target_switch @@ -2906,6 +3182,22 @@ extension __TextureImpl"; + case wgsl: + static_assert(T is float || T is vector || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y))$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z))$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w))$z"; + } + } + __intrinsic_asm "textureLoad($0, $1)$z"; } } @@ -2955,7 +3247,7 @@ extension __TextureImpl || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureStore($0, ($1).x, i32(($1).y), $2)$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureStore($0, ($1).xy, i32(($1).z), $2)$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureStore($0, ($1).xyz, i32(($1).w), $2)$z"; + } + } + __intrinsic_asm "textureStore($0, $1, $2)$z"; } } @@ -3087,7 +3396,7 @@ extension __TextureImpl location, int sampleIndex) { __target_switch @@ -3131,6 +3440,22 @@ extension __TextureImpl || T is vector || T is vector + , "WGSL supports only f32 type textures"); + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_1D): + __intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y))$z"; + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z))$z"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w))$z"; + } + } + __intrinsic_asm "textureLoad($0, $1)$z"; } } @@ -3180,7 +3505,7 @@ extension __TextureImplemit(">"); return; } + case kIROp_TextureType: + if (auto texType = as(type)) + { + switch (texType->getAccess()) + { + case SLANG_RESOURCE_ACCESS_READ_WRITE: + m_writer->emit("texture_storage"); + break; + default: + m_writer->emit("texture"); + break; + } + + if (texType->isShadow()) + { + m_writer->emit("_depth"); + } + + if (texType->isMultisample()) + { + m_writer->emit("_multisampled"); + } + + switch (texType->GetBaseShape()) + { + case SLANG_TEXTURE_1D: m_writer->emit("_1d"); break; + case SLANG_TEXTURE_2D: m_writer->emit("_2d"); break; + case SLANG_TEXTURE_3D: m_writer->emit("_3d"); break; + case SLANG_TEXTURE_CUBE: m_writer->emit("_cube"); break; + } + + if (texType->isArray()) + m_writer->emit("_array"); + + if (!texType->isShadow()) + { + m_writer->emit("<"); + auto elemType = texType->getElementType(); + if (auto vecElemType = as(elemType)) + emitSimpleType(vecElemType->getElementType()); + else + emitType(elemType); + m_writer->emit(">"); + } + } + return; case kIROp_AtomicType: { diff --git a/source/slang/slang-stdlib-textures.cpp b/source/slang/slang-stdlib-textures.cpp index dd4df7d9c..a9f14522b 100644 --- a/source/slang/slang-stdlib-textures.cpp +++ b/source/slang/slang-stdlib-textures.cpp @@ -69,7 +69,8 @@ void TextureTypeInfo::writeFuncBody( const String& spirvDefault, const String& spirvRWDefault, const String& spirvCombined, - const String& metal) + const String& metal, + const String& wgsl) { BraceScope funcScope{i, sb}; { @@ -96,7 +97,7 @@ void TextureTypeInfo::writeFuncBody( sb << i << "case metal:\n"; sb << i << "__intrinsic_asm \"" << metal << "\";\n"; } - if(spirvDefault.getLength() && spirvCombined.getLength()) + if (spirvDefault.getLength() && spirvCombined.getLength()) { sb << i << "case spirv:\n"; sb << i << "if (access == " << kStdlibResourceAccessReadWrite << ")\n"; @@ -122,6 +123,11 @@ void TextureTypeInfo::writeFuncBody( } sb << i << "}\n"; } + if (wgsl.getLength()) + { + sb << i << "case wgsl:\n"; + sb << i << "__intrinsic_asm \"" << wgsl << "\";\n"; + } } } @@ -134,13 +140,14 @@ void TextureTypeInfo::writeFuncWithSig( const String& spirvCombined, const String& cuda, const String& metal, + const String& wgsl, const ReadNoneMode readNoneMode) { if (readNoneMode == ReadNoneMode::Always) sb << i << "[__readNone]\n"; sb << i << "[ForceInline]\n"; sb << i << sig << "\n"; - writeFuncBody(funcName, glsl, cuda, spirvDefault, spirvRWDefault, spirvCombined, metal); + writeFuncBody(funcName, glsl, cuda, spirvDefault, spirvRWDefault, spirvCombined, metal, wgsl); sb << "\n"; } @@ -154,6 +161,7 @@ void TextureTypeInfo::writeFunc( const String& spirvCombined, const String& cuda, const String& metal, + const String& wgsl, const ReadNoneMode readNoneMode) { writeFuncWithSig( @@ -165,6 +173,7 @@ void TextureTypeInfo::writeFunc( spirvCombined, cuda, metal, + wgsl, readNoneMode ); } @@ -197,6 +206,9 @@ void TextureTypeInfo::writeGetDimensionFunctions() StringBuilder metal; const char* metalMipLevel = "0"; + StringBuilder wgsl; + wgsl << "{"; + if (includeMipInfo) { ++paramCount; @@ -212,6 +224,7 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << t << "width"; metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),"; + wgsl << "*($" << String(paramCount) << ") = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");"; sizeDimCount = 1; break; @@ -221,10 +234,13 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << t << "width,"; metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),"; + wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");"; + wgsl << "(*$" << String(paramCount) << ") = dim.x;"; ++paramCount; params << t << "height"; metal << "(*($" << String(paramCount) << ") = $0.get_height(" << String(metalMipLevel) << ")),"; + wgsl << "(*$" << String(paramCount) << ") = dim.y;"; sizeDimCount = 2; break; @@ -233,14 +249,18 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << t << "width,"; metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),"; + wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");"; + wgsl << "(*$" << String(paramCount) << ") = dim.x;"; ++paramCount; params << t << "height,"; metal << "(*($" << String(paramCount) << ") = $0.get_height(" << String(metalMipLevel) << ")),"; + wgsl << "(*$" << String(paramCount) << ") = dim.y;"; ++paramCount; params << t << "depth"; metal << "(*($" << String(paramCount) << ") = $0.get_depth(" << String(metalMipLevel) << ")),"; + wgsl << "(*$" << String(paramCount) << ") = dim.z;"; sizeDimCount = 3; break; @@ -256,6 +276,7 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << ", " << t << "elements"; metal << "(*($" << String(paramCount) << ") = $0.get_array_size()),"; + wgsl << "(*$" << String(paramCount) << ") = textureNumLayers($0);"; } if (isMultisample) @@ -263,6 +284,7 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << ", " << t << "sampleCount"; metal << "(*($" << String(paramCount) << ") = $0.get_num_samples()),"; + wgsl << "(*$" << String(paramCount) << ") = textureNumSamples($0);"; } if (includeMipInfo) @@ -270,9 +292,11 @@ void TextureTypeInfo::writeGetDimensionFunctions() ++paramCount; params << ", " << t << "numberOfLevels"; metal << "(*($" << String(paramCount) << ") = $0.get_num_mip_levels()),"; + wgsl << "(*$" << String(paramCount) << ") = textureNumLevels($0);"; } metal.reduceLength(metal.getLength() - 1); // drop the last comma + wgsl << "}"; StringBuilder glsl; { @@ -453,7 +477,15 @@ void TextureTypeInfo::writeGetDimensionFunctions() sb << " __glsl_version(450)\n"; sb << " __glsl_extension(GL_EXT_samplerless_texture_functions)\n"; - sb << " [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_1)]\n"; + + sb << " [require(cpp"; + if (glsl.getLength()) sb << "_glsl"; + sb << "_hlsl"; + if (metal.getLength()) sb << "_metal"; + if (spirvDefault.getLength() && spirvCombined.getLength()) sb << "_spirv"; + if (wgsl.getLength()) sb << "_wgsl"; + sb << ", texture_sm_4_1)]\n"; + writeFunc( "void", "GetDimensions", @@ -464,6 +496,7 @@ void TextureTypeInfo::writeGetDimensionFunctions() spirvCombined, "", metal, + wgsl, ReadNoneMode::Always); } } diff --git a/source/slang/slang-stdlib-textures.h b/source/slang/slang-stdlib-textures.h index a6166cc2d..a521a44d3 100644 --- a/source/slang/slang-stdlib-textures.h +++ b/source/slang/slang-stdlib-textures.h @@ -69,7 +69,8 @@ public: const String& spirvDefault, const String& spirvRWDefault, const String& spirvCombined, - const String& metal + const String& metal, + const String& wgsl ); void writeFuncWithSig( const char* funcName, @@ -80,6 +81,7 @@ public: const String& spirvCombined = String{}, const String& cuda = String{}, const String& metal = String{}, + const String& wgsl = String{}, const ReadNoneMode readNoneMode = ReadNoneMode::Never ); void writeFunc( @@ -92,6 +94,7 @@ public: const String& spirvCombined = String{}, const String& cuda = String{}, const String& metal = String{}, + const String& wgsl = String{}, const ReadNoneMode readNoneMode = ReadNoneMode::Never ); diff --git a/tests/wgsl/texture.slang b/tests/wgsl/texture.slang new file mode 100644 index 000000000..999555a55 --- /dev/null +++ b/tests/wgsl/texture.slang @@ -0,0 +1,446 @@ +// WGSL supports "textureSample()" only in fragment shader +//TEST:SIMPLE(filecheck=WGSL): -stage fragment -entry fragMain -target wgsl + +//TEST_INPUT: ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_f32v3 +Texture1D t1D_f32v3; +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_f32v3 +Texture2D t2D_f32v3; +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_f32v3 +Texture3D t3D_f32v3; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_f32v3 +TextureCube tCube_f32v3; +//TEST_INPUT: Texture1D(size=4, content = zero, arrayLength=2):name t1DArray_f32v3 +Texture1DArray t1DArray_f32v3; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_f32v3 +Texture2DArray t2DArray_f32v3; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_f32v3 +TextureCubeArray tCubeArray_f32v3; + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_f32v4 +Texture1D t1D_f32v4; +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_f32v4 +Texture2D t2D_f32v4; +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_f32v4 +Texture3D t3D_f32v4; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_f32v4 +TextureCube tCube_f32v4; + +//TEST_INPUT: Texture1D(size=4, content = zero, arrayLength=2):name t1DArray_f32v4 +Texture1DArray t1DArray_f32v4; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_f32v4 +Texture2DArray t2DArray_f32v4; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_f32v4 +TextureCubeArray tCubeArray_f32v4; + +__generic +typealias depth2d = __TextureImpl< + T, + __Shape2D, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias depth2d_array = __TextureImpl< + T, + __Shape2D, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias depthcube = __TextureImpl< + T, + __ShapeCube, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias depthcube_array = __TextureImpl< + T, + __ShapeCube, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +//TEST_INPUT: Texture2D(size=4, content = zero):name d2D +depth2d d2D; +//TEST_INPUT: TextureCube(size=4, content = zero):name dCube +depthcube dCube; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name d2DArray +depth2d_array d2DArray; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name dCubeArray +depthcube_array dCubeArray; + +//TEST_INPUT: Sampler:name samplerState +SamplerState samplerState; +//TEST_INPUT: Sampler:name shadowSampler +SamplerComparisonState shadowSampler; + + +__generic +bool TEST_texture( + Texture1D> t1D, + Texture2D> t2D, + Texture3D> t3D, + TextureCube> tCube, + Texture1DArray> t1DArray, + Texture2DArray> t2DArray, + TextureCubeArray> tCubeArray +) +{ + // WGSL-LABEL: TEST_texture + typealias Tvn = vector; + typealias Tv4 = vector; + + float u = 0; + float u2 = 0.5; + constexpr const float ddx = 0.0f; + constexpr const float ddy = 0.0f; + + uint width = 0, height = 0, depth = 0; + uint elements = 0; + + bool voidResult = true; + + // ====================== + // void GetDimensions() + // ====================== + + // WGSL: textureDimensions({{\(*}}t1D + t1D.GetDimensions(width); + voidResult = voidResult && (uint(4) == width); + + // WGSL: textureDimensions({{\(*}}t2D + t2D.GetDimensions(width, height); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(4) == height); + + // WGSL: textureDimensions({{\(*}}t3D + t3D.GetDimensions(width, height, depth); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(4) == height); + voidResult = voidResult && (uint(4) == depth); + + // WGSL: textureDimensions({{\(*}}tCube + tCube.GetDimensions(width, height); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(4) == height); + + // WGSL: textureDimensions({{\(*}}t1DArray + t1DArray.GetDimensions(width, elements); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(2) == elements); + + // WGSL: textureDimensions({{\(*}}t2DArray + t2DArray.GetDimensions(width, height, elements); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(4) == height); + voidResult = voidResult && (uint(2) == elements); + + // WGSL: textureDimensions({{\(*}}tCubeArray + tCubeArray.GetDimensions(width, height, elements); + voidResult = voidResult && (uint(4) == width); + voidResult = voidResult && (uint(4) == height); + voidResult = voidResult && (uint(2) == elements); + + bool result = voidResult + // =============================== + // float CalculateLevelOfDetail() + // =============================== + // WGSL doesn't have a way to calculate mip-map level for the given coordinate + + // ======================================== + // float CalculateLevelOfDetailUnclamped() + // ======================================== + // WGSL doesn't have a way to calculate mip-map level for the given coordinate + + // =========== + // T Sample() + // https://www.w3.org/TR/WGSL/#texturesample + // =========== + + // WGSL: textureSample({{\(*}}t1D + && all(Tvn(T(0)) == t1D.Sample(samplerState, u)) + + // WGSL: textureSample({{\(*}}t2D + && all(Tvn(T(0)) == t2D.Sample(samplerState, float2(u, u))) + + // WGSL: textureSample({{\(*}}t3D + && all(Tvn(T(0)) == t3D.Sample(samplerState, float3(u, u, u))) + + // WGSL: textureSample({{\(*}}tCube + && all(Tvn(T(0)) == tCube.Sample(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL doesn't support textureSample for 1d_array and 3d_array; only 2d and cube + + // WGSL: textureSample({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.Sample(samplerState, float3(u, u, 0))) + + // WGSL: textureSample({{\(*}}tCubeArray + && all(Tvn(T(0)) == tCubeArray.Sample(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // Offset variant + + // WGSL: textureSample({{\(*}}t1D + && all(Tvn(T(0)) == t1D.Sample(samplerState, u, 1)) + + // WGSL: textureSample({{\(*}}t2D + && all(Tvn(T(0)) == t2D.Sample(samplerState, float2(u, u), int2(1, 1))) + + // WGSL: textureSample({{\(*}}t3D + && all(Tvn(T(0)) == t3D.Sample(samplerState, float3(u, u, u), int3(1, 1, 1))) + + // WGSL doesn't support offset variant for cube and cube_array + + // WGSL: textureSample({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.Sample(samplerState, float3(u, u, 0), int2(1, 1))) + + // Clamp variant + // WGSL doesn't support clamp variants for `textureSample()` + + // =============== + // T SampleBias() + // https://www.w3.org/TR/WGSL/#texturesamplebias + // =============== + + // WGSL doesn't support Bias for 1D texture + + // WGSL: textureSampleBias({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleBias(samplerState, float2(u, u), float(-1))) + + // WGSL: textureSampleBias({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleBias(samplerState, float3(u, u, u), float(-1))) + + // WGSL: textureSampleBias({{\(*}}tCube + && all(Tvn(T(0)) == tCube.SampleBias(samplerState, normalize(float3(u, 1 - u, u)), float(-1))) + + // WGSL: textureSampleBias({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleBias(samplerState, float3(u, u, 0), float(-1))) + + // WGSL: textureSampleBias({{\(*}}tCubeArray + && all(Tvn(T(0)) == tCubeArray.SampleBias(samplerState, float4(normalize(float3(u, 1 - u, u)), 0), float(-1))) + + // Offset variant + + // WGSL: textureSampleBias({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleBias(samplerState, float2(u, u), float(-1), int2(1, 1))) + + // WGSL: textureSampleBias({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleBias(samplerState, float3(u, u, u), float(-1), int3(1, 1, 1))) + + // WGSL: textureSampleBias({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleBias(samplerState, float3(u, u, 0), float(-1), int2(1, 1))) + + // =================================== + // T SampleLevel() + // https://www.w3.org/TR/WGSL/#texturesamplelevel + // =================================== + + // WGSL doesn't support textureSampleLevel for 1D texture + + // WGSL: textureSampleLevel({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleLevel(samplerState, float2(u, u), 0)) + + // WGSL: textureSampleLevel({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleLevel(samplerState, float3(u, u, u), 0)) + + // WGSL: textureSampleLevel({{\(*}}tCube + && all(Tvn(T(0)) == tCube.SampleLevel(samplerState, normalize(float3(u, 1 - u, u)), 0)) + + // WGSL: textureSampleLevel({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleLevel(samplerState, float3(u, u, 0), 0)) + + // WGSL: textureSampleLevel({{\(*}}tCubeArray + && all(Tvn(T(0)) == tCubeArray.SampleLevel(samplerState, float4(normalize(float3(u, 1 - u, u)), 0), 0)) + + // Offset variant + + // WGSL: textureSampleLevel({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleLevel(samplerState, float2(u, u), 0, int2(1, 1))) + + // WGSL: textureSampleLevel({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleLevel(samplerState, float3(u, u, u), 0, int3(1, 1, 1))) + + // WGSL: textureSampleLevel({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleLevel(samplerState, float3(u, u, 0), 0, int2(1, 1))) + + // ================== + // float SampleCmp() + // https://www.w3.org/TR/WGSL/#texturesamplecompare + // ================== + + // WGSL: textureSampleCompare({{\(*}}d2D + && float(0) == d2D.SampleCmp(shadowSampler, float2(u, u), 0) + + // WGSL: textureSampleCompare({{\(*}}d2DArray + && float(0) == d2DArray.SampleCmp(shadowSampler, float3(u, u, 0), 0) + + // WGSL: textureSampleCompare({{\(*}}dCube + && float(0) == dCube.SampleCmp(shadowSampler, normalize(float3(u, 1 - u, u)), 0) + + // WGSL: textureSampleCompare({{\(*}}dCubeArray + && float(0) == dCubeArray.SampleCmp(shadowSampler, float4(normalize(float3(u, 1 - u, u)), 0), 0) + + // Offset variant + + // WGSL doesn't support the offset variant for cube and cube_array + + // WGSL: textureSampleCompare({{\(*}}d2D + && float(0) == d2D.SampleCmp(shadowSampler, float2(u2, u), 0, int2(0, 0)) + + // WGSL: textureSampleCompare({{\(*}}d2DArray + && float(0) == d2DArray.SampleCmp(shadowSampler, float3(u2, u, u), 0, int2(0, 0)) + + // =================================== + // float SampleCmpLevelZero() + // https://www.w3.org/TR/WGSL/#texturesamplecomparelevel + // =================================== + + // WGSL: textureSampleCompareLevel({{\(*}}d2D + && float(0) == d2D.SampleCmpLevelZero(shadowSampler, float2(u, u), 0) + + // WGSL: textureSampleCompareLevel({{\(*}}d2DArray + && float(0) == d2DArray.SampleCmpLevelZero(shadowSampler, float3(u, u, 0), 0) + + // WGSL: textureSampleCompareLevel({{\(*}}dCube + && float(0) == dCube.SampleCmpLevelZero(shadowSampler, normalize(float3(u, 1 - u, u)), 0) + + // WGSL: textureSampleCompareLevel({{\(*}}dCubeArray + && float(0) == dCubeArray.SampleCmpLevelZero(shadowSampler, float4(normalize(float3(u, 1-u, u)), 0), 0) + + // Offset variant + + // WGSL: textureSampleCompareLevel({{\(*}}d2D + && float(0) == d2D.SampleCmpLevelZero(shadowSampler, float2(u2, u), 0, int2(0, 0)) + + // WGSL: textureSampleCompareLevel({{\(*}}d2DArray + && float(0) == d2DArray.SampleCmpLevelZero(shadowSampler, float3(u2, u, u), 0, int2(0, 0)) + + // ================================== + // vector Gather() + // https://www.w3.org/TR/WGSL/#texturegather + // ================================== + +#if 0 + && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u, u))) + + && all(Tv4(T(0)) == tCube.Gather(samplerState, normalize(float3(u, 1 - u, u)))) + + && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u, u, 0))) + + && all(Tv4(T(0)) == tCubeArray.Gather(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // Offset variant + + && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u2, u), int2(0, 0))) + + && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u2, u, 0), int2(0, 0))) +#endif + + // ===================================== + // T SampleGrad() + // https://www.w3.org/TR/WGSL/#texturesamplegrad + // ===================================== + + // WGSL doesn't support textureSampleGrad for 1D textures + + // WGSL: textureSampleGrad({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleGrad(samplerState, float2(u, u), float2(ddx, ddx), float2(ddy, ddy))) + + // WGSL: textureSampleGrad({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleGrad(samplerState, float3(u, u, u), float3(ddx, ddx, ddx), float3(ddy, ddy, ddy))) + + // WGSL: textureSampleGrad({{\(*}}tCube + && all(Tvn(T(0)) == tCube.SampleGrad(samplerState, normalize(float3(u, 1 - u, u)), float3(ddx, ddx, ddx), float3(ddy, ddy, ddy))) + + // WGSL: textureSampleGrad({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleGrad(samplerState, float3(u, u, 0.0f), float2(ddx, ddx), float2(ddy, ddy))) + + // WGSL: textureSampleGrad({{\(*}}tCubeArray + && all(Tvn(T(0)) == tCubeArray.SampleGrad(samplerState, float4(normalize(float3(u, 1 - u, u)), 0), float3(ddx, ddx, ddx), float3(ddy, ddy, ddy))) + + // Offset variant + + // WGSL: textureSampleGrad({{\(*}}t2D + && all(Tvn(T(0)) == t2D.SampleGrad(samplerState, float2(u2, u), float2(ddx, ddx), float2(ddy, ddy), int2(0, 0))) + + // WGSL: textureSampleGrad({{\(*}}t3D + && all(Tvn(T(0)) == t3D.SampleGrad(samplerState, float3(u2, u, u), float3(ddx, ddx, ddx), float3(ddy, ddy, ddy), int3(0, 0, 0))) + + // WGSL: textureSampleGrad({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.SampleGrad(samplerState, float3(u2, u, 0.0f), float2(ddx, ddx), float2(ddy, ddy), int2(0, 0))) + + // =================== + // T Load() + // https://www.w3.org/TR/WGSL/#textureload + // =================== + + // WGSL: textureLoad({{\(*}}t1D + && all(Tvn(T(0)) == t1D.Load(int2(0, 0))) + + // WGSL: textureLoad({{\(*}}t2D + && all(Tvn(T(0)) == t2D.Load(int3(0, 0, 0))) + + // WGSL: textureLoad({{\(*}}t3D + && all(Tvn(T(0)) == t3D.Load(int4(0, 0, 0, 0))) + + // WGSL supports array only for 2D + + // WGSL: textureLoad({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.Load(int4(0, 0, 0, 0))) + + // Offset variant + // WGSL doesn't support offset variants for Load + ; + + return result; +} + +void fragMain() +{ + bool result = true + && TEST_texture( + t1D_f32v3, + t2D_f32v3, + t3D_f32v3, + tCube_f32v3, + t1DArray_f32v3, + t2DArray_f32v3, + tCubeArray_f32v3) + && TEST_texture( + t1D_f32v4, + t2D_f32v4, + t3D_f32v4, + tCube_f32v4, + t1DArray_f32v4, + t2DArray_f32v4, + tCubeArray_f32v4) + ; + + outputBuffer[0] = int(result); +} -- cgit v1.2.3