|
| 1 | +<!-- {% raw %} --> |
| 2 | + |
| 3 | +# Refined `cbuffer` Contexts |
| 4 | + |
| 5 | +## Instructions |
| 6 | + |
| 7 | +* Proposal: [NNNN](NNNN-cbuffer-contexts.md) |
| 8 | +* Author(s): [Chris Bieneman](https://github.com/llvm-beanz), [Helena Kotas](https://github.com/hekota) |
| 9 | +* Sponsor: TBD |
| 10 | +* Status: **Under Consideration** |
| 11 | +* Planned Version: 202x |
| 12 | +* Issues: [DXC #4514](https://github.com/microsoft/DirectXShaderCompiler/issues/4514) |
| 13 | + |
| 14 | +## Introduction |
| 15 | + |
| 16 | +This proposal aligns `cbuffer` declarations more closely with syntactic and |
| 17 | +semantic behaviors that are common in C and C++ to align more closely with user |
| 18 | +expectation and reduce the need for special case handling in the compiler. |
| 19 | + |
| 20 | +## Motivation |
| 21 | + |
| 22 | +The HLSL `cbuffer` declaration is a source of irregularity within the language |
| 23 | +semantics, and the interaction between `cbuffer` declarations and their |
| 24 | +contained declarations can be different and surprising. |
| 25 | + |
| 26 | +In DXC, declarations inside a `cbuffer` are always hoisted out to translation |
| 27 | +unit scope, which effectively ignores the namespace nesting, however the |
| 28 | +declaration context hierarchy within a `cbuffer` is preserved except again in |
| 29 | +the case of a nested `cbuffer` which pops back out to translation unit scope. |
| 30 | + |
| 31 | +This behavior in DXC is clearly a bug, and FXC behaves more reasonably. As an |
| 32 | +example given the following cbuffer declarations: |
| 33 | + |
| 34 | +```hlsl |
| 35 | +namespace ns { |
| 36 | + cbuffer CB { |
| 37 | + float a; |
| 38 | +
|
| 39 | + namespace ns2 { |
| 40 | + cbuffer CB2 { |
| 41 | + float b; |
| 42 | + } // cbuffer CB2 |
| 43 | + } // namespace ns2 |
| 44 | + } // cbuffer CB |
| 45 | +} // namespace ns |
| 46 | +``` |
| 47 | +[FXC @ ShaderPlayground](https://shader-playground.timjones.io/22396dd8aec3318b3e9a598c612f156e) |
| 48 | +[DXC @ Compiler Explorer](https://godbolt.org/z/WYK7jvvfP) |
| 49 | + |
| 50 | +In DXC, `a` and `b` are referenced directly with no namespace qualifications, |
| 51 | +while in FXC they are `ns::a` and `ns::ns2::b` respectively. |
| 52 | + |
| 53 | +In FXC, `cbuffer` declarations behave more like a source range declaration that |
| 54 | +groups global declarations into a single constant buffer rather than a semantic |
| 55 | +declaration grouping. As such, one could replace the `cbuffer` syntax in FXC |
| 56 | +with a preprocessor `pragma` with `push|pop` semantics that specified which |
| 57 | +buffer and binding to group declarations into. |
| 58 | + |
| 59 | +This design does not follow any pattern common in C or C++, and thus runs |
| 60 | +counter to the [principle of least |
| 61 | +astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment). |
| 62 | + |
| 63 | +## Proposed solution |
| 64 | + |
| 65 | +To simplify HLSL's language semantics and the compiler implementation a new |
| 66 | +grammar formation is adopted for cbuffers: |
| 67 | + |
| 68 | +```latex |
| 69 | +
|
| 70 | +\begin{grammar} |
| 71 | + \define{cbuffer-declaration-group}\br |
| 72 | + \terminal{cbuffer} identifier \opt{resource-binding} \terminal{\{} |
| 73 | + \opt{cbuffer-declaration-seq} \terminal {\}}\br |
| 74 | +
|
| 75 | + \define{cbuffer-declaration-seq}\br |
| 76 | + cbuffer-declaration\br |
| 77 | + cbuffer-declaration-seq cbuffer-declaration\br |
| 78 | +
|
| 79 | + \define{cbuffer-declaration}\br |
| 80 | + variable-declaration\br |
| 81 | + empty-declaration\br |
| 82 | +\end{grammar} |
| 83 | +``` |
| 84 | + |
| 85 | + |
| 86 | +This simplified grammar disallows members of `cbuffer` declarations that do not |
| 87 | +have semantic meaning, and allows a simplification of `cbuffer` scoping rules. |
| 88 | + |
| 89 | +A `cbuffer` may only be declared at translation unit or namespace scope. A |
| 90 | +`cbuffer` may only contain variable (or empty) declarations. All declarations |
| 91 | +within a `cbuffer` declare names in the immediate enclosing scope. |
| 92 | + |
| 93 | +<!-- {% endraw %} --> |
0 commit comments