diff options
| author | Jay Kwak <82421531+jkwak-work@users.noreply.github.com> | 2024-09-23 19:46:32 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-23 19:46:32 -0700 |
| commit | ef3552d9cbde0c06ddc77150b8ab68674d8422d3 (patch) | |
| tree | 99da915f30fa4d91d77591231b66f62eda5dd8a0 | |
| parent | 3e950e11f46fa3d2a84f04345ea860907ae9715a (diff) | |
Feature/wgsl intrinsic texture gather (#5141)
This PR implements the texture gather functions for WGSL.
The pattern was very similar to how Metal was implemented.
Before copy and paste from the Metal implementation, I had to
clean up the Metal implementation to make it more readable
and maintainable.
Gather functions are available only for 2D and 3D textures.
Their `array` and `depth` variants may or may not be supported depending on the target.
`static_assert` ensures that Gather functions are available only for 2D and 3D textures.
Removed incorrect use of "$p" argument for targeting GLSL.
| -rw-r--r-- | source/slang/hlsl.meta.slang | 475 | ||||
| -rw-r--r-- | source/slang/slang-capabilities.capdef | 4 | ||||
| -rw-r--r-- | tests/wgsl/texture-sampler-less.slang | 8 | ||||
| -rw-r--r-- | tests/wgsl/texture.slang | 8 |
4 files changed, 303 insertions, 192 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 8d1b3202e..3ea5481b1 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -2188,60 +2188,68 @@ extension __TextureImpl<T,Shape,isArray,1,sampleCount,access,isShadow,isCombined __intrinsic_op($(kIROp_MakeArray)) Array<T,4> __makeArray<T>(T v0, T v1, T v2, T v3); -// Gather for scalar textures. + +// Beginning of Texture Gather __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] -[require(glsl_metal_spirv, texture_gather)] -vector<TElement,4> __texture_gather(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, vector<float, Shape.dimensions+isArray> location, int component) +[require(glsl_metal_spirv_wgsl, texture_gather)] +vector<TElement,4> __texture_gather( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerState s, + vector<float, Shape.dimensions+isArray> location, + int component) { __target_switch { case glsl: - __intrinsic_asm "textureGather($p, $2, $3)"; + __intrinsic_asm "textureGather($0, $1, $2, $3)"; case metal: - if (isShadow == 0) + if (isArray == 1) { switch (Shape.flavor) { case $(SLANG_TEXTURE_2D): - if (isArray == 1) - { - // Tv gather(sampler s, float2 coord, uint array, int2 offset = int2(0), component c = component::x) const - __intrinsic_asm "$0.gather($1, ($2).xy, uint(($2).z), int2(0), metal::component($3))"; - } - else - { - // Tv gather(sampler s, float2 coord, int2 offset = int2(0), component c = component::x) const - __intrinsic_asm "$0.gather($1, $2, int2(0), metal::component($3))"; - } - break; + // Tv gather(sampler s, float2 coord, uint array, int2 offset = int2(0), component c = component::x) const + __intrinsic_asm "$0.gather($1, ($2).xy, uint(($2).z), int2(0), metal::component($3))"; case $(SLANG_TEXTURE_CUBE): - if (isArray == 1) - { - // Tv gather(sampler s, float3 coord, uint array, component c = component::x) const - __intrinsic_asm "$0.gather($1, ($2).xyz, uint(($2).w), metal::component($3))"; - } - else - { - // Tv gather(sampler s, float3 coord, component c = component::x) const - __intrinsic_asm "$0.gather($1, $2, metal::component($3))"; - } - break; + // Tv gather(sampler s, float3 coord, uint array, component c = component::x) const + __intrinsic_asm "$0.gather($1, ($2).xyz, uint(($2).w), metal::component($3))"; } } - // TODO: This needs to be handled by the capability system - __intrinsic_asm "<invalid intrinsic>"; + if (Shape.flavor == $(SLANG_TEXTURE_CUBE)) + { + // Tv gather(sampler s, float3 coord, component c = component::x) const + __intrinsic_asm "$0.gather($1, $2, metal::component($3))"; + } + // Tv gather(sampler s, float2 coord, int2 offset = int2(0), component c = component::x) const + __intrinsic_asm "$0.gather($1, $2, int2(0), metal::component($3))"; case spirv: return spirv_asm { %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s; result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component; }; + case wgsl: + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGather($3, $0, $1, ($2).xy, u32(($2).z))"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGather($3, $0, $1, ($2).xyz, u32(($2).w))"; + } + } + __intrinsic_asm "textureGather($3, $0, $1, $2)"; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gather(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, int component) +vector<TElement,4> __texture_gather( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, + int component) { __target_switch { @@ -2253,45 +2261,60 @@ vector<TElement,4> __texture_gather(__TextureImpl<T, Shape, isArray, 0, sampleCo }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] -[require(glsl_metal_spirv, texture_gather)] -vector<TElement,4> __texture_gather_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, constexpr vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset, int component) +[require(glsl_metal_spirv_wgsl, texture_gather)] +vector<TElement,4> __texture_gather_offset( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerState s, + constexpr vector<float, Shape.dimensions+isArray> location, + constexpr vector<int, Shape.planeDimensions> offset, + int component) { __target_switch { case glsl: - __intrinsic_asm "textureGatherOffset($p, $2, $3, $4)"; + __intrinsic_asm "textureGatherOffset($0, $1, $2, $3, $4)"; case metal: - if (Shape.flavor == $(SLANG_TEXTURE_2D)) + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D), + "Metal supports offset variant of Gather only for 2D textures"); + + if (isArray == 1) { - if (isShadow == 0) - { - if (isArray == 1) - { - // Tv gather(sampler s, float2 coord, uint array, int2 offset = int2(0), component c = component::x) const - __intrinsic_asm "$0.gather($1, ($2).xy, uint(($2).z), $3, metal::component($4))"; - } - else - { - // Tv gather(sampler s, float2 coord, int2 offset = int2(0), component c = component::x) const - __intrinsic_asm "$0.gather($1, $2, $3, metal::component($4))"; - } - } + // Tv gather(sampler s, float2 coord, uint array, int2 offset = int2(0), component c = component::x) const + __intrinsic_asm "$0.gather($1, ($2).xy, uint(($2).z), $3, metal::component($4))"; } - // TODO: This needs to be handled by the capability system - __intrinsic_asm "<Metal support gather with offset only for 2D>"; + // Tv gather(sampler s, float2 coord, int2 offset = int2(0), component c = component::x) const + __intrinsic_asm "$0.gather($1, $2, $3, metal::component($4))"; case spirv: return spirv_asm { %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s; result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component ConstOffset $offset; }; + case wgsl: + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGather($4, $0, $1, ($2).xy, u32(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGather($4, $0, $1, ($2).xyz, u32(($2).w), $3)"; + } + } + __intrinsic_asm "textureGather($4, $0, $1, $2, $3)"; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gather_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset, int component) +vector<TElement,4> __texture_gather_offset( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, + constexpr vector<int, Shape.planeDimensions> offset, + int component) { __target_switch { @@ -2303,10 +2326,14 @@ vector<TElement,4> __texture_gather_offset(__TextureImpl<T, Shape, isArray, 0, s }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gather_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, vector<float, Shape.dimensions+isArray> location, +vector<TElement,4> __texture_gather_offsets( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerState s, + vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset1, constexpr vector<int, Shape.planeDimensions> offset2, constexpr vector<int, Shape.planeDimensions> offset3, @@ -2316,7 +2343,7 @@ vector<TElement,4> __texture_gather_offsets(__TextureImpl<T, Shape, isArray, 0, __target_switch { case glsl: - __intrinsic_asm "textureGatherOffsets($p, $2, $T3[]($3, $4, $5, $6)), $7"; + __intrinsic_asm "textureGatherOffsets($0, $1, $2, $T3[]($3, $4, $5, $6)), $7"; case spirv: let offsets = __makeArray(offset1,offset2,offset3,offset4); return spirv_asm { @@ -2326,11 +2353,13 @@ vector<TElement,4> __texture_gather_offsets(__TextureImpl<T, Shape, isArray, 0, }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gather_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, - +vector<TElement,4> __texture_gather_offsets( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset1, constexpr vector<int, Shape.planeDimensions> offset2, constexpr vector<int, Shape.planeDimensions> offset3, @@ -2349,58 +2378,62 @@ vector<TElement,4> __texture_gather_offsets(__TextureImpl<T, Shape, isArray, 0, }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] -[require(glsl_metal_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, TElement compareValue) +[require(glsl_metal_spirv_wgsl, texture_gather)] +vector<TElement,4> __texture_gatherCmp( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerComparisonState s, + vector<float, Shape.dimensions+isArray> location, + TElement compareValue) { __target_switch { case glsl: - __intrinsic_asm "textureGather($p, $2, $3)"; + __intrinsic_asm "textureGather($0, $1, $2, $3)"; case metal: - if (isShadow == 1) + if (isArray == 1) { - if (Shape.flavor == $(SLANG_TEXTURE_2D)) - { - if (isArray == 1) - { - // Tv gather_compare(sampler s, float2 coord, uint array, float compare_value, int2 offset = int2(0)) const - __intrinsic_asm "$0.gather_compare($1, ($2).xy, uint(($2).z), $3)"; - } - else - { - // Tv gather_compare(sampler s, float2 coord, float compare_value, int2 offset = int2(0)) const - __intrinsic_asm "$0.gather_compare($1, $2, $3)"; - } - } - else if (Shape.flavor == $(SLANG_TEXTURE_CUBE)) + switch (Shape.flavor) { - if (isArray == 1) - { - // Tv gather_compare(sampler s, float3 coord, uint array, float compare_value) const - __intrinsic_asm "$0.gather_compare($1, ($2).xyz, uint(($2).w), $3)"; - } - else - { - // Tv gather_compare(sampler s, float3 coord, float compare_value) const - __intrinsic_asm "$0.gather_compare($1, $2, $3)"; - } + case $(SLANG_TEXTURE_2D): + // Tv gather_compare(sampler s, float2 coord, uint array, float compare_value, int2 offset = int2(0)) const + __intrinsic_asm "$0.gather_compare($1, ($2).xy, uint(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + // Tv gather_compare(sampler s, float3 coord, uint array, float compare_value) const + __intrinsic_asm "$0.gather_compare($1, ($2).xyz, uint(($2).w), $3)"; } } - // TODO: This needs to be handled by the capability system - __intrinsic_asm "<invalid intrinsics>"; + // Tv gather_compare(sampler s, float2 coord, float compare_value, int2 offset = int2(0)) const + __intrinsic_asm "$0.gather_compare($1, $2, $3)"; case spirv: return spirv_asm { %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s; result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue; }; + case wgsl: + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGatherCompare($0, $1, ($2).xy, u32(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGatherCompare($0, $1, ($2).xyz, u32(($2).w), $3)"; + } + } + __intrinsic_asm "textureGatherCompare($0, $1, $2, $3)"; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, TElement compareValue) +vector<TElement,4> __texture_gatherCmp( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, + TElement compareValue) { __target_switch { @@ -2412,45 +2445,60 @@ vector<TElement,4> __texture_gatherCmp(__TextureImpl<T, Shape, isArray, 0, sampl }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] -[require(glsl_metal_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, TElement compareValue, constexpr vector<int, Shape.planeDimensions> offset) +[require(glsl_metal_spirv_wgsl, texture_gather)] +vector<TElement,4> __texture_gatherCmp_offset( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerComparisonState s, + vector<float, Shape.dimensions+isArray> location, + TElement compareValue, + constexpr vector<int, Shape.planeDimensions> offset) { __target_switch { case glsl: - __intrinsic_asm "textureGatherOffset($p, $2, $3, $4)"; + __intrinsic_asm "textureGatherOffset($0, $1, $2, $3, $4)"; case metal: - if (isShadow == 1) + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D), + "Metal supports depth compare Gather only for 2D texture"); + + if (isArray == 1) { - if (Shape.flavor == $(SLANG_TEXTURE_2D)) - { - if (isArray == 1) - { - // Tv gather_compare(sampler s, float2 coord, uint array, float compare_value, int2 offset = int2(0)) const - __intrinsic_asm "$0.gather_compare($1, ($2).xy, uint(($2).z), $3, $4)"; - } - else - { - // Tv gather_compare(sampler s, float2 coord, float compare_value, int2 offset = int2(0)) const - __intrinsic_asm "$0.gather_compare($1, $2, $3, $4)"; - } - } + // Tv gather_compare(sampler s, float2 coord, uint array, float compare_value, int2 offset = int2(0)) const + __intrinsic_asm "$0.gather_compare($1, ($2).xy, uint(($2).z), $3, $4)"; } - // TODO: This needs to be handled by the capability system - __intrinsic_asm "<invalid intrinsics>"; + // Tv gather_compare(sampler s, float2 coord, float compare_value, int2 offset = int2(0)) const + __intrinsic_asm "$0.gather_compare($1, $2, $3, $4)"; case spirv: return spirv_asm { %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s; result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue ConstOffset $offset; }; + case wgsl: + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGatherCompare($0, $1, ($2).xy, u32(($2).z), $3, $4)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGatherCompare($0, $1, ($2).xyz, u32(($2).w), $3, $4)"; + } + } + __intrinsic_asm "textureGatherCompare($0, $1, $2, $3, $4)"; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, TElement compareValue, constexpr vector<int, Shape.planeDimensions> offset) +vector<TElement,4> __texture_gatherCmp_offset( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, + TElement compareValue, + constexpr vector<int, Shape.planeDimensions> offset) { __target_switch { @@ -2462,10 +2510,14 @@ vector<TElement,4> __texture_gatherCmp_offset(__TextureImpl<T, Shape, isArray, 0 }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, TElement compareValue, +vector<TElement,4> __texture_gatherCmp_offsets( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, + SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, + TElement compareValue, vector<int, Shape.planeDimensions> offset1, vector<int, Shape.planeDimensions> offset2, vector<int, Shape.planeDimensions> offset3, @@ -2474,7 +2526,7 @@ vector<TElement,4> __texture_gatherCmp_offsets(__TextureImpl<T, Shape, isArray, __target_switch { case glsl: - __intrinsic_asm "textureGatherOffsets($p, $2, $3, $T4[]($4, $5, $6, $7))"; + __intrinsic_asm "textureGatherOffsets($0, $1, $2, $3, $T4[]($4, $5, $6, $7))"; case spirv: let offsets = __makeArray(offset1,offset2,offset3,offset4); return spirv_asm { @@ -2484,10 +2536,14 @@ vector<TElement,4> __texture_gatherCmp_offsets(__TextureImpl<T, Shape, isArray, }; } } + __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int> [ForceInline] [require(glsl_spirv, texture_gather)] -vector<TElement,4> __texture_gatherCmp_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, vector<float, Shape.dimensions+isArray> location, TElement compareValue, +vector<TElement,4> __texture_gatherCmp_offsets( + __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler, + vector<float, Shape.dimensions+isArray> location, + TElement compareValue, vector<int, Shape.planeDimensions> offset1, vector<int, Shape.planeDimensions> offset2, vector<int, Shape.planeDimensions> offset3, @@ -2510,124 +2566,167 @@ ${{{{ for (int isCombined = 0; isCombined < 2; isCombined++) for (int isScalarTexture = 0; isScalarTexture < 2; isScalarTexture++) { - if (isScalarTexture == 0) - { - sb << "__generic<T:__BuiltinArithmeticType, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>\n"; - sb << "extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow," << isCombined << ",format>\n"; - } - else - { - sb << "__generic<T:__BuiltinArithmeticType, let N:int, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>\n"; - sb << "extension __TextureImpl<vector<T,N>,Shape,isArray,0,sampleCount,0,isShadow," << isCombined << ",format>\n"; - } + const char* extSizeParam = isScalarTexture ? "" : ", let N:int"; + const char* extTexType = isScalarTexture ? "T" : "vector<T,N>"; + }}}} -{ // begin extension for gather +// Gather for [TextureType = $(extTexType), isCombined = $(isCombined)] +__generic<T:__BuiltinArithmeticType $(extSizeParam), Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int> +extension __TextureImpl<$(extTexType),Shape,isArray,0,sampleCount,0,isShadow,$(isCombined),format> +{ ${{{{ - - // Gather component - const char* samplerStateParam = isCombined ? "" : " s,"; - const char* getTexture = isCombined ? "__getTexture()" : "this"; - for (int isCmp = 0; isCmp < 2; ++isCmp) - { - const char* cmp = isCmp ? "Cmp" : ""; - const char* cmpParam = isCmp ? ", T compareValue" : ""; - const char* compareArg = isCmp ? ", compareValue" : ""; - const char* samplerStateType = isCombined ? "" : (isCmp ? "SamplerComparisonState" : "SamplerState"); - const char* getSampler = isCombined ? (isCmp ? " __getComparisonSampler()," : " __getSampler(),") : samplerStateParam; - const char* componentNames[] = { "", "Red", "Green", "Blue", "Alpha"}; - const char* glslComponentNames[] = { ", 0", ", 1", ", 2", ", 3" }; - - for (auto componentId = 0; componentId < 5; componentId++) - { - auto componentName = componentNames[componentId]; - auto glslComponent = (isCmp ? "" :glslComponentNames[componentId == 0 ? 0 : componentId - 1]); - - for (bool isStatus : { false, true }) - { - const char* statusDecl = isStatus ? ", out uint status" : ""; - const char* statusInit = isStatus ? " status = 0;\n" : ""; - const char* statusCapWithMetal = isStatus ? "hlsl" : "glsl_hlsl_metal_spirv"; - const char* statusCapWithoutMetal = isStatus ? "hlsl" : "glsl_hlsl_spirv"; + for (int isShadow = 0; isShadow < 2; isShadow++) + for (auto componentId = 0; componentId < 5; componentId++) + { + const char* compareFunc = isShadow ? "Cmp" : ""; + const char* compareParam = isShadow ? ", T compareValue" : ""; + const char* compareArg = isShadow ? ", compareValue" : ""; + + // Some targets support the combined texture natively + const char* samplerParam = isCombined ? "" : (isShadow ? "SamplerComparisonState s," : "SamplerState s,"); + const char* samplerArg = isCombined ? "" : ", s"; + const char* getTexture = isCombined ? "__getTexture()" : "this"; + const char* getSampler = isCombined ? (isShadow ? ", __getComparisonSampler()" : ", __getSampler()") : samplerArg; + + const char* componentFuncString[] = { "", "Red", "Green", "Blue", "Alpha"}; + const char* componentArgString[] = { ", 0", ", 0", ", 1", ", 2", ", 3" }; + const char* componentFunc = componentFuncString[componentId]; + const char* componentArg = (isShadow ? "" : componentArgString[componentId]); }}}} [ForceInline] - [require($(statusCapWithMetal), texture_gather)] - vector<T,4> Gather$(cmp)$(componentName)($(samplerStateType)$(samplerStateParam) vector<float, Shape.dimensions+isArray> location $(cmpParam) $(statusDecl)) + [require(glsl_hlsl_metal_spirv_wgsl, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam)) { - $(statusInit) + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + __target_switch { - case hlsl: __intrinsic_asm ".Gather$(cmp)$(componentName)"; -${{{{ - if (!isStatus) - { -}}}} + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; case metal: - return __texture_gather$(cmp)<T>($(getTexture),$(getSampler) location $(compareArg) $(glslComponent)); + case wgsl: + return __texture_gather$(compareFunc)<T>($(getTexture) $(getSampler), location $(compareArg) $(componentArg)); case glsl: case spirv: - return __texture_gather$(cmp)<T>(this,$(samplerStateParam) location $(compareArg) $(glslComponent)); -${{{{ - } // if(!isStatus) -}}}} + return __texture_gather$(compareFunc)<T>(this $(samplerArg), location $(compareArg) $(componentArg)); } } + [ForceInline] - [require($(statusCapWithMetal), texture_gather)] - vector<T,4> Gather$(cmp)$(componentName)($(samplerStateType)$(samplerStateParam) vector<float, Shape.dimensions+isArray> location $(cmpParam), constexpr vector<int, Shape.planeDimensions> offset $(statusDecl)) + [require(hlsl, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam), + out uint status) { - $(statusInit) + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + __target_switch { - case hlsl: __intrinsic_asm ".Gather$(cmp)$(componentName)"; -${{{{ - if (!isStatus) - { -}}}} + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; + } + } + + [ForceInline] + [require(glsl_hlsl_metal_spirv_wgsl, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam), + constexpr vector<int, Shape.planeDimensions> offset) + { + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + + __target_switch + { + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; case metal: - return __texture_gather$(cmp)_offset<T>($(getTexture),$(getSampler) location $(compareArg), offset $(glslComponent)); + case wgsl: + return __texture_gather$(compareFunc)_offset<T>($(getTexture) $(getSampler), location $(compareArg), offset $(componentArg)); case glsl: case spirv: - return __texture_gather$(cmp)_offset<T>(this,$(samplerStateParam) location $(compareArg), offset $(glslComponent)); -${{{{ - } // if(!isStatus) -}}}} + return __texture_gather$(compareFunc)_offset<T>(this $(samplerArg), location $(compareArg), offset $(componentArg)); } } + [ForceInline] - [require($(statusCapWithoutMetal), texture_gather)] - vector<T,4> Gather$(cmp)$(componentName)($(samplerStateType)$(samplerStateParam) vector<float, Shape.dimensions+isArray> location $(cmpParam), + [require(hlsl, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam), + constexpr vector<int, Shape.planeDimensions> offset, + out uint status) + { + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + + __target_switch + { + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; + } + } + + [ForceInline] + [require(glsl_hlsl_spirv, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam), constexpr vector<int, Shape.planeDimensions> offset1, constexpr vector<int, Shape.planeDimensions> offset2, constexpr vector<int, Shape.planeDimensions> offset3, - constexpr vector<int, Shape.planeDimensions> offset4 - $(statusDecl)) + constexpr vector<int, Shape.planeDimensions> offset4) { - $(statusInit) + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + __target_switch { - case hlsl: __intrinsic_asm ".Gather$(cmp)$(componentName)"; -${{{{ - if (!isStatus) - { -}}}} + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; case glsl: case spirv: - return __texture_gather$(cmp)_offsets<T>(this,$(samplerStateParam) location $(compareArg), offset1,offset2,offset3,offset4 $(glslComponent)); -${{{{ - } // if(!isStatus) -}}}} + return __texture_gather$(compareFunc)_offsets<T>(this $(samplerArg), location $(compareArg), offset1,offset2,offset3,offset4 $(componentArg)); + } + } + + [ForceInline] + [require(hlsl, texture_gather)] + vector<T,4> Gather$(compareFunc)$(componentFunc)( + $(samplerParam) + vector<float, Shape.dimensions+isArray> location + $(compareParam), + constexpr vector<int, Shape.planeDimensions> offset1, + constexpr vector<int, Shape.planeDimensions> offset2, + constexpr vector<int, Shape.planeDimensions> offset3, + constexpr vector<int, Shape.planeDimensions> offset4, + out uint status) + { + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) || Shape.flavor == $(SLANG_TEXTURE_CUBE), + "Gather is supported only for 2D and 3D textures"); + + __target_switch + { + case hlsl: __intrinsic_asm ".Gather$(compareFunc)$(componentFunc)"; } } + ${{{{ - } // for (isStatus) - } // for (componentId) - } // for (isCmp) + } // for (componentId) }}}} -} // end extension for gather +} // End of: Gather for [TextureType = $(extTexType), isCombined = $(isCombined)] ${{{{ } // for (isScalarTexture) }}}} +// End of all Texture Gather + // Load/Subscript for readonly, no MS textures diff --git a/source/slang/slang-capabilities.capdef b/source/slang/slang-capabilities.capdef index 102671ffb..801d54eca 100644 --- a/source/slang/slang-capabilities.capdef +++ b/source/slang/slang-capabilities.capdef @@ -374,6 +374,10 @@ alias glsl_hlsl_metal_spirv_wgsl = glsl | hlsl | metal | spirv | wgsl; /// [Compound] alias glsl_metal_spirv = glsl | metal | spirv; +/// GLSL, Metal, SPIRV and WGSL code-gen targets +/// [Compound] +alias glsl_metal_spirv_wgsl = glsl | metal | spirv | wgsl; + /// GLSL, and SPIRV code-gen targets /// [Compound] alias glsl_spirv = glsl | spirv; diff --git a/tests/wgsl/texture-sampler-less.slang b/tests/wgsl/texture-sampler-less.slang index 1a6cb5341..893e867b7 100644 --- a/tests/wgsl/texture-sampler-less.slang +++ b/tests/wgsl/texture-sampler-less.slang @@ -311,23 +311,27 @@ bool TEST_texture( // https://www.w3.org/TR/WGSL/#texturegather // ================================== -#if 0 + // WGSL: textureGather({{.*}}t2D && all(Tv4(T(0)) == t2D.Gather(float2(u, u))) + // WGSL: textureGather({{.*}}tCube && all(Tv4(T(0)) == tCube.Gather(normalize(float3(u, 1 - u, u)))) + // WGSL: textureGather({{.*}}t2DArray && all(Tv4(T(0)) == t2DArray.Gather(float3(u, u, 0))) + // WGSL: textureGather({{.*}}tCubeArray && all(Tv4(T(0)) == tCubeArray.Gather(float4(normalize(float3(u, 1 - u, u)), 0))) #if TEST_WHEN_CONSTEXPR_WORKS_FOR_OFFSET // Offset variant + // W-GSL: textureGather({{.*}}t2D && all(Tv4(T(0)) == t2D.Gather(float2(u2, u), int2(0, 0))) + // W-GSL: textureGather({{.*}}t2DArray && all(Tv4(T(0)) == t2DArray.Gather(float3(u2, u, 0), int2(0, 0))) #endif // #if TEST_WHEN_CONSTEXPR_WORKS_FOR_OFFSET -#endif // ===================================== // T SampleGrad() diff --git a/tests/wgsl/texture.slang b/tests/wgsl/texture.slang index 999555a55..af39cf52a 100644 --- a/tests/wgsl/texture.slang +++ b/tests/wgsl/texture.slang @@ -346,21 +346,25 @@ bool TEST_texture( // https://www.w3.org/TR/WGSL/#texturegather // ================================== -#if 0 + // WGSL: textureGather({{.*}}t2D && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u, u))) + // WGSL: textureGather({{.*}}tCube && all(Tv4(T(0)) == tCube.Gather(samplerState, normalize(float3(u, 1 - u, u)))) + // WGSL: textureGather({{.*}}t2DArray && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u, u, 0))) + // WGSL: textureGather({{.*}}tCubeArray && all(Tv4(T(0)) == tCubeArray.Gather(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) // Offset variant + // WGSL: textureGather({{.*}}t2D && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u2, u), int2(0, 0))) + // WGSL: textureGather({{.*}}t2DArray && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u2, u, 0), int2(0, 0))) -#endif // ===================================== // T SampleGrad() |
