// 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 "dawn/common/NonMovable.h"
#include "dawn/tests/unittests/validation/ValidationTest.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

enum class FeatureMode {
    Enabled,
    DisabledViaNotAllowUnsafeAPIs,
    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::DisabledViaNotAllowUnsafeAPIs:
                return {};
            case FeatureMode::DisabledViaBlocklistedFeatures:
                return {"immediate_address_space"};
        }
        DAWN_UNREACHABLE();
        return {};
    }

    bool AllowUnsafeAPIs() override {
        switch (GetParam()) {
            case FeatureMode::Enabled:
                // Currently the only way to enable ImmediateAddressSpace is via AllowUnsafeAPIs.
                // See GetLanguageFeatureStatus.
                return true;
            case FeatureMode::DisabledViaNotAllowUnsafeAPIs:
                return false;
            case FeatureMode::DisabledViaBlocklistedFeatures:
                // Enabling AllowUnsafeAPIs while disabling via blocklist should still fail.
                return true;
        }
        DAWN_UNREACHABLE();
        return false;
    }
};

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

    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::DisabledViaNotAllowUnsafeAPIs,
                                              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 + 1;
        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);
            })");

    // Failed case with too much immediate data in shader
    ASSERT_DEVICE_ERROR(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);
            })"));

    // 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
