Skip to content

Commit 48c3aa3

Browse files
authored
Document DXC handling of resources in non-global structs (#374)
Includes examples where a struct with resource is: - declared as static - declared as local variable - used as a function arguments - initialized with an initializer list Part 2 of #175
1 parent 623106e commit 48c3aa3

File tree

1 file changed

+121
-5
lines changed

1 file changed

+121
-5
lines changed

proposals/0038-resources-in-structs.md

Lines changed: 121 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,21 +312,24 @@ https://godbolt.org/z/3TW565acT
312312
#### Example 8
313313

314314
For resources declared at global scope, DXC validates that they fit within the
315-
specified register slots. If they do not fit, an error is reported during
316-
validation, though the error message is cryptic and the source location points
315+
specified register slots. If they do not fit, errors are reported, though the
316+
error messages are not clear and the source location points
317317
to where the resource is first used rather than where it is declared.
318318

319319
```
320320
RWBuffer<float> Buf[10] : register(u4294967293);
321321
322322
[numthreads(4,1,1)]
323323
void main() {
324-
Buf[0][0] = 0;
324+
Buf[0][0] = 0; // line 5
325325
}
326326
```
327327
https://godbolt.org/z/93d317Ej4
328328
```
329-
<source>:12:3: error: Constant values must be in-range for operation.
329+
<source>:5:3: error: Constant values must be in-range for operation.
330+
<source>:5:3: error: Resource handle should returned by createHandle.
331+
<source>:5:13: error: store should be on uav resource.
332+
<source>:5:13: error: buffer load/store only works on Raw/Typed/StructuredBuffer.
330333
```
331334

332335
#### Example 9
@@ -386,6 +389,113 @@ https://godbolt.org/z/Mo8Paoq7G
386389
<source>:5:7: error: register space cannot be specified on global constants.
387390
```
388391

392+
### Static Structs with Resources
393+
394+
Structs with resources can be declared as static. Same as other statically
395+
declared resources, these struct resource members are not automatically bound.
396+
Instead, the user must explicitly initialize them by assigning an existing
397+
resource to the struct member.
398+
399+
#### Example 11
400+
401+
```
402+
struct M {
403+
RWBuffer<float> Bufs[10];
404+
};
405+
406+
RWBuffer<float> GlobalBufs[10];
407+
408+
static M m = { GlobalBufs };
409+
410+
[numthreads(4,4,4)]
411+
void main(uint3 ID : SV_GroupID) {
412+
m.Bufs[ID.y][1] = m.Bufs[ID.x][0];
413+
}
414+
```
415+
https://godbolt.org/z/8fcTfz6d8
416+
417+
Unlike resource arrays in non-static global struct instances, resource arrays
418+
inside static or local struct variables may be dynamically indexable. This is
419+
possible when all resource elements are initialized from a range of the same
420+
dynamically indexable global resource array, as shown in the example above where
421+
`m.Bufs` is initialized from `GlobalBufs`.
422+
423+
### Local variables and Function Parameters
424+
425+
Structs with resources can also be declared as local variables or used as function parameters.
426+
427+
#### Example 12
428+
429+
```
430+
struct N {
431+
RWBuffer<float> Buf;
432+
};
433+
434+
N n : register(u2);
435+
436+
void foo(N paramN, uint i) {
437+
paramN.Buf[i] = 10;
438+
}
439+
440+
[numthreads(4,4,4)]
441+
void main(uint3 ID : SV_GroupID) {
442+
N localN = n;
443+
localN.Buf[10] = 0.13;
444+
foo(localN, ID.x);
445+
}
446+
```
447+
https://godbolt.org/z/eKq3jzM5r
448+
449+
### Initialization list
450+
451+
Local or static declarations of structs with resources can be initialized using
452+
initialized lists.
453+
454+
#### Example 13
455+
456+
```
457+
struct P {
458+
RWBuffer<float> Bufs[4];
459+
};
460+
461+
RWBuffer<float> GlobalBufs[4];
462+
463+
static P p1 = { GlobalBufs };
464+
465+
[numthreads(4,4,4)]
466+
void main(uint3 ID : SV_GroupID) {
467+
P p2 = { GlobalBufs[3], GlobalBufs[2],
468+
GlobalBufs[1], GlobalBufs[0]};
469+
470+
p1.Bufs[ID.y][0] = p2.Bufs[ID.x][0];
471+
}
472+
```
473+
https://godbolt.org/z/zzKe8bjff
474+
475+
### Assignments
476+
477+
Assignment to resource or resource array members of a global non-static structs
478+
is not allowed.
479+
480+
```c++
481+
struct P {
482+
RWBuffer<float> Buf;
483+
};
484+
485+
P p : register(u2);
486+
487+
RWBuffer<float> GlobalBuf;
488+
489+
[numthreads(4,4,4)]
490+
void main(uint3 ID : SV_GroupID) {
491+
p.Buf = GlobalBuf; // error
492+
p.Buf[0] = 10;
493+
}
494+
```
495+
https://godbolt.org/z/f9dd4GYWq
496+
497+
DXC reports an error `cast<X>() argument of incompatible type!`.
498+
389499
### Summary
390500
391501
- DXC supports resources as members of structs, generating global resources
@@ -409,9 +519,15 @@ https://godbolt.org/z/Mo8Paoq7G
409519
- DXC validates register ranges for global resources but does not check for
410520
overflow in struct members, which may result in silently overflow.
411521
522+
- Structs with resources can be declared as static or local variables, used as
523+
function parameters, and initialized with initializer lists.
524+
412525
## Motivation
413526
414-
We need to support resources in structs in Clang.
527+
While resources in structs may not be a widely used HLSL feature, DXC does
528+
support them, and so should the Clang implementation. This also presents an
529+
opportunity to address usability issues, such as the unpredictable implicit
530+
binding order, to make the feature more robust and user-friendly.
415531
416532
## Proposed solution
417533

0 commit comments

Comments
 (0)