import '../../../../assert/js/assert.js';
import '../../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * TODO: doc
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow, TypedBuffer } from '../../imports.js';
export default class ExecutionContext {
    // TODO: We might use one compute pass, we might split each into one
    constructor(executor, 
    // TODO: consider just referencing the Procedure
    computePipelineMap, bindGroupMap, resourceMap, separateComputePasses) {
        this.executor = executor;
        this.computePipelineMap = computePipelineMap;
        this.bindGroupMap = bindGroupMap;
        this.resourceMap = resourceMap;
        this.separateComputePasses = separateComputePasses;
        this.computePass = null;
    }
    dispatch(pipelineBlueprint, dispatchX = 1, dispatchY = 1, dispatchZ = 1) {
        this.ensureComputePass(pipelineBlueprint.name);
        const computePipeline = this.computePipelineMap.get(pipelineBlueprint);
        assert && assert(computePipeline, 'Missing compute pipeline');
        this.computePass.dispatchPipeline(computePipeline, this.getBindGroups(computePipeline), dispatchX, dispatchY, dispatchZ);
        if (this.separateComputePasses) {
            this.releaseComputePass();
        }
    }
    dispatchIndirect(pipelineBlueprint, indirectBuffer, indirectOffset) {
        this.ensureComputePass(pipelineBlueprint.name);
        const computePipeline = this.computePipelineMap.get(pipelineBlueprint);
        assert && assert(computePipeline, 'Missing compute pipeline');
        this.computePass.dispatchPipelineIndirect(computePipeline, this.getBindGroups(computePipeline), indirectBuffer, indirectOffset);
        if (this.separateComputePasses) {
            this.releaseComputePass();
        }
    }
    // TODO: see if we can get the bind groups to be optimized?
    getEncoderForCustomRender() {
        this.releaseComputePass();
        return this.executor.encoder;
    }
    setTypedBufferValue(bufferSlot, value) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        this.executor.setTypedBufferValue(this.getTypedBuffer(bufferSlot), value);
    }
    async getTypedBufferValue(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.getTypedBufferValue(this.getTypedBuffer(bufferSlot));
    }
    async arrayBuffer(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.arrayBuffer(this.getBuffer(bufferSlot));
    }
    async u32(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.u32(this.getBuffer(bufferSlot));
    }
    async i32(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.i32(this.getBuffer(bufferSlot));
    }
    async f32(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.f32(this.getBuffer(bufferSlot));
    }
    async u32Numbers(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.u32Numbers(this.getBuffer(bufferSlot));
    }
    async i32Numbers(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.i32Numbers(this.getBuffer(bufferSlot));
    }
    async f32Numbers(bufferSlot) {
        this.releaseComputePass(); // we can't run this during a compute pass, so we'll interrupt if there is one
        return this.executor.f32Numbers(this.getBuffer(bufferSlot));
    }
    finish() {
        if (this.computePass) {
            this.releaseComputePass();
        }
    }
    getBuffer(bufferSlot) {
        const resource = this.resourceMap.get(bufferSlot);
        assert && assert(resource, 'Missing resource');
        return resource.resource;
    }
    getTypedBuffer(bufferSlot) {
        const buffer = this.getBuffer(bufferSlot);
        return new TypedBuffer(buffer, bufferSlot.concreteType);
    }
    getBindGroups(computePipeline) {
        const bindGroups = [];
        for (const bindGroupLayout of computePipeline.pipelineLayout.bindGroupLayouts) {
            const bindGroup = this.bindGroupMap.get(bindGroupLayout);
            assert && assert(bindGroup, 'Missing bind group');
            bindGroups.push(bindGroup);
        }
        return bindGroups;
    }
    ensureComputePass(name) {
        if (this.computePass === null) {
            this.computePass = this.executor.getComputePass(this.separateComputePasses ? name : 'primary');
        }
        return this.computePass;
    }
    releaseComputePass() {
        this.computePass?.end();
        this.computePass = null;
    }
}
alpenglow.register('ExecutionContext', ExecutionContext);
//# sourceMappingURL=ExecutionContext.js.map