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

Code before:
    }
    const wgpu::SamplerDescriptor descriptor{
        .label = label,
        .addressModeU = wgpu::AddressMode::ClampToEdge,
        .addressModeV = wgpu::AddressMode::ClampToEdge,
        .addressModeW = wgpu::AddressMode::ClampToEdge,
        .magFilter = magFilter,
        // minFilter and mipmapFilter shouldn't really matter, as the source texture should
        // have 1 mip level, but for consistency (also, Metal blitter implementation does this)...
        .minFilter = minFilter,
        .mipmapFilter = mipmapFilter,
        .lodMinClamp = 0.0f,  // should not matter, just being consistently defined
        .lodMaxClamp = 32.0f, // should not matter, just being consistently defined
        .compare = wgpu::CompareFunction::Undefined, // should not matter, just being consistently
                                                     // defined
        .maxAnisotropy = 1, // should not matter, just being consistently defined
    };
    const wgpu::Sampler sampler{ mDevice.CreateSampler(&descriptor) };
    FILAMENT_CHECK_POSTCONDITION(sampler) << "Failed to create blit sampler?";
    switch (filter) {
        case SamplerMagFilter::NEAREST:
            mNearestSampler = sampler;
            break;
        case SamplerMagFilter::LINEAR:
            mLinearSampler = sampler;
            break;
    }
}

// Caches and returns a render pipeline for a given blit configuration.
// If a pipeline for the given configuration does not exist, it creates and caches one.
// The cache key is a hash of the filter type, source dimension, sample count, and formats.
wgpu::RenderPipeline const& WebGPUBlitter::getOrCreateRenderPipeline(
        const SamplerMagFilter filterType, const wgpu::TextureViewDimension sourceDimension,
        const uint32_t sourceSampleCount, const bool depthSource,
        const wgpu::TextureFormat destinationTextureFormat) {
    const size_t key{ hashRenderPipelineKey(filterType, sourceDimension, sourceSampleCount,
            depthSource, destinationTextureFormat) };
    if (mRenderPipelines.find(key) == mRenderPipelines.end()) {
        mRenderPipelines[key] = createRenderPipeline(filterType, sourceDimension, sourceSampleCount,
                depthSource, destinationTextureFormat);
    }
    return mRenderPipelines[key];
}

// Creates a render pipeline for a blit operation.
// The pipeline is configured with the appropriate vertex and fragment shaders,
// pipeline layout, and render target state based on the blit parameters.
wgpu::RenderPipeline WebGPUBlitter::createRenderPipeline(const SamplerMagFilter filterType,
        const wgpu::TextureViewDimension sourceDimension, const uint32_t sourceSampleCount,
        const bool depthSource, const wgpu::TextureFormat destinationTextureFormat) {

Review comment (performance):
I think I would remove this comment and add to the header for the function something like:
```cpp
/**
  * If a pipeline for the given configuration already exists, that one is returned from the cache.
  * Otherwise, this creates, caches, and returns one.
  */
```

This same kind of wording could be applied to the other getOrCreate functions.

I think the cache key bit is redundant with the hashing function documentations/implementations.

Code after:
        .addressModeV = wgpu::AddressMode::ClampToEdge,
        .addressModeW = wgpu::AddressMode::ClampToEdge,
        .magFilter = magFilter,
        // minFilter and mipmapFilter shouldn't really matter, as the source texture should
        // have 1 mip level, but for consistency (also, Metal blitter implementation does this)...
        .minFilter = minFilter,
        .mipmapFilter = mipmapFilter,
        .lodMinClamp = 0.0f,  // should not matter, just being consistently defined
        .lodMaxClamp = 32.0f, // should not matter, just being consistently defined
        .compare = wgpu::CompareFunction::Undefined, // should not matter, just being consistently
                                                     // defined
        .maxAnisotropy = 1, // should not matter, just being consistently defined
    };
    const wgpu::Sampler sampler{ mDevice.CreateSampler(&descriptor) };
    FILAMENT_CHECK_POSTCONDITION(sampler) << "Failed to create blit sampler.";
    switch (filter) {
        case SamplerMagFilter::NEAREST:
            mNearestSampler = sampler;
            break;
        case SamplerMagFilter::LINEAR:
            mLinearSampler = sampler;
            break;
    }
}

// Caches and returns a render pipeline for a given blit configuration.
// If a pipeline for the given configuration does not exist, it creates and caches one.
wgpu::RenderPipeline const& WebGPUBlitter::getOrCreateRenderPipeline(
        const SamplerMagFilter filterType, const wgpu::TextureViewDimension sourceDimension,
        const uint32_t sourceSampleCount, const bool depthSource,
        const wgpu::TextureFormat destinationTextureFormat) {
    const size_t key{ hashRenderPipelineKey(filterType, sourceDimension, sourceSampleCount,
            depthSource, destinationTextureFormat) };
    if (mRenderPipelines.find(key) == mRenderPipelines.end()) {
        mRenderPipelines[key] = createRenderPipeline(filterType, sourceDimension, sourceSampleCount,
                depthSource, destinationTextureFormat);
    }
    return mRenderPipelines[key];
}

// Creates a render pipeline for a blit operation.
// The pipeline is configured with the appropriate vertex and fragment shaders,
// pipeline layout, and render target state based on the blit parameters.
wgpu::RenderPipeline WebGPUBlitter::createRenderPipeline(const SamplerMagFilter filterType,
        const wgpu::TextureViewDimension sourceDimension, const uint32_t sourceSampleCount,
        const bool depthSource, const wgpu::TextureFormat destinationTextureFormat) {
    const bool depthDestination{ hasDepth(destinationTextureFormat) };
    const wgpu::ColorTargetState colorTargetState{ .format = destinationTextureFormat };
    const wgpu::DepthStencilState depthStencilState{
        .format = destinationTextureFormat,
        .depthWriteEnabled = true,