import '../../../assert/js/assert.js';
import '../../../globals.js';
// Copyright 2024, University of Colorado Boulder
/**
 * WebGPU commands should be run through here, so we can record them for later playback (and possibly other reasons).
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow, WebGPURecorder } from '../imports.js';
export default class WebGPUAPI {
    constructor() {
        this.recorder = null;
    }
    enableRecording() {
        this.recorder = this.recorder || new WebGPURecorder();
    }
    startRecording() {
        this.enableRecording();
        assert && assert(this.recorder);
        return this.recorder.start();
    }
    stopRecording(commandList) {
        assert && assert(this.recorder);
        this.recorder.stop(commandList);
    }
    async getAdapter(options) {
        const adapter = await navigator.gpu?.requestAdapter(options);
        if (this.recorder) {
            this.recorder.recordGetAdapter(adapter, options);
        }
        return adapter;
    }
    getPreferredCanvasFormat() {
        const preferredCanvasFormat = navigator.gpu.getPreferredCanvasFormat();
        assert && assert(preferredCanvasFormat === 'bgra8unorm' || preferredCanvasFormat === 'rgba8unorm', 'According to WebGPU documentation, this should only be bgra8unorm or rgba8unorm');
        return preferredCanvasFormat;
    }
    adapterHasFeature(adapter, featureName) {
        return adapter.features.has(featureName) || false;
    }
    async adapterRequestDevice(adapter, descriptor) {
        const device = await adapter.requestDevice(descriptor) || null;
        if (this.recorder && device) {
            this.recorder.recordAdapterRequestDevice(device, adapter, descriptor);
        }
        return device;
    }
    deviceCreateBuffer(device, descriptor) {
        const buffer = device.createBuffer(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateBuffer(buffer, device, descriptor);
        }
        return buffer;
    }
    deviceCreateQuerySet(device, descriptor) {
        const querySet = device.createQuerySet(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateQuerySet(querySet, device, descriptor);
        }
        return querySet;
    }
    deviceCreateBindGroupLayout(device, descriptor) {
        const bindGroupLayout = device.createBindGroupLayout(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateBindGroupLayout(bindGroupLayout, device, descriptor);
        }
        return bindGroupLayout;
    }
    deviceCreatePipelineLayout(device, descriptor) {
        const pipelineLayout = device.createPipelineLayout(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreatePipelineLayout(pipelineLayout, device, descriptor);
        }
        return pipelineLayout;
    }
    deviceCreateShaderModule(device, descriptor) {
        const shaderModule = device.createShaderModule(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateShaderModule(shaderModule, device, descriptor);
        }
        return shaderModule;
    }
    deviceCreateComputePipeline(device, descriptor) {
        const computePipeline = device.createComputePipeline(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateComputePipeline(computePipeline, device, descriptor, false);
        }
        return computePipeline;
    }
    async deviceCreateComputePipelineAsync(device, descriptor) {
        const computePipeline = await device.createComputePipelineAsync(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateComputePipeline(computePipeline, device, descriptor, true);
        }
        return computePipeline;
    }
    deviceCreateBindGroup(device, descriptor) {
        const bindGroup = device.createBindGroup(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateBindGroup(bindGroup, device, descriptor);
        }
        return bindGroup;
    }
    deviceCreateCommandEncoder(device, descriptor) {
        const commandEncoder = device.createCommandEncoder(descriptor);
        if (this.recorder) {
            this.recorder.recordDeviceCreateCommandEncoder(commandEncoder, device, descriptor);
        }
        return commandEncoder;
    }
    deviceWriteBuffer(device, buffer, bufferOffset, data, dataOffset, size) {
        device.queue.writeBuffer(buffer, bufferOffset, data, dataOffset, size);
        if (this.recorder) {
            this.recorder.recordDeviceWriteBuffer(device, buffer, bufferOffset, data, dataOffset, size);
        }
    }
    deviceQueueSubmit(device, commandBuffers) {
        device.queue.submit(commandBuffers);
        if (this.recorder) {
            this.recorder.recordDeviceQueueSubmit(device, commandBuffers);
        }
    }
    deviceHasFeature(device, featureName) {
        return device.features.has(featureName) || false;
    }
    deviceDestroy(device) {
        device.destroy();
        if (this.recorder) {
            this.recorder.recordDeviceDestroy(device);
        }
    }
    bufferMapAsync(buffer, mode, offset, size) {
        if (this.recorder) {
            this.recorder.recordBufferMapAsync(buffer, mode, offset, size);
        }
        return buffer.mapAsync(mode, offset, size);
    }
    bufferUnmap(buffer) {
        buffer.unmap();
        if (this.recorder) {
            this.recorder.recordBufferUnmap(buffer);
        }
    }
    bufferGetMappedRange(buffer, offset, size) {
        return buffer.getMappedRange(offset, size);
    }
    bufferDestroy(buffer) {
        buffer.destroy();
        if (this.recorder) {
            this.recorder.recordBufferDestroy(buffer);
        }
    }
    encoderBeginRenderPass(encoder, descriptor) {
        const renderPassEncoder = encoder.beginRenderPass(descriptor);
        if (this.recorder) {
            this.recorder.recordEncoderBeginRenderPass(renderPassEncoder, encoder, descriptor);
        }
        return renderPassEncoder;
    }
    encoderBeginComputePass(encoder, descriptor) {
        const computePassEncoder = encoder.beginComputePass(descriptor);
        if (this.recorder) {
            this.recorder.recordEncoderBeginComputePass(computePassEncoder, encoder, descriptor);
        }
        return computePassEncoder;
    }
    encoderCopyBufferToBuffer(encoder, source, sourceOffset, destination, destinationOffset, size) {
        encoder.copyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size);
        if (this.recorder) {
            this.recorder.recordEncoderCopyBufferToBuffer(encoder, source, sourceOffset, destination, destinationOffset, size);
        }
    }
    encoderCopyBufferToTexture(encoder, source, destination, copySize) {
        encoder.copyBufferToTexture(source, destination, copySize);
        if (this.recorder) {
            this.recorder.recordEncoderCopyBufferToTexture(encoder, source, destination, copySize);
        }
    }
    encoderCopyTextureToBuffer(encoder, source, destination, copySize) {
        encoder.copyTextureToBuffer(source, destination, copySize);
        if (this.recorder) {
            this.recorder.recordEncoderCopyTextureToBuffer(encoder, source, destination, copySize);
        }
    }
    encoderCopyTextureToTexture(encoder, source, destination, copySize) {
        encoder.copyTextureToTexture(source, destination, copySize);
        if (this.recorder) {
            this.recorder.recordEncoderCopyTextureToTexture(encoder, source, destination, copySize);
        }
    }
    encoderClearBuffer(encoder, buffer, offset, size) {
        encoder.clearBuffer(buffer, offset, size);
        if (this.recorder) {
            this.recorder.recordEncoderClearBuffer(encoder, buffer, offset, size);
        }
    }
    encoderResolveQuerySet(encoder, querySet, firstQuery, queryCount, destination, destinationOffset) {
        encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
        if (this.recorder) {
            this.recorder.recordEncoderResolveQuerySet(encoder, querySet, firstQuery, queryCount, destination, destinationOffset);
        }
    }
    encoderFinish(encoder, descriptor) {
        const commandBuffer = encoder.finish(descriptor);
        if (this.recorder) {
            this.recorder.recordEncoderFinish(commandBuffer, encoder, descriptor);
        }
        return commandBuffer;
    }
    computePassEncoderSetPipeline(computePassEncoder, pipeline) {
        computePassEncoder.setPipeline(pipeline);
        if (this.recorder) {
            this.recorder.recordComputePassEncoderSetPipeline(computePassEncoder, pipeline);
        }
    }
    computePassEncoderDispatchWorkgroups(computePassEncoder, x, y, z) {
        computePassEncoder.dispatchWorkgroups(x, y, z);
        if (this.recorder) {
            this.recorder.recordComputePassEncoderDispatchWorkgroups(computePassEncoder, x, y, z);
        }
    }
    computePassEncoderDispatchWorkgroupsIndirect(computePassEncoder, indirectBuffer, indirectOffset) {
        computePassEncoder.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset);
        if (this.recorder) {
            this.recorder.recordComputePassEncoderDispatchWorkgroupsIndirect(computePassEncoder, indirectBuffer, indirectOffset);
        }
    }
    // TODO: consider adding the other approach to dynamic offsets?
    passEncoderSetBindGroup(passEncoder, index, bindGroup, dynamicOffsets) {
        passEncoder.setBindGroup(index, bindGroup, dynamicOffsets);
        if (this.recorder) {
            this.recorder.recordPassEncoderSetBindGroup(passEncoder, index, bindGroup, dynamicOffsets);
        }
    }
    computePassEncoderEnd(computePassEncoder) {
        computePassEncoder.end();
        if (this.recorder) {
            this.recorder.recordComputePassEncoderEnd(computePassEncoder);
        }
    }
    querySetDestroy(querySet) {
        querySet.destroy();
        if (this.recorder) {
            this.recorder.recordQuerySetDestroy(querySet);
        }
    }
}
alpenglow.register('WebGPUAPI', WebGPUAPI);
export const webgpu = new WebGPUAPI();
alpenglow.register('webgpu', webgpu);
//# sourceMappingURL=WebGPUAPI.js.map