Skip to content

Commit 187ec44

Browse files
jkwak-workjsmall-zzzslangbotcsyonghe
authored
Support for dynamic array of textures access for Texture footprint. (#6392)
* Support for dynamic array of textures access for Texture footprint. * Do a check for DXIL for dynamic array/footprint. * format code (#40) --------- Co-authored-by: jsmall-nvidia <jsmall@nvidia.com> Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: Yong He <yonghe@outlook.com>
1 parent 0460eb6 commit 187ec44

File tree

2 files changed

+188
-1
lines changed

2 files changed

+188
-1
lines changed

source/slang/slang-ir-lower-binding-query.cpp

+112-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,118 @@ struct BindingQueryLoweringContext : public WorkListPass
288288
//
289289
OpaqueValueInfo computeOpaqueValueInfo(IRInst* opaqueValue)
290290
{
291-
if (auto globalParam = as<IRGlobalParam>(opaqueValue))
291+
if (auto getElement = as<IRGetElement>(opaqueValue))
292+
{
293+
IRInst* baseInst = getElement->getBase();
294+
IRInst* indexInst = getElement->getIndex();
295+
296+
IRInst* elementType = getElement->getDataType();
297+
298+
// TODO(JS): This a hack to make this work for arrays of resource type.
299+
// It won't work in the general case as it stands because we would need
300+
// to propogate layout kind types needed at usage sites.
301+
// Without knowing the resource kind that is being processed it's not possible
302+
// to accumulate the calculation.
303+
//
304+
// So presumably we need to request a binding query for a specific resource kind.
305+
// We could do this by making the type of the binding query hold the type.
306+
307+
// We need to add instructions which will work out the binding for the base
308+
OpaqueValueInfo baseInfo = findOrComputeOpaqueValueInfo(baseInst);
309+
310+
// If we couldn't find it we are done
311+
if (baseInfo.registerIndex == nullptr || baseInfo.registerSpace == nullptr)
312+
{
313+
return baseInfo;
314+
}
315+
316+
317+
LayoutResourceKind kind = LayoutResourceKind::None;
318+
Index stride = 1;
319+
320+
if (auto resourceType = as<IRResourceType>(elementType))
321+
{
322+
const auto shape = resourceType->getShape();
323+
324+
switch (shape)
325+
{
326+
case SLANG_TEXTURE_1D:
327+
case SLANG_TEXTURE_2D:
328+
case SLANG_TEXTURE_3D:
329+
case SLANG_TEXTURE_CUBE:
330+
case SLANG_STRUCTURED_BUFFER:
331+
case SLANG_BYTE_ADDRESS_BUFFER:
332+
case SLANG_TEXTURE_BUFFER:
333+
{
334+
const auto access = resourceType->getAccess();
335+
bool isReadOnly = (access == SLANG_RESOURCE_ACCESS_READ);
336+
337+
kind = isReadOnly ? LayoutResourceKind::ShaderResource
338+
: LayoutResourceKind::UnorderedAccess;
339+
break;
340+
}
341+
default:
342+
break;
343+
}
344+
}
345+
else if (as<IRSamplerStateTypeBase>(elementType))
346+
{
347+
kind = LayoutResourceKind::SamplerState;
348+
}
349+
else if (as<IRConstantBufferType>(elementType))
350+
{
351+
kind = LayoutResourceKind::ConstantBuffer;
352+
}
353+
354+
if (kind == LayoutResourceKind::None)
355+
{
356+
// Can't determine the kind
357+
return OpaqueValueInfo();
358+
}
359+
360+
// If the element type has type layout we can try and use that
361+
if (auto layoutDecoration = elementType->findDecoration<IRLayoutDecoration>())
362+
{
363+
// We have to calculate
364+
if (auto elementTypeLayout = as<IRTypeLayout>(layoutDecoration->getLayout()))
365+
{
366+
IRTypeSizeAttr* sizeAttr = elementTypeLayout->findSizeAttr(kind);
367+
sizeAttr = sizeAttr ? sizeAttr
368+
: elementTypeLayout->findSizeAttr(
369+
LayoutResourceKind::DescriptorTableSlot);
370+
371+
if (!sizeAttr)
372+
{
373+
// Couldn't work it out
374+
return OpaqueValueInfo();
375+
}
376+
377+
// TODO(JS): Perhaps we have to do something else if not finite?
378+
stride = sizeAttr->getFiniteSize();
379+
}
380+
}
381+
382+
SLANG_UNUSED(indexInst);
383+
384+
// Okay we need to create an instruction which is
385+
// base + stride * index
386+
387+
IRBuilder builder(module);
388+
389+
builder.setInsertBefore(opaqueValue);
390+
391+
auto calcRegisterInst = builder.emitAdd(
392+
indexType,
393+
builder.emitMul(indexType, builder.getIntValue(indexType, stride), indexInst),
394+
baseInfo.registerIndex);
395+
396+
OpaqueValueInfo finalInfo;
397+
finalInfo.registerIndex = calcRegisterInst;
398+
finalInfo.registerSpace = baseInfo.registerSpace;
399+
400+
return finalInfo;
401+
}
402+
else if (auto globalParam = as<IRGlobalParam>(opaqueValue))
292403
{
293404
// The simple/base case is when we have a global shader
294405
// parameter that has layout information attached.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//DISABLE_TEST:SIMPLE:-target dxil-assembly -entry fragmentMain -profile sm_6_5 -stage fragment -DNV_SHADER_EXTN_SLOT=u0
2+
3+
//TEST:SIMPLE(filecheck=SPIRV):-target spirv-assembly -entry fragmentMain -stage fragment
4+
//TEST:SIMPLE(filecheck=DXIL):-target dxil-assembly -entry fragmentMain -profile sm_6_5 -stage fragment -DNV_SHADER_EXTN_SLOT=u0
5+
//TEST:SIMPLE(filecheck=HLSL):-target hlsl -entry fragmentMain -stage fragment
6+
7+
//DISABLED_TEST:SIMPLE:-target spirv-assembly -entry fragmentMain -stage fragment
8+
//DISABLED_TEST:SIMPLE:-target dxil-assembly -entry fragmentMain -stage fragment
9+
//DISABLED_TEST:SIMPLE:-target hlsl -entry fragmentMain -stage fragment
10+
11+
uniform Texture2D textures[] : register(t2, space10);
12+
uniform SamplerState sampler;
13+
uniform RWStructuredBuffer<uint> outputBuffer;
14+
15+
static Texture2D _getBindlessTexture2d(uint texIdx)
16+
{
17+
return textures[NonUniformResourceIndex(texIdx)];
18+
}
19+
20+
void accumulate(inout uint r, uint u)
21+
{
22+
r = r ^ u;
23+
}
24+
25+
void accumulate(inout uint r, bool b)
26+
{
27+
accumulate(r, uint(b));
28+
}
29+
30+
void accumulate(inout uint r, uint2 u)
31+
{
32+
accumulate(r, u.x);
33+
accumulate(r, u.y);
34+
}
35+
36+
void accumulate(inout uint r, uint3 u)
37+
{
38+
accumulate(r, u.x);
39+
accumulate(r, u.y);
40+
accumulate(r, u.z);
41+
}
42+
43+
void accumulate(inout uint r, TextureFootprint2D f)
44+
{
45+
accumulate(r, f.anchor);
46+
accumulate(r, f.offset);
47+
accumulate(r, f.mask);
48+
accumulate(r, f.lod);
49+
accumulate(r, f.granularity);
50+
accumulate(r, f.isSingleLevel);
51+
}
52+
53+
cbuffer Uniforms
54+
{
55+
uniform float2 coords;
56+
uniform uint granularity;
57+
};
58+
59+
void fragmentMain(
60+
float v : VARYING)
61+
{
62+
uint index = uint(v);
63+
uint r = 0;
64+
65+
accumulate(r, _getBindlessTexture2d(index).queryFootprintCoarse(granularity, sampler, coords));
66+
67+
// SPIRV: Extension "SPV_NV_shader_image_footprint"
68+
// SPIRV: ImageSampleFootprintNV
69+
70+
// DXIL: struct struct.NvShaderExtnStruct
71+
72+
// HLSL: NvFootprintCoarse
73+
74+
outputBuffer[index] = r;
75+
}
76+

0 commit comments

Comments
 (0)