// Copyright 2025 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 <utility>
#include <vector>

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

namespace dawn {
namespace {

class ResourceTableValidationTest : public ValidationTest {
  protected:
    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        return {wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable};
    }

    wgpu::ResourceTable MakeResourceTable(uint32_t size) {
        wgpu::ResourceTableDescriptor desc;
        desc.size = size;
        return device.CreateResourceTable(&desc);
    }

    wgpu::ResourceTable MakeErrorResourceTable(uint32_t size = 1) {
        wgpu::RenderPassMaxDrawCount maxDraw;
        maxDraw.maxDrawCount = 1000;
        wgpu::ResourceTableDescriptor desc{
            .nextInChain = &maxDraw,
            .size = size,
        };

        wgpu::ResourceTable table;
        ASSERT_DEVICE_ERROR(table = device.CreateResourceTable(&desc));
        return table;
    }

    wgpu::ComputePipeline MakeComputePipeline(bool defaulted, bool usesResourceTable) {
        auto shaderModuleUsesTable = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @compute @workgroup_size(1) fn main() {
                _ = hasResource<texture_2d<f32>>(0);
            }
        )");
        auto shaderModuleNoTable = utils::CreateShaderModule(device, R"(
            @compute @workgroup_size(1) fn main() {}
        )");

        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = usesResourceTable ? shaderModuleUsesTable : shaderModuleNoTable;

        if (defaulted) {
            csDesc.layout = nullptr;
            return device.CreateComputePipeline(&csDesc);
        }

        wgpu::PipelineLayoutResourceTable plResourceTable;
        plResourceTable.usesResourceTable = true;

        wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
        pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
        if (usesResourceTable) {
            pipelineLayoutDescriptor.nextInChain = &plResourceTable;
        }

        csDesc.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
        return device.CreateComputePipeline(&csDesc);
    }

    wgpu::RenderPipeline MakeRenderPipeline(bool defaulted, bool usesResourceTable) {
        auto shaderModuleUsesTable = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f();
            }
            @fragment fn fs() -> @location(0) vec4f {
                _ = hasResource<texture_2d<f32>>(0);
                return vec4f();
            }
        )");
        auto shaderModuleNoTable = utils::CreateShaderModule(device, R"(
            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f();
            }
            @fragment fn fs() -> @location(0) vec4f {
                return vec4f();
            }
        )");

        utils::ComboRenderPipelineDescriptor pDesc;
        pDesc.vertex.module = usesResourceTable ? shaderModuleUsesTable : shaderModuleNoTable;
        pDesc.cFragment.module = usesResourceTable ? shaderModuleUsesTable : shaderModuleNoTable;

        if (defaulted) {
            pDesc.layout = nullptr;
            return device.CreateRenderPipeline(&pDesc);
        }

        wgpu::PipelineLayoutResourceTable plResourceTable;
        plResourceTable.usesResourceTable = true;

        wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
        pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
        if (usesResourceTable) {
            pipelineLayoutDescriptor.nextInChain = &plResourceTable;
        }

        pDesc.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
        return device.CreateRenderPipeline(&pDesc);
    }

    enum class Mutator : uint8_t {
        Update,
        InsertBinding,
    };
    void TestMutator(Mutator mutator, const wgpu::BindingResource* resource, bool success) {
        wgpu::ResourceTable table = MakeResourceTable(1);

        switch (mutator) {
            case Mutator::Update: {
                wgpu::Status status;
                if (success) {
                    status = table.Update(0, resource);
                } else {
                    ASSERT_DEVICE_ERROR(status = table.Update(0, resource));
                }
                EXPECT_EQ(status, wgpu::Status::Success);
                break;
            }

            case Mutator::InsertBinding: {
                uint32_t slot = wgpu::kInvalidBinding;
                if (success) {
                    slot = table.InsertBinding(resource);
                } else {
                    ASSERT_DEVICE_ERROR(slot = table.InsertBinding(resource));
                }
                EXPECT_EQ(slot, 0u);
                break;
            }
        }
    }

    // Helper to make sure that the resource table is marked as used. Even if internally Dawn
    // doesn't track this, it makes tests more clearly correct.
    void UseResourceTableInSubmit(wgpu::ResourceTable table) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }
};

class ResourceTableValidationTestDisabled : public ValidationTest {
  protected:
    std::vector<wgpu::FeatureName> GetRequiredFeatures() override { return {}; }
};

// Test that validates that the feature must be enabled
TEST_F(ResourceTableValidationTestDisabled, FeatureNotEnabled) {
    wgpu::ResourceTableDescriptor descriptor;
    descriptor.size = 1u;
    ASSERT_DEVICE_ERROR(device.CreateResourceTable(&descriptor));
}

// Test that setting invalid size returns nullptr
TEST_F(ResourceTableValidationTest, InvalidSize) {
    wgpu::ResourceTableDescriptor descriptor;

    // Size 0 is valid
    descriptor.size = 0u;
    device.CreateResourceTable(&descriptor);

    // Size of 1 is valid
    descriptor.size = 1u;
    device.CreateResourceTable(&descriptor);

    // Size of kMaxResourceTableSize is valid
    descriptor.size = kMaxResourceTableSize;
    device.CreateResourceTable(&descriptor);

    // Size > limits is invalid
    descriptor.size = kMaxResourceTableSize + 1u;
    wgpu::ResourceTable table = device.CreateResourceTable(&descriptor);
    ASSERT_EQ(table.Get(), nullptr);
}

// Test that setting nextInChain to anything is an error
TEST_F(ResourceTableValidationTest, NextInChain) {
    // Control case, nextInChain = nullptr is valid.
    {
        wgpu::ResourceTableDescriptor descriptor{
            .nextInChain = nullptr,
            .size = 3,
        };
        device.CreateResourceTable(&descriptor);
    }

    // Control case, nextInChain = non null is invalid.
    {
        wgpu::RenderPassMaxDrawCount maxDraw;
        maxDraw.maxDrawCount = 1000;
        wgpu::ResourceTableDescriptor descriptor{
            .nextInChain = &maxDraw,
            .size = 3,
        };
        ASSERT_DEVICE_ERROR(device.CreateResourceTable(&descriptor));
    }
}

// Test the Destroy call on a ResourceTable
TEST_F(ResourceTableValidationTest, Destroy) {
    wgpu::ResourceTableDescriptor descriptor;
    descriptor.size = 1u;
    wgpu::ResourceTable resourceTable = device.CreateResourceTable(&descriptor);

    // Calling destroy is valid
    resourceTable.Destroy();

    // Calling it multiple times is valid
    resourceTable.Destroy();
}

