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
5.1 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 __partitionedInclusiveMax subgroupPartitionedInclusiveMaxNV
12#define __partitionedExclusiveMax subgroupPartitionedExclusiveMaxNV
13#else
14#define __partitionedInclusiveMax WaveMultiPrefixInclusiveMax
15#define __partitionedExclusiveMax WaveMultiPrefixExclusiveMax
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 test1MinMax(uint4 mask)
25{
26    let smaller = T(gSmaller);
27    let maxValue = T(gMaxValue);
28
29    // The larger values are set to be the last in the partition, exclusive variants will never get these values.
30    bool exclusiveRes = true
31                        & (__partitionedExclusiveMax(maxValue, mask) == smaller)
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        & (__partitionedInclusiveMax(maxValue, mask) == maxValue)
42        & exclusiveRes
43        ;
44}
45
46__generic<T : __BuiltinArithmeticType, let N : int>
47bool testVMinMax(uint4 mask) {
48    typealias GVec = vector<T, N>;
49
50    let smaller = GVec(T(gSmaller));
51    let maxValue = GVec(T(gMaxValue));
52
53    // The larger values are set to be the last in the partition, exclusive variants will never get these values.
54    bool exclusiveRes = true
55                        & all(__partitionedExclusiveMax(maxValue, mask) == smaller)
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(__partitionedInclusiveMax(maxValue, mask) == maxValue)
66        & exclusiveRes;
67        ;
68}
69
70bool testMinMax(uint4 mask)
71{
72    return true
73        & test1MinMax<int>(mask)
74        & testVMinMax<int, 2>(mask)
75        & testVMinMax<int, 3>(mask)
76        & testVMinMax<int, 4>(mask)
77        & test1MinMax<uint>(mask)
78        & testVMinMax<uint, 2>(mask)
79        & testVMinMax<uint, 3>(mask)
80        & testVMinMax<uint, 4>(mask)
81        & test1MinMax<float>(mask)
82        & testVMinMax<float, 2>(mask)
83        & testVMinMax<float, 3>(mask)
84        & testVMinMax<float, 4>(mask)
85        & test1MinMax<double>(mask)
86        & testVMinMax<double, 2>(mask)
87        & testVMinMax<double, 3>(mask)
88        & testVMinMax<double, 4>(mask)
89        & test1MinMax<int8_t>(mask)
90        & testVMinMax<int8_t, 2>(mask)
91        & testVMinMax<int8_t, 3>(mask)
92        & testVMinMax<int8_t, 4>(mask)
93        & test1MinMax<int16_t>(mask)
94        & testVMinMax<int16_t, 2>(mask)
95        & testVMinMax<int16_t, 3>(mask)
96        & testVMinMax<int16_t, 4>(mask)
97        & test1MinMax<int64_t>(mask)
98        & testVMinMax<int64_t, 2>(mask)
99        & testVMinMax<int64_t, 3>(mask)
100        & testVMinMax<int64_t, 4>(mask)
101        & test1MinMax<uint8_t>(mask)
102        & testVMinMax<uint8_t, 2>(mask)
103        & testVMinMax<uint8_t, 3>(mask)
104        & testVMinMax<uint8_t, 4>(mask)
105        & test1MinMax<uint16_t>(mask)
106        & testVMinMax<uint16_t, 2>(mask)
107        & testVMinMax<uint16_t, 3>(mask)
108        & testVMinMax<uint16_t, 4>(mask)
109        & test1MinMax<uint64_t>(mask)
110        & testVMinMax<uint64_t, 2>(mask)
111        & testVMinMax<uint64_t, 3>(mask)
112        & testVMinMax<uint64_t, 4>(mask)
113        & test1MinMax<half>(mask)
114        & testVMinMax<half, 2>(mask)
115        & testVMinMax<half, 3>(mask)
116        & testVMinMax<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    gSmaller = isSecondGroup ? 2 : 0;
135    gLarger = isSecondGroup ? 3 : 1;
136    gMaxValue = isLastInPartition ? gLarger : gSmaller;
137
138    bool result = true
139            & testMinMax(mask)
140            ;
141
142    // CHECK-COUNT-32: 1
143    outputBuffer[index] = uint(result);
144}