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

Code before:
        queue.WriteBuffer(buffer, byteOffset + legalSize, &mRemainderChunk, 4);
    }
}

WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
        AttributeArray const& attributes, wgpu::Limits const& deviceLimits)
    : HwVertexBufferInfo(bufferCount, attributeCount) {
    FILAMENT_CHECK_PRECONDITION(attributeCount <= MAX_VERTEX_ATTRIBUTE_COUNT &&
                                attributeCount <= deviceLimits.maxVertexAttributes)
            << "The number of vertex attributes requested (" << attributeCount
            << ") exceeds Filament's MAX_VERTEX_ATTRIBUTE_COUNT limit ("
            << MAX_VERTEX_ATTRIBUTE_COUNT << ") and/or the device's limit ("
            << deviceLimits.maxVertexAttributes << ")";
    mVertexAttributes.reserve(attributeCount);
    if (attributeCount == 0) {
        mVertexBufferLayouts.resize(0);
        mWebGPUSlotBindingInfos.resize(0);
        return; // should not be possible, but being defensive. nothing to do otherwise
    }
    // populate mWebGPUSlotBindingInfos and attribute info (slot + attribute) by going through each
    // attribute...
    constexpr uint32_t IMPOSSIBLE_SLOT_INDEX = MAX_VERTEX_BUFFER_COUNT;
    struct AttributeInfo final {
        uint8_t slot = IMPOSSIBLE_SLOT_INDEX;
        wgpu::VertexAttribute attribute = {};
        AttributeInfo() {
            slot = IMPOSSIBLE_SLOT_INDEX;
            attribute = {};
        }
        AttributeInfo(uint8_t slot_in, wgpu::VertexAttribute attribute_in) {
            slot = slot_in;
            attribute = attribute_in;
        }
    };
    std::array<AttributeInfo, MAX_VERTEX_ATTRIBUTE_COUNT> attributeInfos{};
    uint8_t currentWebGPUSlotIndex = 0;
    uint8_t currentAttributeIndex = 0;
    mVertexBufferLayouts.reserve(MAX_VERTEX_BUFFER_COUNT);
    mWebGPUSlotBindingInfos.reserve(mVertexBufferLayouts.capacity());
    for (uint32_t attributeIndex = 0; attributeIndex < attributes.size(); ++attributeIndex) {
        const auto& attribute = attributes[attributeIndex];
        if (attribute.buffer == Attribute::BUFFER_UNUSED) {
            // We ignore "unused" attributes, ones not associated with a buffer. If a shader
            // references such an attribute we have a bug one way or another. Either the API/CPU
            // will produce an error (best case scenario), where an attribute is referenced in the
            // shader but not provided by the backend API (CPU-side), or the shader would be getting
            // junk/undefined data from the GPU, since we do not have a valid buffer of data to
            // provide to the shader/GPU.
            continue;
        }
        bool const isInteger = attribute.flags & Attribute::FLAG_INTEGER_TARGET;

Review comment (performance):
We should use constructor initializer lists when we can, as they are more efficient, among other things, -> [ML Filament WebGPU C++ Coding Guidelines > Consider Doing (weaker opinions) > Prefer Constructor Initialization Lists When Possible](https://docs.google.com/document/d/1bBvYFjfAZ6sWXwYvbdQzh9egNItLMHzyGgLxpr1HY8M/edit?resourcekey=0-95-dhqXNMLgD_LG6haAmFw&tab=t.0#heading=h.1lpf8wdztltp).

Does this work?:
```cpp
AttributeInfo() : slot(IMPOSSIBLE_SLOT_INDEX), attribute({}) {}
AttributeInfo(uint8_t slot, wgpu::VertexAttribute attribute) : slot(slot), attribute(attribute) {}
```

Code after:
        queue.WriteBuffer(buffer, byteOffset + legalSize, &mRemainderChunk, 4);
    }
}

WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
        AttributeArray const& attributes, wgpu::Limits const& deviceLimits)
    : HwVertexBufferInfo(bufferCount, attributeCount) {
    FILAMENT_CHECK_PRECONDITION(attributeCount <= MAX_VERTEX_ATTRIBUTE_COUNT &&
                                attributeCount <= deviceLimits.maxVertexAttributes)
            << "The number of vertex attributes requested (" << attributeCount
            << ") exceeds Filament's MAX_VERTEX_ATTRIBUTE_COUNT limit ("
            << MAX_VERTEX_ATTRIBUTE_COUNT << ") and/or the device's limit ("
            << deviceLimits.maxVertexAttributes << ")";
    mVertexAttributes.reserve(attributeCount);
    if (attributeCount == 0) {
        mVertexBufferLayouts.resize(0);
        mWebGPUSlotBindingInfos.resize(0);
        return; // should not be possible, but being defensive. nothing to do otherwise
    }
    // populate mWebGPUSlotBindingInfos and attribute info (slot + attribute) by going through each
    // attribute...
    constexpr uint32_t IMPOSSIBLE_SLOT_INDEX = MAX_VERTEX_BUFFER_COUNT;
    struct AttributeInfo final {
        uint8_t slot = IMPOSSIBLE_SLOT_INDEX;
        wgpu::VertexAttribute attribute = {};
        AttributeInfo()
            : slot(IMPOSSIBLE_SLOT_INDEX),
              attribute({}) {}
        AttributeInfo(uint8_t slot, wgpu::VertexAttribute attribute)
            : slot(slot),
              attribute(attribute) {}
    };
    std::array<AttributeInfo, MAX_VERTEX_ATTRIBUTE_COUNT> attributeInfos{};
    uint8_t currentWebGPUSlotIndex = 0;
    uint8_t currentAttributeIndex = 0;
    mVertexBufferLayouts.reserve(MAX_VERTEX_BUFFER_COUNT);
    mWebGPUSlotBindingInfos.reserve(mVertexBufferLayouts.capacity());
    for (uint32_t attributeIndex = 0; attributeIndex < attributes.size(); ++attributeIndex) {
        const auto& attribute = attributes[attributeIndex];
        if (attribute.buffer == Attribute::BUFFER_UNUSED) {
            // We ignore "unused" attributes, ones not associated with a buffer. If a shader
            // references such an attribute we have a bug one way or another. Either the API/CPU
            // will produce an error (best case scenario), where an attribute is referenced in the
            // shader but not provided by the backend API (CPU-side), or the shader would be getting
            // junk/undefined data from the GPU, since we do not have a valid buffer of data to
            // provide to the shader/GPU.
            continue;
        }
        bool const isInteger = attribute.flags & Attribute::FLAG_INTEGER_TARGET;
        bool const isNormalized = attribute.flags & Attribute::FLAG_NORMALIZED;
        wgpu::VertexFormat const vertexFormat =