summaryrefslogtreecommitdiffstats
path: root/tests/reflection/buffer-layout.slang
blob: b2cc3f72422fdac77c4754bac35dffe916540ad4 (plain)
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
// buffer-layout.slang

// This test mirrors `tests/compute/buffer-layout.slang`, and it meant
// to confirm that our reflection logic correctly reports the offsets
// that the compute test sees in practice.

//TEST:REFLECTION:-stage compute -entry main -target hlsl -no-codegen
//TEST:REFLECTION:-stage compute -entry main -target spirv -no-codegen

struct A
{
    float x;
    float y;
}

struct S
{
    // The first field in a struct isn't going to be that
    // interesting, because it will always get offset zero,
    // so we just use this to establish a poorly-aligned
    // starting point for the next field.
    //
    //          offset  size    alignment
    //
    //          0       4       4
    //
    float z;

    // The `std140` and D3D constant buffer ruless both
    // ensure a minimum of 16-byte alignment on `struct`
    // types, but differ in that D3D does not round up
    // the total size of a type to its alignment.
    //
    // The `std430` and structured buffer rules don't
    // perform any over-alignment on `struct` types and
    // instead align them using the "natural" rules one
    // might expect of, e.g., a C compiler.
    //
    //          offset  size    alignment
    //
    // cbuffer  16      8       16
    // std140   16      16      16
    //
    // struct   4       8       4
    // std430   4       8       4
    //
    A      a;

    // Now we insert an ordinary `int` field just as
    // a way to probe the offset so far.
    //
    //          offset  size    alignment
    //
    // cbuffer  24      4       4
    // std140   32      4       4
    //
    // struct   12      4       4
    // std430   12      4       4
    //
    int    b;

    // As our next stress-test case, we will insert an
    // array with elements that aren't a multiple of
    // 16 bytes in size.
    //
    // The contant/uniform buffer rules will set the
    // array stride to a multiple of 16 bytes in this case.
    // The only difference between D3D rules and `std140`
    // here is that D3D does not round up the size to
    // the alignment.
    //
    // The structured/std430 rules don't do anything
    // to over-align an array, so it is laid out relatively
    // naturally, but note that D3D still follows its rule
    // of not letting a vector "straddle" a 16-byte boundary,
    // even if it doesn't bump up the alignment of
    // vector types.
    //
    //          offset  size    alignment
    //
    // cbuffer  32      24      16
    // std140   48      32      32
    //
    // struct   16      16      4
    // std430   16      16      8
    //
    float2 c[2];

    // Now we put in one more ordinary `int` field
    // just to probe the offset computed so far.
    //          offset  size    alignment
    //
    // cbuffer  56      4      4
    // std140   80      4      4
    //
    // struct   32      4      4
    // std430   32      4      4
    //
    int    d;
}

ConstantBuffer<S> cb;
RWStructuredBuffer<S> sb;

[numthreads(1, 1, 1)]
void main(
    uint3 dispatchThreadID : SV_DispatchThreadID)
{
}