// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cstdint>
#include <limits>
#include <string>
#include <vector>

#include "src/dawn/tests/unittests/validation/ValidationTest.h"
#include "src/dawn/utils/ComboRenderPipelineDescriptor.h"
#include "src/dawn/utils/WGPUHelpers.h"
#include "src/utils/non_movable.h"

namespace dawn {
namespace {

enum class FeatureMode {
    Enabled,
    DisabledViaBlocklistedFeatures,
};

// Test that the feature only works when enabled
struct ImmediateDataDisableTest : ValidationTestWithParam<FeatureMode> {
    std::vector<const char*> GetWGSLBlocklistedFeatures() override {
        switch (GetParam()) {
            case FeatureMode::Enabled:
                return {};
            case FeatureMode::DisabledViaBlocklistedFeatures:
                return {"immediate_address_space"};
        }
        DAWN_UNREACHABLE();
        return {};
    }
};

// Check that creating a PipelineLayout with non-zero immediateSize is disallowed
// without the feature enabled.
TEST_P(ImmediateDataDisableTest, ImmediateSizeNotAllowed) {
    wgpu::PipelineLayoutDescriptor desc{};
    desc.immediateSize = 4;

    if (GetParam() == FeatureMode::Enabled) {
        device.CreatePipelineLayout(&desc);
    } else {
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
}

// Check that SetImmediates doesn't work (even with size=0) without the feature enabled.
TEST_P(ImmediateDataDisableTest, SetImmediates) {
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetImmediates(0, nullptr, 0);
        pass.End();
        if (GetParam() == FeatureMode::Enabled) {
            encoder.Finish();
        } else {
            ASSERT_DEVICE_ERROR(encoder.Finish());
        }
    }
    {
        const uint32_t data = 0;

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetImmediates(0, &data, 4);
        pass.End();
        if (GetParam() == FeatureMode::Enabled) {
            encoder.Finish();
        } else {
            ASSERT_DEVICE_ERROR(encoder.Finish());
        }
    }
}

// Check that limits.maxImmediateSize is 0 when the feature is disabled, and kMaxImmediateDataBytes
// otherwise.
TEST_P(ImmediateDataDisableTest, MaxImmediateSizeIsZero) {
    if (GetParam() == FeatureMode::Enabled) {
        ASSERT_EQ(GetSupportedLimits().maxImmediateSize, kMaxImmediateDataBytes);
    } else {
        ASSERT_EQ(GetSupportedLimits().maxImmediateSize, 0u);
    }
}

INSTANTIATE_TEST_SUITE_P(,
                         ImmediateDataDisableTest,
                         ::testing::ValuesIn({FeatureMode::Enabled,
                                              FeatureMode::DisabledViaBlocklistedFeatures}));

class ImmediateDataTest : public ValidationTest {
  protected:
    wgpu::BindGroupLayout CreateBindGroupLayout() {
        wgpu::BindGroupLayoutEntry entries[1];
        entries[0].binding = 0;
        entries[0].visibility = wgpu::ShaderStage::Compute;
        entries[0].buffer.type = wgpu::BufferBindingType::Storage;

        wgpu::BindGroupLayoutDescriptor bindGroupLayoutDesc;
        bindGroupLayoutDesc.entryCount = 1;
        bindGroupLayoutDesc.entries = entries;

        return device.CreateBindGroupLayout(&bindGroupLayoutDesc);
    }

    wgpu::PipelineLayout CreatePipelineLayout(uint32_t requiredImmediateSize) {
        wgpu::BindGroupLayout bindGroupLayout = CreateBindGroupLayout();

        wgpu::PipelineLayoutDescriptor pipelineLayoutDesc;
        pipelineLayoutDesc.bindGroupLayoutCount = 1;
        pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
        pipelineLayoutDesc.immediateSize = requiredImmediateSize;
        return device.CreatePipelineLayout(&pipelineLayoutDesc);
    }

