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

Code before:
}

WGPUIndexBuffer::WGPUIndexBuffer(wgpu::Device const& device, uint8_t elementSize,
        uint32_t indexCount)
    : indexFormat(elementSize == 2 ? wgpu::IndexFormat::Uint16 : wgpu::IndexFormat::Uint32) {
    createBuffer(device, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Index,
            elementSize * indexCount, "index_buffer");
}


WGPUVertexBuffer::WGPUVertexBuffer(wgpu::Device const& device, uint32_t vertexCount,
        uint32_t bufferCount, Handle<HwVertexBufferInfo> vbih)
    : HwVertexBuffer(vertexCount),
      vbih(vbih),
      buffers(bufferCount) {}

WGPUBufferObject::WGPUBufferObject(wgpu::Device const& device, BufferObjectBinding bindingType,
        uint32_t byteCount)
    : HwBufferObject(byteCount) {
    createBuffer(device, wgpu::BufferUsage::CopyDst | getBufferObjectUsage(bindingType), byteCount,
            "buffer_object");
}

wgpu::ShaderStage WebGPUDescriptorSetLayout::filamentStageToWGPUStage(ShaderStageFlags fFlags) {
    wgpu::ShaderStage retStages = wgpu::ShaderStage::None;
    if (any(ShaderStageFlags::VERTEX & fFlags)) {
        retStages |= wgpu::ShaderStage::Vertex;
    }
    if (any(ShaderStageFlags::FRAGMENT & fFlags)) {
        retStages |= wgpu::ShaderStage::Fragment;
    }
    if (any(ShaderStageFlags::COMPUTE & fFlags)) {
        retStages |= wgpu::ShaderStage::Compute;
    }
    return retStages;
}

WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout,
        wgpu::Device const& device) {
    assert_invariant(device);

    std::string baseLabel;
    if (std::holds_alternative<utils::StaticString>(layout.label)) {
        const auto& temp = std::get_if<utils::StaticString>(&layout.label);
        baseLabel = temp->c_str();
    } else if (std::holds_alternative<utils::CString>(layout.label)) {
        const auto& temp = std::get_if<utils::CString>(&layout.label);
        baseLabel = temp->c_str();
    }

    // TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for

Review comment (suggestion):
@jc3265 @bridgewaterrobbie any idea why this isn't simply `attribute.offset`? I am trying to understand why we subtract `attribute.offset % attribute.stride`.

Code after:
            mVertexAttributes[DUMMY_WEBGPU_SLOT].push_back({
                .format = vertexFormat,
                .offset = 0,
                .shaderLocation = attributeIndex,
            });
            mVertexBufferLayouts[DUMMY_WEBGPU_SLOT].attributeCount++;
            continue;
        }

        auto it = std::find_if(mWebGPUSlotBindingInfos.begin(), mWebGPUSlotBindingInfos.end(),
                [&](const auto& info) {
                    return info.sourceBuffer == attribute.buffer && info.stride == attribute.stride;
                });

        uint32_t assignedSlot;
        if (it != mWebGPUSlotBindingInfos.end()) {
            assignedSlot = it->slot;
        } else {
            // New combination, allocate a new WebGPU slot
            assert_invariant(currentWebGPUSlotIndex < MAX_VERTEX_BUFFER_COUNT);
            assignedSlot = currentWebGPUSlotIndex++;

            mWebGPUSlotBindingInfos.push_back({
                .sourceBuffer = attribute.buffer,
                .slot = assignedSlot,
                .bufferOffset = attribute.offset - (attribute.offset % attribute.stride),
                .stride = attribute.stride,
            });

            mVertexBufferLayouts[assignedSlot].arrayStride = attribute.stride;
            mVertexBufferLayouts[assignedSlot].stepMode = wgpu::VertexStepMode::Vertex;
            mVertexBufferLayouts[assignedSlot].attributeCount = 0;
        }

        mVertexAttributes[assignedSlot].push_back({
            .format = vertexFormat,
            .offset = attribute.offset % attribute.stride,
            .shaderLocation = attributeIndex,
        });
        mVertexBufferLayouts[assignedSlot].attributeCount++;
    }

    mVertexBufferLayouts.resize(currentWebGPUSlotIndex);

    for (const auto& info: mWebGPUSlotBindingInfos) {
        mVertexBufferLayouts[info.slot].attributes = mVertexAttributes[info.slot].data();
    }
}

WGPUIndexBuffer::WGPUIndexBuffer(wgpu::Device const& device, uint8_t elementSize,
        uint32_t indexCount)