import '../../../../../assert/js/assert.js';
import '../../../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * Meant for reduction on u32/i32 values (could be generalized to things that can be represented with multiple atomic
 * values, haven't run into that yet).
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { combineOptions, optionize3 } from '../../../../../phet-core/js/optionize.js';
import { alpenglow, BufferBindingType, decimalS, loadReducedWGSL, reduceWGSL, wgsl, WGSLMainModule, WGSLSlot, wgslString } from '../../../imports.js';
export const MAIN_REDUCE_ATOMIC_DEFAULTS = {
    loadReducedOptions: {
        inputAccessOrder: 'striped'
    },
    reduceOptions: {
        convergent: true
    }
};
const mainReduceAtomicWGSL = (providedOptions) => {
    const options = optionize3()({}, MAIN_REDUCE_ATOMIC_DEFAULTS, providedOptions);
    const workgroupSize = options.workgroupSize;
    const grainSize = options.grainSize;
    const binaryOp = options.binaryOp;
    assert && assert(binaryOp.atomicName);
    return new WGSLMainModule([
        new WGSLSlot('input', options.input, BufferBindingType.READ_ONLY_STORAGE),
        new WGSLSlot('output', options.output, BufferBindingType.STORAGE) // TODO: assert that this is an atomic(!)
    ], wgsl `
    
    var<workgroup> scratch: array<${binaryOp.type.valueType}, ${decimalS(workgroupSize)}>;
    
    @compute @workgroup_size(${decimalS(workgroupSize)})
    fn main(
      @builtin(global_invocation_id) global_id: vec3u,
      @builtin(local_invocation_id) local_id: vec3u,
      @builtin(workgroup_id) workgroup_id: vec3u
    ) {
    
      ${loadReducedWGSL(combineOptions({
        value: wgsl `value`,
        binaryOp: binaryOp,
        loadExpression: i => wgsl `input[ ${i} ]`,
        workgroupSize: workgroupSize,
        grainSize: grainSize
    }, options.loadReducedOptions))}
    
      ${reduceWGSL(combineOptions({
        value: wgsl `value`,
        binaryOp: binaryOp,
        scratch: wgsl `scratch`,
        workgroupSize: workgroupSize
    }, options.reduceOptions))}
    
      if ( local_id.x == 0u ) {
        // TODO: better way to handle atomic names
        ${wgslString(binaryOp.atomicName)}( &output, value );
      }
    }
  `);
};
export default mainReduceAtomicWGSL;
alpenglow.register('mainReduceAtomicWGSL', mainReduceAtomicWGSL);
//# sourceMappingURL=mainReduceAtomicWGSL.js.map