From 03765a691531d69a30734beb0433d8d4cac45024 Mon Sep 17 00:00:00 2001 From: Jay Kwak <82421531+jkwak-work@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:04:22 -0700 Subject: [PATCH] WGSL texture support for depth and multisampled (#5152) * WGSL texture support for depth and multisampled This commit fixes a few issues with WGSL texture intrinsics. - static_assert-s are corrected. - Gather functions work properly with depth textures - Load functions work properly with depth textures and multisampled textures --- source/slang/hlsl.meta.slang | 116 +++++---- source/slang/slang-intrinsic-expand.cpp | 11 +- tests/wgsl/texture-gather.slang | 331 ++++++++++++++++++++++++ tests/wgsl/texture-load.slang | 198 ++++++++++++++ tests/wgsl/texture.slang | 47 ---- 5 files changed, 600 insertions(+), 103 deletions(-) create mode 100644 tests/wgsl/texture-gather.slang create mode 100644 tests/wgsl/texture-load.slang diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index bbdfc3b030..c646f5cb7b 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -2229,6 +2229,22 @@ vector __texture_gather( result:$$vector = OpImageGather %sampledImage $location $component; }; case wgsl: + if (isShadow == 1) + { + // If depth texture, `textureGather` doesn't take channel value, `$3`. + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGather($0, $1, ($2).xy, u32(($2).z))"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGather($0, $1, ($2).xyz, u32(($2).w))"; + } + } + __intrinsic_asm "textureGather($0, $1, $2)"; + } + if (isArray == 1) { switch (Shape.flavor) @@ -2293,6 +2309,22 @@ vector __texture_gather_offset( result:$$vector = OpImageGather %sampledImage $location $component ConstOffset $offset; }; case wgsl: + if (isShadow == 1) + { + // If depth texture, `textureGather` doesn't take channel value, `$4`. + if (isArray == 1) + { + switch (Shape.flavor) + { + case $(SLANG_TEXTURE_2D): + __intrinsic_asm "textureGather($0, $1, ($2).xy, u32(($2).z), $3)"; + case $(SLANG_TEXTURE_CUBE): + __intrinsic_asm "textureGather($0, $1, ($2).xyz, u32(($2).w), $3)"; + } + } + __intrinsic_asm "textureGather($0, $1, $2, $3)"; + } + if (isArray == 1) { switch (Shape.flavor) @@ -2413,6 +2445,8 @@ vector __texture_gatherCmp( result:$$vector = OpImageDrefGather %sampledImage $location $compareValue; }; case wgsl: + static_assert(isShadow == 1, "WGSL supports textureGatherCompare only for depth textures."); + if (isArray == 1) { switch (Shape.flavor) @@ -2477,6 +2511,8 @@ vector __texture_gatherCmp_offset( result:$$vector = OpImageDrefGather %sampledImage $location $compareValue ConstOffset $offset; }; case wgsl: + static_assert(isShadow == 1, "WGSL supports textureGatherCompare only for depth textures."); + if (isArray == 1) { switch (Shape.flavor) @@ -2841,12 +2877,13 @@ 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"); + , "WGSL doesn't supports textureLoad for Cube texture."); + static_assert(isArray == 0 || Shape.flavor == $(SLANG_TEXTURE_2D) + , "WGSL supports textureLoad for texture_2d_array but not for array of 1D, 3D or Cube."); + if (isArray == 1) { switch (Shape.flavor) @@ -2871,7 +2908,7 @@ extension __TextureImpl location, constexpr vector offset) { __target_switch @@ -2902,22 +2939,6 @@ 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"; } } @@ -3045,20 +3066,11 @@ 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"; - } - } + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) + , "WGSL supports textureLoad for texture_multisampled_2d but not for multisampled of 1D, 3D or Cube."); + static_assert(isArray == 0 + , "WGSL doesn't support array variants of multisampled textures for textureLoad."); + __intrinsic_asm "textureLoad($0, $1, $2)$z"; } } @@ -3283,18 +3295,21 @@ extension __TextureImpl"; case wgsl: - static_assert(T is float || T is vector || 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 doesn't supports textureLoad for Cube texture."); + static_assert(isArray == 0 || Shape.flavor == $(SLANG_TEXTURE_2D) + , "WGSL supports textureLoad for texture_storage_2d_array but not for array of 1D, 3D or Cube."); + static_assert(isShadow == 0 || T is float + , "WGSL supports only f32 depth 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"; @@ -3541,21 +3556,12 @@ 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"; + static_assert(Shape.flavor == $(SLANG_TEXTURE_2D) + , "WGSL supports textureLoad for texture_multisampled_2d but not for multisampled of 1D, 3D or Cube."); + static_assert(isArray == 0 + , "WGSL doesn't support array variants of multisampled textures for textureLoad."); + + __intrinsic_asm "textureLoad($0, $1, $2)$z"; } } diff --git a/source/slang/slang-intrinsic-expand.cpp b/source/slang/slang-intrinsic-expand.cpp index 08f21ff1d0..7cde707773 100644 --- a/source/slang/slang-intrinsic-expand.cpp +++ b/source/slang/slang-intrinsic-expand.cpp @@ -530,10 +530,12 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) auto textureArg = m_args[0].get(); IRType* elementType = nullptr; + bool isShadowTexture = false; if (auto baseTextureType = as(textureArg->getDataType())) { elementType = baseTextureType->getElementType(); + isShadowTexture = baseTextureType->isShadow(); } else { @@ -548,7 +550,14 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) if (const auto basicType = as(elementType)) { // A scalar result is expected - m_writer->emit(".x"); + + // If the texture type is a scalar type, the return type from the target intrinsic + // probably returns a scalar type already. For GLSL, ".x" swizzling happened to + // work fine on a scalar value like "1.x", but it is invalid for WGSL. + if (!isShadowTexture) + { + m_writer->emit(".x"); + } } else if (auto vectorType = as(elementType)) { diff --git a/tests/wgsl/texture-gather.slang b/tests/wgsl/texture-gather.slang new file mode 100644 index 0000000000..a95428a1de --- /dev/null +++ b/tests/wgsl/texture-gather.slang @@ -0,0 +1,331 @@ +//TEST:SIMPLE(filecheck=WGSL): -stage fragment -entry fragMain -target wgsl + +// In WGSL, `textureSample` and other variants work only for f32 type. +// But textureGather works for i32, u32 and f32. + +//TEST_INPUT: ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +// f32 types + +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_f32v3 +Texture2D t2D_f32v3; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_f32v3 +TextureCube tCube_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: Texture2D(size=4, content = zero):name t2D_f32v4 +Texture2D t2D_f32v4; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_f32v4 +TextureCube tCube_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; + +// i32 types + +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_i32v3 +Texture2D t2D_i32v3; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_i32v3 +TextureCube tCube_i32v3; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_i32v3 +Texture2DArray t2DArray_i32v3; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_i32v3 +TextureCubeArray tCubeArray_i32v3; + +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_i32v4 +Texture2D t2D_i32v4; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_i32v4 +TextureCube tCube_i32v4; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_i32v4 +Texture2DArray t2DArray_i32v4; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_i32v4 +TextureCubeArray tCubeArray_i32v4; + +// u32 types + +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_u32v3 +Texture2D t2D_u32v3; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_u32v3 +TextureCube tCube_u32v3; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_u32v3 +Texture2DArray t2DArray_u32v3; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_u32v3 +TextureCubeArray tCubeArray_u32v3; + +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_u32v4 +Texture2D t2D_u32v4; +//TEST_INPUT: TextureCube(size=4, content = zero):name tCube_u32v4 +TextureCube tCube_u32v4; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_u32v4 +Texture2DArray t2DArray_u32v4; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name tCubeArray_u32v4 +TextureCubeArray tCubeArray_u32v4; + +// depth + +__generic +typealias Depth2D = __TextureImpl< + float, + __Shape2D, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias Depth2DArray = __TextureImpl< + float, + __Shape2D, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias DepthCube = __TextureImpl< + float, + __ShapeCube, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias DepthCubeArray = __TextureImpl< + float, + __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 +Depth2DArray d2DArray; +//TEST_INPUT: TextureCube(size=4, content = zero, arrayLength=2):name dCubeArray +DepthCubeArray dCubeArray; + +//TEST_INPUT: Sampler:name samplerState +SamplerState samplerState; +//TEST_INPUT: Sampler:name depthSampler +SamplerComparisonState depthSampler; + + +__generic +bool TEST_textureGather( + Texture2D> t2D, + TextureCube> tCube, + Texture2DArray> t2DArray, + TextureCubeArray> tCubeArray) +{ + // WGSL-LABEL: TEST_textureGather + typealias Tv4 = vector; + + float u = 0; + float u2 = 0.5; + + return true + // ================================== + // vector Gather() + // https://www.w3.org/TR/WGSL/#texturegather + // ================================== + + // WGSL-COUNT-2: textureGather({{.*}}0{{.*}}t2D + && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u, u))) + && all(Tv4(T(0)) == t2D.Gather(samplerState, float2(u2, u), int2(0,0))) + + // WGSL: textureGather({{.*}}0{{.*}}tCube + && all(Tv4(T(0)) == tCube.Gather(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-2: textureGather({{.*}}0{{.*}}t2DArray + && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u, u, 0))) + && all(Tv4(T(0)) == t2DArray.Gather(samplerState, float3(u2, u, 0), int2(0,0))) + + // WGSL: textureGather({{.*}}0{{.*}}tCubeArray + && all(Tv4(T(0)) == tCubeArray.Gather(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // ================================== + // vector GatherRed() + // ================================== + + // WGSL-COUNT-2: textureGather({{.*}}0{{.*}}t2D + && all(Tv4(T(0)) == t2D.GatherRed(samplerState, float2(u, u))) + && all(Tv4(T(0)) == t2D.GatherRed(samplerState, float2(u2, u), int2(0,0))) + + // WGSL: textureGather({{.*}}0{{.*}}tCube + && all(Tv4(T(0)) == tCube.GatherRed(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-2: textureGather({{.*}}0{{.*}}t2DArray + && all(Tv4(T(0)) == t2DArray.GatherRed(samplerState, float3(u, u, 0))) + && all(Tv4(T(0)) == t2DArray.GatherRed(samplerState, float3(u2, u, 0), int2(0,0))) + + // WGSL: textureGather({{.*}}0{{.*}}tCubeArray + && all(Tv4(T(0)) == tCubeArray.GatherRed(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // ================================== + // vector GatherGreen() + // ================================== + + // WGSL-COUNT-2: textureGather({{.*}}1{{.*}}t2D + && all(Tv4(T(0)) == t2D.GatherGreen(samplerState, float2(u, u))) + && all(Tv4(T(0)) == t2D.GatherGreen(samplerState, float2(u2, u), int2(0,0))) + + // WGSL: textureGather({{.*}}1{{.*}}tCube + && all(Tv4(T(0)) == tCube.GatherGreen(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-2: textureGather({{.*}}1{{.*}}t2DArray + && all(Tv4(T(0)) == t2DArray.GatherGreen(samplerState, float3(u, u, 0))) + && all(Tv4(T(0)) == t2DArray.GatherGreen(samplerState, float3(u2, u, 0), int2(0,0))) + + // WGSL: textureGather({{.*}}1{{.*}}tCubeArray + && all(Tv4(T(0)) == tCubeArray.GatherGreen(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // ================================== + // vector GatherBlue() + // ================================== + + // WGSL-COUNT-2: textureGather({{.*}}2{{.*}}t2D + && all(Tv4(T(0)) == t2D.GatherBlue(samplerState, float2(u, u))) + && all(Tv4(T(0)) == t2D.GatherBlue(samplerState, float2(u2, u), int2(0,0))) + + // WGSL: textureGather({{.*}}2{{.*}}tCube + && all(Tv4(T(0)) == tCube.GatherBlue(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-2: textureGather({{.*}}2{{.*}}t2DArray + && all(Tv4(T(0)) == t2DArray.GatherBlue(samplerState, float3(u, u, 0))) + && all(Tv4(T(0)) == t2DArray.GatherBlue(samplerState, float3(u2, u, 0), int2(0,0))) + + // WGSL: textureGather({{.*}}2{{.*}}tCubeArray + && all(Tv4(T(0)) == tCubeArray.GatherBlue(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // ================================== + // vector GatherAlpha() + // ================================== + + // WGSL-COUNT-2: textureGather({{.*}}3{{.*}}t2D + && all(Tv4(T(0)) == t2D.GatherAlpha(samplerState, float2(u, u))) + && all(Tv4(T(0)) == t2D.GatherAlpha(samplerState, float2(u2, u), int2(0,0))) + + // WGSL: textureGather({{.*}}3{{.*}}tCube + && all(Tv4(T(0)) == tCube.GatherAlpha(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-2: textureGather({{.*}}3{{.*}}t2DArray + && all(Tv4(T(0)) == t2DArray.GatherAlpha(samplerState, float3(u, u, 0))) + && all(Tv4(T(0)) == t2DArray.GatherAlpha(samplerState, float3(u2, u, 0), int2(0,0))) + + // WGSL: textureGather({{.*}}3{{.*}}tCubeArray + && all(Tv4(T(0)) == tCubeArray.GatherAlpha(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + ; +} + +bool TEST_textureGather_depth() +{ + // WGSL-LABEL: TEST_textureGather_depth + float u = 0.f; + float u2 = 0.5f; + float depthCompare = 0.5f; + + return true + // ================================== + // vector Gather() + // https://www.w3.org/TR/WGSL/#texturegather + // ================================== + + // WGSL-COUNT-10: textureGather({{\(*}}d2D + && all(float4(0) == d2D.Gather (samplerState, float2(u, u))) + && all(float4(0) == d2D.GatherRed (samplerState, float2(u, u))) + && all(float4(0) == d2D.GatherGreen(samplerState, float2(u, u))) + && all(float4(0) == d2D.GatherBlue (samplerState, float2(u, u))) + && all(float4(0) == d2D.GatherAlpha(samplerState, float2(u, u))) + && all(float4(0) == d2D.Gather (samplerState, float2(u, u), int2(0,0))) + && all(float4(0) == d2D.GatherRed (samplerState, float2(u, u), int2(0,0))) + && all(float4(0) == d2D.GatherGreen(samplerState, float2(u, u), int2(0,0))) + && all(float4(0) == d2D.GatherBlue (samplerState, float2(u, u), int2(0,0))) + && all(float4(0) == d2D.GatherAlpha(samplerState, float2(u, u), int2(0,0))) + + // WGSL-COUNT-5: textureGather({{\(*}}dCube + && all(float4(0) == dCube.Gather (samplerState, normalize(float3(u, 1 - u, u)))) + && all(float4(0) == dCube.GatherRed (samplerState, normalize(float3(u, 1 - u, u)))) + && all(float4(0) == dCube.GatherGreen(samplerState, normalize(float3(u, 1 - u, u)))) + && all(float4(0) == dCube.GatherBlue (samplerState, normalize(float3(u, 1 - u, u)))) + && all(float4(0) == dCube.GatherAlpha(samplerState, normalize(float3(u, 1 - u, u)))) + + // WGSL-COUNT-10: textureGather({{\(*}}d2DArray + && all(float4(0) == d2DArray.Gather (samplerState, float3(u, u, 0))) + && all(float4(0) == d2DArray.GatherRed (samplerState, float3(u, u, 0))) + && all(float4(0) == d2DArray.GatherGreen(samplerState, float3(u, u, 0))) + && all(float4(0) == d2DArray.GatherBlue (samplerState, float3(u, u, 0))) + && all(float4(0) == d2DArray.GatherAlpha(samplerState, float3(u, u, 0))) + && all(float4(0) == d2DArray.Gather (samplerState, float3(u, u, 0), int2(0,0))) + && all(float4(0) == d2DArray.GatherRed (samplerState, float3(u, u, 0), int2(0,0))) + && all(float4(0) == d2DArray.GatherGreen(samplerState, float3(u, u, 0), int2(0,0))) + && all(float4(0) == d2DArray.GatherBlue (samplerState, float3(u, u, 0), int2(0,0))) + && all(float4(0) == d2DArray.GatherAlpha(samplerState, float3(u, u, 0), int2(0,0))) + + // WGSL-COUNT-5: textureGather({{\(*}}dCubeArray + && all(float4(0) == dCubeArray.Gather (samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + && all(float4(0) == dCubeArray.GatherRed (samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + && all(float4(0) == dCubeArray.GatherGreen(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + && all(float4(0) == dCubeArray.GatherBlue (samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + && all(float4(0) == dCubeArray.GatherAlpha(samplerState, float4(normalize(float3(u, 1 - u, u)), 0))) + + // ================================== + // vector GatherCmp() + // https://www.w3.org/TR/WGSL/#texturegathercompare + // ================================== + + // WGSL-COUNT-2: textureGatherCompare({{\(*}}d2D + && all(float4(0) == d2D.GatherCmp(depthSampler, float2(u, u), depthCompare)) + && all(float4(0) == d2D.GatherCmp(depthSampler, float2(u, u), depthCompare, int2(0,0))) + + // WGSL: textureGatherCompare({{\(*}}dCube + && all(float4(0) == dCube.GatherCmp(depthSampler, normalize(float3(u, 1 - u, u)), depthCompare)) + + // WGSL-COUNT-2: textureGatherCompare({{\(*}}d2DArray + && all(float4(0) == d2DArray.GatherCmp(depthSampler, float3(u, u, 0), depthCompare)) + && all(float4(0) == d2DArray.GatherCmp(depthSampler, float3(u, u, 0), depthCompare, int2(0,0))) + + // WGSL: textureGatherCompare({{\(*}}dCubeArray + && all(float4(0) == dCubeArray.GatherCmp(depthSampler, float4(normalize(float3(u, 1 - u, u)), 0), depthCompare)) + ; +} + + +void fragMain() +{ + bool result = true + && TEST_textureGather(t2D_f32v3, tCube_f32v3, t2DArray_f32v3, tCubeArray_f32v3) + && TEST_textureGather(t2D_f32v4, tCube_f32v4, t2DArray_f32v4, tCubeArray_f32v4) + && TEST_textureGather(t2D_i32v3, tCube_i32v3, t2DArray_i32v3, tCubeArray_i32v3) + && TEST_textureGather(t2D_i32v4, tCube_i32v4, t2DArray_i32v4, tCubeArray_i32v4) + && TEST_textureGather(t2D_u32v3, tCube_u32v3, t2DArray_u32v3, tCubeArray_u32v3) + && TEST_textureGather(t2D_u32v4, tCube_u32v4, t2DArray_u32v4, tCubeArray_u32v4) + && TEST_textureGather_depth() + ; + + outputBuffer[0] = int(result); +} diff --git a/tests/wgsl/texture-load.slang b/tests/wgsl/texture-load.slang new file mode 100644 index 0000000000..cc49b87096 --- /dev/null +++ b/tests/wgsl/texture-load.slang @@ -0,0 +1,198 @@ +//TEST:SIMPLE(filecheck=WGSL): -stage fragment -entry fragMain -target wgsl + +// In WGSL, `textureSample` and other variants work only for f32 type. +// But textureLoad works for i32, u32 and f32. + +//TEST_INPUT: ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +// f32 types + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_f32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_f32v3 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_f32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_f32v3 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_f32v3 +Texture1D t1D_f32v3; +Texture2D t2D_f32v3; +Texture3D t3D_f32v3; +Texture2DMS t2DMS_f32v3; +Texture2DArray t2DArray_f32v3; + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_f32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_f32v4 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_f32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_f32v4 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_f32v4 +Texture1D t1D_f32v4; +Texture2D t2D_f32v4; +Texture3D t3D_f32v4; +Texture2DMS t2DMS_f32v4; +Texture2DArray t2DArray_f32v4; + +// i32 types + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_i32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_i32v3 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_i32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_i32v3 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_i32v3 +Texture1D t1D_i32v3; +Texture2D t2D_i32v3; +Texture3D t3D_i32v3; +Texture2DMS t2DMS_i32v3; +Texture2DArray t2DArray_i32v3; + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_i32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_i32v4 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_i32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_i32v4 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_i32v4 +Texture1D t1D_i32v4; +Texture2D t2D_i32v4; +Texture3D t3D_i32v4; +Texture2DMS t2DMS_i32v4; +Texture2DArray t2DArray_i32v4; + +// u32 types + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_u32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_u32v3 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_u32v3 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_u32v3 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_u32v3 +Texture1D t1D_u32v3; +Texture2D t2D_u32v3; +Texture3D t3D_u32v3; +Texture2DMS t2DMS_u32v3; +Texture2DArray t2DArray_u32v3; + +//TEST_INPUT: Texture1D(size=4, content = zero):name t1D_u32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2D_u32v4 +//TEST_INPUT: Texture3D(size=4, content = zero):name t3D_u32v4 +//TEST_INPUT: Texture2D(size=4, content = zero):name t2DMS_u32v4 +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name t2DArray_u32v4 +Texture1D t1D_u32v4; +Texture2D t2D_u32v4; +Texture3D t3D_u32v4; +Texture2DMS t2DMS_u32v4; +Texture2DArray t2DArray_u32v4; + +// depth + +__generic +typealias Depth2D = __TextureImpl< + float, + __Shape2D, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias Depth2DMS = __TextureImpl< + float, + __Shape2D, + 0, // isArray + 1, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic +typealias Depth2DArray = __TextureImpl< + float, + __Shape2D, + 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: Texture2D(size=4, content = zero):name d2DMS +Depth2DMS d2DMS; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name d2DArray +Depth2DArray d2DArray; + + +__generic +bool TEST_textureLoad( + Texture1D> t1D, + Texture2D> t2D, + Texture3D> t3D, + Texture2DMS> t2DMS, + Texture2DArray> t2DArray) +{ + // WGSL-LABEL: TEST_textureLoad + typealias Tvn = vector; + + return true + // =================== + // 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: textureLoad({{\(*}}t2DMS + && all(Tvn(T(0)) == t2DMS.Load(int3(0, 0, 0))) + + // WGSL: textureLoad({{\(*}}t2DArray + && all(Tvn(T(0)) == t2DArray.Load(int4(0, 0, 0, 0))) + ; +} + +bool TEST_textureLoad_depth() +{ + // WGSL-LABEL: TEST_textureLoad_depth + + return true + // =================== + // T Load() + // https://www.w3.org/TR/WGSL/#textureload + // =================== + + // WGSL: textureLoad({{\(*}}d2D + && all(0.f == d2D.Load(int3(0, 0, 0))) + + // WGSL: textureLoad({{\(*}}d2DMS + && all(0.f == d2DMS.Load(int2(0, 0), 0)) + + // WGSL: textureLoad({{\(*}}d2DArray + && all(0.f == d2DArray.Load(int4(0, 0, 0, 0))) + ; +} + +void fragMain() +{ + bool result = true + && TEST_textureLoad(t1D_f32v3, t2D_f32v3, t3D_f32v3, t2DMS_f32v3, t2DArray_f32v3) + && TEST_textureLoad(t1D_f32v4, t2D_f32v4, t3D_f32v4, t2DMS_f32v4, t2DArray_f32v4) + && TEST_textureLoad(t1D_i32v3, t2D_i32v3, t3D_i32v3, t2DMS_i32v3, t2DArray_i32v3) + && TEST_textureLoad(t1D_i32v4, t2D_i32v4, t3D_i32v4, t2DMS_i32v4, t2DArray_i32v4) + && TEST_textureLoad(t1D_u32v3, t2D_u32v3, t3D_u32v3, t2DMS_u32v3, t2DArray_u32v3) + && TEST_textureLoad(t1D_u32v4, t2D_u32v4, t3D_u32v4, t2DMS_u32v4, t2DArray_u32v4) + && TEST_textureLoad_depth() + ; + + outputBuffer[0] = int(result); +} diff --git a/tests/wgsl/texture.slang b/tests/wgsl/texture.slang index af39cf52ab..49f730eebd 100644 --- a/tests/wgsl/texture.slang +++ b/tests/wgsl/texture.slang @@ -341,31 +341,6 @@ bool TEST_texture( // 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 - // ================================== - - // 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))) - // ===================================== // T SampleGrad() // https://www.w3.org/TR/WGSL/#texturesamplegrad @@ -398,28 +373,6 @@ bool TEST_texture( // 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;