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
144
|
// interface-shader-param3.slang
// This test builds on `interface-shader-param2.slang` by putting
// interface types at more complicated places in the overall layout.
//
// NOTE TO SELF:
//
// First issue is that the constant buffer layouts aren't being
// computed correctly for `gStrategy` (even in the previous test),
// so that it doesn't get a `b` register bound.
//
// Second issue is that the type legalization logic is now overzealous,
// and moves the `modifier` member of the entry-point constant buffer
// out to global scope, when it should allocate it inside the constant
// buffer.
//
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
// A lot of the setup is the same as for `interface-shader-param`,
// so look there if you want the comments.
interface IRandomNumberGenerator
{
[mutating]
int randomInt();
}
interface IRandomNumberGenerationStrategy
{
associatedtype Generator : IRandomNumberGenerator;
Generator makeGenerator(int seed);
}
interface IModifier
{
int modify(int val);
}
int test(
int seed,
IRandomNumberGenerationStrategy inStrategy,
IModifier modifier)
{
let strategy = inStrategy;
var generator = strategy.makeGenerator(seed);
let unused = generator.randomInt();
let val = generator.randomInt();
let modifiedVal = modifier.modify(val);
return modifiedVal;
}
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
RWStructuredBuffer<int> gOutputBuffer;
//TEST_INPUT:cbuffer(data=[1 0 0 0], stride=4):dxbinding(0),glbinding(1)
ConstantBuffer<IRandomNumberGenerationStrategy> gStrategy;
[numthreads(4, 1, 1)]
void computeMain(
// We will be declaring two different `uniform` parameters in the
// entry-point parameter list, which will both get allocated to
// the same constant buffer.
//
// The first parameter will use an interface type, while the second
// will be plain-old-data.
//
uniform IModifier modifier,
uniform int extra,
//
// The computed layout for the entry-point constant buffer will
// always place the non-interface-type data first, so the first
// four bytes of our buffer represent the `extra` field.
//
// After all the non-interface-type data is laid out, we lay out
// the contents of extistential value slots in order, using the
// ordinary constant buffer packing rules. Because the concrete
// type we'll be plugging in for `modifier` is a `struct` type,
// it will need to start on a 16-byte-aligned boundary.
//
// Here's the incantation to make the test runner fill in the constant buffer:
//
//TEST_INPUT:cbuffer(data=[256 0 0 0 16 0 0 0], stride=4):dxbinding(1),glbinding(2)
//
// So, the value `256` will be used for `extra` and the value `16`
// will be written to the first four bytes of the concrete value
// being used for `modifier`.
uint3 dispatchThreadID : SV_DispatchThreadID)
{
let tid = dispatchThreadID.x;
let inputVal : int = tid;
let outputVal = test(inputVal, gStrategy, modifier)
+ extra*extra;
gOutputBuffer[tid] = outputVal;
}
// Okay, now we get to the part that is unique starting
// in this test: we add data to the concrete types
// that we will use as parameters.
struct MyStrategy : IRandomNumberGenerationStrategy
{
int globalSeed;
struct Generator : IRandomNumberGenerator
{
int state;
[mutating]
int randomInt()
{
return state++;
}
}
Generator makeGenerator(int seed)
{
Generator generator = { seed ^ globalSeed };
return generator;
}
}
struct MyModifier : IModifier
{
int localModifier;
int modify(int val)
{
return val * localModifier;
}
}
//TEST_INPUT: globalExistentialType MyStrategy
//TEST_INPUT: entryPointExistentialType MyModifier
|