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