Skip to content

Commit f0bc464

Browse files
aleino-nvcsyonghe
andauthored
Insert some casts for WGSL texture attribute queries (shader-slang#5560)
* Add new texture sampling test for WebGPU There are no 1d array textures in WGSL, so add texture-sampling-no-1d-arrays.slang based on texture-sampling.slang, but without 1d texture arrays. This helps to address issue shader-slang#4943. * Insert needed conversion when querying texture attributes in WGSL This helps to address issue shader-slang#4943. --------- Co-authored-by: Yong He <yonghe@outlook.com>
1 parent 147ceb1 commit f0bc464

3 files changed

+200
-13
lines changed

source/slang/slang-core-module-textures.cpp

+77-13
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,67 @@ void TextureTypeInfo::writeFunc(
180180
readNoneMode);
181181
}
182182

183+
enum class DimType
184+
{
185+
Float,
186+
Int,
187+
UInt,
188+
189+
Count,
190+
};
191+
192+
// The WGSL texture attribute types for 'expr' are unsigned int, and anything else requires a
193+
// conversion.
194+
template<typename S>
195+
static String wgslTextureAttributeConversion(DimType type, S expr)
196+
{
197+
198+
switch (type)
199+
{
200+
201+
case DimType::UInt:
202+
return expr;
203+
204+
205+
case DimType::Float:
206+
{
207+
// Conversion to float is exact for values <= 2^24.
208+
String castExpr("f32(");
209+
castExpr.append(expr);
210+
castExpr.append(")");
211+
return castExpr;
212+
}
213+
break;
214+
215+
case DimType::Int:
216+
{
217+
// We can assume two's complement and just do a bitcast, since texture dimensions can't
218+
// be anywhere near big enough to yield a negative result.
219+
String castExpr("bitcast<i32>(");
220+
castExpr.append(expr);
221+
castExpr.append(")");
222+
return castExpr;
223+
}
224+
break;
225+
226+
default:
227+
SLANG_UNREACHABLE("Unexpected DimType enum value");
228+
break;
229+
};
230+
}
231+
183232
void TextureTypeInfo::writeGetDimensionFunctions()
184233
{
185234
static const char* kComponentNames[]{"x", "y", "z", "w"};
186235

187236
SlangResourceShape baseShape = base.baseShape;
188237

189238
// `GetDimensions`
190-
const char* dimParamTypes[] = {"out float ", "out int ", "out uint "};
191-
const char* dimParamTypesInner[] = {"float", "int", "uint"};
192-
for (int tid = 0; tid < 3; tid++)
239+
const char* dimParamTypes[int(DimType::Count)] = {"out float ", "out int ", "out uint "};
240+
const char* dimParamTypesInner[int(DimType::Count)] = {"float", "int", "uint"};
241+
for (int tid = 0; tid < int(DimType::Count); tid++)
193242
{
243+
DimType dimType = DimType(tid);
194244
auto t = dimParamTypes[tid];
195245
auto rawT = dimParamTypesInner[tid];
196246

@@ -227,8 +277,11 @@ void TextureTypeInfo::writeGetDimensionFunctions()
227277
params << t << "width";
228278
metal << "(*($" << String(paramCount) << ") = $0.get_width("
229279
<< String(metalMipLevel) << ")),";
230-
wgsl << "($" << String(paramCount) << ") = textureDimensions($0"
231-
<< (includeMipInfo ? ", $1" : "") << ");";
280+
wgsl << "($" << String(paramCount) << ") = "
281+
<< wgslTextureAttributeConversion(
282+
dimType,
283+
String("textureDimensions($0") + (includeMipInfo ? ", $1" : "") + ")")
284+
<< ";";
232285

233286
sizeDimCount = 1;
234287
break;
@@ -240,13 +293,15 @@ void TextureTypeInfo::writeGetDimensionFunctions()
240293
metal << "(*($" << String(paramCount) << ") = $0.get_width("
241294
<< String(metalMipLevel) << ")),";
242295
wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");";
243-
wgsl << "($" << String(paramCount) << ") = dim.x;";
296+
wgsl << "($" << String(paramCount)
297+
<< ") = " << wgslTextureAttributeConversion(dimType, "dim.x") << ";";
244298

245299
++paramCount;
246300
params << t << "height";
247301
metal << "(*($" << String(paramCount) << ") = $0.get_height("
248302
<< String(metalMipLevel) << ")),";
249-
wgsl << "($" << String(paramCount) << ") = dim.y;";
303+
wgsl << "($" << String(paramCount)
304+
<< ") = " << wgslTextureAttributeConversion(dimType, "dim.y") << ";";
250305

251306
sizeDimCount = 2;
252307
break;
@@ -257,19 +312,22 @@ void TextureTypeInfo::writeGetDimensionFunctions()
257312
metal << "(*($" << String(paramCount) << ") = $0.get_width("
258313
<< String(metalMipLevel) << ")),";
259314
wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");";
260-
wgsl << "($" << String(paramCount) << ") = dim.x;";
315+
wgsl << "($" << String(paramCount)
316+
<< ") = " << wgslTextureAttributeConversion(dimType, "dim.x") << ";";
261317

262318
++paramCount;
263319
params << t << "height,";
264320
metal << "(*($" << String(paramCount) << ") = $0.get_height("
265321
<< String(metalMipLevel) << ")),";
266-
wgsl << "($" << String(paramCount) << ") = dim.y;";
322+
wgsl << "($" << String(paramCount)
323+
<< ") = " << wgslTextureAttributeConversion(dimType, "dim.y") << ";";
267324

268325
++paramCount;
269326
params << t << "depth";
270327
metal << "(*($" << String(paramCount) << ") = $0.get_depth("
271328
<< String(metalMipLevel) << ")),";
272-
wgsl << "($" << String(paramCount) << ") = dim.z;";
329+
wgsl << "($" << String(paramCount)
330+
<< ") = " << wgslTextureAttributeConversion(dimType, "dim.z") << ";";
273331

274332
sizeDimCount = 3;
275333
break;
@@ -285,23 +343,29 @@ void TextureTypeInfo::writeGetDimensionFunctions()
285343
++paramCount;
286344
params << ", " << t << "elements";
287345
metal << "(*($" << String(paramCount) << ") = $0.get_array_size()),";
288-
wgsl << "($" << String(paramCount) << ") = textureNumLayers($0);";
346+
wgsl << "($" << String(paramCount)
347+
<< ") = " << wgslTextureAttributeConversion(dimType, "textureNumLayers($0)")
348+
<< ";";
289349
}
290350

291351
if (isMultisample)
292352
{
293353
++paramCount;
294354
params << ", " << t << "sampleCount";
295355
metal << "(*($" << String(paramCount) << ") = $0.get_num_samples()),";
296-
wgsl << "($" << String(paramCount) << ") = textureNumSamples($0);";
356+
wgsl << "($" << String(paramCount)
357+
<< ") = " << wgslTextureAttributeConversion(dimType, "textureNumSamples($0)")
358+
<< ";";
297359
}
298360

299361
if (includeMipInfo)
300362
{
301363
++paramCount;
302364
params << ", " << t << "numberOfLevels";
303365
metal << "(*($" << String(paramCount) << ") = $0.get_num_mip_levels()),";
304-
wgsl << "($" << String(paramCount) << ") = textureNumLevels($0);";
366+
wgsl << "($" << String(paramCount)
367+
<< ") = " << wgslTextureAttributeConversion(dimType, "textureNumLevels($0)")
368+
<< ";";
305369
}
306370

307371
metal.reduceLength(metal.getLength() - 1); // drop the last comma
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj -output-using-type
2+
//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj -output-using-type -vk
3+
//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj -output-using-type -mtl
4+
5+
6+
//TEST_INPUT: Texture1D(size=4, content = one):name=t1D
7+
//TEST_INPUT: Texture2D(size=4, content = one):name=t2D
8+
//TEST_INPUT: Texture3D(size=4, content = one):name=t3D
9+
//TEST_INPUT: TextureCube(size=4, content = one):name=tCube
10+
//TEST_INPUT: Texture2D(size=4, content = one, arrayLength=2):name=t2dArray
11+
//TEST_INPUT: TextureCube(size=4, content = one, arrayLength=2):name=tCubeArray
12+
//TEST_INPUT: Sampler:name=samplerState
13+
//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
14+
15+
// There are still some issues to fix in RHI, see issue #4943
16+
//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu
17+
18+
Texture1D t1D;
19+
Texture2D t2D;
20+
Texture3D t3D;
21+
TextureCube tCube;
22+
Texture2DArray t2dArray;
23+
TextureCubeArray tCubeArray;
24+
SamplerState samplerState;
25+
RWStructuredBuffer<float> outputBuffer;
26+
27+
cbuffer Uniforms
28+
{
29+
float4x4 modelViewProjection;
30+
}
31+
32+
struct AssembledVertex
33+
{
34+
float3 position;
35+
float3 color;
36+
float2 uv;
37+
};
38+
39+
struct CoarseVertex
40+
{
41+
float3 color;
42+
float2 uv;
43+
};
44+
45+
struct Fragment
46+
{
47+
float4 color;
48+
};
49+
50+
51+
// Vertex Shader
52+
53+
struct VertexStageInput
54+
{
55+
AssembledVertex assembledVertex : A;
56+
};
57+
58+
struct VertexStageOutput
59+
{
60+
CoarseVertex coarseVertex : CoarseVertex;
61+
float4 sv_position : SV_Position;
62+
};
63+
64+
VertexStageOutput vertexMain(VertexStageInput input)
65+
{
66+
VertexStageOutput output;
67+
68+
float3 position = input.assembledVertex.position;
69+
float3 color = input.assembledVertex.color;
70+
71+
output.coarseVertex.color = color;
72+
output.sv_position = mul(modelViewProjection, float4(position, 1.0));
73+
output.coarseVertex.uv = input.assembledVertex.uv;
74+
return output;
75+
}
76+
77+
// Fragment Shader
78+
79+
struct FragmentStageInput
80+
{
81+
CoarseVertex coarseVertex : CoarseVertex;
82+
};
83+
84+
struct FragmentStageOutput
85+
{
86+
Fragment fragment : SV_Target;
87+
};
88+
89+
FragmentStageOutput fragmentMain(FragmentStageInput input)
90+
{
91+
FragmentStageOutput output;
92+
93+
float3 color = input.coarseVertex.color;
94+
float2 uv = input.coarseVertex.uv;
95+
output.fragment.color = float4(color, 1.0);
96+
97+
float4 val = 0.0;
98+
val += t1D.Sample(samplerState, uv.x);
99+
val += t2D.Sample(samplerState, uv);
100+
val += t3D.Sample (samplerState, float3(uv, 0.5));
101+
102+
val += t2dArray.Sample(samplerState, float3(uv, 0.0));
103+
104+
val += tCubeArray.Sample(samplerState, float4(uv, 0.5, 0.0));
105+
val += tCube.Sample(samplerState, float3(uv, 0.5));
106+
107+
val += t2D.Load(int3(0));
108+
val += t2dArray.Load(int4(0));
109+
110+
val += t3D[int3(0)];
111+
112+
outputBuffer[0] = val.x;
113+
114+
int w, h, l, lods;
115+
t2dArray.GetDimensions(0, w, h, l, lods);
116+
outputBuffer[1] = w + h + l + lods;
117+
return output;
118+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type: float
2+
9.000000
3+
13.000000
4+
0.000000
5+
0.000000

0 commit comments

Comments
 (0)