import { BaseRenderPass } from "../RenderPass.js";
import {} from "./GPUParticleBackend.js";
import { ParticleRenderer } from "./ParticleRenderer.js";
import {} from "./ParticleSystem.js";
export class ParticleRenderPass extends BaseRenderPass {
    options;
    renderer;
    lastBatch = null;
    lastUpdateMode = "none";
    constructor(options) {
        super("particles", options.reads ?? ["color"], options.writes ?? ["color"], ["color"]);
        this.options = options;
        this.renderer = options.renderer ?? new ParticleRenderer();
    }
    execute(_context) {
        if (this.requiresAsyncUpdate()) {
            throw new Error("ParticleRenderPass with a supported GPU update backend must run through RenderGraph.executeAsync().");
        }
        this.updateSync();
        this.lastBatch = this.renderer.render(this.options.system, this.options.target, this.options.renderOptions);
    }
    async executeAsync(_context) {
        await this.updateAsync();
        this.lastBatch = this.renderer.render(this.options.system, this.options.target, this.options.renderOptions);
    }
    getLastBatch() {
        if (!this.lastBatch) {
            return null;
        }
        return {
            sprites: this.lastBatch.sprites.map((sprite) => ({
                ...sprite,
                position: { ...sprite.position },
                color: { ...sprite.color }
            })),
            liveCount: this.lastBatch.liveCount,
            uploadedBytes: this.lastBatch.uploadedBytes,
            bounds: this.lastBatch.bounds ? {
                min: { ...this.lastBatch.bounds.min },
                max: { ...this.lastBatch.bounds.max }
            } : null
        };
    }
    getLastUpdateMode() {
        return this.lastUpdateMode;
    }
    requiresAsyncUpdate() {
        const update = this.options.update;
        return Boolean(update?.gpuBackend?.capabilities.supported && (update.preferGPU ?? true));
    }
    updateSync() {
        const update = this.options.update;
        if (!update) {
            this.lastUpdateMode = "none";
            return;
        }
        validateDeltaTime(update.deltaTime);
        if (update.gpuBackend && update.preferGPU !== false && !update.gpuBackend.capabilities.supported && update.allowCPUFallback === false) {
            throw new Error(update.gpuBackend.capabilities.reason ?? "GPU particle backend is unsupported.");
        }
        this.options.system.update(update.deltaTime);
        this.lastUpdateMode = "cpu";
    }
    async updateAsync() {
        const update = this.options.update;
        if (!update) {
            this.lastUpdateMode = "none";
            return;
        }
        validateDeltaTime(update.deltaTime);
        const backend = update.gpuBackend;
        if (backend && (update.preferGPU ?? true)) {
            if (backend.capabilities.supported) {
                await this.options.system.updateOnGPU(update.deltaTime, backend);
                this.lastUpdateMode = "gpu";
                return;
            }
            if (update.allowCPUFallback === false) {
                throw new Error(backend.capabilities.reason ?? "GPU particle backend is unsupported.");
            }
        }
        this.options.system.update(update.deltaTime);
        this.lastUpdateMode = "cpu";
    }
}
function validateDeltaTime(deltaTime) {
    if (!Number.isFinite(deltaTime) || deltaTime < 0) {
        throw new RangeError("ParticleRenderPass update deltaTime must be a finite non-negative number.");
    }
}
//# sourceMappingURL=ParticleRenderPass.js.map