    wgpu::ShaderModule mShaderModule;
};

// Check that non-zero immediateSize is possible with feature enabled and size must
// below max size limits.
TEST_F(ImmediateDataTest, ValidateImmediateSize) {
    wgpu::PipelineLayoutDescriptor desc{};

    // Success case with valid immediateSize.
    {
        desc.immediateSize = kMaxImmediateDataBytes;
        device.CreatePipelineLayout(&desc);
    }

    // Failed case with invalid immediateSize that exceed limits.
    {
        desc.immediateSize = kMaxImmediateDataBytes + 4;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
}

// Check that immediateSize must be aligned to kImmediateElementByteSize (4 bytes).
TEST_F(ImmediateDataTest, ValidateImmediateSizeAlignment) {
    wgpu::PipelineLayoutDescriptor desc{};

    // Success case: aligned to 4 bytes.
    {
        desc.immediateSize = 4;
        device.CreatePipelineLayout(&desc);
    }
    {
        desc.immediateSize = 8;
        device.CreatePipelineLayout(&desc);
    }
    {
        desc.immediateSize = kMaxImmediateDataBytes;
        device.CreatePipelineLayout(&desc);
    }

    // Failed case: not aligned to 4 bytes.
    {
        desc.immediateSize = 1;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
    {
        desc.immediateSize = 2;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
    {
        desc.immediateSize = 3;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
    {
        desc.immediateSize = 5;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
    }
}

// Check that SetImmediates offset and length must be aligned to 4 bytes.
TEST_F(ImmediateDataTest, ValidateSetImmediatesAlignment) {
    // Success cases
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t data = 0;
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(0, &data, 4);
        computePass.End();
        encoder.Finish();
    }

    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(4, nullptr, 0);
        computePass.End();
        encoder.Finish();
    }

    // Failed case with non-aligned offset bytes
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(2, nullptr, 0);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failed cases with non-aligned size
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint8_t data = 0;
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(0, &data, 2);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Check that SetImmediates offset + length must be in bound.
TEST_F(ImmediateDataTest, ValidateSetImmediatesOOB) {
    // Success cases
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        std::vector<uint32_t> data(kMaxImmediateDataBytes / 4, 0);
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(0, data.data(), kMaxImmediateDataBytes);
        computePass.End();
        encoder.Finish();
    }

    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(kMaxImmediateDataBytes, nullptr, 0);
        computePass.End();
        encoder.Finish();
    }

    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t data = 0;
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(kMaxImmediateDataBytes - 4, &data, 4);
        computePass.End();
        encoder.Finish();
    }

    // Failed case with offset oob
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t offset = kMaxImmediateDataBytes + 4;
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(offset, nullptr, 0);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failed cases with size oob
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t size = kMaxImmediateDataBytes + 4;
        std::vector<uint32_t> data(size / 4, 0);
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(0, data.data(), size);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failed cases with offset + size oob
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t offset = kMaxImmediateDataBytes;
        uint32_t data[] = {0};
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(offset, data, 4);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failed case with super large offset + size oob but looping back to zero
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        uint32_t offset = std::numeric_limits<uint32_t>::max() - 3;
        uint32_t data[] = {0};
        wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
        computePass.SetImmediates(offset, data, 4);
        computePass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Check that pipelineLayout immediate data bytes compatible with shaders.
TEST_F(ImmediateDataTest, ValidatePipelineLayoutImmediateDataBytesAndShaders) {
    constexpr uint32_t kShaderImmediateDataBytes = 12u;
    wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, R"(
        var<immediate> fragmentConstants: vec3f;
        var<immediate> computeConstants: vec3u;
        @vertex fn vsMain(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
            const pos = array(
                vec2( 1.0, -1.0),
                vec2(-1.0, -1.0),
                vec2( 0.0,  1.0),
            );
            return vec4(pos[VertexIndex], 0.0, 1.0);
        }

        // to reuse the same pipeline layout
        @fragment fn fsMain() -> @location(0) vec4f {
            return vec4f(fragmentConstants, 1.0);
        }


        @group(0) @binding(0) var<storage, read_write> output : vec3u;

        @compute @workgroup_size(1, 1, 1)
        fn csMain() {
            output = computeConstants;
        })");

    // Success cases
    {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;
        pipelineDescriptor.vertex.module = shaderModule;
        pipelineDescriptor.cFragment.module = shaderModule;
        pipelineDescriptor.layout = CreatePipelineLayout(kShaderImmediateDataBytes);
        device.CreateRenderPipeline(&pipelineDescriptor);
    }

    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = shaderModule;
        csDesc.layout = CreatePipelineLayout(kShaderImmediateDataBytes);

        device.CreateComputePipeline(&csDesc);
    }

