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

Code before:
#endif

namespace filament::backend {

class WebGPUSwapChain;

/**
 * WebGPU backend (driver) implementation
 */
class WebGPUDriver final : public DriverBase {
public:
    ~WebGPUDriver() noexcept override;

    [[nodiscard]] Dispatcher getDispatcher() const noexcept final;
    [[nodiscard]] static Driver* create(WebGPUPlatform& platform, const Platform::DriverConfig& driverConfig) noexcept;

private:
    explicit WebGPUDriver(WebGPUPlatform& platform, const Platform::DriverConfig& driverConfig) noexcept;
    [[nodiscard]] ShaderModel getShaderModel() const noexcept final;
    [[nodiscard]] ShaderLanguage getShaderLanguage() const noexcept final;

    template<typename GPUBufferObject>
    void updateGPUBuffer(GPUBufferObject* gpuBufferObject, BufferDescriptor&& bufferDescriptor,
            uint32_t byteOffset) {
        if (bufferDescriptor.size + byteOffset > gpuBufferObject->buffer.GetSize()) {
            FWGPU_LOGE << "Insufficient destination buffer size: "
                       << gpuBufferObject->buffer.GetSize() << utils::io::endl;
            scheduleDestroy(std::move(bufferDescriptor));
            return;
        }

        // TODO: All buffer objects are created with CopyDst usage.
        // This may have some performance implications. That should be investigated later.
        assert_invariant(gpuBufferObject->buffer.GetUsage() & wgpu::BufferUsage::CopyDst);

        // WriteBuffer is an async call. But cpu buffer data is already written to the staging
        // buffer on return from the WriteBuffer.
        mQueue.WriteBuffer(gpuBufferObject->buffer, byteOffset, bufferDescriptor.buffer,
                bufferDescriptor.size);
        scheduleDestroy(std::move(bufferDescriptor));
    }

    // the platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
    // handled in the WebGPUPlatform
    WebGPUPlatform& mPlatform;
    wgpu::Adapter mAdapter = nullptr;
    wgpu::Device mDevice = nullptr;
    wgpu::Queue mQueue = nullptr;
    void* mNativeWindow = nullptr;
    WebGPUSwapChain* mSwapChain = nullptr;
    uint64_t mNextFakeHandle = 1;

Review comment (bug):
Do the other backends just log an error and not update the buffer in this case or just us? Should we panic/crash? This is essentially a user (of Filament) error right?

Code after:
#endif

namespace filament::backend {

class WebGPUSwapChain;

/**
 * WebGPU backend (driver) implementation
 */
class WebGPUDriver final : public DriverBase {
public:
    ~WebGPUDriver() noexcept override;

    [[nodiscard]] Dispatcher getDispatcher() const noexcept final;
    [[nodiscard]] static Driver* create(WebGPUPlatform& platform, const Platform::DriverConfig& driverConfig) noexcept;

private:
    explicit WebGPUDriver(WebGPUPlatform& platform, const Platform::DriverConfig& driverConfig) noexcept;
    [[nodiscard]] ShaderModel getShaderModel() const noexcept final;
    [[nodiscard]] ShaderLanguage getShaderLanguage() const noexcept final;

    template<typename GPUBufferObject>
    void updateGPUBuffer(GPUBufferObject* gpuBufferObject, BufferDescriptor&& bufferDescriptor,
            uint32_t byteOffset) {
        FILAMENT_CHECK_PRECONDITION(bufferDescriptor.buffer)
                << "copyIntoBuffer called with a null buffer";
        FILAMENT_CHECK_PRECONDITION(
                bufferDescriptor.size + byteOffset <= gpuBufferObject->buffer.GetSize())
                << "Attempting to copy " << bufferDescriptor.size << " bytes into a buffer of size "
                << gpuBufferObject->buffer.GetSize() << " at offset " << byteOffset;

        // TODO: All buffer objects are created with CopyDst usage.
        // This may have some performance implications. That should be investigated later.
        assert_invariant(gpuBufferObject->buffer.GetUsage() & wgpu::BufferUsage::CopyDst);

        // WriteBuffer is an async call. But cpu buffer data is already written to the staging
        // buffer on return from the WriteBuffer.
        mQueue.WriteBuffer(gpuBufferObject->buffer, byteOffset, bufferDescriptor.buffer,
                bufferDescriptor.size);
        scheduleDestroy(std::move(bufferDescriptor));
    }

    // the platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
    // handled in the WebGPUPlatform
    WebGPUPlatform& mPlatform;
    wgpu::Adapter mAdapter = nullptr;
    wgpu::Device mDevice = nullptr;
    wgpu::Queue mQueue = nullptr;
    void* mNativeWindow = nullptr;
    WebGPUSwapChain* mSwapChain = nullptr;
    uint64_t mNextFakeHandle = 1;