javascriptwebgpuwgsl

WebGPU: Vertex range requires a larger buffer than the bound buffer size


I am simply trying to send an array of vertex positions to the vertex shader.

Here is a snippet of my JS code:

const vertices = new Float32Array([0, 0.5, 0, 1, -0.5, -0.5, 0, 2, 0.5, -0.5, 0, 1]);
const vertexBuffer = device.createBuffer({
    // equal to 48
    size: vertices.byteLength,
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(vertexBuffer, 0, vertices);

const vertexBuffers = [
    {
        attributes: [
            {
                shaderLocation: 0,
                offset: 0,
                format: "float32x4",
            },
        ],
        arrayStride: 16,
        stepMode: "vertex",
    },
];

The Float32Array is 12 long, therefore 48 bytes. However, I receive this error message stating that I need 192 bytes:

Vertex range (first: 0, count: 12) requires a larger buffer (192) than the bound buffer size (48) of the vertex buffer at slot 0 with stride 16. - While encoding [RenderPassEncoder].Draw(12, 1, 0, 0).

This may be irrelevant to the problem, but for context, here is my shader program:

@vertex
fn vMain(@location(0) vertexPosition: vec4<f32>, @builtin(vertex_index) vertexIndex: u32) -> @builtin(position) vec4<f32>  {
    var positions = array<vec4<f32>, 3>(
        vec4<f32>(0, 0.5, 0, 1),
        vec4<f32>(-0.5, -0.5, 0, 2),
        vec4<f32>(0.5, -0.5, 0, 1),
    );

    return positions[vertexIndex];
}

@fragment
fn fMain() -> @location(0) vec4<f32> {
    return vec4<f32>(1, 1, 1, 1);
}

It does not use the vertices array but I use it only to show whether or not everything runs without errors. When I change the buffer size on line 3 of my snippet from vertices.byteLength to 368, it functions correctly and a triangle is rendered. Anything below 368 causes it to fail.

Upon further testing, I have found that doubling the size of the Float32Array by adding 4 more floats per vertex and changing the stride to 32 will cause WebGPU to state that I need 768 bytes.


Solution

  • You set your arrayStride to 32, which means that each vertex will occupy 32 bytes (https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API#define_and_create_the_render_pipeline).

    Judging from your vertex layout this should be 16, because you only define one format as float32x4 = 16 bytes.

    Judging from the error message (Draw(12, 1, 0, 0)) it seems like you are trying to draw 12 vertices. Which means the total expected buffer size is: 12*32 = 368. According to your format this should probably be Draw(3, 1, 0, 0) instead. That way your vertexBuffer can be partioned into 3 vertices, each with a positional value of vec4<f32>