Repository: google/filament
File: filament/backend/src/webgpu/WebGPUDriver.cpp (C++)

Code before:
void WebGPUDriver::blit(
        Handle<HwTexture> dst, uint8_t srcLevel, uint8_t srcLayer, math::uint2 dstOrigin,
        Handle<HwTexture> src, uint8_t dstLevel, uint8_t dstLayer, math::uint2 srcOrigin,
        math::uint2 size) {
}

void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
    const auto* program = handleCast<WGPUProgram>(pipelineState.program);
    assert_invariant(program);
    FILAMENT_CHECK_POSTCONDITION(program->computeShaderModule == nullptr)
            << "WebGPU backend does not (yet) support compute pipelines.";
    FILAMENT_CHECK_POSTCONDITION(program->vertexShaderModule)
            << "WebGPU backend requires a vertex shader module for a render pipeline";
    std::array<wgpu::BindGroupLayout, MAX_DESCRIPTOR_SET_COUNT> bindGroupLayouts{};
    assert_invariant(bindGroupLayouts.size() == pipelineState.pipelineLayout.setLayout.size());
    size_t bindGroupLayoutCount = 0;
    for (size_t i = 0; i < bindGroupLayouts.size(); i++) {
        const auto handle = pipelineState.pipelineLayout.setLayout[bindGroupLayoutCount];
        if (handle.getId() == HandleBase::nullid) {
            continue;
        }
        bindGroupLayouts[bindGroupLayoutCount++] =
                handleCast<WebGPUDescriptorSetLayout>(handle)->getLayout();
    }
    std::stringstream layoutLabelStream;
    layoutLabelStream << program->name.c_str() << " layout";
    const auto layoutLabel = layoutLabelStream.str();
    const wgpu::PipelineLayoutDescriptor layoutDescriptor{
        .label = wgpu::StringView(layoutLabel),
        .bindGroupLayoutCount = bindGroupLayoutCount,
        .bindGroupLayouts = bindGroupLayouts.data()
        // TODO investigate immediateDataRangeByteSize
    };
    const wgpu::PipelineLayout layout = mDevice.CreatePipelineLayout(&layoutDescriptor);
    FILAMENT_CHECK_POSTCONDITION(layout)
            << "Failed to create wgpu::PipelineLayout for render pipeline for "
            << layoutDescriptor.label;
    auto const* vertexBufferInfo = handleCast<WGPUVertexBufferInfo>(pipelineState.vertexBufferInfo);
    assert_invariant(vertexBufferInfo);
    const wgpu::RenderPipeline pipeline = createWebGPURenderPipeline(mDevice, *program,
            *vertexBufferInfo, layout, pipelineState.rasterState, pipelineState.stencilState,
            pipelineState.polygonOffset, pipelineState.primitiveType, mSwapChain->getColorFormat(),
            mSwapChain->getDepthFormat());
    // TODO: uncomment once we have a valid pipeline to set
    // mRenderPassEncoder.SetPipeline(pipeline);
}

void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
    auto* renderPrimitive = handleCast<WGPURenderPrimitive>(rph);

    // This *must* match the WGPUVertexBufferInfo that was bound in bindPipeline(). But we want

Review comment (bug):
I'd consider doing all the strings/labels stuff only for debug builds. Seems a bit expensive to do it for release.  But we can revisit later.

Code after:
void WebGPUDriver::blit(
        Handle<HwTexture> dst, uint8_t srcLevel, uint8_t srcLayer, math::uint2 dstOrigin,
        Handle<HwTexture> src, uint8_t dstLevel, uint8_t dstLayer, math::uint2 srcOrigin,
        math::uint2 size) {
}

void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
    const auto* program = handleCast<WGPUProgram>(pipelineState.program);
    assert_invariant(program);
    assert_invariant(program->computeShaderModule == nullptr &&
                     "WebGPU backend does not (yet) support compute pipelines.");
    FILAMENT_CHECK_POSTCONDITION(program->vertexShaderModule)
            << "WebGPU backend requires a vertex shader module for a render pipeline";
    std::array<wgpu::BindGroupLayout, MAX_DESCRIPTOR_SET_COUNT> bindGroupLayouts{};
    assert_invariant(bindGroupLayouts.size() >= pipelineState.pipelineLayout.setLayout.size());
    size_t bindGroupLayoutCount = 0;
    for (size_t i = 0; i < bindGroupLayouts.size(); i++) {
        const auto handle = pipelineState.pipelineLayout.setLayout[bindGroupLayoutCount];
        if (handle.getId() == HandleBase::nullid) {
            continue;
        }
        bindGroupLayouts[bindGroupLayoutCount++] =
                handleCast<WebGPUDescriptorSetLayout>(handle)->getLayout();
    }
    std::stringstream layoutLabelStream;
    layoutLabelStream << program->name.c_str() << " layout";
    const auto layoutLabel = layoutLabelStream.str();
    const wgpu::PipelineLayoutDescriptor layoutDescriptor{
        .label = wgpu::StringView(layoutLabel),
        .bindGroupLayoutCount = bindGroupLayoutCount,
        .bindGroupLayouts = bindGroupLayouts.data()
        // TODO investigate immediateDataRangeByteSize
    };
    const wgpu::PipelineLayout layout = mDevice.CreatePipelineLayout(&layoutDescriptor);
    FILAMENT_CHECK_POSTCONDITION(layout)
            << "Failed to create wgpu::PipelineLayout for render pipeline for "
            << layoutDescriptor.label;
    auto const* vertexBufferInfo = handleCast<WGPUVertexBufferInfo>(pipelineState.vertexBufferInfo);
    assert_invariant(vertexBufferInfo);
    const wgpu::RenderPipeline pipeline = createWebGPURenderPipeline(mDevice, *program,
            *vertexBufferInfo, layout, pipelineState.rasterState, pipelineState.stencilState,
            pipelineState.polygonOffset, pipelineState.primitiveType, mSwapChain->getColorFormat(),
            mSwapChain->getDepthFormat());
    // TODO: uncomment once we have a valid pipeline to set
    // mRenderPassEncoder.SetPipeline(pipeline);
}

void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
    auto* renderPrimitive = handleCast<WGPURenderPrimitive>(rph);

    // This *must* match the WGPUVertexBufferInfo that was bound in bindPipeline(). But we want