xref: /aosp_15_r20/external/skia/resources/sksl/compute/AtomicOperationsOverArrayAndStruct.compute (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Workerlayout(local_size_x = 256) in;
2*c8dee2aaSAndroid Build Coastguard Workerconst uint WORKGROUP_SIZE = 256;
3*c8dee2aaSAndroid Build Coastguard Worker
4*c8dee2aaSAndroid Build Coastguard Workerstruct GlobalCounts {
5*c8dee2aaSAndroid Build Coastguard Worker    atomicUint firstHalfCount;
6*c8dee2aaSAndroid Build Coastguard Worker    atomicUint secondHalfCount;
7*c8dee2aaSAndroid Build Coastguard Worker};
8*c8dee2aaSAndroid Build Coastguard Workerlayout(metal, binding = 0) buffer ssbo {
9*c8dee2aaSAndroid Build Coastguard Worker    GlobalCounts globalCounts;
10*c8dee2aaSAndroid Build Coastguard Worker};
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Workerworkgroup atomicUint localCounts[2];
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard Workervoid main() {
15*c8dee2aaSAndroid Build Coastguard Worker    // Initialize the local counts.
16*c8dee2aaSAndroid Build Coastguard Worker    if (sk_LocalInvocationID.x == 0) {
17*c8dee2aaSAndroid Build Coastguard Worker        atomicStore(localCounts[0], 0);
18*c8dee2aaSAndroid Build Coastguard Worker        atomicStore(localCounts[1], 0);
19*c8dee2aaSAndroid Build Coastguard Worker    }
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker    // Synchronize the threads in the workgroup so they all see the initial value.
22*c8dee2aaSAndroid Build Coastguard Worker    workgroupBarrier();
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker    // Each thread increments one of the local counters based on its invocation index.
25*c8dee2aaSAndroid Build Coastguard Worker    uint idx = sk_LocalInvocationID.x < (WORKGROUP_SIZE / 2) ? 0 : 1;
26*c8dee2aaSAndroid Build Coastguard Worker    atomicAdd(localCounts[idx], 1);
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker    // Synchronize the threads again to ensure they have all executed the increments
29*c8dee2aaSAndroid Build Coastguard Worker    // and the following load reads the same value across all threads in the
30*c8dee2aaSAndroid Build Coastguard Worker    // workgroup.
31*c8dee2aaSAndroid Build Coastguard Worker    workgroupBarrier();
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker    // Add the workgroup-only tally to the global counter.
34*c8dee2aaSAndroid Build Coastguard Worker    if (sk_LocalInvocationID.x == 0) {
35*c8dee2aaSAndroid Build Coastguard Worker        atomicAdd(globalCounts.firstHalfCount, atomicLoad(localCounts[0]));
36*c8dee2aaSAndroid Build Coastguard Worker        atomicAdd(globalCounts.secondHalfCount, atomicLoad(localCounts[1]));
37*c8dee2aaSAndroid Build Coastguard Worker    }
38*c8dee2aaSAndroid Build Coastguard Worker}
39