Commit 5353bc5
authored
Add bindless resource metadata usage query (#11436)
Fixes #10439
## Motivation
`ShaderReflection::getBindlessSpaceIndex()` reports a layout
reservation, not final
target-code usage. Since bindless space allocation moved into frontend
layout, a shader
can keep a non-negative bindless space index even when later
optimization removes every
descriptor-handle heap path. A host that treats `getBindlessSpaceIndex()
>= 0` as "bind
the descriptor heap" can therefore do unnecessary bindless setup for
ordinary shaders.
The motivating shape is a compute shader with only ordinary resources,
such as
`RWStructuredBuffer` inputs and outputs, or a shader that declares a
`DescriptorHandle`
inside a parameter block but never reads it. Both shapes can reserve a
bindless space in
layout while producing target IR with no surviving bindless heap use.
## Proposed solution
Add `slang::IBindlessResourceMetadata` as a side interface on emitted
artifact metadata.
Callers keep using `getBindlessSpaceIndex()` to learn which space layout
reserved, then
cast target metadata to `IBindlessResourceMetadata` and call
`usesBindlessResourceHeap()` to learn whether the compiled target IR
still contains a
descriptor-handle or bindless resource path.
This keeps the public `IMetadata` vtable stable by adding a separate
castable interface
instead of appending methods to `IMetadata`. It also keeps the usage
query tied to the
late IR that code generation actually sees, rather than inferring usage
from frontend
syntax or from the existence of a layout reservation.
## Change summary
- Public API: `include/slang.h:3735` and
`include/slang-deprecated.h:1054`
clarify that `getBindlessSpaceIndex()` reports reserved layout space.
The new
`IBindlessResourceMetadata` interface and `usesBindlessResourceHeap()`
query are
declared in `include/slang.h:4549`.
- Metadata object: `ArtifactPostEmitMetadata` implements
`IBindlessResourceMetadata`, exposes it from `getInterface()`, and
stores
`m_usesBindlessResourceHeap` in
`source/compiler-core/slang-artifact-associated-impl.h:221` and
`source/compiler-core/slang-artifact-associated-impl.cpp:292`.
- Metadata collection: `collectMetadata()` now takes `TargetProgram*`,
obtains the
existing layout with `TargetProgram::getExistingLayout()`, scans final
IR with
`doesInstAndChildrenUseBindlessResourceHeap()`, and stores the result in
`source/slang/slang-ir-metadata.cpp:278`.
- Bindless heap detection: `_isBindlessResourceHeapGlobalParam()`
identifies the
lowered synthetic heap from its unbounded descriptor-table layout in the
reserved
bindless space, and `_instUsesBindlessResourceHeap()` recognizes the
descriptor-heap
opcodes and descriptor-handle cast opcodes in
`source/slang/slang-ir-metadata.cpp:122`
and `source/slang/slang-ir-metadata.cpp:157`.
- Dynamic heap lowering: `getBindlessSpaceIndex()` now asserts that
layout exists and
that it reserved a bindless space before `lowerDynamicResourceHeap()`
synthesizes the
heap global in
`source/slang/slang-ir-lower-dynamic-resource-heap.cpp:16`.
- Emit pipeline: `linkAndOptimizeIR()` realizes layout before post-emit
metadata for
descriptor-handle-capable non-PyTorch targets, then calls
`collectMetadata()` in
`source/slang/slang-emit.cpp:2411`.
- Tests and docs: bindless metadata coverage lives in
`tools/slang-unit-test/unit-test-bindless-space-reflection.cpp:200`,
vtable
stability coverage for the new interface is in
`tools/slang-unit-test/unit-test-vtable-stability.cpp:918`, IR metadata
checks are in
`tests/language-feature/descriptor-handle/`, and user-facing docs are
updated in
`docs/user-guide/09-reflection.md:1568` and
`docs/user-guide/03-convenience-features.md:672`.
## Concepts and vocabulary
- Bindless space index: the descriptor set or register space reserved by
program layout
for Slang's bindless resource heap. It is intentionally stable and can
survive even
when final target code does not use the heap.
- Bindless resource heap usage: a post-lowering code-generation signal
that final IR
still contains descriptor-handle, descriptor-heap, or lowered synthetic
heap access.
- Synthetic resource heap global: the global parameter created by
`lowerDynamicResourceHeap()` after it replaces `GetDynamicResourceHeap`.
Metadata must
identify it from semantic layout data, not only from a name hint.
## Process report
The API change separates layout reservation from target-code usage. The
old public
contract encouraged hosts to infer runtime heap setup from
`ShaderReflection::getBindlessSpaceIndex()`. That is not precise after
frontend layout
starts reserving bindless space before optimization, so this PR
documents the old query
as a layout signal in `include/slang.h:3735` and adds the target
metadata side query in
`include/slang.h:4549`.
The metadata implementation uses a side interface because `IMetadata` is
already a
public COM-style interface. `ArtifactPostEmitMetadata` inherits
`IBindlessResourceMetadata` in
`source/compiler-core/slang-artifact-associated-impl.h:221`
and returns it from `getInterface()` in
`source/compiler-core/slang-artifact-associated-impl.cpp:292`; this
makes
`metadata->castAs(IBindlessResourceMetadata::getTypeGuid())` the
extension mechanism
without changing existing `IMetadata` slots.
The usage bit is computed in `collectMetadata()` after target-specific
lowering, in
`source/slang/slang-ir-metadata.cpp:278`. The scan first asks the target
program for an
existing layout; when no layout exists, `bindlessSpaceIndex` remains
`-1` and the
bindless scan is skipped. That no-layout shape is intentional for
targets such as
PyTorch binding emission, where forcing layout solely for metadata would
be the wrong
layer. For descriptor-handle-capable non-PyTorch targets,
`source/slang/slang-emit.cpp:2411`
realizes layout before metadata so the reserved bindless space is
available.
The synthetic heap-global case is handled by layout, not by a new IR
marker. After
`lowerDynamicResourceHeap()` replaces `GetDynamicResourceHeap` with a
global parameter,
opcode scanning alone can no longer see the original intrinsic. The
helper at
`source/slang/slang-ir-metadata.cpp:122` identifies that global only
when it has an
infinite `DescriptorTableSlot` layout in the reserved bindless space.
That keeps normal
user-declared unbounded resource arrays from being mistaken for Slang's
heap, including
the case where the user array occupies the originally requested bindless
space and
layout moves the system heap to another space.
The opcode scan at `source/slang/slang-ir-metadata.cpp:157` covers
target-independent
heap loads, SPIR-V descriptor heap operations, texel-pointer heap
operations, and
descriptor-handle cast opcodes that can survive to emit for native
targets. The scan is
recursive via `doesInstAndChildrenUseBindlessResourceHeap()` in
`source/slang/slang-ir-metadata.cpp:188`, so handle usage inside helper
functions is
covered directly through instruction children.
The dynamic-resource-heap lowering path now treats layout as its
contract. The helper at
`source/slang/slang-ir-lower-dynamic-resource-heap.cpp:16` asserts that
`TargetProgram`
and its existing layout are present, and that the layout reserved a
bindless space. The
pass still returns early at
`source/slang/slang-ir-lower-dynamic-resource-heap.cpp:59`
when there are no `GetDynamicResourceHeap` instructions, so targets
without heap work do
not pay the capability or layout checks.
The tests exercise the truth table that motivated the fix. The shared
unit-test helper
casts target metadata and checks both layout reservation and
`usesBindlessResourceHeap()` in
`tools/slang-unit-test/unit-test-bindless-space-reflection.cpp:200`.
Negative cases cover
ordinary resources, dead descriptor handles, no reserved space,
unbounded user arrays,
and metadata queried before explicit layout. Positive cases cover SPIR-V
descriptor heap
paths, SPIR-V NV paths, WGSL dynamic resource heap, HLSL resource and
sampler handles,
native handle casts, texel-pointer heap usage, stripped name hints, and
helper-function
handle use. The vtable probe in
`tools/slang-unit-test/unit-test-vtable-stability.cpp:918`
pins the new side interface slot.
## Reviewer Directives (maintained by agent)
- [human @jkwak-work] Avoid a dedicated `BindlessResourceHeapDecoration`
and module-version bump when existing layout metadata can identify the
lowered resource heap; only reintroduce a marker if the existing layout
signal proves insufficient.
(#11436 (comment))
- [human @jkwak-work] Treat `CastDescriptorHandleToResource` as
`usesBindlessResourceHeap()` usage unconditionally, regardless of target
or capability. This supersedes the earlier SPIR-V `spvBindlessTextureNV`
gating directive.
(#11436 (comment))
- [human @jkwak-work] Keep `collectMetadata` generic by passing
`TargetProgram*` rather than bindless-specific parameters, and avoid
requiring information from `TargetRequest` for the bindless metadata
query.
(#11436 (comment))
- [human @jkwak-work] Use `TargetProgram::getExistingLayout()` directly
as the optional layout probe for metadata; do not keep a separate
`hasExistingLayout()` accessor. Dynamic-resource-heap lowering should
assert its required layout/bindless-space invariants inside
`getBindlessSpaceIndex()`.
(#11436 (comment))
- [human @jkwak-work] Keep the dynamic-resource-heap bindless-space
helper returning `UInt`, and assert required layout/bindless-space
invariants inside the helper instead of returning a nullable/boolean
result.
(#11436 (comment))
- [human @jkwak-work] Do not call helper functions such as
`getBindlessSpaceIndex()` inside assertion expressions; compute the
result first and assert the stored value when a caller-side assertion is
needed.
(#11436 (comment))
- [human @jkwak-work] Treat `bindlessSpaceIndex >= 0` as a caller
contract for bindless heap global-param detection: callers should
early-out when no bindless space is reserved, and the helper should
assert the invariant with `SLANG_ASSERT(bindlessSpaceIndex >= 0)`.
(#11436 (comment),
#11436 (comment))
- [human @csyonghe] Use direct recursive instruction-child traversal for
the bindless metadata scan, name the helper
`doesInstAndChildrenUseBindlessResourceHeap()`, and include comments
explaining the synthetic heap/global and cast-opcode detection.
(#11436 (comment),
#11436 (comment),
#11436 (comment))
- [bot github-actions] For post-emit bindless metadata, keep
`collectMetadata` generic over `TargetProgram*`:
descriptor-handle-capable targets may realize layout before metadata,
but targets without an existing layout use `bindlessSpaceIndex == -1`;
do not force layout for PyTorch binding emission just to collect
bindless metadata.
(#11436 (comment))1 parent 4f56990 commit 5353bc5
16 files changed
Lines changed: 878 additions & 46 deletions
File tree
- docs/user-guide
- include
- source
- compiler-core
- slang
- tests/language-feature/descriptor-handle
- tools/slang-unit-test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
668 | 668 | | |
669 | 669 | | |
670 | 670 | | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
671 | 677 | | |
672 | 678 | | |
673 | 679 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1564 | 1564 | | |
1565 | 1565 | | |
1566 | 1566 | | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
1567 | 1595 | | |
1568 | 1596 | | |
1569 | 1597 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1047 | 1047 | | |
1048 | 1048 | | |
1049 | 1049 | | |
1050 | | - | |
1051 | | - | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
1052 | 1059 | | |
1053 | 1060 | | |
1054 | 1061 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3759 | 3759 | | |
3760 | 3760 | | |
3761 | 3761 | | |
3762 | | - | |
3763 | | - | |
| 3762 | + | |
| 3763 | + | |
| 3764 | + | |
| 3765 | + | |
| 3766 | + | |
| 3767 | + | |
| 3768 | + | |
| 3769 | + | |
| 3770 | + | |
3764 | 3771 | | |
3765 | 3772 | | |
3766 | 3773 | | |
| |||
4566 | 4573 | | |
4567 | 4574 | | |
4568 | 4575 | | |
| 4576 | + | |
| 4577 | + | |
| 4578 | + | |
| 4579 | + | |
| 4580 | + | |
| 4581 | + | |
| 4582 | + | |
| 4583 | + | |
| 4584 | + | |
| 4585 | + | |
| 4586 | + | |
| 4587 | + | |
| 4588 | + | |
| 4589 | + | |
| 4590 | + | |
| 4591 | + | |
| 4592 | + | |
| 4593 | + | |
| 4594 | + | |
| 4595 | + | |
| 4596 | + | |
| 4597 | + | |
| 4598 | + | |
| 4599 | + | |
| 4600 | + | |
| 4601 | + | |
| 4602 | + | |
| 4603 | + | |
| 4604 | + | |
| 4605 | + | |
| 4606 | + | |
| 4607 | + | |
| 4608 | + | |
4569 | 4609 | | |
4570 | 4610 | | |
4571 | 4611 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
289 | 289 | | |
290 | 290 | | |
291 | 291 | | |
| 292 | + | |
| 293 | + | |
292 | 294 | | |
293 | 295 | | |
294 | 296 | | |
| |||
356 | 358 | | |
357 | 359 | | |
358 | 360 | | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
359 | 366 | | |
360 | 367 | | |
361 | 368 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
220 | 220 | | |
221 | 221 | | |
222 | 222 | | |
| 223 | + | |
223 | 224 | | |
224 | 225 | | |
225 | 226 | | |
| |||
249 | 250 | | |
250 | 251 | | |
251 | 252 | | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
252 | 256 | | |
253 | 257 | | |
254 | 258 | | |
| |||
299 | 303 | | |
300 | 304 | | |
301 | 305 | | |
| 306 | + | |
302 | 307 | | |
303 | 308 | | |
304 | 309 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
2516 | 2517 | | |
2517 | 2518 | | |
2518 | 2519 | | |
2519 | | - | |
| 2520 | + | |
| 2521 | + | |
| 2522 | + | |
| 2523 | + | |
| 2524 | + | |
| 2525 | + | |
| 2526 | + | |
| 2527 | + | |
| 2528 | + | |
| 2529 | + | |
| 2530 | + | |
2520 | 2531 | | |
2521 | 2532 | | |
2522 | 2533 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
25 | 21 | | |
26 | | - | |
27 | | - | |
28 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
29 | 27 | | |
30 | 28 | | |
31 | 29 | | |
| |||
58 | 56 | | |
59 | 57 | | |
60 | 58 | | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
61 | 62 | | |
62 | 63 | | |
63 | | - | |
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
118 | 119 | | |
119 | 120 | | |
120 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
121 | 204 | | |
122 | 205 | | |
123 | 206 | | |
| |||
190 | 273 | | |
191 | 274 | | |
192 | 275 | | |
193 | | - | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
194 | 280 | | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
195 | 289 | | |
196 | 290 | | |
| 291 | + | |
197 | 292 | | |
198 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
199 | 300 | | |
200 | 301 | | |
201 | 302 | | |
| |||
216 | 317 | | |
217 | 318 | | |
218 | 319 | | |
| 320 | + | |
219 | 321 | | |
220 | 322 | | |
221 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
21 | 25 | | |
22 | 26 | | |
0 commit comments