Skip to content

WebGPU BYOW: to submit to queue twice would cause the program to freeze in surface.present. #24313

@chirsz-ever

Description

@chirsz-ever

deno --version:

deno 1.44.4 (release, x86_64-unknown-linux-gnu)
v8 12.6.228.9
typescript 5.4.5

Platform: ArchLinux, KDE Plasma 6, wayland

Example code:

// https://deno.com/blog/v1.40#webgpu-windowing--bring-your-own-window

import {
    EventType,
    WindowBuilder,
    getKeyName
} from "jsr:@divy/sdl2@0.10.5";

const width = 800;
const height = 600;

const win = new WindowBuilder("Hello, World!", width, height).build();

const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
    console.error("WebGPU not supported!");
    Deno.exit(1);
}
const device = await adapter.requestDevice();

/* Returns a Deno.UnsafeWindowSurface */
let surface = win.windowSurface();
/* Returns a WebGPU GPUCanvasContext */
const context = surface.getContext("webgpu");

context.configure({
    device,
    format: navigator.gpu.getPreferredCanvasFormat(),
    width,
    height,
});

const SDL_WINDOWEVENT_RESIZED = 5;

for await (const event of win.events()) {
    // console.log("get event ", event);
    if (event.type === EventType.Quit) break;
    else if (event.type === EventType.KeyDown) {
        // console.log(`key down `, getKeyName(event.keysym.sym))
        if (getKeyName(event.keysym.sym) === "Escape") {
            break;
        }
        continue;
    }
    else if (event.type === EventType.WindowEvent) {
        switch (event.event) {
            case SDL_WINDOWEVENT_RESIZED:
                console.info("resized!")
                surface = win.windowSurface();
                continue;
        }
    }
    else if (event.type !== EventType.Draw) continue;

    // Sine wave
    const r = Math.sin(Date.now() / 1000) / 2 + 0.5;
    const g = Math.sin(Date.now() / 1000 + 2) / 2 + 0.5;
    const b = Math.sin(Date.now() / 1000 + 4) / 2 + 0.5;

    const encode = (textureView: GPUTextureView) => {
        const commandEncoder = device.createCommandEncoder();
        const passEncoder = commandEncoder.beginRenderPass({
            colorAttachments: [
                {
                    view: textureView,
                    clearValue: { r, g, b, a: 1.0 },
                    loadOp: "clear",
                    storeOp: "store",
                },
            ],
        });
        passEncoder.end();

        return commandEncoder.finish();
    };

    // this would cause to freeze when calling `surface.present()`
    {
        device.queue.submit([encode(context.getCurrentTexture().createView())]);
        device.queue.submit([encode(context.getCurrentTexture().createView())]);
    }

    // this would also cause to freeze
    // {
    //     const cmbBuffers = [];
    //     cmbBuffers.push(encode(context.getCurrentTexture().createView()));
    //     cmbBuffers.push(encode(context.getCurrentTexture().createView()));
    //     device.queue.submit(cmbBuffers);
    // }

    // this would not cause to freeze
    // {
    //     const cmbBuffers = [];
    //     cmbBuffers.push(encode(context.getCurrentTexture().createView()));
    //     encode(context.getCurrentTexture().createView());
    //     device.queue.submit(cmbBuffers);
    // }

    surface.present();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working correctlywebgpuWebGPU API

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions