Skip to content

Commit

Permalink
Keep const-ness in generic functions (shader-slang#4028)
Browse files Browse the repository at this point in the history
* Keep const-ness in generic functions

Closes shader-slang#3834

The issue was that "const" variables inside of generic functions became
non-const variables.  This issue prevented some of GLSL texture
functions from being called inside of generic functions.

When `propagateConstExpr()` iterates the global functions, the generic
functions had to be handled little differently. This commit allows the
iteration to happen for the generic functions.

* Adding an explantion of the test as a comment
  • Loading branch information
jkwak-work authored Apr 25, 2024
1 parent 366a947 commit ed06811
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 26 deletions.
8 changes: 8 additions & 0 deletions source/slang/slang-ir-constexpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,14 @@ void propagateConstExpr(
default:
break;

case kIROp_Generic:
{
auto gen = as<IRGeneric>(gv);
gv = as<IRFunc>(findGenericReturnVal(gen));
if (nullptr == gv)
break;
}
[[fallthrough]];
case kIROp_Func:
case kIROp_GlobalVar:
{
Expand Down
33 changes: 33 additions & 0 deletions tests/bugs/gh-3834.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -target glsl -allow-glsl
//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -target glsl -allow-glsl -DUSE_GENERIC

// This tests an issue that "const" variable was losing the
// const-ness when they are in a generic function

uniform sampler2D uniform_sampler2D;
RWStructuredBuffer<float> outputBuffer;

#ifdef USE_GENERIC
__generic<T:__BuiltinArithmeticType>
#endif
vec4 MyFunc()
{
//CHECK: const ivec2 offset0
//CHECK: const ivec2 offset1
const ivec2 offset0 = ivec2(0,0);
const ivec2 offset1 = ivec2(1,1);
const ivec2[4] offsets = { offset0, offset0, offset1, offset1 };
return textureGatherOffsets(uniform_sampler2D, vec2(0), offsets);
}

[numthreads(4, 1, 1)]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
#ifdef USE_GENERIC
vec4 result = MyFunc<float>();
#else
vec4 result = MyFunc();
#endif

outputBuffer[0] = result[0];
}
44 changes: 18 additions & 26 deletions tests/glsl-intrinsic/intrinsic-texture.slang
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
//DISABLE_TEST:SIMPLE(filecheck=CHECK_HLSL): -allow-glsl -stage compute -entry computeMain -target hlsl -DCOMPUTE
//DISABLE_TEST:SIMPLE(filecheck=CHECK_CPP): -allow-glsl -stage compute -entry computeMain -target cpp -DCOMPUTE

// "Offset" family of texture functions in GLSL requires offset parameter to be a constant value.
// It appears that slangc removes the constant-ness of constant values.
//#define TEST_when_constexpr_works

// It appears that CUDA doesn't have implementations for multisampling samplers.
// When targetting glsl and spirv, the DEBUG build of slangc encounters issues with "Array" variant
// of multisampling samplers: sampler2DMSArray, isampler2DMSArray and usampler2DMSArray.
Expand Down Expand Up @@ -354,17 +350,15 @@ bool textureFuncs( Sampler1D<vector<T,N>> gsampler1D
&& gvec4(T(0)) == textureGatherOffset(gsampler2DRect, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffset(gsampler2DRect, vec2(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffset(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ })
#if defined(TEST_when_constexpr_works)
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }, int(0)) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }, int(0)) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DShadow, vec2(0), float(0), { __LINE__ }) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DArrayShadow, vec3(0), float(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }, int(0)) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ }) // constexpr not working
#endif // #if defined(TEST_when_constexpr_works)
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }, int(0))
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffsets(uniform_sampler2DShadow, vec2(0), float(0), { __LINE__ })
&& vec4(0) == textureGatherOffsets(uniform_sampler2DArrayShadow, vec3(0), float(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffsets(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ })

// 8.9.5. Compatibility Profile Texture Functions
&& vec4(0) == texture1D(uniform_sampler1D, float(0))
Expand Down Expand Up @@ -493,17 +487,15 @@ bool itextureFuncs(Sampler1D<vector<T, N>> gsampler1D
&& gvec4(T(0)) == textureGatherOffset(gsampler2DRect, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffset(gsampler2DRect, vec2(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffset(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ })
#if defined(TEST_when_constexpr_works)
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }, int(0)) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }, int(0)) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DShadow, vec2(0), float(0), { __LINE__ }) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DArrayShadow, vec3(0), float(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }) // constexpr not working
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }, int(0)) // constexpr not working
&& vec4(0) == textureGatherOffsets(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ }) // constexpr not working
#endif // #if defined(TEST_when_constexpr_works)
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2D, vec2(0), { __LINE__ }, int(0))
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DArray, vec3(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffsets(uniform_sampler2DShadow, vec2(0), float(0), { __LINE__ })
&& vec4(0) == textureGatherOffsets(uniform_sampler2DArrayShadow, vec3(0), float(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ })
&& gvec4(T(0)) == textureGatherOffsets(gsampler2DRect, vec2(0), { __LINE__ }, int(0))
&& vec4(0) == textureGatherOffsets(uniform_sampler2DRectShadow, vec2(0), float(0), { __LINE__ })
;
}

Expand Down

0 comments on commit ed06811

Please sign in to comment.