Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPU: renderPassEncoder attributes somehow affecting compute pass output #24821

Open
matthew-wong1 opened this issue Jul 31, 2024 · 0 comments
Labels
bug Something isn't working correctly webgpu WebGPU API

Comments

@matthew-wong1
Copy link

matthew-wong1 commented Jul 31, 2024

Hi! I've been working on the most recent commit as of writing(b153065) and came across a bit of a weird bug. If you change the dimension of view from 2d to 2d-array, it changes the output of a subsequent compute pass.

Normally, it has the output 0 0 0 0 250 255 255 255 0 0 0 0 255 255 255 255 65 29 0 0 0 0 0 0 2 0 0 0 192 2 227 92, when view is 2d. This is also the output I get regardless of dimension on Google's dawn.

But if you use 2d-array in your render pass, for some reason, that changes the output to 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.

Weirdly, if you omit renderPassEncoder.end(), you get the output that you expect. Not too sure if it's related to #24672

I've included the compute shader that I used, but it was a computer-generated compute shader so it's pretty unreadable. If you think it might have something to do with the shader, I could try reducing with a program reducer.

import * as fs from "node:fs"

function loadShader(file) {
    try {
        const data = fs.readFileSync(file, 'utf8');
        return data;
    } catch (err) {
        console.error('Failed to load shader:', err);
    }
}
const inputArray = new Uint8Array([150, 70, 43, 68, 72, 93, 63, 3, 183, 151, 92, 60, 76, 35, 220, 145, 218, 41, 20, 253, 167, 52, 142, 101, 213, 48, 121, 26, 214, 81, 179, 223, 193, 2, 227, 92, 253, 187, 11, 222, 231, 31, 209, 196, 41, 242, 17, 90])
const shader = loadShader('compute.wgsl');

async function main() {
    const adapter = await navigator.gpu.requestAdapter();
    const device = await adapter.requestDevice();
    const queue = device.queue
    
    // Setup for beginning a render pass
    const encoder = device.createCommandEncoder();
    const texture = device.createTexture({
        format: "bgra8unorm",
        label: "texture",
        size: {
            width: 12,
            height: 12,
            depthOrArrayLayers: 1
        },
        usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
        viewFormats: ["bgra8unorm"]
    });

    const view = texture.createView({
        dimension: "2d-array", // Works fine when it is "2d" 
    })

    const renderPassEncoder = encoder.beginRenderPass({
        colorAttachments: [{
            loadOp: "load",
            storeOp: "discard",
            view: view
        }],
        maxDrawCount: 10,
    });
    renderPassEncoder.end(); // This also affects the output of the compute pass 

    // Setup for compute pass
    const inputBuffer = device.createBuffer({
        size: 48,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.INDEX | GPUBufferUsage.QUERY_RESOLVE
    });
    const storageBuffer = device.createBuffer({
        size: 32,
        usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.INDIRECT | GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.VERTEX | GPUBufferUsage.INDEX
    });

    const shaderModule = device.createShaderModule({
        code: shader
    });
    const computePipeline = device.createComputePipeline({
        compute: {
            entryPoint: "main",
            module: shaderModule
        },
        layout: "auto"
    });

    const computePassEncoder = encoder.beginComputePass();
    computePassEncoder.setPipeline(computePipeline);
    queue.writeBuffer(inputBuffer, 0, inputArray);

    const GPUBindGroup3 = device.createBindGroup({
        layout: computePipeline.getBindGroupLayout(0),
        entries: [{
            binding: 0,
            resource: {
                buffer: inputBuffer
            }
        }, {
            binding: 1,
            resource: {
                buffer: storageBuffer
            }
        }]
    });
    computePassEncoder.setBindGroup(0, GPUBindGroup3);
    computePassEncoder.dispatchWorkgroups(1);
    computePassEncoder.end();

    // Copy results of storage buffer to output buffer
    const outputBuffer = device.createBuffer({
        size: 32,
        usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
    });
    encoder.copyBufferToBuffer(storageBuffer, 0, outputBuffer, 0, 32);

    queue.submit([encoder.finish()]);

    // Print the output of the compute pass
    await outputBuffer.mapAsync(GPUMapMode.READ)
    const arrayBuffer = outputBuffer.getMappedRange();
    const computePassResult = arrayBuffer.slice(0)
    const readableArray = new Uint8Array(computePassResult)
    console.log("Compute pass has output:", ...readableArray);
}
main().catch(console.error);

compute.wgsl.txt

@lucacasonato lucacasonato added bug Something isn't working correctly webgpu WebGPU API labels Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working correctly webgpu WebGPU API
Projects
None yet
Development

No branches or pull requests

2 participants