import '../../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * Assists in logging out buffers for WebGPU debugging.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow, DeviceContext, webgpu } from '../../imports.js';
const COLLAPSE_LOGS = true;
class BufferLogger {
    constructor(deviceContext) {
        this.deviceContext = deviceContext;
        this.callbacksOnComplete = [];
    }
    async complete() {
        for (const callback of this.callbacksOnComplete) {
            await callback();
        }
        this.callbacksOnComplete.length = 0;
    }
    hasCallbacks() {
        return this.callbacksOnComplete.length > 0;
    }
    withBuffer(encoder, buffer, callback) {
        const mappableBuffer = this.deviceContext.createMapReadableBuffer(buffer.size);
        webgpu.encoderCopyBufferToBuffer(encoder, buffer, 0, mappableBuffer, 0, mappableBuffer.size);
        this.callbacksOnComplete.push(async () => {
            const arrayBuffer = await DeviceContext.getMappedArrayBuffer(mappableBuffer);
            await callback(arrayBuffer);
            webgpu.bufferDestroy(mappableBuffer);
        });
    }
    arrayBufferPromise(encoder, buffer) {
        return new Promise((resolve, reject) => {
            this.withBuffer(encoder, buffer, async (arrayBuffer) => {
                resolve(arrayBuffer);
            });
        });
    }
    async arrayBuffer(encoder, buffer) {
        return this.arrayBufferPromise(encoder, buffer);
    }
    async u32(encoder, buffer) {
        return new Uint32Array(await this.arrayBufferPromise(encoder, buffer));
    }
    async i32(encoder, buffer) {
        return new Int32Array(await this.arrayBufferPromise(encoder, buffer));
    }
    async f32(encoder, buffer) {
        return new Float32Array(await this.arrayBufferPromise(encoder, buffer));
    }
    async u32Numbers(encoder, buffer) {
        return [...(await this.u32(encoder, buffer))];
    }
    async i32Numbers(encoder, buffer) {
        return [...(await this.i32(encoder, buffer))];
    }
    async f32Numbers(encoder, buffer) {
        return [...(await this.f32(encoder, buffer))];
    }
    logIndexed(encoder, buffer, name, type, lengthCallback = null) {
        this.withBuffer(encoder, buffer, async (arrayBuffer) => {
            let elements = type.fromArrayBuffer(arrayBuffer);
            const length = lengthCallback ? lengthCallback() : elements.length;
            elements = elements.slice(0, length);
            BufferLogger.startGroup(`[buffer] ${name} (${length})`);
            console.log(elements.map(BufferLogger.toIndexedString).join('\n'));
            BufferLogger.endGroup();
        });
    }
    logIndexedMultiline(encoder, buffer, name, type, lengthCallback = null) {
        this.withBuffer(encoder, buffer, async (arrayBuffer) => {
            // TODO refactor this bit out
            let elements = type.fromArrayBuffer(arrayBuffer);
            const length = lengthCallback ? lengthCallback() : elements.length;
            elements = elements.slice(0, length);
            BufferLogger.startGroup(`[buffer] ${name} (${length})`);
            console.log(elements.map(BufferLogger.toMultiIndexedString).join('\n'));
            BufferLogger.endGroup();
        });
    }
    logIndexedImmediate(arrayBuffer, name, type, lengthCallback = null) {
        this.callbacksOnComplete.push(async () => {
            let elements = type.fromArrayBuffer(arrayBuffer);
            const length = lengthCallback ? lengthCallback() : elements.length;
            elements = elements.slice(0, length);
            BufferLogger.startGroup(`[buffer] ${name} (${length})`);
            console.log(elements.map(BufferLogger.toIndexedString).join('\n'));
            BufferLogger.endGroup();
        });
    }
    static toIndexedString(n, i) {
        return `${i} ${n.toString()}`;
    }
    static toMultiIndexedString(n, i) {
        const padding = i.toString().replace(/./g, ' ');
        return n.toStrings().map((s, j) => `${j === 0 ? i : padding} ${s}`).join('\n');
    }
    static startGroup(name) {
        if (COLLAPSE_LOGS) {
            console.groupCollapsed(name);
        }
        else {
            console.group(name);
        }
    }
    static endGroup() {
        console.groupEnd();
    }
}
BufferLogger.RasterU32 = {
    fromArrayBuffer(arrayBuffer) {
        return [...new Uint32Array(arrayBuffer)];
    }
};
BufferLogger.RasterI32 = {
    fromArrayBuffer(arrayBuffer) {
        return [...new Int32Array(arrayBuffer)];
    }
};
BufferLogger.RasterF32 = {
    fromArrayBuffer(arrayBuffer) {
        return [...new Float32Array(arrayBuffer)];
    }
};
export default BufferLogger;
alpenglow.register('BufferLogger', BufferLogger);
//# sourceMappingURL=BufferLogger.js.map