// Control case where enabling use of a resource table with the feature enabled is valid.
TEST_F(ResourceTableValidationTest, PipelineLayoutCreation_SuccessWithFeatureEnabled) {
    wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
    pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
    wgpu::PipelineLayoutResourceTable resourceTable;
    resourceTable.usesResourceTable = true;
    pipelineLayoutDescriptor.nextInChain = &resourceTable;
    device.CreatePipelineLayout(&pipelineLayoutDescriptor);
}

// Error case where enabling use of a resource table with the feature disabled is an error.
TEST_F(ResourceTableValidationTestDisabled, PipelineLayoutCreation_FailureWithFeatureDisabled) {
    wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
    pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
    wgpu::PipelineLayoutResourceTable resourceTable;
    pipelineLayoutDescriptor.nextInChain = &resourceTable;

    // Failure case
    resourceTable.usesResourceTable = true;
    ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&pipelineLayoutDescriptor));

    // Success case
    resourceTable.usesResourceTable = false;
    device.CreatePipelineLayout(&pipelineLayoutDescriptor);
}

// Error case where compiling a shader using the resource table with the extension disabled is an
// error.
TEST_F(ResourceTableValidationTestDisabled, WGSLEnableNotAllowed) {
    ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
        }
    )"));
}

// Test that a shader using a resource table requires a layout with one.
TEST_F(ResourceTableValidationTest, PipelineCreation_ShaderRequiresLayoutWithResourceTable) {
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
        }
    )");

    wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
    pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
    wgpu::PipelineLayoutResourceTable resourceTable;
    pipelineLayoutDescriptor.nextInChain = &resourceTable;

    // Success case, the layout uses a resource table
    resourceTable.usesResourceTable = true;
    csDesc.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
    device.CreateComputePipeline(&csDesc);

    // Failure case, the layout does not use a resource table
    resourceTable.usesResourceTable = false;
    csDesc.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
    ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
}

// Test that it is valid to have a layout specifying a resource table with a shader that
// doesn't have one.
TEST_F(ResourceTableValidationTest, PipelineCreation_ShaderNoResourceTableWithLayoutThatHasOne) {
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        @compute @workgroup_size(1) fn main() {
        }
    )");

    wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
    pipelineLayoutDescriptor.bindGroupLayoutCount = 0;
    wgpu::PipelineLayoutResourceTable resourceTable;
    pipelineLayoutDescriptor.nextInChain = &resourceTable;

    resourceTable.usesResourceTable = true;
    csDesc.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
    device.CreateComputePipeline(&csDesc);
}

// Test that an defaulted pipeline layout with a shader that uses a resource table has a
// PipelineLayoutResourceTable with usesResourceTable == true.
TEST_F(ResourceTableValidationTest, PipelineCreation_DefaultedLayoutWithResourceTable) {
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
        }
    )");

    csDesc.layout = nullptr;  // Auto
    device.CreateComputePipeline(&csDesc);
}

// Test that an defaulted pipeline layout with a multi-stage shader where only one stage uses a
// resource table has a PipelineLayoutResourceTable with usesResourceTable == true.
TEST_F(ResourceTableValidationTest, PipelineCreation_OneShaderDefaultedLayoutWithResourceTable) {
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }
        @compute @workgroup_size(1) fn compute_main() {
            _ = hasResource<texture_2d<f32>>(0);
        }
        @fragment fn fs() -> @location(0) vec4f {
            return vec4f(1.0, 0.0, 0.0, 1.0);
        }
    )");

    csDesc.layout = nullptr;  // Auto
    device.CreateComputePipeline(&csDesc);
}

// Test that a resource table uses up a BindGroupLayout slot
TEST_F(ResourceTableValidationTest, PipelineLayoutCreation_ResourceTableUsesBindGroupLayoutSlot) {
    // Control case: max bgls, no resource table
    {
        std::vector bgLayout(kMaxBindGroups, utils::MakeBindGroupLayout(device, {}));
        wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
        pipelineLayoutDescriptor.bindGroupLayoutCount = bgLayout.size();
        pipelineLayoutDescriptor.bindGroupLayouts = bgLayout.data();
        device.CreatePipelineLayout(&pipelineLayoutDescriptor);
    }

    // Failure case: not enough room for bgls and a resource table
    {
        std::vector bgLayout(kMaxBindGroups, utils::MakeBindGroupLayout(device, {}));
        wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
        pipelineLayoutDescriptor.bindGroupLayoutCount = bgLayout.size();
        pipelineLayoutDescriptor.bindGroupLayouts = bgLayout.data();
        wgpu::PipelineLayoutResourceTable resourceTable;
        resourceTable.usesResourceTable = true;
        pipelineLayoutDescriptor.nextInChain = &resourceTable;
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&pipelineLayoutDescriptor));
    }

    // Success case: enough room for bgls and a resource table
    {
        std::vector bgLayout(kMaxBindGroups - 1, utils::MakeBindGroupLayout(device, {}));
        wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
        pipelineLayoutDescriptor.bindGroupLayoutCount = bgLayout.size();
        pipelineLayoutDescriptor.bindGroupLayouts = bgLayout.data();
        wgpu::PipelineLayoutResourceTable resourceTable;
        resourceTable.usesResourceTable = true;
        pipelineLayoutDescriptor.nextInChain = &resourceTable;
        device.CreatePipelineLayout(&pipelineLayoutDescriptor);
    }
}

