Closed Bug 1947823 Opened 6 months ago Closed 1 month ago

Some Sokol WebGPU demos have wildly misplaced vertex geometry on macOS

Categories

(Core :: Graphics: WebGPU, defect)

Unspecified
macOS
defect

Tracking

()

RESOLVED FIXED

People

(Reporter: ErichDonGubler, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(4 files)

Some entries from the Sokol demos' WebGPU variants have some wildly misplaced vertices.

Steps to reproduce

  1. Open a demo that is known to exhibit this behavior in Firefox. Observe broken geometry.

    The sbuftex and ozz-storagebuffer entries are the two examples I'm currently aware of that follow this.

  2. Compare the entry selected in the previous step in Chrome. Observe that the demo functions as expected.

From the WebGPU team's internal chat:

Erich Gubler: This seems like vertex pulling for macOS might not be handling a vertex format properly (CC :bradwerth).

Jim Blandy: Right. The first thing I would check is which vertex format the vertex buffer is using, and then see if the code generated by naga::back::msl::Writer::write_unpacking_function is correct.

Attached image sbuftex-ff.gif

N.B., we have not confirmed whether this reproduces on platforms outside of macOS yet.

I managed to test on windows (d3d12 backend) and the examples display properly - the issue is most likely macOS only (due to vertex pulling).

I also tried a few other examples on the website and they also work properly.

Blocks: webgpu-apps
Summary: Some Sokol WebGPU demos have wildly misplaced vertex geometry → Some Sokol WebGPU demos have wildly misplaced vertex geometry on macOS
OS: Unspecified → macOS
Version: unspecified → Trunk

Filed an upstream issue: wgpu#7456

Andre Weissflog (the author of the demo, CC'd) has speculated the following about the root cause of this issue (Matrix link):

  1. this sample should render a cube via vertex pulling, but renders a mess... I suspect there's something wrong with struct item alignment in storage buffers: https://floooh.github.io/sokol-webgpu/sbuftex-sapp.html

I stumbled upon https://github.com/gfx-rs/wgpu/issues/5262 last week, which seems like it could be relevant here.

I can provide a bit more info:

This vertex-pulling sample (https://floooh.github.io/sokol-webgpu/vertexpull-sapp.html) works fine with the vertex struct in the storage buffer looking like this:

struct sb_vertex {
    pos: vec3f,
    color: vec4f,
}

The C-side struct looks like this (generated by my shader-cross-compiler):

SOKOL_SHDC_ALIGN(16) typedef struct sb_vertex_t {
    float pos[3];
    uint8_t _pad_12[4];
    float color[4];
} sb_vertex_t;

When running that same shader through SPIRVCross with MetalSL output, the struct looks like this:

struct sb_vertex
{
    float3 pos;
    float4 color;
};

This sample (https://floooh.github.io/sokol-webgpu/sbuftex-sapp.html) is broken and uses a vertex struct like this:

struct sb_vertex {
    pos : vec3f,
    idx : u32,
    uv : vec2f,
}

The C-side struct looks like this:

SOKOL_SHDC_ALIGN(16) typedef struct sb_vertex_t {
    float pos[3];
    uint32_t idx;
    float uv[2];
    uint8_t _pad_24[8];
} sb_vertex_t;

...and that same struct as MetalSL via SPIRVCross:

struct sb_vertex
{
    packed_float3 pos;
    uint idx;
    float2 uv;
    char _m0_final_padding[8];
};

Note how SPIRVCross picks packed_float3 here instead of float3. I guess the Firefox WGSL compiler simply doesn't do this when generating Metal output and causing the float3.

Also note that there's a closed issue which seems to be related here: https://github.com/gfx-rs/wgpu/issues/4522

...but maybe this is only for uniform data, not storage buffer data?

Bah, I can't edit my comments here can I? :) Excuse the weird typo in my above comment :)

TL;DR: I guess the Firefox WGSL compiler needs to be smarter about picking float3 vs packed_float3 when translating storage buffer array item structs to Metal.

PS: also note how SPIRVCross adds explicit padding bytes at the end to cause the struct size to be a multiple of 16 (maybe this is the actual issue?).

Ok, it's not the packed_float3, but the struct size which is the problem:

When I change the WGSL struct item to so that the size if a multiple of 16 bytes the problem is fixed, e.g.:

    struct sb_vertex {
      pos : vec3f,
      idx : u32,
      uv : vec2f,
      unused : vec2f,
    }

...e.g. the last unused: vec2f makes it work because it brings the struct size to 16 bytes. I guess Naga needs to add explicit padding bytes like SPIRVCross does (or maybe force a 16-byte alignment on the whole struct - assuming that this also works when the struct is in an array).

Blocks: webgpu-sokol
No longer blocks: webgpu-apps

Confirmed as fixed upstream! 🙌🏻

Status: NEW → RESOLVED
Closed: 1 month ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: