yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Harsh Aggarwal (NVIDIA)Updated support to enable batch3 (#8219)e0c20a076

master
4.9 KiB144 linesraw
1//TEST_CATEGORY(wave, compute)
2//TEST:COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -shaderobj -emit-spirv-directly
3//TEST:COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -shaderobj -emit-spirv-via-glsl
4//TEST:COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-cuda -capability cuda_sm_7_0 -compute -shaderobj
5//TEST:COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -shaderobj -emit-spirv-directly -xslang -DUSE_GLSL_SYNTAX -allow-glsl
6
7//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer
8RWStructuredBuffer<uint> outputBuffer;
9
10#if defined(USE_GLSL_SYNTAX)
11#define __partitionedInclusiveMin subgroupPartitionedInclusiveMinNV
12#define __partitionedExclusiveMin subgroupPartitionedExclusiveMinNV
13#else
14#define __partitionedInclusiveMin WaveMultiPrefixInclusiveMin
15#define __partitionedExclusiveMin WaveMultiPrefixExclusiveMin
16#endif
17
18static bool isFirstInPartition = false;
19static uint gSmaller = 0;
20static uint gLarger = 0;
21static uint gMaxValue = 0;
22
23__generic<T : __BuiltinArithmeticType>
24bool test1Min(uint4 mask)
25{
26    let larger = T(gLarger);
27    let minValue = T(gMaxValue);
28
29    // The smaller values are set to be the last in the partition, exclusive variants will never get these values.
30    bool exclusiveRes = true
31                        & (__partitionedExclusiveMin(minValue, mask) == larger)
32                        ;
33    // Do not check exclusive prefix for the first invocation in partition as their values(identity values) depend on the builtin type `T`. It would be
34    // nice to have something like T::min or T::max.
35    if (isFirstInPartition)
36    {
37        exclusiveRes = true;
38    }
39
40    return true
41        & (__partitionedInclusiveMin(minValue, mask) == minValue)
42        & exclusiveRes
43        ;
44}
45
46__generic<T : __BuiltinArithmeticType, let N : int>
47bool testVMin(uint4 mask) {
48    typealias GVec = vector<T, N>;
49
50    let larger = GVec(T(gLarger));
51    let minValue = GVec(T(gMaxValue));
52
53    // The smaller values are set to be the last in the partition, exclusive variants will never get these values.
54    bool exclusiveRes = true
55                        & all(__partitionedExclusiveMin(minValue, mask) == larger)
56                        ;
57    // Do not check exclusive prefix for the first invocation in partition as their values(identity values) depend on the builtin type `T`. It would be
58    // nice to have something like T::min or T::max.
59    if (isFirstInPartition)
60    {
61        exclusiveRes = true;
62    }
63
64    return true
65        & all(__partitionedInclusiveMin(minValue, mask) == minValue)
66        & exclusiveRes
67        ;
68}
69
70bool testMin(uint4 mask)
71{
72    return true
73        & test1Min<int>(mask)
74        & testVMin<int, 2>(mask)
75        & testVMin<int, 3>(mask)
76        & testVMin<int, 4>(mask)
77        & test1Min<uint>(mask)
78        & testVMin<uint, 2>(mask)
79        & testVMin<uint, 3>(mask)
80        & testVMin<uint, 4>(mask)
81        & test1Min<float>(mask)
82        & testVMin<float, 2>(mask)
83        & testVMin<float, 3>(mask)
84        & testVMin<float, 4>(mask)
85        & test1Min<double>(mask)
86        & testVMin<double, 2>(mask)
87        & testVMin<double, 3>(mask)
88        & testVMin<double, 4>(mask)
89        & test1Min<int8_t>(mask)
90        & testVMin<int8_t, 2>(mask)
91        & testVMin<int8_t, 3>(mask)
92        & testVMin<int8_t, 4>(mask)
93        & test1Min<int16_t>(mask)
94        & testVMin<int16_t, 2>(mask)
95        & testVMin<int16_t, 3>(mask)
96        & testVMin<int16_t, 4>(mask)
97        & test1Min<int64_t>(mask)
98        & testVMin<int64_t, 2>(mask)
99        & testVMin<int64_t, 3>(mask)
100        & testVMin<int64_t, 4>(mask)
101        & test1Min<uint8_t>(mask)
102        & testVMin<uint8_t, 2>(mask)
103        & testVMin<uint8_t, 3>(mask)
104        & testVMin<uint8_t, 4>(mask)
105        & test1Min<uint16_t>(mask)
106        & testVMin<uint16_t, 2>(mask)
107        & testVMin<uint16_t, 3>(mask)
108        & testVMin<uint16_t, 4>(mask)
109        & test1Min<uint64_t>(mask)
110        & testVMin<uint64_t, 2>(mask)
111        & testVMin<uint64_t, 3>(mask)
112        & testVMin<uint64_t, 4>(mask)
113        & test1Min<half>(mask)
114        & testVMin<half, 2>(mask)
115        & testVMin<half, 3>(mask)
116        & testVMin<half, 4>(mask)
117        ;
118}
119
120[numthreads(32, 1, 1)]
121[shader("compute")]
122[MaximallyReconverges]
123void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
124{
125    let index = dispatchThreadID.x;
126
127    // Split into two groups, first group has 15 invocations/lanes and second group has 17.
128    let isSecondGroup = index >= 15;
129    uint4 mask = isSecondGroup ? uint4(0xFFFF8000, 0, 0, 0) : uint4(0x0007FFF, 0, 0, 0);
130
131    isFirstInPartition = (index == 0) || (index == 15);
132    let isLastInPartition = (index == 14) || (index == 31);
133
134    bool result = true
135            & testMin(mask)
136            ;
137
138    gSmaller = isSecondGroup ? 2 : 0;
139    gLarger = isSecondGroup ? 3 : 1;
140    gMaxValue = isLastInPartition ? gLarger : gSmaller;
141
142    // CHECK-COUNT-32: 1
143    outputBuffer[index] = uint(result);
144}