// Test that a resource table uses up a storage buffer binding
TEST_F(ResourceTableValidationTest, PipelineLayoutCreation_ResourceTableUsesOneStorageBuffer) {
    const uint32_t maxStorageBuffers = deviceLimits.maxStorageBuffersPerShaderStage;
    std::vector<wgpu::BindGroupLayoutEntry> storageBufferEntries(maxStorageBuffers);
    for (size_t i = 0; i < storageBufferEntries.size(); i++) {
        storageBufferEntries[i].buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
        storageBufferEntries[i].visibility =
            wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute;
        storageBufferEntries[i].binding = i;
    }

    // Success case: exactly maxStorageBuffers are used (1 for the resource table, max - 1 for BGL
    // entries).
    {
        wgpu::BindGroupLayoutDescriptor bglDesc = {
            .entryCount = maxStorageBuffers - 1,
            .entries = storageBufferEntries.data(),
        };
        wgpu::BindGroupLayout bgl = device.CreateBindGroupLayout(&bglDesc);

        wgpu::PipelineLayoutResourceTable resourceTable;
        resourceTable.usesResourceTable = true;
        wgpu::PipelineLayoutDescriptor plDesc = {
            .nextInChain = &resourceTable,
            .bindGroupLayoutCount = 1,
            .bindGroupLayouts = &bgl,
        };
        device.CreatePipelineLayout(&plDesc);
    }

    // Error case: the resource table additional storage buffer make the layout go over the limit.
    {
        wgpu::BindGroupLayoutDescriptor bglDesc = {
            .entryCount = maxStorageBuffers,
            .entries = storageBufferEntries.data(),
        };
        wgpu::BindGroupLayout bgl = device.CreateBindGroupLayout(&bglDesc);

        wgpu::PipelineLayoutResourceTable resourceTable;
        resourceTable.usesResourceTable = true;
        wgpu::PipelineLayoutDescriptor plDesc = {
            .nextInChain = &resourceTable,
            .bindGroupLayoutCount = 1,
            .bindGroupLayouts = &bgl,
        };
        ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&plDesc));
    }
}

// Test that an defaulted pipeline layout with a resource table uses up a BindGroupLayout slot
TEST_F(ResourceTableValidationTest,
       PipelineCreation_DefaultedLayoutWithResourceTableUsesBindGroupLayoutSlot) {
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.layout = nullptr;  // Auto

    // Control case: max bgls, no resource table
    {
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @group(0) @binding(0) var<uniform> a : u32;
            @group(1) @binding(0) var<uniform> b : u32;
            @group(2) @binding(0) var<uniform> c : u32;
            @group(3) @binding(0) var<uniform> d : u32;
            @compute @workgroup_size(1) fn main() {
                // _ = hasResource<texture_2d<f32>>(0);
                _ = a;
                _ = b;
                _ = c;
                _ = d;
            }
        )");
        device.CreateComputePipeline(&csDesc);
    }

    // Failure case: not enough room for bgls and a resource table
    {
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @group(0) @binding(0) var<uniform> a : u32;
            @group(1) @binding(0) var<uniform> b : u32;
            @group(2) @binding(0) var<uniform> c : u32;
            @group(3) @binding(0) var<uniform> d : u32;
            @compute @workgroup_size(1) fn main() {
                _ = hasResource<texture_2d<f32>>(0);
                _ = a;
                _ = b;
                _ = c;
                _ = d;
            }
        )");
        ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
    }

    // Success case: enough room for bgls and a resource table
    {
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @group(0) @binding(0) var<uniform> a : u32;
            @group(1) @binding(0) var<uniform> b : u32;
            @group(2) @binding(0) var<uniform> c : u32;
            @compute @workgroup_size(1) fn main() {
                _ = hasResource<texture_2d<f32>>(0);
                _ = a;
                _ = b;
                _ = c;
            }
        )");
        device.CreateComputePipeline(&csDesc);
    }
}

// Test that GetBindGroupLayout is valid for one less BGL if resource tables are used.
TEST_F(ResourceTableValidationTest, GetBindGroupLayoutValidForOneLessIndex) {
    // Default behavior case: GetBGL is valid until kMaxBindGroups - 1 when no resource table is
    // used.
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.layout = nullptr;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @compute @workgroup_size(1) fn main() {
            }
        )");
        wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

        pipeline.GetBindGroupLayout(kMaxBindGroups - 1);
        ASSERT_DEVICE_ERROR(pipeline.GetBindGroupLayout(kMaxBindGroups));
    }

    // Resource table case: GetBGL is valid until kMaxBindGroups - 2.
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.layout = nullptr;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;
            @compute @workgroup_size(1) fn main() {
                _ = hasResource<texture_2d<f32>>(0);
            }
        )");
        wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

        pipeline.GetBindGroupLayout(kMaxBindGroups - 2);
        ASSERT_DEVICE_ERROR(pipeline.GetBindGroupLayout(kMaxBindGroups - 1));
    }
}

// Tests calling ComputePassEncoder::SetResourceTable
TEST_F(ResourceTableValidationTest, ComputePassEncoder_SetResourceTable) {
    // Failure case: invalid encoder state
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.End();
        pass.SetResourceTable(nullptr);
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failure case: invalid resource table
    {
        ASSERT_DEVICE_ERROR(wgpu::ResourceTable resourceTable = MakeErrorResourceTable());

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Success case: valid resource table
    {
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.End();
        encoder.Finish();
    }

    // Success case: null resource table
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(nullptr);
        pass.End();
        encoder.Finish();
    }
}

// Tests calling RenderPassEncoder::SetResourceTable
TEST_F(ResourceTableValidationTest, RenderPassEncoder_SetResourceTable) {
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);

    // Failure case: invalid encoder state
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.End();
        pass.SetResourceTable(nullptr);
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Failure case: invalid resource table
    {
        ASSERT_DEVICE_ERROR(wgpu::ResourceTable resourceTable = MakeErrorResourceTable());

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Success case: valid resource table
    {
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.End();
        encoder.Finish();
    }

    // Success case: null resource table
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(nullptr);
        pass.End();
        encoder.Finish();
    }
}

// Tests calling RenderBundleEncoder::SetResourceTable
TEST_F(ResourceTableValidationTest, RenderBundleEncoder_SetResourceTable) {
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatCount = 1;
    desc.cColorFormats[0] = rp.colorFormat;

    // Failure case: invalid encoder state
    {
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        ASSERT_DEVICE_ERROR(rbe.SetResourceTable(nullptr));
    }

    // Failure case: invalid resource table
    {
        ASSERT_DEVICE_ERROR(wgpu::ResourceTable resourceTable = MakeErrorResourceTable());

        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = rbe.Finish());
    }

    // Success case: valid resource table
    {
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        encoder.Finish();
    }

    // Success case: null resource table
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(nullptr);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        encoder.Finish();
    }
}

// Tests calling ComputePassEncoder::SetResourceTable when the feature is disabled
TEST_F(ResourceTableValidationTestDisabled, ComputePassEncoder_SetResourceTable) {
    // Failure case: feature is disabled
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    pass.SetResourceTable(nullptr);
    pass.End();
    ASSERT_DEVICE_ERROR(encoder.Finish());
}