    // Default layout
    {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;
        pipelineDescriptor.vertex.module = shaderModule;
        pipelineDescriptor.cFragment.module = shaderModule;
        device.CreateRenderPipeline(&pipelineDescriptor);
    }

    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = shaderModule;

        device.CreateComputePipeline(&csDesc);
    }

    // Failed case with fragment shader requires more immediate data.
    {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;
        pipelineDescriptor.vertex.module = shaderModule;
        pipelineDescriptor.cFragment.module = shaderModule;
        pipelineDescriptor.layout = CreatePipelineLayout(kShaderImmediateDataBytes - 4);
        ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&pipelineDescriptor));
    }

    // Failed cases with compute shader requires more immediate data.
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = shaderModule;
        csDesc.layout = CreatePipelineLayout(kShaderImmediateDataBytes - 4);

        ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
    }
}

// Check that default pipelineLayout has too many immediate data bytes .
TEST_F(ImmediateDataTest, ValidateDefaultPipelineLayout) {
    wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, R"(
            var<immediate> fragmentConstants: vec4f;

            var<immediate> computeConstants: vec4u;

            @vertex fn vsMain(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
                const pos = array(
                    vec2( 1.0, -1.0),
                    vec2(-1.0, -1.0),
                    vec2( 0.0,  1.0),
                );
                return vec4(pos[VertexIndex], 0.0, 1.0);
            }

            // to reuse the same pipeline layout
            @fragment fn fsMain() -> @location(0) vec4f {
                return vec4f(fragmentConstants.x, fragmentConstants.yzw);
            }

            @group(0) @binding(0) var<storage, read_write> output : vec4u;

            @compute @workgroup_size(1, 1, 1)
            fn csMain() {
                output = vec4u(computeConstants.x, computeConstants.yzw);
            })");

    // Shader module creation should succeed even with too much immediate data.
    // The validation error should occur at pipeline creation time.
    wgpu::ShaderModule oobShaderModule = utils::CreateShaderModule(device, R"(
            struct FragmentConstants {
                c0: vec4f,
                c1: vec4f,
                c2: vec4f,
                c3: vec4f,
                constantsOOB: f32,
            };

            struct ComputeConstants {
                c0: vec4u,
                c1: vec4u,
                c2: vec4u,
                c3: vec4u,
                constantsOOB: u32,
            };
            var<immediate> fragmentConstants: FragmentConstants;
            var<immediate> computeConstants: ComputeConstants;
            @vertex fn vsMain(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
                const pos = array(
                    vec2( 1.0, -1.0),
                    vec2(-1.0, -1.0),
                    vec2( 0.0,  1.0),
                );
                return vec4(pos[VertexIndex], 0.0, 1.0);
            }

            // to reuse the same pipeline layout
            @fragment fn fsMain() -> @location(0) vec4f {
                return vec4f(fragmentConstants.c0.x + fragmentConstants.constantsOOB,
                             fragmentConstants.c0.yzw);
            }

            @group(0) @binding(0) var<storage, read_write> output : vec4u;

            @compute @workgroup_size(1, 1, 1)
            fn csMain() {
                output = vec4u(computeConstants.c0.x + computeConstants.constantsOOB,
                               computeConstants.c0.yzw);
            })");

    // Failed case: too much immediate data in shader should fail at pipeline creation.
    {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;
        pipelineDescriptor.vertex.module = oobShaderModule;
        pipelineDescriptor.cFragment.module = oobShaderModule;
        ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&pipelineDescriptor));
    }

    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = oobShaderModule;

        ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
    }

    // Success cases
    {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;
        pipelineDescriptor.vertex.module = shaderModule;
        pipelineDescriptor.cFragment.module = shaderModule;
        device.CreateRenderPipeline(&pipelineDescriptor);
    }

    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = shaderModule;

        device.CreateComputePipeline(&csDesc);
    }
}

