1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// slang-ir-metadata.cpp
#include "slang-ir-metadata.h"
#include "../compiler-core/slang-artifact-associated-impl.h"
#include "slang-ir-insts.h"
#include "slang-ir.h"
namespace Slang
{
// This file currently implements a pass that collects information about the shader parameters that
// are referenced in the IR. It's named 'metadata' in order to support other potential code
// analysis scenarios in the future.
// Inserts a single resource binding (which takes `count` slots, where 0 means unbounded) into the
// list of resource ranges.
static void _insertBinding(
List<ShaderBindingRange>& ranges,
LayoutResourceKind kind,
UInt spaceIndex,
UInt registerIndex,
UInt count)
{
// Construct a new range from the provided resource.
ShaderBindingRange newRange;
newRange.category = kind;
newRange.spaceIndex = spaceIndex;
newRange.registerIndex = registerIndex;
newRange.registerCount = count;
// See if the new range is adjacent to any of the existing ranges, merge with that.
for (auto& range : ranges)
{
if (range.adjacentTo(newRange))
{
range.mergeWith(newRange);
return;
}
}
// No adjacent ranges found - create a new one.
ranges.add(newRange);
}
void collectMetadataFromInst(IRInst* param, ArtifactPostEmitMetadata& outMetadata)
{
auto layoutDecoration = param->findDecoration<IRLayoutDecoration>();
if (!layoutDecoration)
return;
auto varLayout = as<IRVarLayout>(layoutDecoration->getLayout());
if (!varLayout)
return;
UInt spaceOffset = 0;
if (auto spaceAttr = varLayout->findOffsetAttr(LayoutResourceKind::RegisterSpace))
{
spaceOffset = spaceAttr->getOffset();
}
for (auto sizeAttr : varLayout->getTypeLayout()->getSizeAttrs())
{
auto kind = sizeAttr->getResourceKind();
// Only track resource types that we can reliably track, such as textures.
// Do not track individual uniforms, for example.
if (!ShaderBindingRange::isUsageTracked(kind))
continue;
if (auto offsetAttr = varLayout->findOffsetAttr(kind))
{
// Get the binding information from this attribute and insert it into the list
auto spaceIndex = spaceOffset + offsetAttr->getSpace();
auto registerIndex = offsetAttr->getOffset();
auto size = sizeAttr->getSize();
auto count = size.isFinite() ? size.getFiniteValue() : 0;
_insertBinding(outMetadata.m_usedBindings, kind, spaceIndex, registerIndex, count);
}
}
// If the global parameter is a parameter block, make sure to collect bindings for its
// default constant buffer, if there is one.
// The default constant buffer binding will be represented in the container var layout.
//
auto paramGroupTypeLayout = as<IRParameterGroupTypeLayout>(varLayout->getTypeLayout());
if (!paramGroupTypeLayout)
return;
auto containerVarLayout = paramGroupTypeLayout->getContainerVarLayout();
if (!containerVarLayout)
return;
auto containerSpaceOffset =
varLayout->findOffsetAttr(LayoutResourceKind::SubElementRegisterSpace);
if (!containerSpaceOffset)
return;
spaceOffset += containerSpaceOffset->getOffset();
for (auto sizeAttr : containerVarLayout->getTypeLayout()->getSizeAttrs())
{
auto kind = sizeAttr->getResourceKind();
if (!ShaderBindingRange::isUsageTracked(kind))
continue;
if (auto offsetAttr = containerVarLayout->findOffsetAttr(kind))
{
auto spaceIndex = spaceOffset + offsetAttr->getSpace();
auto registerIndex = offsetAttr->getOffset();
auto size = sizeAttr->getSize();
auto count = size.isFinite() ? size.getFiniteValue() : 0;
_insertBinding(outMetadata.m_usedBindings, kind, spaceIndex, registerIndex, count);
}
}
}
// Collects the metadata from the provided IR module, saves it in outMetadata.
void collectMetadata(const IRModule* irModule, ArtifactPostEmitMetadata& outMetadata)
{
// Scan the instructions looking for global resource declarations
// and exported functions.
for (const auto& inst : irModule->getGlobalInsts())
{
if (auto func = as<IRFunc>(inst))
{
if (func->findDecoration<IRDownstreamModuleExportDecoration>())
{
auto name = func->findDecoration<IRExportDecoration>()->getMangledName();
outMetadata.m_exportedFunctionMangledNames.add(name);
}
// Collect metadata from entrypoint params.
for (auto param : func->getParams())
{
collectMetadataFromInst(param, outMetadata);
}
}
auto param = as<IRGlobalParam>(inst);
if (!param)
continue;
collectMetadataFromInst(param, outMetadata);
}
}
} // namespace Slang
|