// Tests calling RenderPassEncoder::SetResourceTable when the feature is disabled
TEST_F(ResourceTableValidationTestDisabled, RenderPassEncoder_SetResourceTable) {
    // Failure case: feature is disabled
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
    pass.SetResourceTable(nullptr);
    pass.End();
    ASSERT_DEVICE_ERROR(encoder.Finish());
}

// Tests calling RenderBundleEncoder::SetResourceTable when the feature is disabled
TEST_F(ResourceTableValidationTestDisabled, RenderBundleEncoder_SetResourceTable) {
    // Failure case: feature is disabled
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatCount = 1;
    desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
    rbe.SetResourceTable(nullptr);
    ASSERT_DEVICE_ERROR(rbe.Finish());
}

// Tests that resource tables set on a compute pass can be used in submit
TEST_F(ResourceTableValidationTest, ComputePassEncoder_CanUseInSubmit) {
    wgpu::ResourceTable resourceTable = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable3 = MakeResourceTable(1);

    // Success case: resource table can be used in submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Success case: resource table can be used in multiple passes for submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::ComputePassEncoder pass2 = encoder.BeginComputePass();
        pass2.SetResourceTable(resourceTable);
        pass2.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Failure case: resource table has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(resourceTable2);
        pass.SetResourceTable(resourceTable3);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable2.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables in another pass has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(resourceTable2);
        pass.End();
        wgpu::ComputePassEncoder pass2 = encoder.BeginComputePass();
        pass2.SetResourceTable(resourceTable);
        pass2.SetResourceTable(resourceTable3);
        pass2.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable3.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: resource table must still be valid if set, then nullptr is set
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(nullptr);  // Clear it
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }
}

// Tests that resource tables set on a render pass can be used in submit
TEST_F(ResourceTableValidationTest, RenderPassEncoder_CanUseInSubmit) {
    wgpu::ResourceTable resourceTable = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable3 = MakeResourceTable(1);
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);

    // Success case: resource table can be used in submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Success case: resource table can be used in multiple passes for submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass2.SetResourceTable(resourceTable);
        pass2.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Failure case: resource table has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(resourceTable2);
        pass.SetResourceTable(resourceTable3);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable2.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables in another pass has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(resourceTable2);
        pass.End();
        wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass2.SetResourceTable(resourceTable);
        pass2.SetResourceTable(resourceTable3);
        pass2.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable3.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: resource table must still be valid if set, then nullptr is set
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.SetResourceTable(resourceTable);
        pass.SetResourceTable(nullptr);  // Clear it
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }
}

// Tests that resource tables set on a render bundle can be used in submit
TEST_F(ResourceTableValidationTest, RenderBundleEncoder_CanUseInSubmit) {
    wgpu::ResourceTable resourceTable = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);
    wgpu::ResourceTable resourceTable3 = MakeResourceTable(1);
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatCount = 1;
    desc.cColorFormats[0] = rp.colorFormat;

    // Success case: resource table can be used in submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Success case: resource table can be used in multiple passes for submit
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();

        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();

        wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe2 = device.CreateRenderBundleEncoder(&desc);
        rbe2.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle2 = rbe2.Finish();
        pass2.ExecuteBundles(1, &renderBundle2);
        pass2.End();

        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Success case: resource table can be used in multiple rbes in one pass for submit
    {
        std::vector<wgpu::RenderBundle> renderBundles;

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);

        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        renderBundles.push_back(rbe.Finish());

        wgpu::RenderBundleEncoder rbe2 = device.CreateRenderBundleEncoder(&desc);
        rbe2.SetResourceTable(resourceTable);
        renderBundles.push_back(rbe2.Finish());

        pass.ExecuteBundles(renderBundles.size(), renderBundles.data());
        pass.End();

        wgpu::CommandBuffer commands = encoder.Finish();
        device.GetQueue().Submit(1, &commands);
    }

    // Failure case: resource table has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        rbe.SetResourceTable(resourceTable2);
        rbe.SetResourceTable(resourceTable3);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable2.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: one of multiple resource tables in another pass has been destroyed
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();

        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        rbe.SetResourceTable(resourceTable2);
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();

        wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe2 = device.CreateRenderBundleEncoder(&desc);
        rbe2.SetResourceTable(resourceTable);
        rbe2.SetResourceTable(resourceTable3);
        wgpu::RenderBundle renderBundle2 = rbe2.Finish();
        pass2.ExecuteBundles(1, &renderBundle2);
        pass2.End();

        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable3.Destroy();  // Destroy one
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }

    // Failure case: resource table must still be valid if set, then nullptr is set
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);
        rbe.SetResourceTable(nullptr);  // Clear it
        wgpu::RenderBundle renderBundle = rbe.Finish();
        pass.ExecuteBundles(1, &renderBundle);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        resourceTable.Destroy();  // Destroy it
        ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands));
    }
}

// Tests that the resource table can be used in dispatch
TEST_F(ResourceTableValidationTest, Submit_DispatchRequiresResourceTable) {
    for (bool defaulted : {true, false}) {
        wgpu::ComputePipeline pipelineUsesTable = MakeComputePipeline(defaulted, true);
        wgpu::ComputePipeline pipelineNoTable = MakeComputePipeline(defaulted, false);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);

        // Success case: `usesResourceTable` is enabled, and one has been set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetResourceTable(resourceTable);
            pass.SetPipeline(pipelineUsesTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: `usesResourceTable` is enabled, but none has been set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetPipeline(pipelineUsesTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }

        // Failure case: `usesResourceTable` is enabled, one then nullptr set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetResourceTable(resourceTable);  // Set a valid one
            pass.SetResourceTable(nullptr);        // Then clear it
            pass.SetPipeline(pipelineUsesTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }

        // Success case: `usesResourceTable` is enabled, one then nullptr then another set on the
        // pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetResourceTable(resourceTable);   // Set a valid one
            pass.SetResourceTable(nullptr);         // Then clear it
            pass.SetResourceTable(resourceTable2);  // Then set another valid one
            pass.SetPipeline(pipelineUsesTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Success case: `usesResourceTable` enabled only on pass 2 with table set
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetPipeline(pipelineNoTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            wgpu::ComputePassEncoder pass2 = encoder.BeginComputePass();
            pass2.SetResourceTable(resourceTable);
            pass2.SetPipeline(pipelineUsesTable);
            pass2.DispatchWorkgroups(1);
            pass2.End();
            wgpu::CommandBuffer commands = encoder.Finish();
        }

        // Failure case: `usesResourceTable` enabled only on pass 2 but no table set
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
            pass.SetPipeline(pipelineNoTable);
            pass.DispatchWorkgroups(1);
            pass.End();
            wgpu::ComputePassEncoder pass2 = encoder.BeginComputePass();
            pass2.SetPipeline(pipelineUsesTable);
            pass2.DispatchWorkgroups(1);
            pass2.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }
    }
}

