Closed Bug 1827117 (webgpu-thimbleberry) Opened 1 year ago Closed 8 months ago

Thimbleberry's WebGPU demo doesn't work yet

Categories

(Core :: Graphics: WebGPU, defect, P3)

Firefox 113
defect

Tracking

()

RESOLVED FIXED

People

(Reporter: bugz, Unassigned)

References

(Blocks 1 open bug, )

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0

Steps to reproduce:

visit thimbleberry.dev

Actual results:

the demo app makes more progress after the fix for after 1825186 (thanks!), but still fails quickly because:

createTexture() returns undefined.

src here: https://github.com/mighdoll/thimbleberry/blob/main/src/shader-util/ImageToTexture.ts

Expected results:

(works on chrome)

The severity field is not set for this bug.
:jimb, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jimb)

mighdoll: AFAICT, createTexture is working, but I am running into bug 1830762 when visiting https://thimbleberry.dev/, where the GPUTexture.format attribute of the returned texture isn't being populated, i.e.:

Uncaught (in promise) TypeError: GPUDevice.createRenderPipeline: Missing required 'format' member of GPUColorTargetState.
    createMosaicPipeline MosaicPipeline.ts:86
    memoMemo MemoMemo.ts:44
    memoizeWithDevice CacheKeyWithDevice.ts:33
    get pipeline MosaicShader.ts:101

Is this what you were referring to, mighdoll?

Blocks: webgpu-v1
Severity: -- → S3
Depends on: 1830762
Flags: needinfo?(jimb)
Alias: webgpu-v1-thimbleberry
Assignee: nobody → egubler
Status: UNCONFIRMED → NEW
Ever confirmed: true
Assignee: egubler → nobody

This should be making more progress now, though in my latest testing, I still see these blockages in the JS console for the tab:

15:30:44.997 Invalid URI. Load of media resource  failed. thimbleberry.dev
15:30:45.828 In a draw command, indexed:false indirect:false, caused by: The pipeline layout, associated with the current render pipeline, contains a bind group layout at index 0 which is incompatible with the bind group layout associated with the bind group at 0
15:30:45.828 Command encoder is invalid 
Priority: -- → P3
Summary: thimbleberry WebGPU demo doesn't work yet on firefox: createTexture() → Thimbleberry's WebGPU demo doesn't work yet
Blocks: webgpu-apps
No longer blocks: webgpu-v1

The problem I found with comment 3 is blocked on bug 1611425.

Alias: webgpu-v1-thimbleberry → webgpu-thimbleberry
Attached file wgpu trace

This trace allows us to reproduce the bind group mismatch error in wgpu's replay tool. As can be seen in the .ron file copied below, a pipeline layout is created with a bind group layout, and later a render pass uses the pipeline without setting a compatible bind group.

Erich found out that we are (incorrectly) discarding the set_bind_group before it gets a chance to be recorded in the command buffer.