// Check that executing multiple bundles with different immediate data requirements works.
TEST_F(ImmediateDataTest, ExecuteBundlesWithDifferentImmediateData) {
    // Pipeline 4: requires 4 bytes
    wgpu::ShaderModule module4 = utils::CreateShaderModule(device, R"(
        var<immediate> constants: u32;
        @vertex fn vs() -> @builtin(position) vec4f {
            _ = constants;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
        @fragment fn fs() -> @location(0) vec4f {
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
    )");
    utils::ComboRenderPipelineDescriptor desc4;
    desc4.vertex.module = module4;
    desc4.cFragment.module = module4;
    wgpu::RenderPipeline pipeline4 = device.CreateRenderPipeline(&desc4);

    // Pipeline 8: requires 8 bytes
    wgpu::ShaderModule module8 = utils::CreateShaderModule(device, R"(
        struct Constants {
            a: u32,
            b: u32,
        }
        var<immediate> constants: Constants;
        @vertex fn vs() -> @builtin(position) vec4f {
            _ = constants.b;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
        @fragment fn fs() -> @location(0) vec4f {
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
    )");
    utils::ComboRenderPipelineDescriptor desc8;
    desc8.vertex.module = module8;
    desc8.cFragment.module = module8;
    wgpu::RenderPipeline pipeline8 = device.CreateRenderPipeline(&desc8);

    utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // Bundle 4
    wgpu::RenderBundle bundle4;
    {
        wgpu::RenderBundleEncoderDescriptor bundleDesc;
        bundleDesc.colorFormatCount = 1;
        bundleDesc.colorFormats = &renderPass.colorFormat;
        wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&bundleDesc);
        encoder.SetPipeline(pipeline4);
        uint32_t data = 0;
        encoder.SetImmediates(0, &data, 4);
        encoder.Draw(3);
        bundle4 = encoder.Finish();
    }

    // Bundle 8
    wgpu::RenderBundle bundle8;
    {
        wgpu::RenderBundleEncoderDescriptor bundleDesc;
        bundleDesc.colorFormatCount = 1;
        bundleDesc.colorFormats = &renderPass.colorFormat;
        wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&bundleDesc);
        encoder.SetPipeline(pipeline8);
        uint32_t data[] = {0, 0};
        encoder.SetImmediates(0, data, 8);
        encoder.Draw(3);
        bundle8 = encoder.Finish();
    }

    // Execute both
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
    wgpu::RenderBundle bundles[] = {bundle4, bundle8};
    pass.ExecuteBundles(2, bundles);
    pass.End();
    encoder.Finish();
}

// Check that ExecuteBundles resets the immediate data state in the RenderPass.
TEST_F(ImmediateDataTest, ExecuteBundlesResetsImmediateDataState) {
    // Pipeline 4: requires 4 bytes
    wgpu::ShaderModule module4 = utils::CreateShaderModule(device, R"(
        var<immediate> constants: u32;
        @vertex fn vs() -> @builtin(position) vec4f {
            _ = constants;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
        @fragment fn fs() -> @location(0) vec4f {
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
    )");
    utils::ComboRenderPipelineDescriptor desc4;
    desc4.vertex.module = module4;
    desc4.cFragment.module = module4;
    wgpu::RenderPipeline pipeline4 = device.CreateRenderPipeline(&desc4);

    // Bundle (placeholder, just to execute)
    wgpu::RenderBundle bundle;
    {
        wgpu::RenderBundleEncoderDescriptor bundleDesc;
        bundleDesc.colorFormatCount = 1;
        wgpu::TextureFormat format = wgpu::TextureFormat::RGBA8Unorm;
        bundleDesc.colorFormats = &format;
        wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&bundleDesc);
        bundle = encoder.Finish();
    }

    // Case 1: Immediate -> ExecuteBundles -> SetPipeline -> Draw (Fail: No immediate data)
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);

        pass.SetPipeline(pipeline4);
        uint32_t data = 0;
        pass.SetImmediates(0, &data, 4);

        pass.ExecuteBundles(1, &bundle);

        pass.SetPipeline(pipeline4);  // Restore pipeline
        pass.Draw(3);                 // Should fail (Immediate data lost)
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Case 2: ExecuteBundles -> SetImmediates -> SetPipeline -> Draw (Success)
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.ExecuteBundles(1, &bundle);
        uint32_t data = 0;
        pass.SetImmediates(0, &data, 4);
        pass.SetPipeline(pipeline4);
        pass.Draw(3);
        pass.End();
        encoder.Finish();
    }
}

enum class EncoderType {
    Compute,
    RenderPass,
    RenderBundle,
};

struct ImmediateDataRange {
    uint32_t offset;
    uint32_t size;
};

class ImmediateDataRequiredTest : public ImmediateDataTest,
                                  public testing::WithParamInterface<EncoderType> {
  protected:
    void TestImmediateDataValidation(std::string entryPoint,
                                     std::vector<ImmediateDataRange> ranges,
                                     bool success,
                                     EncoderType encoderType) {
        // Structs with padding:
        // PadMiddle:
        //   a: u32 (0..4)
        //   padding (4..16) -> 12 bytes
        //   b: vec4<f32> (16..32)
        //   Size: 32
        //
        // PadTail:
        //   a: vec3<f32> (0..12)
        //   padding (12..16) -> 4 bytes
        //   Size: 16
        //
        // Layout:
        //   padMiddle: offset 0, size 32
        //   padTail: offset 32, size 16
        const char* kShader = R"(
        struct PadMiddle {
            a : u32,
            b : vec4<f32>,
        }
        struct PadTail {
            a : vec3<f32>,
        }
        var<immediate> padMiddle : PadMiddle;
        var<immediate> padTail : PadTail;

        @compute @workgroup_size(1)
        fn mainMiddle() {
            _ = padMiddle.b;
        }

        @compute @workgroup_size(1)
        fn mainTail() {
            _ = padTail.a;
        }

        @vertex fn vsMiddle() -> @builtin(position) vec4f {
            _ = padMiddle.b;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
        @fragment fn fsMiddle() -> @location(0) vec4f {
            _ = padMiddle.b;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }

        @vertex fn vsTail() -> @builtin(position) vec4f {
            _ = padTail.a;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
        @fragment fn fsTail() -> @location(0) vec4f {
            _ = padTail.a;
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
    )";

        wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, kShader);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();

        auto SetImmediates = [&](auto& pass) {
            for (const auto& range : ranges) {
                if (range.size > 0) {
                    std::vector<uint32_t> data((range.size + 3) / 4, 0);
                    pass.SetImmediates(range.offset, data.data(), range.size);
                }
            }
        };

        auto CreateRenderPipeline = [&]() {
            utils::ComboRenderPipelineDescriptor descriptor;
            descriptor.vertex.module = shaderModule;
            descriptor.cFragment.module = shaderModule;

            if (entryPoint == "mainMiddle") {
                descriptor.vertex.entryPoint = "vsMiddle";
                descriptor.cFragment.entryPoint = "fsMiddle";
            } else {
                descriptor.vertex.entryPoint = "vsTail";
                descriptor.cFragment.entryPoint = "fsTail";
            }

            return device.CreateRenderPipeline(&descriptor);
        };

        switch (encoderType) {
            case EncoderType::Compute: {
                wgpu::ComputePipelineDescriptor descriptor;
                descriptor.compute.module = shaderModule;
                descriptor.compute.entryPoint = entryPoint.c_str();
                wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&descriptor);

                wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
                pass.SetPipeline(pipeline);
                SetImmediates(pass);
                pass.DispatchWorkgroups(1);
                pass.End();
                break;
            }
            case EncoderType::RenderPass: {
                wgpu::RenderPipeline pipeline = CreateRenderPipeline();
                utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
                wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
                pass.SetPipeline(pipeline);
                SetImmediates(pass);
                pass.Draw(3);
                pass.End();
                break;
            }
            case EncoderType::RenderBundle: {
                wgpu::RenderPipeline pipeline = CreateRenderPipeline();
                wgpu::RenderBundleEncoderDescriptor bundleDesc;
                bundleDesc.colorFormatCount = 1;
                wgpu::TextureFormat format = wgpu::TextureFormat::RGBA8Unorm;
                bundleDesc.colorFormats = &format;

                wgpu::RenderBundleEncoder bundleEncoder =
                    device.CreateRenderBundleEncoder(&bundleDesc);
                bundleEncoder.SetPipeline(pipeline);
                SetImmediates(bundleEncoder);
                bundleEncoder.Draw(3);

                if (success) {
                    bundleEncoder.Finish();
                } else {
                    ASSERT_DEVICE_ERROR(bundleEncoder.Finish());
                }
                return;
            }
        }

        if (success) {
            encoder.Finish();
        } else {
            ASSERT_DEVICE_ERROR(encoder.Finish());
        }
    }

    void RunTests(std::string entryPoint, std::vector<ImmediateDataRange> ranges, bool success) {
        TestImmediateDataValidation(entryPoint, ranges, success, GetParam());
    }
};

TEST_P(ImmediateDataRequiredTest, PadMiddleMissesA) {
    RunTests("mainMiddle", {{16, 16}}, false);
}

TEST_P(ImmediateDataRequiredTest, PadMiddleCoversAll) {
    RunTests("mainMiddle", {{0, 32}}, true);
}

TEST_P(ImmediateDataRequiredTest, PadMiddleMissesB) {
    RunTests("mainMiddle", {{0, 16}}, false);
}

TEST_P(ImmediateDataRequiredTest, PadMiddlePartialB) {
    RunTests("mainMiddle", {{16, 12}}, false);
}

TEST_P(ImmediateDataRequiredTest, PadMiddleSplitCoverage) {
    RunTests("mainMiddle", {{0, 4}, {16, 16}}, true);
}

TEST_P(ImmediateDataRequiredTest, PadTailCoversA) {
    RunTests("mainTail", {{0, 12}}, true);
}

TEST_P(ImmediateDataRequiredTest, PadTailCoversAll) {
    RunTests("mainTail", {{0, 16}}, true);
}

TEST_P(ImmediateDataRequiredTest, PadTailPartialA) {
    RunTests("mainTail", {{0, 8}}, false);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    ImmediateDataRequiredTest,
    ::testing::Values(EncoderType::Compute, EncoderType::RenderPass, EncoderType::RenderBundle),
    [](const testing::TestParamInfo<ImmediateDataRequiredTest::ParamType>& info) {
        switch (info.param) {
            case EncoderType::Compute:
                return "Compute";
            case EncoderType::RenderPass:
                return "RenderPass";
            case EncoderType::RenderBundle:
                return "RenderBundle";
        }
        return "Unknown";
    });

}  // anonymous namespace
}  // namespace dawn