// Tests that the resource table can be used in draw
TEST_F(ResourceTableValidationTest, Submit_DrawRequiresResourceTable) {
    for (bool defaulted : {true, false}) {
        wgpu::RenderPipeline pipelineUsesTable = MakeRenderPipeline(defaulted, true);
        wgpu::RenderPipeline pipelineNoTable = MakeRenderPipeline(defaulted, false);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);
        auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);

        // Success case: `usesResourceTable` is enabled, and one has been set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetResourceTable(resourceTable);
            pass.SetPipeline(pipelineUsesTable);
            pass.Draw(1);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: `usesResourceTable` is enabled, but none has been set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineUsesTable);
            pass.Draw(1);
            pass.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }

        // Failure case: `usesResourceTable` is enabled, one then nullptr set on the pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetResourceTable(resourceTable);  // Set a valid one
            pass.SetResourceTable(nullptr);        // Then clear it
            pass.SetPipeline(pipelineUsesTable);
            pass.Draw(1);
            pass.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }

        // Success case: `usesResourceTable` is enabled, one then nullptr then another set on the
        // pass
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetResourceTable(resourceTable);
            pass.SetResourceTable(nullptr);         // Then clear it
            pass.SetResourceTable(resourceTable2);  // Then set another valid one
            pass.SetPipeline(pipelineUsesTable);
            pass.Draw(1);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Success case: single pass toggles between pipelines that do not use and use a table
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineNoTable);
            pass.Draw(1);
            pass.SetPipeline(pipelineUsesTable);
            pass.SetResourceTable(resourceTable);
            pass.Draw(1);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: single pass toggles between pipelines that do not use and use a table, but
        // does not set a table when required
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineNoTable);
            pass.Draw(1);
            pass.SetPipeline(pipelineUsesTable);
            pass.Draw(1);
            pass.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }

        // Success case: `usesResourceTable` enabled only on pass 2 with table set
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineNoTable);
            pass.Draw(1);
            pass.End();
            wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass2.SetResourceTable(resourceTable);
            pass2.SetPipeline(pipelineUsesTable);
            pass2.Draw(1);
            pass2.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: `usesResourceTable` enabled only on pass 2 but no table set
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineNoTable);
            pass.Draw(1);
            pass.End();
            wgpu::RenderPassEncoder pass2 = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass2.SetPipeline(pipelineUsesTable);
            pass2.Draw(1);
            pass2.End();
            ASSERT_DEVICE_ERROR(wgpu::CommandBuffer commands = encoder.Finish());
        }
    }
}

// Tests that the resource table in RenderBundle can be used in draw
TEST_F(ResourceTableValidationTest, Submit_RenderBundleDrawRequiresResourceTable) {
    for (bool defaulted : {true, false}) {
        wgpu::RenderPipeline pipelineUsesTable = MakeRenderPipeline(defaulted, true);
        wgpu::RenderPipeline pipelineNoTable = MakeRenderPipeline(defaulted, false);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        wgpu::ResourceTable resourceTable2 = MakeResourceTable(1);

        auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);

        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.colorFormatCount = 1;
        desc.cColorFormats[0] = rp.colorFormat;

        // Success case: `usesResourceTable` is enabled, and one has been set on the encoder
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetResourceTable(resourceTable);
            rbe.SetPipeline(pipelineUsesTable);
            rbe.Draw(1);
            wgpu::RenderBundle renderBundle = rbe.Finish();
            pass.ExecuteBundles(1, &renderBundle);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: `usesResourceTable` is enabled, but none has been set on the encoder
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetPipeline(pipelineUsesTable);
            rbe.Draw(1);
            ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = rbe.Finish());
        }

        // Failure case: `usesResourceTable` is enabled, one then nullptr set on the encoder
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetResourceTable(resourceTable);  // Set a valid one
            rbe.SetResourceTable(nullptr);        // Then clear it
            rbe.SetPipeline(pipelineUsesTable);
            rbe.Draw(1);
            ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = rbe.Finish());
        }

        // Success case: `usesResourceTable` is enabled, one then nullptr then another set on the
        // encoder
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetResourceTable(resourceTable);   // Set a valid one
            rbe.SetResourceTable(nullptr);         // Then clear it
            rbe.SetResourceTable(resourceTable2);  // Then set another valid one
            rbe.SetPipeline(pipelineUsesTable);
            rbe.Draw(1);
            wgpu::RenderBundle renderBundle = rbe.Finish();
            pass.ExecuteBundles(1, &renderBundle);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Success case: single rbe toggles between pipelines that do not use and use a table
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetPipeline(pipelineUsesTable);
            rbe.SetResourceTable(resourceTable);
            rbe.Draw(1);
            rbe.SetPipeline(pipelineNoTable);
            rbe.Draw(1);
            wgpu::RenderBundle renderBundle = rbe.Finish();
            pass.ExecuteBundles(1, &renderBundle);
            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }

        // Failure case: single rbe toggles between pipelines that do not use and use a table, but
        // does not set a table when required
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetPipeline(pipelineUsesTable);
            rbe.Draw(1);
            rbe.SetPipeline(pipelineNoTable);
            rbe.Draw(1);
            ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = rbe.Finish());
        }

        // Success case: mix pass and rbe
        {
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
            pass.SetPipeline(pipelineUsesTable);
            pass.SetResourceTable(resourceTable);
            pass.SetPipeline(pipelineNoTable);
            pass.Draw(1);

            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
            rbe.SetPipeline(pipelineUsesTable);
            rbe.SetResourceTable(resourceTable);
            rbe.Draw(1);
            rbe.SetPipeline(pipelineNoTable);
            rbe.Draw(1);
            wgpu::RenderBundle renderBundle = rbe.Finish();
            pass.ExecuteBundles(1, &renderBundle);

            pass.End();
            wgpu::CommandBuffer commands = encoder.Finish();
            device.GetQueue().Submit(1, &commands);
        }
    }
}

