import '../../../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow, BufferBindingType, decimalS, loadReducedWGSL, logStringWGSL, reduceWGSL, toConvergentIndexWGSL, toStripedIndexWGSL, wgsl, WGSLMainModule, WGSLSlot } from '../../../imports.js';
import { combineOptions, optionize3 } from '../../../../../phet-core/js/optionize.js';
export const MAIN_REDUCE_DEFAULTS = {
    stripeOutput: false,
    convergentRemap: false,
    loadReducedOptions: {},
    reduceOptions: {}
};
const mainReduceWGSL = (providedOptions) => {
    const options = optionize3()({}, MAIN_REDUCE_DEFAULTS, providedOptions);
    const workgroupSize = options.workgroupSize;
    const grainSize = options.grainSize;
    const binaryOp = options.binaryOp;
    const stripeOutput = options.stripeOutput;
    const convergentRemap = options.convergentRemap;
    return new WGSLMainModule([
        new WGSLSlot('input', options.input, BufferBindingType.READ_ONLY_STORAGE),
        new WGSLSlot('output', options.output, BufferBindingType.STORAGE)
    ], 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
    ) {
      ${logStringWGSL(`mainReduceWGSL start ${binaryOp.name}`)}
    
      ${loadReducedWGSL(combineOptions({
        value: wgsl `value`,
        binaryOp: binaryOp,
        loadExpression: i => wgsl `input[ ${i} ]`,
        workgroupSize: workgroupSize,
        grainSize: grainSize
    }, options.loadReducedOptions))}
    
      ${convergentRemap ? wgsl `
        scratch[ ${toConvergentIndexWGSL({ i: wgsl `local_id.x`, size: workgroupSize })} ] = value;
    
        workgroupBarrier();
      ` : wgsl ``}
    
      ${reduceWGSL(combineOptions({
        value: wgsl `value`,
        binaryOp: binaryOp,
        scratch: wgsl `scratch`,
        workgroupSize: workgroupSize,
        scratchPreloaded: convergentRemap, // if we convergently reloaded, we don't need to update the scratch
        valuePreloaded: !convergentRemap // if we convergently reloaded, we'll need to load the value from scratch
    }, options.reduceOptions))}
    
      if ( local_id.x == 0u ) {
        output[ ${stripeOutput ? toStripedIndexWGSL({
        i: wgsl `workgroup_id.x`,
        workgroupSize: workgroupSize,
        grainSize: grainSize
    }) : wgsl `workgroup_id.x`} ] = value;
      }
    }
  `);
};
export default mainReduceWGSL;
alpenglow.register('mainReduceWGSL', mainReduceWGSL);
//# sourceMappingURL=mainReduceWGSL.js.map