forked from shader-slang/slang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterface-shader-param.slang
139 lines (115 loc) · 3.78 KB
/
interface-shader-param.slang
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
// interface-shader-param.slang
// Test using interface tops as top-level shader parameters
// (whether global, or on an entry point).
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -profile sm_6_0 -use-dxil
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute
//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl
// Passing, but: slang-test: Test context Slang session is leaking #5610
//DISABLE_TEST(compute):COMPARE_COMPUTE:-wgpu
// First we will define some fake interfaces for testing.
// Let's pretend we are doing some kind of random number
// generation, so we need an interface for a generator.
//
interface IRandomNumberGenerator
{
[mutating]
int randomInt();
}
// We want each shader thread to have its own generator,
// so what we actually pass to the shader is a "strategy"
// for random number generation, which has the generator
// as its associated type.
//
interface IRandomNumberGenerationStrategy
{
associatedtype Generator : IRandomNumberGenerator;
Generator makeGenerator(int seed);
}
// Finally, just to give us another interface type to pass
// in, we'll define an interface to modify the generated
// random number (e.g., to make them fit an expected
// distribution).
//
interface IModifier
{
int modify(int val);
}
// Let's define a subroutine that will use these interfaces
// to do something mildly interesting.
//
int test(
int seed,
IRandomNumberGenerationStrategy inStrategy,
IModifier modifier)
{
// HACK: The compiler currently has a problem with
// looking up the conformance witness for `inStrategy`
// to the `IRandomNumberGenreationStrategy` interface,
// because it requires creating an `ExtractExistentialSubtypeWitness`
// which refers to the value bound in a `LetExpr` created
// by `maybeOpenExistential`, but we have no guarantee that
// the code will actually emit the logic to initialize
// that `LetExpr`...
//
let strategy = inStrategy;
var generator = strategy.makeGenerator(seed);
let unused = generator.randomInt();
let val = generator.randomInt();
let modifiedVal = modifier.modify(val);
return modifiedVal;
}
// Now we'll define a shader entry point that will use
// these interfaces to define its behavior.
//
// We'll start with the buffer for writing the test output.
//TEST_INPUT:set gOutputBuffer = out ubuffer(data=[0 0 0 0], stride=4)
RWStructuredBuffer<int> gOutputBuffer;
// Now we'll define a global shader parameter for the
// random number generation strategy.
//
//TEST_INPUT:set gStrategy = new MyStrategy{}
uniform IRandomNumberGenerationStrategy gStrategy;
// The other parameter (for the modifier) will be attached
// the entry point instead, so that we are testing both
// cases.
//
[numthreads(4, 1, 1)]
void computeMain(
//TEST_INPUT:set modifier = new MyModifier{}
uniform IModifier modifier,
int3 dispatchThreadID : SV_DispatchThreadID)
{
let tid = dispatchThreadID.x;
let inputVal : int = tid;
let outputVal = test(inputVal, gStrategy, modifier);
gOutputBuffer[tid] = outputVal;
}
// Now that we've define all the logic of the entry point,
// we will define some concrete types that we can plug
// in for the interface-type parameters.
struct MyStrategy : IRandomNumberGenerationStrategy
{
struct Generator : IRandomNumberGenerator
{
int state;
[mutating]
int randomInt()
{
return state++;
}
}
Generator makeGenerator(int seed)
{
Generator generator = { seed };
return generator;
}
}
struct MyModifier : IModifier
{
int modify(int val)
{
return val * 16;
}
}