// Test that render bundles do not persist resource tables onto a render pass
TEST_F(ResourceTableValidationTest, RenderBundleDoesNotPersistResourceTable) {
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatCount = 1;
    desc.cColorFormats[0] = rp.colorFormat;

    // Success case: pipeline uses table, one is set on the bundle, and one on the pass
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);

        // Create render bundle with a resource table
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();

        auto pipelineUsesTable = MakeRenderPipeline(true, true);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipelineUsesTable);
        pass.SetResourceTable(resourceTable);  // Set table on the pass
        pass.Draw(1);
        pass.End();

        encoder.Finish();
    }

    // Failure case: pipeline uses table, one is set on the bundle, but not on the pass
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);

        // Create render bundle with a resource table
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);
        rbe.SetResourceTable(resourceTable);
        wgpu::RenderBundle renderBundle = rbe.Finish();

        auto pipelineUsesTable = MakeRenderPipeline(true, true);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipelineUsesTable);
        pass.Draw(1);
        pass.End();

        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Test that render bundles do not inherit resource tables from a render pass
TEST_F(ResourceTableValidationTest, RenderBundleDoesNotInheritResourceTable) {
    auto rp = utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatCount = 1;
    desc.cColorFormats[0] = rp.colorFormat;

    // Success case: pipeline uses table, one is set on the bundle, and one on the pass
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);

        // Create render bundle with a resource table
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        rbe.SetResourceTable(resourceTable);  // Set table on the bundle
        wgpu::RenderBundle renderBundle = rbe.Finish();

        auto pipelineUsesTable = MakeRenderPipeline(true, true);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipelineUsesTable);
        pass.SetResourceTable(resourceTable);  // Set table on the pass
        pass.Draw(1);
        pass.End();

        encoder.Finish();
    }

    // Failure case: pipeline uses table, one is set on the pass, but not on the bundle
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        wgpu::ResourceTable resourceTable = MakeResourceTable(1);

        // Create render bundle without a resource table
        wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);
        wgpu::RenderBundle renderBundle = rbe.Finish();

        auto pipelineUsesTable = MakeRenderPipeline(true, true);
        pass.SetPipeline(pipelineUsesTable);
        pass.SetResourceTable(resourceTable);  // Set table on the pass
        pass.ExecuteBundles(1, &renderBundle);
        pass.Draw(1);
        pass.End();

        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Checks that only texture views and samplers are allowed as resources in mutators for
// SamplingResourceTable.
TEST_F(ResourceTableValidationTest, MutatorBindingKindValidation) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc = {
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::Texture texture = device.CreateTexture(&tDesc);

    // Create the buffer to put in the table.
    wgpu::BufferDescriptor bDesc{
        .usage = wgpu::BufferUsage::Storage,
        .size = 4,
    };
    wgpu::Buffer buffer = device.CreateBuffer(&bDesc);

    // Create the sampler to put in the table.
    wgpu::Sampler sampler = device.CreateSampler();

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Success case: a single texture is valid.
        {
            wgpu::BindingResource resource = {.textureView = texture.CreateView()};
            TestMutator(mutator, &resource, true);
        }

        // Success case: a single sampler is valid
        {
            wgpu::BindingResource resource = {.sampler = sampler};
            TestMutator(mutator, &resource, true);
        }

        // Error case: a buffer is an error.
        {
            wgpu::BindingResource resource = {.buffer = buffer};
            TestMutator(mutator, &resource, false);
        }

        // Error case: both a sampler and a texture at the same time is an error.
        {
            wgpu::BindingResource resource = {.sampler = sampler,
                                              .textureView = texture.CreateView()};
            TestMutator(mutator, &resource, false);
        }
    }
}

// Tests that resources added/inserted on a table must be valid objects
TEST_F(ResourceTableValidationTest, MutatorResourceMustBeValid) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc = {
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::Texture textureGood = device.CreateTexture(&tDesc);

    tDesc.size = {0, 0};
    ASSERT_DEVICE_ERROR(wgpu::Texture textureBad = device.CreateTexture(&tDesc));

    // Create the sampler to put in the table.
    wgpu::SamplerDescriptor sDesc = {};
    wgpu::Sampler samplerGood = device.CreateSampler(&sDesc);

    sDesc.lodMinClamp = -1;
    ASSERT_DEVICE_ERROR(wgpu::Sampler samplerBad = device.CreateSampler(&sDesc));

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Success case: valid texture
        {
            wgpu::BindingResource resource = {.textureView = textureGood.CreateView()};
            TestMutator(mutator, &resource, true);
        }

        // Error case: invalid texture
        {
            ASSERT_DEVICE_ERROR(
                wgpu::BindingResource resource = {.textureView = textureBad.CreateView()});
            TestMutator(mutator, &resource, false);
        }

        // Success case: valid sampler
        {
            wgpu::BindingResource resource = {.sampler = samplerGood};
            TestMutator(mutator, &resource, true);
        }

        // Error case: invalid sampler
        {
            wgpu::BindingResource resource = {.sampler = samplerBad};
            TestMutator(mutator, &resource, false);
        }
    }
}

// Tests that adding and removing different types of resources works
TEST_F(ResourceTableValidationTest, MutatorsMultipleResources) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource textureResource = {.textureView =
                                                 device.CreateTexture(&tDesc).CreateView()};
    wgpu::BindingResource samplerResource = {.sampler = device.CreateSampler()};

    auto table = MakeResourceTable(42);

    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &textureResource));
    EXPECT_EQ(wgpu::Status::Success, table.Update(1, &samplerResource));
    EXPECT_EQ(2u, table.InsertBinding(&textureResource));
    EXPECT_EQ(3u, table.InsertBinding(&samplerResource));

    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(2));
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(3));
}