[
Init(
    desc: (
        label: None,
        features: 2,
        limits: (
            maxTextureDimension1D: 8192,
            maxTextureDimension2D: 8192,
            maxTextureDimension3D: 2048,
            maxTextureArrayLayers: 256,
            maxBindGroups: 4,
            maxBindingsPerBindGroup: 1000,
            maxDynamicUniformBuffersPerPipelineLayout: 8,
            maxDynamicStorageBuffersPerPipelineLayout: 4,
            maxSampledTexturesPerShaderStage: 16,
            maxSamplersPerShaderStage: 16,
            maxStorageBuffersPerShaderStage: 8,
            maxStorageTexturesPerShaderStage: 4,
            maxUniformBuffersPerShaderStage: 12,
            maxUniformBufferBindingSize: 65536,
            maxStorageBufferBindingSize: 134217728,
            maxVertexBuffers: 8,
            maxBufferSize: 268435456,
            maxVertexAttributes: 16,
            maxVertexBufferArrayStride: 2048,
            minUniformBufferOffsetAlignment: 256,
            minStorageBufferOffsetAlignment: 256,
            maxInterStageShaderComponents: 60,
            maxComputeWorkgroupStorageSize: 16384,
            maxComputeInvocationsPerWorkgroup: 256,
            maxComputeWorkgroupSizeX: 256,
            maxComputeWorkgroupSizeY: 256,
            maxComputeWorkgroupSizeZ: 64,
            maxComputeWorkgroupsPerDimension: 65535,
            maxPushConstantSize: 256,
            maxNonSamplerBindings: 10000,
        ),
    ),
    backend: Vulkan,
),
CreateTexture(Id(0, 1, Vulkan), (
    label: Some("placeholder texture"),
    size: (
        width: 50,
        height: 50,
        depthOrArrayLayers: 1,
    ),
    mip_level_count: 1,
    sample_count: 1,
    dimension: r#2d,
    format: "rgba8unorm",
    usage: 23,
    view_formats: [],
)),
CreateTexture(Id(1, 1, Vulkan), (
    label: Some("bird.jpg"),
    size: (
        width: 400,
        height: 400,
        depthOrArrayLayers: 1,
    ),
    mip_level_count: 1,
    sample_count: 1,
    dimension: r#2d,
    format: "bgra8unorm",
    usage: 23,
    view_formats: [],
)),
WriteTexture(
    to: (
        texture: Id(1, 1, Vulkan),
        mip_level: 0,
        origin: (
            x: 0,
            y: 0,
            z: 0,
        ),
        aspect: all,
    ),
    data: "data1.bin",
    layout: (
        offset: 0,
        bytes_per_row: Some(1600),
        rows_per_image: Some(400),
    ),
    size: (
        width: 400,
        height: 400,
        depthOrArrayLayers: 1,
    ),
),
CreateTexture(Id(2, 1, Vulkan), (
    label: None,
    size: (
        width: 1200,
        height: 900,
        depthOrArrayLayers: 1,
    ),
    mip_level_count: 1,
    sample_count: 1,
    dimension: r#2d,
    format: "bgra8unorm",
    usage: 19,
    view_formats: [],
)),
CreateTexture(Id(3, 1, Vulkan), (
    label: None,
    size: (
        width: 400,
        height: 900,
        depthOrArrayLayers: 1,
    ),
    mip_level_count: 1,
    sample_count: 1,
    dimension: r#2d,
    format: "bgra8unorm",
    usage: 19,
    view_formats: [],
)),
CreateTexture(Id(4, 1, Vulkan), (
    label: None,
    size: (
        width: 400,
        height: 400,
        depthOrArrayLayers: 1,
    ),
    mip_level_count: 1,
    sample_count: 1,
    dimension: r#2d,
    format: "bgra8unorm",
    usage: 19,
    view_formats: [],
)),
CreateTextureView(
    id: Id(0, 1, Vulkan),
    parent_id: Id(4, 1, Vulkan),
    desc: (
        label: Some("view-canvas current texture 0"),
        format: None,
        dimension: None,
        range: (
            aspect: all,
            base_mip_level: 0,
            mip_level_count: None,
            base_array_layer: 0,
            array_layer_count: None,
        ),
    ),
),
CreateBindGroupLayout(Id(0, 1, Vulkan), (
    label: Some("mosaic layout"),
    entries: [
        (
            binding: 0,
            visibility: 3,
            ty: Buffer(
                ty: Uniform,
                has_dynamic_offset: false,
                min_binding_size: None,
            ),
            count: None,
        ),
        (
            binding: 1,
            visibility: 1,
            ty: Texture(
                sample_type: Float(
                    filterable: false,
                ),
                view_dimension: r#2d,
                multisampled: false,
            ),
            count: None,
        ),
        (
            binding: 11,
            visibility: 2,
            ty: Buffer(
                ty: Storage(
                    read_only: false,
                ),
                has_dynamic_offset: false,
                min_binding_size: None,
            ),
            count: None,
        ),
    ],
)),
CreateShaderModule(
    id: Id(0, 1, Vulkan),
    desc: (
        label: None,
        shader_bound_checks: (
            runtime_checks: true,
        ),
    ),
    data: "data2.wgsl",
),
CreatePipelineLayout(Id(0, 1, Vulkan), (
    label: None,
    bind_group_layouts: [
        Id(0, 1, Vulkan),
    ],
    push_constant_ranges: [],
)),
CreateRenderPipeline(
    id: Id(0, 1, Vulkan),
    desc: (
        label: Some("Mosaic Pipeline"),
        layout: Some(Id(0, 1, Vulkan)),
        vertex: (
            stage: (
                module: Id(0, 1, Vulkan),
                entry_point: "vertMain",
            ),
            buffers: [
                (
                    arrayStride: 8,
                    stepMode: vertex,
                    attributes: [
                        (
                            format: float32x2,
                            offset: 0,
                            shaderLocation: 0,
                        ),
                    ],
                ),
                (
                    arrayStride: 8,
                    stepMode: instance,
                    attributes: [
                        (
                            format: float32x2,
                            offset: 0,
                            shaderLocation: 1,
                        ),
                    ],
                ),
            ],
        ),
        primitive: (
            topology: r#triangle-strip,
            stripIndexFormat: None,
            frontFace: ccw,
            cullMode: None,
            unclippedDepth: false,
            polygonMode: fill,
            conservative: false,
        ),
        depth_stencil: None,
        multisample: (
            count: 1,
            mask: 4294967295,
            alphaToCoverageEnabled: false,
        ),
        fragment: Some((
            stage: (
                module: Id(0, 1, Vulkan),
                entry_point: "fragMain",
            ),
            targets: [
                Some((
                    format: "bgra8unorm",
                    blend: Some((
                        color: (
                            srcFactor: one,
                            dstFactor: r#one-minus-src-alpha,
                            operation: add,
                        ),
                        alpha: (
                            srcFactor: zero,
                            dstFactor: one,
                            operation: add,
                        ),
                    )),
                    writeMask: 15,
                )),
            ],
        )),
        multiview: None,
    ),
    implicit_context: None,
),
CreateBuffer(Id(30, 1, Vulkan), (
    label: None,
    size: 32,
    usage: 40,
    mapped_at_creation: false,
)),
WriteBuffer(
    id: Id(30, 1, Vulkan),
    data: "data3.bin",
    range: (
        start: 0,
        end: 32,
    ),
    queued: true,
),
CreateBuffer(Id(31, 1, Vulkan), (
    label: None,
    size: 5456,
    usage: 40,
    mapped_at_creation: false,
)),
WriteBuffer(
    id: Id(31, 1, Vulkan),
    data: "data4.bin",
    range: (
        start: 0,
        end: 5456,
    ),
    queued: true,
),
CreateTextureView(
    id: Id(1, 1, Vulkan),
    parent_id: Id(1, 1, Vulkan),
    desc: (
        label: Some("view "),
        format: None,
        dimension: None,
        range: (
            aspect: all,
            base_mip_level: 0,
            mip_level_count: None,
            base_array_layer: 0,
            array_layer_count: None,
        ),
    ),
),
CreateBuffer(Id(32, 1, Vulkan), (
    label: None,
    size: 32,
    usage: 72,
    mapped_at_creation: false,
)),
CreateBuffer(Id(33, 1, Vulkan), (
    label: None,
    size: 64,
    usage: 132,
    mapped_at_creation: false,
)),
Submit(1, [
    RunRenderPass(
        base: (
            label: Some("Mosaic shader render pass"),
            commands: [
                SetPipeline(Id(0, 1, Vulkan)),
                SetVertexBuffer(
                    slot: 0,
                    buffer_id: Id(30, 1, Vulkan),
                    offset: 0,
                    size: None,
                ),
                SetVertexBuffer(
                    slot: 1,
                    buffer_id: Id(31, 1, Vulkan),
                    offset: 0,
                    size: None,
                ),
                Draw(    // the error happens here, we set a pipeline that requires a bind group but did not set the bind group.
                    vertex_count: 4,
                    instance_count: 682,
                    first_vertex: 0,
                    first_instance: 0,
                ),
            ],
            dynamic_offsets: [],
            string_data: [],
            push_constant_data: [],
        ),
        target_colors: [
            Some((
                view: Id(0, 1, Vulkan),
                resolve_target: None,
                channel: (
                    load_op: clear,
                    store_op: store,
                    clear_value: (
                        r: 0.1,
                        g: 0.3,
                        b: 0.4,
                        a: 1.0,
                    ),
                    read_only: false,
                ),
            )),
        ],
        target_depth_stencil: None,
        timestamp_writes: None,
        occlusion_query_set_id: None,
    ),
]),
CreateBuffer(Id(29, 1, Vulkan), (
    label: None,
    size: 716800,
    usage: 9,
    mapped_at_creation: false,
)),
Submit(2, [
    CopyTextureToBuffer(
        src: (
            texture: Id(4, 1, Vulkan),
            mip_level: 0,
            origin: (
                x: 0,
                y: 0,
                z: 0,
            ),
            aspect: all,
        ),
        dst: (
            buffer: Id(29, 1, Vulkan),
            layout: (
                offset: 0,
                bytes_per_row: Some(1792),
                rows_per_image: None,
            ),
        ),
        size: (
            width: 400,
            height: 400,
            depthOrArrayLayers: 1,
        ),
    ),
]),
DestroyTexture(Id(3, 1, Vulkan)),
DestroyTexture(Id(2, 1, Vulkan)),
DestroyShaderModule(Id(0, 1, Vulkan)),
DestroyTextureView(Id(1, 1, Vulkan)),
]

And now that I attached all of this information to the bug I realize that the trace is merely a product of the issue but does not really reproduce it because it is recorded after we incorrectly discard the setBindGroup from the commands.

So at least two bad things happening here:

  • When we create a pipeline, we don't populate the list of implicit bind group layouts in all cases (source) which causes us to fail to create a valid bind group layout when calling pipeline.getBindGroupLayout(0) later. We try to create a bind group from the invalid layout and get an invalid one as a result.
  • The invalid bind groups and bind group layouts are represented by both an invalid ID (value zero) and an mValid = false flag. On the rust side of things the Id types are NonZero, so it is pretty bad to pass zero ids through the ffi boundary without checking. This is what is happening when we do setBindGroup in the render pass.

At this point I think that we should not be able to express invalid objects on the content side. Every object should have a valid ID and a spot in the registry on the parent side. The validity of the object must always be managed by the parent side. The spec has been specifically designed for thing to work this way and straying away from this structure is sure to create lots of unexpected bugs and undefined behavior.

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

Attachment

General

Created:
Updated:
Size: