summaryrefslogtreecommitdiffstats
path: root/tests/metal/parameter-block.slang
blob: 75127f4606f1bba58b06952fa802169cfac8ac14 (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
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
//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -target metal
//TEST:SIMPLE(filecheck=CHECK-ASM): -stage compute -entry computeMain -target metallib

// This test verifies that resource types within structs and arrays
// are preserved in Metal. This is done by lowering resource tyeps into
// descriptor handle types during lower-buffer-element-type pass.

struct Val
{
    RWStructuredBuffer<float> buffer;
}

struct Val_f
{
    float f;
}

struct ResourceStruct {
    RWStructuredBuffer<float> buffer;
    Texture2D<float4> texture;
}

struct NestedStruct {
    Array<ResourceStruct, 2> resources;
    ResourceStruct resource;
    int padding;
}

struct ComplexStruct {
    Array<NestedStruct, 3> nested;
    RWStructuredBuffer<float> directBuffer;
}

struct ParentStruct {
    struct ChildStruct {
        Texture2D<float> texture;
        int i;
        float f;
    } c;

    Array<Texture2D<float>, 2> tex_array;
}

struct OtherParent {
      ParentStruct::ChildStruct c2;
}

struct StructWithParameterBlock {
    RWStructuredBuffer<float> buffer;
    ParameterBlock<Array<Val, 2>> arr;
}

uniform StructWithParameterBlock struct_with_parameter_block;


// Test various parameter block configurations
ParameterBlock<ResourceStruct> simpleBlock;
ParameterBlock<Array<ResourceStruct, 4>> arrayBlock; 
ParameterBlock<NestedStruct> nestedBlock;
ParameterBlock<ComplexStruct> complexBlock;
ParameterBlock<Array<ComplexStruct, 2>> arrayComplexBlock;
ParameterBlock<ParentStruct> parentBlock;

ParameterBlock<RWStructuredBuffer<Val_f>> valBlock;


RWStructuredBuffer<float> outputBuffer;

void func(ParentStruct::ChildStruct c) {
    outputBuffer[0] = c.texture.Load(int3(0));
    Texture2D<float> tex = c.texture;
    outputBuffer[0] = tex.Load(int3(0));

}

void func2(ParentStruct p) {
    Array<Texture2D<float>, 2> tex_array_local = p.tex_array;
    outputBuffer[1] = tex_array_local[0].Load(int3(0));
    outputBuffer[2] = p.c.texture.Load(int3(3));
}

void func3(Array<Texture2D<float>, 2> arr) {
    outputBuffer[3] = arr[0].Load(int3(0));
}

void func4(ParameterBlock<ParentStruct> block) {
    ParentStruct p = block;
    outputBuffer[8] = p.c.texture.Load(int3(0));
}

// CHECK-ASM: {{.*}} @computeMain
[numthreads(1, 1, 1)]
void computeMain(uint3 tid: SV_DispatchThreadID)
{

    // CHECK: {{.*}}->buffer{{.*}}
    outputBuffer[0] = simpleBlock.buffer[0];
    
    // CHECK: arrayBlock{{.*}}->data{{.*}}[int(1)].buffer
    ResourceStruct fromArray = arrayBlock[1];
    outputBuffer[1] = fromArray.buffer[1];
        
    // CHECK: complexBlock{{.*}}->nested{{.*}}->data{{.*}}[int(1)])->resources{{.*}})->data{{.*}}[int(1)])->buffer{{.*}}
    outputBuffer[3] = complexBlock.nested[1].resources[1].buffer[3];
    
    // CHECK: {{.*}}arrayComplexBlock{{.*}}->data{{.*}}[int(0)])->nested{{.*}})->data{{.*}}[int(2)])->resources{{.*}})->data{{.*}}[int(0)].buffer
    ComplexStruct complexFromArray = arrayComplexBlock[0];
    outputBuffer[4] = complexFromArray.nested[2].resources[0].buffer[4];
    
    // CHECK: {{.*}}->directBuffer{{.*}}
    outputBuffer[5] = complexBlock.directBuffer[5];
    
    // Test parameter block accessed via a local variable
    // CHECK: nestedBlock{{.*}}->resource{{.*}}.buffer_0
    ResourceStruct resStruct = nestedBlock.resource;
    outputBuffer[6] = resStruct.buffer[2];

    // CHECK: {{.*}}valBlock{{.*}}
    outputBuffer[7] = valBlock[0].f;

    // Test parameter block inside a struct
    // CHECK: {{.*}}struct_with_parameter_block_arr{{.*}}
    StructWithParameterBlock local = struct_with_parameter_block;
    outputBuffer[8] = local.arr[0].buffer[0];

    // Test function with parameter block containing a struct with a resource type
    func(parentBlock.c);

    // Test function with a copy of the parameter block
    OtherParent other_p;
    other_p.c2 = parentBlock.c;
    func(other_p.c2);

    ParentStruct p;
    p = parentBlock;
    func2(p);

    // Test function with a field from the parameter block
    func3(p.tex_array);

    // Test function with a parameter block in the function signature
    func4(parentBlock);
}