// Check that the view must have only the TextureBinding usage for SamplingResourceTable.
// TODO(https://issues.chromium.org/473444515): Support storage textures in FullResourceTable
// TODO(https://issues.chromium.org/382544164): Support texel buffers in FullResourceTable
TEST_F(ResourceTableValidationTest, MutatorTextureViewMustBeOnlyTextureBinding) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding |
                 wgpu::TextureUsage::StorageBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R32Uint,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Control case: limiting the usage to TextureBinding is valid.
        {
            wgpu::TextureViewDescriptor vDesc{
                .usage = wgpu::TextureUsage::TextureBinding,
            };
            wgpu::BindingResource resource = {.textureView = tex.CreateView(&vDesc)};
            TestMutator(mutator, &resource, true);
        }

        // Error case: having unrelated usages in the view is not allowed. RenderAttachment case.
        {
            wgpu::TextureViewDescriptor vDesc{
                .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment,
            };
            wgpu::BindingResource resource = {.textureView = tex.CreateView(&vDesc)};
            TestMutator(mutator, &resource, false);
        }

        // Error case: having unrelated usages in the view is not allowed. StorageBinding case.
        {
            wgpu::TextureViewDescriptor vDesc{
                .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::StorageBinding,
            };
            wgpu::BindingResource resource = {.textureView = tex.CreateView(&vDesc)};
            TestMutator(mutator, &resource, false);
        }

        // Error case: the defaulted texture usages don't contain TextureBinding.
        {
            wgpu::TextureDescriptor tDesc2 = tDesc;
            tDesc2.usage = wgpu::TextureUsage::CopyDst;
            wgpu::BindingResource resource = {.textureView =
                                                  device.CreateTexture(&tDesc2).CreateView()};
            TestMutator(mutator, &resource, false);
        }
    }
}

// Check that the texture view must have a single aspect for mutators.
TEST_F(ResourceTableValidationTest, MutatorTextureViewMustBeSingleAspect) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::Depth24PlusStencil8,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Success case, only the depth aspect is selected.
        {
            wgpu::TextureViewDescriptor vDesc{
                .aspect = wgpu::TextureAspect::DepthOnly,
            };
            wgpu::BindingResource resource = {.textureView = tex.CreateView(&vDesc)};
            TestMutator(mutator, &resource, true);
        }

        // Success case, only the stencil aspect is selected.
        {
            wgpu::TextureViewDescriptor vDesc{
                .aspect = wgpu::TextureAspect::StencilOnly,
            };
            wgpu::BindingResource resource = {.textureView = tex.CreateView(&vDesc)};
            TestMutator(mutator, &resource, true);
        }

        // Error case: both aspects are selected.
        {
            wgpu::BindingResource resource = {.textureView = tex.CreateView()};
            TestMutator(mutator, &resource, false);
        }
    }
}

class ResourceTableStaticSamplerValidationTest : public ResourceTableValidationTest {
  protected:
    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        return {
            wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable,
            wgpu::FeatureName::StaticSamplers,
            wgpu::FeatureName::YCbCrVulkanSamplers,
        };
    }
};

// Checks that YCbCr samplers cannot be added to a resource table
TEST_F(ResourceTableStaticSamplerValidationTest, MutatorSamplerMustNotBeYCbCr) {
    wgpu::SamplerDescriptor samplerDesc = {};
    wgpu::Sampler samplerDefault = device.CreateSampler(&samplerDesc);

    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
    yCbCrDesc.externalFormat = 1;
    samplerDesc.nextInChain = &yCbCrDesc;
    wgpu::Sampler samplerYCbCr = device.CreateSampler(&samplerDesc);

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Success case: default sampler
        {
            wgpu::BindingResource resource = {.sampler = samplerDefault};
            TestMutator(mutator, &resource, true);
        }

        // Error case: YCbCr sampler
        {
            wgpu::BindingResource resource = {.sampler = samplerYCbCr};
            TestMutator(mutator, &resource, false);
        }
    }
}

// Checks that YCbCr texture views cannot be added to a resource table
TEST_F(ResourceTableStaticSamplerValidationTest, MutatorViewMustNotBeYCbCr) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::Texture textureDefault = device.CreateTexture(&tDesc);

    tDesc.format = wgpu::TextureFormat::OpaqueYCbCrAndroid;
    wgpu::Texture textureYCbCr = device.CreateTexture(&tDesc);

    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
    yCbCrDesc.externalFormat = 1;

    wgpu::TextureViewDescriptor vDesc{
        .nextInChain = &yCbCrDesc,
        .format = wgpu::TextureFormat::OpaqueYCbCrAndroid,
        .arrayLayerCount = 1,
        .usage = wgpu::TextureUsage::TextureBinding,
    };

    for (auto mutator : {Mutator::Update, Mutator::InsertBinding}) {
        // Success case: default texture view
        {
            wgpu::BindingResource resource = {.textureView = textureDefault.CreateView()};
            TestMutator(mutator, &resource, true);
        }

        // Error case: YCbCr texture view
        {
            wgpu::BindingResource resource = {.textureView = textureYCbCr.CreateView(&vDesc)};
            // TestMutator(mutator, &resource, false);
        }
    }
}

// Test that it is not allowed to call Update, RemoveBinding or InsertBinding after the table is
// destroyed.
TEST_F(ResourceTableValidationTest, MutatorsAfterDestroy) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(7), MakeErrorResourceTable(7)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        // Add a few bindings just to test RemoveBinding
        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &resource));

        // Success cases, calling mutators before destroying is valid.
        EXPECT_EQ(wgpu::Status::Success, table.Update(2, &resource));
        EXPECT_NE(wgpu::kInvalidBinding, table.InsertBinding(&resource));
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));

        // Error case, after destruction all mutators return errors.
        table.Destroy();
        EXPECT_EQ(wgpu::Status::Error, table.Update(6, &resource));
        EXPECT_EQ(wgpu::kInvalidBinding, table.InsertBinding(&resource));
        EXPECT_EQ(wgpu::Status::Error, table.RemoveBinding(1));
    }
}

// Test that it is not allowed to call Update, RemoveBinding with slots past the end.
TEST_F(ResourceTableValidationTest, MutatorsAfterTableEnd) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(42), MakeErrorResourceTable(42)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        // Success cases, calling mutators with slots in bounds.
        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
        EXPECT_EQ(wgpu::Status::Success, table.Update(41, &resource));
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(41));

        // Error case, calling mutators with out of bounds slots.
        EXPECT_EQ(wgpu::Status::Error, table.Update(42, &resource));
        EXPECT_EQ(wgpu::Status::Error, table.RemoveBinding(42));
    }
}

// Test that Update/RemoveBinding return success but generates a validation error when used on an
// invalid table.
TEST_F(ResourceTableValidationTest, MutatorsOnInvalidTable) {
    // Create the texture to put in the table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // Test on a valid table.
    {
        wgpu::ResourceTable table = MakeResourceTable(3);

        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
        EXPECT_NE(wgpu::kInvalidBinding, table.InsertBinding(&resource));
    }

    // Test on an invalid table.
    {
        wgpu::ResourceTable table = MakeErrorResourceTable(3);

        ASSERT_DEVICE_ERROR(EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource)));
        ASSERT_DEVICE_ERROR(EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0)));
        ASSERT_DEVICE_ERROR(EXPECT_NE(wgpu::kInvalidBinding, table.InsertBinding(&resource)));
    }
}

// Test that Update() can be called on a table slot if it has never been used before.
TEST_F(ResourceTableValidationTest, UpdateBindingWhenNeverUsed) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(3), MakeErrorResourceTable(3)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        // Updating slot 0 when it has never been used is valid, but a second time is an error.
        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
        EXPECT_EQ(wgpu::Status::Error, table.Update(0, &resource));

        // Even after using the table, a previously unused entry is valid to update.
        UseResourceTableInSubmit(table);
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &resource));
    }
}

// Test that Remove() can be called on a table slot even when it was never used.
TEST_F(ResourceTableValidationTest, RemoveBindingWhenNeverUsed) {
    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(3), MakeErrorResourceTable(3)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    }
}

// Check that a table slot can be updated only after all commands submitted prior to RemoveBinding
// are completed.
TEST_F(ResourceTableValidationTest, UpdateAfterRemoveRequiresGPUIsFinished) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(1), MakeErrorResourceTable(1)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        // Removing while the table is still potentially in used by the GPU is an error. But
        // immediately after we know that the GPU is finished, it is valid.
        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));

        bool updateValid = false;
        UseResourceTableInSubmit(table);
        device.GetQueue().OnSubmittedWorkDone(
            wgpu::CallbackMode::AllowSpontaneous,
            [&](wgpu::QueueWorkDoneStatus, wgpu::StringView) { updateValid = true; });
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));

        // The null backend happens to call OnSubmittedWorkDone immediately because commands take 0
        // time. This test is duplicated in the end2end tests where OnSubmittedWorkDone won't fire
        // immediately.
        if (updateValid) {
            EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
            updateValid = false;
        } else {
            EXPECT_EQ(wgpu::Status::Error, table.Update(0, &resource));
        }

        WaitForAllOperations();

        if (updateValid) {
            EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
        } else {
            EXPECT_EQ(wgpu::Status::Error, table.Update(0, &resource));
        }
    }
}

// Check that trying to insert bindings fail when no more are available.
TEST_F(ResourceTableValidationTest, InsertBindingFailWhenNoMoreSpace) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(3), MakeErrorResourceTable(3)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        // There is space for only three resources.
        EXPECT_EQ(0u, table.InsertBinding(&resource));
        EXPECT_EQ(1u, table.InsertBinding(&resource));
        EXPECT_EQ(2u, table.InsertBinding(&resource));
        EXPECT_EQ(wgpu::kInvalidBinding, table.InsertBinding(&resource));

        // Remove one binding (and wait for it to be recycled), it will be available for
        // InsertBinding after which a new InsertBinding will still run out of space.
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
        UseResourceTableInSubmit(table);
        WaitForAllOperations();

        EXPECT_EQ(1u, table.InsertBinding(&resource));
        EXPECT_EQ(wgpu::kInvalidBinding, table.InsertBinding(&resource));
    }
}

// Check that bindings that are inserted are unavailable for Update() until RemoveBinding.
TEST_F(ResourceTableValidationTest, InsertBindingPreventsUpdate) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(1), MakeErrorResourceTable(1)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

        EXPECT_EQ(0u, table.InsertBinding(&resource));
        EXPECT_EQ(wgpu::Status::Error, table.Update(0, &resource));

        // Remove one binding (and wait for it to be recycled), it will be available for Update.
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
        UseResourceTableInSubmit(table);
        WaitForAllOperations();

        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));
    }
}

// Check that InsertBinding skips over used slots.
TEST_F(ResourceTableValidationTest, InsertBindingSkipsOverUsedSlots) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::RGBA8Unorm,
    };
    wgpu::BindingResource resource = {.textureView = device.CreateTexture(&tDesc).CreateView()};

    // This is "content timeline" validation so it works the same on error tables and valid tables,
    // and we ignore device-timeline validation errors, they are not what we are testing here.
    for (auto table : {MakeResourceTable(5), MakeErrorResourceTable(5)}) {
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &resource));
        EXPECT_EQ(wgpu::Status::Success, table.Update(3, &resource));

        // InsertBinding skips over entries used by Update()
        EXPECT_EQ(0u, table.InsertBinding(&resource));
        EXPECT_EQ(2u, table.InsertBinding(&resource));
        EXPECT_EQ(4u, table.InsertBinding(&resource));

        // Remove bindings in inverse order.
        for (uint32_t i : {4, 3, 2}) {
            EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(i));
        }
        UseResourceTableInSubmit(table);
        WaitForAllOperations();

        // InsertBinding should still return the min available slot.
        EXPECT_EQ(2u, table.InsertBinding(&resource));
        EXPECT_EQ(3u, table.InsertBinding(&resource));
        EXPECT_EQ(4u, table.InsertBinding(&resource));
    }
}

// Test the value returned by GetSize right after creating the table.
TEST_F(ResourceTableValidationTest, GetSizeAfterCreation) {
    // Valid resource tables of varying size.
    {
        EXPECT_EQ(0u, MakeResourceTable(0).GetSize());
        EXPECT_EQ(42u, MakeResourceTable(42).GetSize());
        EXPECT_EQ(kMaxResourceTableSize, MakeResourceTable(kMaxResourceTableSize).GetSize());
    }

    // Invalid resource tables of varying size under the limit.
    {
        EXPECT_EQ(0u, MakeErrorResourceTable(0).GetSize());
        EXPECT_EQ(42u, MakeErrorResourceTable(42).GetSize());
        EXPECT_EQ(kMaxResourceTableSize, MakeErrorResourceTable(kMaxResourceTableSize).GetSize());
    }
}

// Test the value returned by GetSize after calling Destroy() should return the same value.
TEST_F(ResourceTableValidationTest, GetSizeAfterDestroy) {
    // Valid resource table.
    {
        wgpu::ResourceTable table = MakeResourceTable(42);
        EXPECT_EQ(42u, table.GetSize());
        table.Destroy();
        EXPECT_EQ(42u, table.GetSize());
    }

    // Invalid resource table.
    {
        wgpu::ResourceTable table = MakeResourceTable(42);
        EXPECT_EQ(42u, table.GetSize());
        table.Destroy();
        EXPECT_EQ(42u, table.GetSize());
    }
}

}  // namespace
}  // namespace dawn
