// 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 <string>
#include <unordered_set>
#include <utility>
#include <variant>
#include <vector>

#include "dawn/common/Enumerator.h"
#include "dawn/common/Range.h"
#include "dawn/tests/DawnTest.h"
#include "dawn/utils/ComboRenderBundleEncoderDescriptor.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/ScopedIgnoreValidationErrors.h"
#include "dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

// The number of unique default samplers on D3D12, derived form ResourceTableDefaultResources.
// These necessarily take up a couple of slots in a resource table.
constexpr uint32_t kUniqueDefaultSamplers = 2;
// On D3D12, the max number of unique sampler descriptors available to the user in a ResourceTable.
constexpr uint32_t kD3D12MaxUniqueSamplers = 2048 - kUniqueDefaultSamplers;

class ResourceTableTests : public DawnTest {
  protected:
    void SetUp() override {
        DawnTest::SetUp();
        DAWN_TEST_UNSUPPORTED_IF(
            !SupportsFeatures({wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable}));

        // Swiftshader doesn't support variable count descriptor sets used in draw operations. In
        // vk::DescriptorSet::ParseDescriptors it iterates over all the descriptors to prep various
        // things but iterates over the whole size defined in the vkDescriptorSetLayout instead of
        // taking into account the variable count.
        DAWN_SUPPRESS_TEST_IF(IsSwiftshader());
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        if (SupportsFeatures({wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable})) {
            return {wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable};
        }
        return {};
    }

    wgpu::ResourceTable MakeResourceTable(
        uint32_t size,
        std::vector<std::pair<uint32_t, wgpu::BindingResource>> resources = {}) {
        wgpu::ResourceTableDescriptor desc;
        desc.size = size;
        wgpu::ResourceTable table = device.CreateResourceTable(&desc);

        for (auto& [slot, resource] : resources) {
            EXPECT_EQ(wgpu::Status::Success, table.Update(slot, &resource));
        }

        return table;
    }

    wgpu::PipelineLayout MakePipelineLayoutWithTable(std::vector<wgpu::BindGroupLayout> bgls = {},
                                                     uint32_t immediateSize = 0) {
        wgpu::PipelineLayoutResourceTable plTable;
        plTable.usesResourceTable = true;

        wgpu::PipelineLayoutDescriptor desc{
            .nextInChain = &plTable,
            .bindGroupLayoutCount = bgls.size(),
            .bindGroupLayouts = bgls.data(),
            .immediateSize = immediateSize,
        };

        return device.CreatePipelineLayout(&desc);
    }

    // Test that the `table`, has resources of `wgslType` in the `expected` slots.
    void TestHasResource(wgpu::ResourceTable table,
                         std::vector<bool> expected,
                         std::string wgslType = "texture_2d<f32>") {
        ASSERT_EQ(table.GetSize(), expected.size());

        // Create the test pipeline.
        wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;

            @group(0) @binding(0) var<storage, read_write> results : array<u32>;
            var<immediate> resourceCount : u32;
            @compute @workgroup_size(1) fn main() {
                for (var i = 0u; i < resourceCount; i++) {
                    results[i] = u32(hasResource<)" + wgslType + R"(>(i));
                }
            }
        )");
        wgpu::ComputePipelineDescriptor csDesc = {.compute = {
                                                      .module = module,
                                                  }};
        wgpu::ComputePipeline testPipeline = device.CreateComputePipeline(&csDesc);

        // Create the result buffer.
        wgpu::BufferDescriptor bDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(uint32_t) * expected.size(),
        };
        wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
        wgpu::BindGroup resultBG =
            utils::MakeBindGroup(device, testPipeline.GetBindGroupLayout(0), {{0, resultBuffer}});
        uint32_t resourceCount = table.GetSize();

        // Run the test.
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetImmediates(0, &resourceCount, sizeof(resourceCount));
        pass.SetBindGroup(0, resultBG);
        pass.SetPipeline(testPipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        // Check we have the expected results.
        std::vector<uint32_t> expectedU32;
        for (bool b : expected) {
            expectedU32.push_back(b ? 1u : 0u);
        }

        EXPECT_BUFFER_U32_RANGE_EQ(expectedU32.data(), resultBuffer, 0, expectedU32.size())
            << " for WGSL type " << wgslType;
    }

    void DoSomeWorkInSubmit() {
        wgpu::BufferDescriptor bufDesc = {
            .usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc,
            .size = 4,
        };
        wgpu::Buffer src = device.CreateBuffer(&bufDesc);
        wgpu::Buffer dst = device.CreateBuffer(&bufDesc);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToBuffer(src, 0, dst, 0, 4);

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

    wgpu::TextureView MakePinnedU8View(uint8_t value) {
        // Create the texture.
        wgpu::TextureDescriptor tDesc{
            .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst,
            .size = {1, 1},
            .format = wgpu::TextureFormat::R8Uint,
        };
        wgpu::Texture tex = device.CreateTexture(&tDesc);

        // Write the u8
        wgpu::TexelCopyTextureInfo srcInfo = utils::CreateTexelCopyTextureInfo(tex);
        wgpu::TexelCopyBufferLayout dstInfo = {};
        wgpu::Extent3D copySize = {1, 1, 1};
        queue.WriteTexture(&srcInfo, &value, 1, &dstInfo, &copySize);

        // Return a view to the pinned texture.
        tex.Pin(wgpu::TextureUsage::TextureBinding);
        return tex.CreateView();
    }

    // For each table in `cases`, sets the `table` and dipatches on a compute pass encoder,
    // and validates that each `table` has a texture_2d<u32> iff the `expected` has a value, and
    // that the textures have the expected value, if any.
    struct TableAndExpected {
        wgpu::ResourceTable table;
        std::vector<std::optional<uint8_t>> expected;
    };
    void TestHasU8BindingsCompute(std::vector<TableAndExpected> cases) {
        wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;

            @group(0) @binding(0) var<storage, read_write> results : array<u32>;
            struct Immediates {
                resourceCount : u32,
                offset : u32,
            }
            var<immediate> immediates : Immediates;
            @compute @workgroup_size(1) fn main() {
                for (var i = 0u; i < immediates.resourceCount; i++) {
                    if !hasResource<texture_2d<u32>>(i) {
                        results[immediates.offset + i] = 0xBEEF;
                    } else {
                        let tex = getResource<texture_2d<u32>>(i);
                        results[immediates.offset + i] = textureLoad(tex, vec2(0), 0).x;
                    }
                }
            }
        )");

        // Make the result buffer large enough for all cases
        size_t resultSize = 0;
        for (auto& [table, expected] : cases) {
            ASSERT_EQ(table.GetSize(), expected.size());
            resultSize += expected.size();
        }

        wgpu::ComputePipelineDescriptor csDesc = {.compute = {
                                                      .module = module,
                                                  }};
        wgpu::ComputePipeline testPipeline = device.CreateComputePipeline(&csDesc);

        // Create the result buffer.
        wgpu::BufferDescriptor bDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(uint32_t) * resultSize,
        };
        wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
        wgpu::BindGroup resultBG =
            utils::MakeBindGroup(device, testPipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

        // Run the test.
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        uint32_t offset = 0;
        for (auto& [table, expected] : cases) {
            pass.SetResourceTable(table);

            uint32_t immediates[] = {table.GetSize(), offset};
            pass.SetImmediates(0, &immediates, sizeof(immediates));
            offset += expected.size();

            pass.SetBindGroup(0, resultBG);

            pass.SetPipeline(testPipeline);
            pass.DispatchWorkgroups(1);
        }
        pass.End();

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

        // Check we have the expected results.
        std::vector<uint32_t> expectedU32;
        for (auto& [_, expected] : cases) {
            for (auto optValue : expected) {
                expectedU32.push_back(optValue ? *optValue : 0xBEEFu);
            }
        }

        EXPECT_BUFFER_U32_RANGE_EQ(expectedU32.data(), resultBuffer, 0, expectedU32.size());
    }

    // For each table in `cases`, sets the `table` and dipatches on a render pass/bundle encoder,
    // and validates that each `table` has a texture_2d<u32> iff the `expected` has a value, and
    // that the textures have the expected value, if any.
    void TestHasU8BindingsRender(std::vector<TableAndExpected> cases, bool useRenderBundles) {
        wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
            enable chromium_experimental_resource_table;

            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f(0, 0, 0.5, 0.5);
            }

            @group(0) @binding(0) var<storage, read_write> results : array<u32>;
            struct Immediates {
                resourceCount : u32,
                offset : u32,
            }
            var<immediate> immediates : Immediates;

            @fragment fn main() -> @location(0) vec4f {
                for (var i = 0u; i < immediates.resourceCount; i++) {
                    if !hasResource<texture_2d<u32>>(i) {
                        results[immediates.offset + i] = 0xBEEF;
                    } else {
                        let tex = getResource<texture_2d<u32>>(i);
                        results[immediates.offset + i] = textureLoad(tex, vec2(0), 0).x;
                    }
                }
                return vec4();
            }
        )");

        // Make the result buffer large enough for all cases
        size_t resultSize = 0;
        for (auto& [table, expected] : cases) {
            ASSERT_EQ(table.GetSize(), expected.size());
            resultSize += expected.size();
        }

        wgpu::BindGroupLayout resultBGL = utils::MakeBindGroupLayout(
            device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}});

        wgpu::RenderPipeline testPipeline;
        {
            utils::ComboRenderPipelineDescriptor desc;
            desc.layout = MakePipelineLayoutWithTable({resultBGL}, 8);
            desc.vertex.module = module;
            desc.cFragment.module = module;
            desc.primitive.topology = wgpu::PrimitiveTopology::PointList;
            testPipeline = device.CreateRenderPipeline(&desc);
        }

        // Create the result buffer.
        wgpu::BufferDescriptor bDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(uint32_t) * resultSize,
        };
        wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
        wgpu::BindGroup resultBG = utils::MakeBindGroup(device, resultBGL, {{0, resultBuffer}});

        // Run the test.
        auto rp = utils::CreateBasicRenderPass(device, 1, 1);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);

        if (useRenderBundles) {
            utils::ComboRenderBundleEncoderDescriptor desc = {};
            desc.colorFormatCount = 1;
            desc.cColorFormats[0] = rp.colorFormat;
            wgpu::RenderBundleEncoder rbe = device.CreateRenderBundleEncoder(&desc);

            uint32_t offset = 0;
            for (auto& [table, expected] : cases) {
                uint32_t immediates[] = {table.GetSize(), offset};
                rbe.SetResourceTable(table);
                rbe.SetImmediates(0, &immediates, sizeof(immediates));
                rbe.SetBindGroup(0, resultBG);
                rbe.SetPipeline(testPipeline);
                rbe.Draw(1);
                offset += expected.size();
            }

            wgpu::RenderBundle bundle = rbe.Finish();
            pass.ExecuteBundles(1, &bundle);
        } else {
            uint32_t offset = 0;
            for (auto& [table, expected] : cases) {
                uint32_t immediates[] = {table.GetSize(), offset};
                pass.SetResourceTable(table);
                pass.SetImmediates(0, &immediates, sizeof(immediates));
                pass.SetBindGroup(0, resultBG);
                pass.SetPipeline(testPipeline);
                pass.Draw(1);
                offset += expected.size();
            }
        }
        pass.End();

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

        // Check we have the expected results.
        std::vector<uint32_t> expectedU32;
        for (auto& [_, expected] : cases) {
            for (auto optValue : expected) {
                expectedU32.push_back(optValue ? *optValue : 0xBEEFu);
            }
        }

        EXPECT_BUFFER_U32_RANGE_EQ(expectedU32.data(), resultBuffer, 0, expectedU32.size());
    }

    // Convenience that tests cases using compute, render, and render bundle encoders
    void TestHasU8BindingsAll(std::vector<TableAndExpected> cases) {
        TestHasU8BindingsCompute(cases);
        TestHasU8BindingsRender(cases, true);
        TestHasU8BindingsRender(cases, false);
    }

    // Convenience for single table
    void TestHasU8BindingsAll(wgpu::ResourceTable table,
                              std::vector<std::optional<uint8_t>> expected) {
        TestHasU8BindingsAll({{table, expected}});
    }

    // Creates a sampler by address mode
    wgpu::Sampler CreateSampler(wgpu::AddressMode mode,
                                wgpu::CompareFunction compare = wgpu::CompareFunction::Undefined) {
        wgpu::SamplerDescriptor descriptor = {};
        descriptor.addressModeU = mode;
        descriptor.addressModeV = mode;
        descriptor.addressModeW = mode;
        descriptor.compare = compare;
        return device.CreateSampler(&descriptor);
    }

    // Creates a 2x2 checkerboard texture, with red in the top left and bottom right corners, green
    // in the other two.
    wgpu::Texture CreateCheckerboardTexture() {
        wgpu::TextureDescriptor descriptor;
        descriptor.dimension = wgpu::TextureDimension::e2D;
        descriptor.size = {2, 2};
        descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
        descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
        auto texture = device.CreateTexture(&descriptor);

        const uint32_t rowPixels = kTextureBytesPerRowAlignment / sizeof(utils::RGBA8);
        std::array<utils::RGBA8, rowPixels * 2> pixels;
        pixels[0] = pixels[rowPixels + 1] = utils::RGBA8::kRed;
        pixels[1] = pixels[rowPixels] = utils::RGBA8::kGreen;

        wgpu::TexelCopyTextureInfo srcInfo =
            utils::CreateTexelCopyTextureInfo(texture, 0, {0, 0, 0});
        wgpu::TexelCopyBufferLayout dstInfo = {};
        dstInfo.bytesPerRow = kTextureBytesPerRowAlignment;
        wgpu::Extent3D copySize = {2, 2, 1};
        queue.WriteTexture(&srcInfo, pixels.data(), pixels.size() * sizeof(utils::RGBA8), &dstInfo,
                           &copySize);

        return texture;
    }

    wgpu::Texture CreateColorTexture(utils::RGBA8 color) {
        wgpu::TextureDescriptor descriptor;
        descriptor.dimension = wgpu::TextureDimension::e2D;
        descriptor.size = {1, 1};
        descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
        descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
        auto texture = device.CreateTexture(&descriptor);

        const uint32_t rowPixels = kTextureBytesPerRowAlignment / sizeof(utils::RGBA8);
        std::array<utils::RGBA8, rowPixels> pixels;
        pixels[0] = color;

        wgpu::TexelCopyTextureInfo srcInfo =
            utils::CreateTexelCopyTextureInfo(texture, 0, {0, 0, 0});
        wgpu::TexelCopyBufferLayout dstInfo = {};
        dstInfo.bytesPerRow = kTextureBytesPerRowAlignment;
        wgpu::Extent3D copySize = {1, 1, 1};
        queue.WriteTexture(&srcInfo, pixels.data(), pixels.size() * sizeof(utils::RGBA8), &dstInfo,
                           &copySize);

        return texture;
    }

    wgpu::Sampler CreateUniqueSampler(uint32_t i) {
        // Make samplers unique by making one of the values different for each
        wgpu::SamplerDescriptor descriptor;
        descriptor.lodMinClamp = (i + 1) / 1000.0f;
        return device.CreateSampler(&descriptor);
    }
};

// Test that creating resource tables doesn't crash in backends.
TEST_P(ResourceTableTests, ResourceTableCreation) {
    // Creating an empty resource table.
    MakeResourceTable(0);

    // Creating a resource table with a few entries.
    MakeResourceTable(36);

    // Creating a resource table with the maximum number of entries.
    MakeResourceTable(kMaxResourceTableSize);
}

// Test that creating pipeline layouts with resources tables doesn't crash in backends.
TEST_P(ResourceTableTests, PipelineLayoutWithResourceTableCreation) {
    // Make layouts with no BGLs with / without immediates.
    MakePipelineLayoutWithTable({}, 0);
    MakePipelineLayoutWithTable({}, 4);

    // Make layouts with one BGL, with / without immediates.
    wgpu::BindGroupLayout testBgl = utils::MakeBindGroupLayout(
        device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform}});
    MakePipelineLayoutWithTable({testBgl}, 0);
    MakePipelineLayoutWithTable({testBgl}, 4);

    // Make layouts with max BGLs (3 because the resource tables "consumes" one bind group), with /
    // without immediates.
    MakePipelineLayoutWithTable({testBgl, testBgl, testBgl}, 0);
    MakePipelineLayoutWithTable({testBgl, testBgl, testBgl}, 4);
}

// Test that creating pipelines that use resource tables doesn't crash in backends.
TEST_P(ResourceTableTests, ShaderWithResourceTableCreation) {
    wgpu::ComputePipelineDescriptor csDesc;

    // Test compiling a pipeline using only the resource table.
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
        }
    )");
    device.CreateComputePipeline(&csDesc);

    // Test compiling a pipeline using the resource table and a bindgroup.
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @group(0) @binding(0) var t0 : texture_2d<f32>;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
            _ = t0;
        }
    )");
    device.CreateComputePipeline(&csDesc);

    // Test compiling a pipeline using the resource table and many bindgroup.
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;
        @group(0) @binding(0) var t0 : texture_2d<f32>;
        @group(1) @binding(0) var t1 : texture_2d<f32>;
        @group(2) @binding(0) var t2 : texture_2d<f32>;
        @compute @workgroup_size(1) fn main() {
            _ = hasResource<texture_2d<f32>>(0);
            _ = t0;
            _ = t1;
            _ = t2;
        }
    )");
    device.CreateComputePipeline(&csDesc);
}

// Test that creating resource tables of different sizes doesn't end up reusing incorrectly sized
// allocations.
TEST_P(ResourceTableTests, RecyclingDoesntReuseTooSmallAllocation) {
    for (uint32_t i = 0; i < 10; i++) {
        MakeResourceTable(i);

        // Wait to ensure some deallocation happens and has a chance to cause incorrect recycling.
        WaitForAllOperations();
    }
}

// Tests that pinning / unpinning doesn't crash in backends.
TEST_P(ResourceTableTests, PinningBalancedInBackends) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R16Float,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    // Frontend should skip that unpinning as the texture is not pinned.
    tex.Unpin();

    // Duplicate pinning should be skipped by the frontend.
    tex.Pin(wgpu::TextureUsage::TextureBinding);
    tex.Pin(wgpu::TextureUsage::TextureBinding);

    // Duplicate unpinning should be skipped by the frontend.
    tex.Unpin();
    tex.Unpin();

    // Force a queue submit to flush pending commands and potentially find more issues.
    queue.Submit(0, nullptr);
}

// Test WGSL `hasResource` reflects the state of the resource table.
TEST_P(ResourceTableTests, HasResourceOneTexturePinUnpin) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(3, {{1, {.textureView = tex.CreateView()}}});

    // Before pinning, the table has no valid entries.
    TestHasResource(table, {false, false, false});

    // After pinning it has the one valid entry valid.
    tex.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {false, true, false});

    // After unpinning it has the no more valid entries.
    tex.Unpin();
    TestHasResource(table, {false, false, false});
}

// Test WGSL `hasResource` reflects the state of the resource table.
TEST_P(ResourceTableTests, HasResourceFilterableToUnfilterable) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(3, {{1, {.textureView = tex.CreateView()}}});

    tex.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {false, true, false}, "texture_2d<f32>");
}

// Test that calling texture.Destroy() implicitly unpins it.
TEST_P(ResourceTableTests, HasResourceOneTexturePinDestroy) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(3, {{1, {.textureView = tex.CreateView()}}});

    // Before pinning, the table has no valid entries.
    TestHasResource(table, {false, false, false});

    // After pinning it has the one valid entry valid.
    tex.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {false, true, false});

    // After texture destruction it has the no more valid entries.
    tex.Destroy();
    TestHasResource(table, {false, false, false});
}

// Test that a texture used multiple times in the same table has its availability correctly updated.
TEST_P(ResourceTableTests, HasResourceSameTextureMultipleTimesPinUnpin) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(4, {
                                                         {1, {.textureView = tex.CreateView()}},
                                                         {3, {.textureView = tex.CreateView()}},
                                                     });

    // Before pinning, the table has no valid entries.
    TestHasResource(table, {false, false, false, false});

    // After pinning it has valid entries.
    tex.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {false, true, false, true});

    // After unpinning it has the no more valid entries.
    tex.Unpin();
    TestHasResource(table, {false, false, false, false});
}

// Test that updating a table with an already destroyed texture works, but doesn't show that entry
// as available.
TEST_P(ResourceTableTests, HasResourceUpdateWithTextureAlreadyDestroyed) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);
    tex.Destroy();

    wgpu::ResourceTable table = MakeResourceTable(1, {{0, {.textureView = tex.CreateView()}}});

    // Before pinning, the table has no valid entries.
    TestHasResource(table, {false});
}

// Test that a texture used in multiple resource tables has its availability correctly updated.
TEST_P(ResourceTableTests, HasResourceSameTextureMultipleTables) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table1 = MakeResourceTable(3, {{1, {.textureView = tex.CreateView()}}});
    wgpu::ResourceTable table2 = MakeResourceTable(1, {{0, {.textureView = tex.CreateView()}}});

    // Before pinning, the tables have no valid entries.
    TestHasResource(table1, {false, false, false});
    TestHasResource(table2, {false});

    // After pinning the texture, they have valid entries.
    tex.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table1, {false, true, false});
    TestHasResource(table2, {true});

    // After destroying one table, the other still has the texture available.
    table1.Destroy();
    TestHasResource(table2, {true});
}

// Test that texture availabililty is controlled per-texture.
TEST_P(ResourceTableTests, HasResourceMultipleTexturesTable) {
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex0 = device.CreateTexture(&tDesc);
    wgpu::Texture tex1 = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(2, {
                                                         {0, {.textureView = tex0.CreateView()}},
                                                         {1, {.textureView = tex1.CreateView()}},
                                                     });

    // Before pinning, the table has no valid entries.
    TestHasResource(table, {false, false});

    // After pinning tex0 it has one valid entry.
    tex0.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {true, false});

    // After pinning tex1 it has two valid entries.
    tex1.Pin(wgpu::TextureUsage::TextureBinding);
    TestHasResource(table, {true, true});

    // After unpinning tex0 it has only one valid entry.
    tex0.Unpin();
    TestHasResource(table, {false, true});
}

constexpr auto kWgslSampledTextureTypes = std::array{
    "texture_1d<f32>",
    "texture_1d<i32>",
    "texture_1d<u32>",
    "texture_2d<f32>",
    "texture_2d<i32>",
    "texture_2d<u32>",
    "texture_2d_array<f32>",
    "texture_2d_array<i32>",
    "texture_2d_array<u32>",
    "texture_cube<f32>",
    "texture_cube<i32>",
    "texture_cube<u32>",
    "texture_cube_array<f32>",
    "texture_cube_array<i32>",
    "texture_cube_array<u32>",
    "texture_3d<f32>",
    "texture_3d<i32>",
    "texture_3d<u32>",

    "texture_multisampled_2d<f32>",
    "texture_multisampled_2d<i32>",
    "texture_multisampled_2d<u32>",

    "texture_depth_2d",
    "texture_depth_2d_array",
    "texture_depth_cube",
    "texture_depth_cube_array",
    "texture_depth_multisampled_2d",

    "sampler",
    "sampler_comparison",
};

struct ResourceDescForTypeIDCase {
    // Set of all WGSL types that can be validly bound to the underlying resource described by
    // `desc`.
    std::unordered_set<std::string_view> wgslTypes;

    struct TextureDesc {
        wgpu::TextureFormat format;
        wgpu::TextureDimension dimension;
        wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::Undefined;
        uint32_t sampleCount = 1;
        wgpu::TextureAspect viewAspect = wgpu::TextureAspect::All;
    };
    struct SamplerDesc {
        bool filtering = false;
        bool comparison = false;
    };
    // The descriptor used to create the resource
    std::variant<TextureDesc, SamplerDesc> desc;

    // Create a view for a pinned texture for this case.
    wgpu::TextureView CreateTestView(const wgpu::Device& device) {
        auto& d = std::get<TextureDesc>(desc);

        wgpu::TextureDescriptor tDesc = {
            .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc,
            .dimension = d.dimension,
            .size = {1, 1, 1},
            .format = d.format,
            .sampleCount = d.sampleCount,
        };
        if (d.viewDimension == wgpu::TextureViewDimension::Cube ||
            d.viewDimension == wgpu::TextureViewDimension::CubeArray) {
            tDesc.size.depthOrArrayLayers = 6;
        }
        if (d.sampleCount != 1) {
            tDesc.usage |= wgpu::TextureUsage::RenderAttachment;
        }

        wgpu::TextureViewDescriptor vDesc{
            .dimension = d.viewDimension,
            .aspect = d.viewAspect,
            .usage = wgpu::TextureUsage::TextureBinding,
        };

        wgpu::Texture texture = device.CreateTexture(&tDesc);
        texture.Pin(wgpu::TextureUsage::TextureBinding);
        return texture.CreateView(&vDesc);
    }

    // Create a sampler for this case.
    wgpu::Sampler CreateTestSampler(const wgpu::Device& device) {
        auto& d = std::get<SamplerDesc>(desc);

        wgpu::SamplerDescriptor desc{};
        if (d.filtering) {
            desc.magFilter = wgpu::FilterMode::Linear;
            desc.minFilter = wgpu::FilterMode::Linear;
            desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
        }
        if (d.comparison) {
            desc.compare = wgpu::CompareFunction::Less;
        }
        return device.CreateSampler(&desc);
    }
};

std::vector<ResourceDescForTypeIDCase> MakeDescForTypeIDCases() {
    std::vector<ResourceDescForTypeIDCase> cases;

    using TextureDesc = ResourceDescForTypeIDCase::TextureDesc;
    using SamplerDesc = ResourceDescForTypeIDCase::SamplerDesc;

    // Regular 1D textures.
    cases.push_back({.wgslTypes = {{"texture_1d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e1D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_1d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e1D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_1d<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e1D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_1d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e1D,
                     }});

    // Regular 2D textures.
    cases.push_back({.wgslTypes = {{"texture_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});

    // Regular 2D array textures.
    cases.push_back({.wgslTypes = {{"texture_2d_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d_array<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d_array<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});

    // Regular cube textures.
    cases.push_back({.wgslTypes = {{"texture_cube<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});

    // Regular cube array textures.
    cases.push_back({.wgslTypes = {{"texture_cube_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube_array<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube_array<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});

    // Regular 3d textures.
    cases.push_back({.wgslTypes = {{"texture_3d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e3D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_3d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Float,
                         .dimension = wgpu::TextureDimension::e3D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_3d<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Sint,
                         .dimension = wgpu::TextureDimension::e3D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_3d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA32Uint,
                         .dimension = wgpu::TextureDimension::e3D,
                     }});

    // Color multisampled textures.
    cases.push_back({.wgslTypes = {{"texture_multisampled_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA8Unorm,
                         .dimension = wgpu::TextureDimension::e2D,
                         .sampleCount = 4,
                     }});
    cases.push_back({.wgslTypes = {{"texture_multisampled_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA16Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .sampleCount = 4,
                     }});
    cases.push_back({.wgslTypes = {{"texture_multisampled_2d<i32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA16Sint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .sampleCount = 4,
                     }});
    cases.push_back({.wgslTypes = {{"texture_multisampled_2d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::RGBA16Uint,
                         .dimension = wgpu::TextureDimension::e2D,
                         .sampleCount = 4,
                     }});

    // Depth textures (including multisampled).
    cases.push_back({.wgslTypes = {{"texture_depth_2d"}, {"texture_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_depth_2d_array"}, {"texture_2d_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_depth_cube"}, {"texture_cube<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});
    cases.push_back({.wgslTypes = {{"texture_depth_cube_array"}, {"texture_cube_array<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_depth_multisampled_2d"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth32Float,
                         .dimension = wgpu::TextureDimension::e2D,
                         .sampleCount = 4,
                     }});

    // Stencil textures can be used as 2D.
    cases.push_back({.wgslTypes = {{"texture_2d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Stencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d_array<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Stencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::e2DArray,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Stencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::Cube,
                     }});
    cases.push_back({.wgslTypes = {{"texture_cube_array<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Stencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewDimension = wgpu::TextureViewDimension::CubeArray,
                     }});

    // Depth-stencil textures with only one aspect selected.
    cases.push_back({.wgslTypes = {{"texture_depth_2d"}, {"texture_2d<f32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth24PlusStencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewAspect = wgpu::TextureAspect::DepthOnly,
                     }});
    cases.push_back({.wgslTypes = {{"texture_2d<u32>"}},
                     .desc = TextureDesc{
                         .format = wgpu::TextureFormat::Depth24PlusStencil8,
                         .dimension = wgpu::TextureDimension::e2D,
                         .viewAspect = wgpu::TextureAspect::StencilOnly,
                     }});

    // Non-filtering sampler
    cases.push_back({
        .wgslTypes = {{"sampler"}},
        .desc = SamplerDesc{},
    });
    // Filtering sampler
    cases.push_back({
        .wgslTypes = {{"sampler"}},
        .desc =
            SamplerDesc{
                .filtering = true,
            },
    });
    // Comparison sampler
    cases.push_back({
        .wgslTypes = {{"sampler_comparison"}},
        .desc =
            SamplerDesc{
                .comparison = true,
            },
    });

    return cases;
}

// Test that hasResource() works as expected for all supported resources in WGSL.
TEST_P(ResourceTableTests, HasResourceCompatibilityAllTypes) {
    // We rely on RGBA32Float being unfilterable for this test so that we can test both filterable /
    // unfilterable float without needing any additional extensions.
    DAWN_ASSERT(!device.HasFeature(wgpu::FeatureName::Float32Filterable));

    auto cases = MakeDescForTypeIDCases();

    // Make a resource table with all of our test texture views.
    wgpu::ResourceTable table = MakeResourceTable(cases.size());
    for (auto [i, c] : Enumerate(cases)) {
        if (std::holds_alternative<ResourceDescForTypeIDCase::TextureDesc>(c.desc)) {
            wgpu::BindingResource resource = {.textureView = c.CreateTestView(device)};
            EXPECT_EQ(wgpu::Status::Success, table.Update(i, &resource));
        } else if (std::holds_alternative<ResourceDescForTypeIDCase::SamplerDesc>(c.desc)) {
            wgpu::BindingResource resource = {.sampler = c.CreateTestSampler(device)};
            EXPECT_EQ(wgpu::Status::Success, table.Update(i, &resource));
        }
    }

    // Test hasResource returning for each of the supported WGSL types, against each resource.
    for (auto wgslType : kWgslSampledTextureTypes) {
        std::vector<bool> expected;
        expected.reserve(cases.size());
        for (auto& c : cases) {
            // The reasons wgslTypes is a vector is because some textures can be
            // both filterable and non-filterable, so hasResource will return true for both types on
            // the one table entry with such a texture.
            expected.push_back(c.wgslTypes.contains(wgslType));
        }

        TestHasResource(table, expected, wgslType);
    }
}

// Test that calling hasResource() with values outside of the resource table size returns false.
TEST_P(ResourceTableTests, HasResourceOOBIsFalse) {
    // Create the test pipeline
    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> result : array<u32, 4>;
        var<immediate> resourceCount : u32;
        @compute @workgroup_size(1) fn getArrayLengths() {
            result[0] = u32(hasResource<texture_2d<f32>>(resourceCount - 1));
            result[1] = u32(hasResource<texture_2d<f32>>(resourceCount));

            // Check against all the slots where the default resources are.
            var result2 = 0u;
            for (var i = 1u; i < 100; i++) {
                result2 += u32(hasResource<texture_2d<f32>>(resourceCount + i));
            }
            result[2] = result2;

            result[3] = u32(hasResource<texture_2d<f32>>(resourceCount + 10000000));
        }
    )");
    wgpu::ComputePipelineDescriptor csDesc = {.compute = {
                                                  .module = module,
                                              }};
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    // Create the test resource table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R8Unorm,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);
    tex.Pin(wgpu::TextureUsage::TextureBinding);

    wgpu::ResourceTable table = MakeResourceTable(3, {
                                                         {0, {.textureView = tex.CreateView()}},
                                                         {1, {.textureView = tex.CreateView()}},
                                                         {2, {.textureView = tex.CreateView()}},
                                                     });

    // Create the other test resources.
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = 4 * sizeof(uint32_t),
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});
    uint32_t resourceCount = table.GetSize();

    // Run the test and check results are the expected ones.
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    pass.SetResourceTable(table);
    pass.SetImmediates(0, &resourceCount, sizeof(resourceCount));
    pass.SetBindGroup(0, resultBG);
    pass.SetPipeline(pipeline);
    pass.DispatchWorkgroups(1);
    pass.End();

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

    EXPECT_BUFFER_U32_EQ(1, resultBuffer, 0);
    EXPECT_BUFFER_U32_EQ(0, resultBuffer, 4);
    EXPECT_BUFFER_U32_EQ(0, resultBuffer, 8);
    EXPECT_BUFFER_U32_EQ(0, resultBuffer, 12);
}

// Check that the default bindings are of size 1 and filled with zeroes. This is not an exhaustive
// test (that's for the CTS) but tries to check a few different interesting cases (MS, DS, Cube, 2D
// array).
TEST_P(ResourceTableTests, DefaultBindingsAreZeroAndSizeOne) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create the test pipeline
    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> error : u32;
        @group(0) @binding(1) var s : sampler;

        var<private> checkIndex = 0u;
        fn check(b : bool) {
            if (!b && error == 0) {
                error = 1 + checkIndex;
            }
            checkIndex++;
        }

        @compute @workgroup_size(1) fn checkDefault() {
            // Default texture_2d<f32>
            {
                check(!hasResource<texture_2d<f32>>(0));
                let t = getResource<texture_2d<f32>>(0);
                check(all(textureDimensions(t) == vec2(1)));
                check(textureNumLevels(t) == 1);
                check(all(textureLoad(t, vec2(0), 0) == vec4(0, 0, 0, 1)));
            }

            // Default texture_multisampled_2d
            {
                check(!hasResource<texture_multisampled_2d<u32>>(0));
                let t = getResource<texture_multisampled_2d<u32>>(0);
                check(all(textureDimensions(t) == vec2(1)));
                check(textureNumSamples(t) == 4);
                check(all(textureLoad(t, vec2(0), 0) == vec4(0, 0, 0, 1)));
            }

            // Default texture_depth_cube
            {
                check(!hasResource<texture_depth_cube>(0));
                let t = getResource<texture_depth_cube>(0);
                check(all(textureDimensions(t) == vec2(1)));
                check(textureNumLevels(t) == 1);
                check(textureSampleLevel(t, s, vec3(0), 0) == 0);
            }

            // Default texture_2d_array<i32>
            {
                check(!hasResource<texture_2d_array<i32>>(0));
                let t = getResource<texture_2d_array<i32>>(0);
                check(all(textureDimensions(t) == vec2(1)));
                check(textureNumLevels(t) == 1);
                check(textureNumLayers(t) == 1);
                check(all(textureLoad(t, vec2(0), 0, 0) == vec4(0, 0, 0, 1)));
            }
        }
    )");
    wgpu::ComputePipelineDescriptor csDesc = {.compute = {
                                                  .module = module,
                                              }};
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    // Create the test resources.
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(uint32_t),
    };
    wgpu::Buffer errorBuffer = device.CreateBuffer(&bDesc);

    wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                              {
                                                  {0, errorBuffer},
                                                  {1, device.CreateSampler()},
                                              });
    wgpu::ResourceTable table = MakeResourceTable(0);

    // Run the test and check results are the expected ones.
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    pass.SetResourceTable(table);
    pass.SetBindGroup(0, bg);
    pass.SetPipeline(pipeline);
    pass.DispatchWorkgroups(1);
    pass.End();

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

    EXPECT_BUFFER_U32_EQ(0, errorBuffer, 0);
}

// Test that a resource table texture can be sampled by a resource table sampler.
TEST_P(ResourceTableTests, Sampler) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    // Create a 1x1 texture with a single red pixel.
    wgpu::TextureDescriptor texDesc;
    texDesc.size = {1, 1};
    texDesc.format = wgpu::TextureFormat::RGBA8Unorm;
    texDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst;
    wgpu::Texture texture = device.CreateTexture(&texDesc);

    const utils::RGBA8 red = utils::RGBA8::kRed;
    wgpu::TexelCopyTextureInfo srcInfo = utils::CreateTexelCopyTextureInfo(texture, 0, {0, 0, 0});
    wgpu::TexelCopyBufferLayout dstInfo = {};
    wgpu::Extent3D copySize = {1, 1, 1};
    queue.WriteTexture(&srcInfo, &red, sizeof(red), &dstInfo, &copySize);

    wgpu::Sampler sampler = device.CreateSampler();

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let s = getResource<sampler>(0);
            let t = getResource<texture_2d<f32>>(1);
            return textureSample(t, s, vec2f(0.5, 0.5));
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    texture.Pin(wgpu::TextureUsage::TextureBinding);
    wgpu::ResourceTable table = MakeResourceTable(2, {
                                                         {0, {.sampler = sampler}},
                                                         {1, {.textureView = texture.CreateView()}},
                                                     });

    // Create a 1x1 render target to verify the result.
    utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // Render.
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
    pass.SetPipeline(pipeline);
    pass.SetResourceTable(table);
    pass.Draw(1);
    pass.End();
    wgpu::CommandBuffer commands = encoder.Finish();
    queue.Submit(1, &commands);

    // Verify the result is red.
    EXPECT_PIXEL_RGBA8_EQ(red, renderPass.color, 0, 0);
}

// Test that a resource table texture can be sampled by multiple resource table samplers.
TEST_P(ResourceTableTests, MultipleSamplers) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
    // TODO(https://crbug.com/510904606): Fails on LLVMPipe
    DAWN_SUPPRESS_TEST_IF(IsMesaSoftware());

    struct Case {
        size_t tableSize;
        uint32_t samplerIndex0;
        uint32_t samplerIndex1;
        uint32_t samplerIndex2;
        uint32_t textureIndex;
    };
    constexpr auto kMax = kMaxResourceTableSize;
    Case cases[] = {
        {4, 0, 1, 2, 3},
        {2048, 2048 - 1, 2048 - 2, 2048 - 3, 2048 - 4},
        {kMax, kMax - 1, kMax - 2, kMax - 3, kMax - 4},
        {2048, 2048 / 4 * 1 - 1, 2048 / 4 * 2 - 1, 2048 / 4 * 3 - 1, 2048 / 4 * 4 - 1},
        {kMax, kMax / 4 * 1 - 1, kMax / 4 * 2 - 1, kMax / 4 * 3 - 1, kMax / 4 * 4 - 1},
    };

    for (auto c : cases) {
        wgpu::ShaderModule module =
            utils::CreateShaderModule(device, absl::StrFormat(R"(
            enable chromium_experimental_resource_table;

            @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f(0, 0, 0.5, 0.5);
            }

            @fragment fn fs() -> @location(0) vec4f {
                let samplerRepeat = getResource<sampler>(%u);
                let samplerMirror = getResource<sampler>(%u);
                let samplerClamp = getResource<sampler>(%u);
                let t = getResource<texture_2d<f32>>(%u);

                results[0] = textureSample(t, samplerRepeat, vec2f(1, 0));
                results[1] = textureSample(t, samplerRepeat, vec2f(1.5, 0));

                results[2] = textureSample(t, samplerMirror, vec2f(1, 0));
                results[3] = textureSample(t, samplerMirror, vec2f(1.5, 0));

                results[4] = textureSample(t, samplerClamp, vec2f(1, 0));
                results[5] = textureSample(t, samplerClamp, vec2f(1.5, 0));

                return vec4f(0);
            }
        )",
                                                              c.samplerIndex0, c.samplerIndex1,
                                                              c.samplerIndex2, c.textureIndex));

        // Create the pipeline.
        utils::ComboRenderPipelineDescriptor pDesc;
        pDesc.vertex.module = module;
        pDesc.cFragment.module = module;
        pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
        pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

        // Create the texture
        wgpu::Texture texture = CreateCheckerboardTexture();

        // Create 3 samplers
        wgpu::Sampler samplerRepeat = CreateSampler(wgpu::AddressMode::Repeat);
        wgpu::Sampler samplerMirror = CreateSampler(wgpu::AddressMode::MirrorRepeat);
        wgpu::Sampler samplerClamp = CreateSampler(wgpu::AddressMode::ClampToEdge);

        // Create the result buffer resource
        wgpu::BufferDescriptor bDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(float) * 4 * 6,  // 6 vec4fs
        };
        wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
        wgpu::BindGroup resultBG =
            utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

        // Create resource table and add the samplers and texture view to it
        texture.Pin(wgpu::TextureUsage::TextureBinding);
        wgpu::ResourceTable table = MakeResourceTable(
            c.tableSize, {
                             {c.samplerIndex0, {.sampler = samplerRepeat}},
                             {c.samplerIndex1, {.sampler = samplerMirror}},
                             {c.samplerIndex2, {.sampler = samplerClamp}},
                             {c.textureIndex, {.textureView = texture.CreateView()}},
                         });

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

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, resultBG);
        pass.SetResourceTable(table);
        pass.Draw(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);

        float expectedGreen[4] = {0.0, 1.0, 0.0, 1.0};
        float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};

        // repeat: 1,0 -> red, 1.5,0 -> green
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0 * 4 * sizeof(float), 4);
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 1 * 4 * sizeof(float), 4);

        // mirror: 1,0 -> green, 1.5,0 -> red
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 2 * 4 * sizeof(float), 4);
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 3 * 4 * sizeof(float), 4);

        // clamp: 1,0 -> green, 1.5,0 -> green
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 4 * 4 * sizeof(float), 4);
        EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 5 * 4 * sizeof(float), 4);
    }
}

// Test that default samplers are correctly created, and accessed when an invalid index it provided.
TEST_P(ResourceTableTests, UseDefaultSamplers) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    auto CreateDepthTexture = [&]() {
        wgpu::TextureDescriptor descriptor;
        // descriptor.dimension = wgpu::TextureDimension::e2D;
        descriptor.size = {1, 1};
        descriptor.format = wgpu::TextureFormat::Depth24Plus;
        descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
        return device.CreateTexture(&descriptor);
    };

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let t = getResource<texture_2d<f32>>(0);
            let dt = getResource<texture_depth_2d>(1);

            let samplerNonFiltering = getResource<sampler>(2);
            let samplerFiltering = getResource<sampler>(3);
            let samplerComparison = getResource<sampler_comparison>(4);

            results[0] = textureSample(t, samplerNonFiltering, vec2f(0.5, 0.5));
            results[1] = textureSample(t, samplerNonFiltering, vec2f(0.6, 0.6));

            results[2] = textureSample(t, samplerFiltering, vec2f(0.5, 0.5));
            results[3] = textureSample(t, samplerFiltering, vec2f(0.6, 0.6));

            let c = textureSampleCompare(dt, samplerComparison, vec2f(0.5, 0.5), 0.5);
            results[4] = vec4f(c, 42.0f, c, 83.5f);

            return vec4f(0);
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    // Create the textures
    wgpu::Texture colorTexture = CreateCheckerboardTexture();
    wgpu::Texture depthTexture = CreateDepthTexture();

    // Create the result buffer resource
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(float) * 4 * 5,  // 5 vec4fs
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

    // Create resource table and only textures to it, no samplers, so that the default
    // samplers get used
    colorTexture.Pin(wgpu::TextureUsage::TextureBinding);
    depthTexture.Pin(wgpu::TextureUsage::TextureBinding);
    wgpu::ResourceTable table =
        MakeResourceTable(10, {
                                  {0, {.textureView = colorTexture.CreateView()}},
                                  {1, {.textureView = depthTexture.CreateView()}},
                              });

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

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
    pass.SetPipeline(pipeline);
    pass.SetBindGroup(0, resultBG);
    pass.SetResourceTable(table);
    pass.Draw(1);
    pass.End();
    wgpu::CommandBuffer commands = encoder.Finish();
    queue.Submit(1, &commands);

    float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};
    float expectedGreen[4] = {1.0, 0.0, 0.0, 1.0};

    // The default non-filtering sampler should return red at (0.5, 0.5), and green at (0.6, 0.6)
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 1 * 4 * sizeof(float), 4);

    // The default filtering sampler is actually a non-filtering one, so should return the same
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 2 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 3 * 4 * sizeof(float), 4);

    // The comparison sampler is an 'always' one, so it should return 1.0, which the shader returns
    // in two of the vector elements.
    float expectedCompare[4] = {1.0, 42.0, 1.0, 83.5};
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedCompare, resultBuffer, 4 * 4 * sizeof(float), 4);
}

// Test that removing then adding a new sampler in a slot that already has a sampler of the same
// type (e.g. filterable) works as expected. This ensures, for example, that the metadata buffer
// gets an updated sampler index on D3D12.
TEST_P(ResourceTableTests, RemoveThenAddSamplerInSameSlot) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
    // TODO(https://crbug.com/510904606): Fails on LLVMPipe
    DAWN_SUPPRESS_TEST_IF(IsMesaSoftware());

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let t = getResource<texture_2d<f32>>(0);
            let s = getResource<sampler>(1);

            results[0] = textureSample(t, s, vec2f(1, 0));
            results[1] = textureSample(t, s, vec2f(1.5, 0));
            return vec4f(0);
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    // Create texture
    wgpu::Texture texture = CreateCheckerboardTexture();
    texture.Pin(wgpu::TextureUsage::TextureBinding);

    // Create samplers
    wgpu::Sampler samplerRepeat = CreateSampler(wgpu::AddressMode::Repeat);
    wgpu::Sampler samplerMirror = CreateSampler(wgpu::AddressMode::MirrorRepeat);

    // Create the result buffer resource
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(float) * 4 * 2,  // 2 vec4fs
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

    // Create resource table
    wgpu::ResourceTable table = MakeResourceTable(2, {
                                                         {0, {.textureView = texture.CreateView()}},
                                                     });

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

    auto draw = [&]() {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, resultBG);
        pass.SetResourceTable(table);
        pass.Draw(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    wgpu::BindingResource res;
    float expectedGreen[4] = {0.0, 1.0, 0.0, 1.0};
    float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};

    // Add repeat sampler and draw
    res = {.sampler = samplerRepeat};
    EXPECT_EQ(wgpu::Status::Success, table.Update(1, &res));
    draw();

    // repeat: 1,0 -> red, 1.5,0 -> green
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 1 * 4 * sizeof(float), 4);

    // Now test removing then adding mirror sampler
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
    WaitForAllOperations();
    res = {.sampler = samplerMirror};
    EXPECT_EQ(wgpu::Status::Success, table.Update(1, &res));
    draw();

    // mirror: 1,0 -> green, 1.5,0 -> red
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 0 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 1 * 4 * sizeof(float), 4);
}

// Test that adding and removing samplers in the same slot between draws ensure that
// backends only see the effective diff (first one added to last one added).
TEST_P(ResourceTableTests, RemoveThenAddSamplerMultipleInSameSlot) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let t = getResource<texture_2d<f32>>(0);
            let s = getResource<sampler>(1);

            results[0] = textureSample(t, s, vec2f(1, 0));
            results[1] = textureSample(t, s, vec2f(1.5, 0));
            return vec4f(0);
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    // Create texture
    wgpu::Texture texture = CreateCheckerboardTexture();
    texture.Pin(wgpu::TextureUsage::TextureBinding);

    // Create samplers
    wgpu::Sampler samplerRepeat = CreateSampler(wgpu::AddressMode::Repeat);
    wgpu::Sampler samplerMirror[] = {
        // Create different types to make sure they don't get de-duped
        CreateSampler(wgpu::AddressMode::MirrorRepeat, wgpu::CompareFunction::Always),
        CreateSampler(wgpu::AddressMode::MirrorRepeat, wgpu::CompareFunction::Equal),
        CreateSampler(wgpu::AddressMode::MirrorRepeat, wgpu::CompareFunction::GreaterEqual)};
    wgpu::Sampler samplerClamp = CreateSampler(wgpu::AddressMode::ClampToEdge);

    // Create the result buffer resource
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(float) * 4 * 2,  // 2 vec4fs
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

    // Create resource table and add the samplers and texture view to it
    wgpu::ResourceTable table = MakeResourceTable(2, {
                                                         {0, {.textureView = texture.CreateView()}},
                                                     });

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

    auto draw = [&]() {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, resultBG);
        pass.SetResourceTable(table);
        pass.Draw(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    wgpu::BindingResource res;
    float expectedGreen[4] = {0.0, 1.0, 0.0, 1.0};
    float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};

    // Add repeat sampler and draw
    res = {.sampler = samplerRepeat};
    EXPECT_EQ(wgpu::Status::Success, table.Update(1, &res));
    draw();

    // repeat: 1,0 -> red, 1.5,0 -> green
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 1 * 4 * sizeof(float), 4);

    // Remove then add mirror samplers
    for (auto sampler : samplerMirror) {
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
        WaitForAllOperations();
        res = {.sampler = sampler};
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &res));
    }

    // Finally, remove and add clamp sampler
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
    WaitForAllOperations();
    res = {.sampler = samplerClamp};
    EXPECT_EQ(wgpu::Status::Success, table.Update(1, &res));

    // Now draw. Backends should basically ignore the adding and removal of the mirror sampler.
    draw();

    // clamp: 1,0 -> green, 1.5,0 -> green
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 0 * 4 * sizeof(float), 4);
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 1 * 4 * sizeof(float), 4);
}

// Test what happens when we add more than kD3D12MaxUniqueSamplers unique samplers
TEST_P(ResourceTableTests, AddUniqueSamplersOverLimit) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    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);
        }
    )");
    auto pipeline = device.CreateComputePipeline(&csDesc);

    auto dispatch = [&](wgpu::ResourceTable table, bool shouldSucceed = true) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        if (shouldSucceed) {
            queue.Submit(1, &commands);
        } else {
            ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
        }
    };

    wgpu::ResourceTable table = MakeResourceTable(2049);

    // Initial draw so that default resources are processed
    dispatch(table);

    // Add kD3D12MaxUniqueSamplers, should all succeed
    for (auto i : Range(kD3D12MaxUniqueSamplers)) {
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(i)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(i, &br));
    }

    dispatch(table);

    // Now add one more, should fail
    {
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(kD3D12MaxUniqueSamplers)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(kD3D12MaxUniqueSamplers, &br));
    }

    bool shouldSucceed = !IsD3D12();
    dispatch(table, shouldSucceed);
}

// Test that adding a sampler, draw, then remove and add a duplicate sampler and draw works. This
// tests that deduplication logic handles when no more refs are left to a sampler, and then a
// duplicate sampler is added back. On D3D12, internally this may result in a new sampler index,
// which should be fine.
TEST_P(ResourceTableTests, RemoveAddDuplicateSampler) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    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);
        }
    )");
    auto pipeline = device.CreateComputePipeline(&csDesc);

    auto dispatch = [&](wgpu::ResourceTable table) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    wgpu::ResourceTable table = MakeResourceTable(2);

    // Initial draw so that default resources are processed
    dispatch(table);

    {
        // Add a unique sampler in slot 1
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(42)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &br));
    }
    dispatch(table);

    {
        // Remove the sampler in slot 1
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));

        WaitForAllOperations();

        // Add another sampler in slot 0
        // This is to coax the backend into potentially assigning a different sampler index for this
        // same sampler.
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(123)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(0, &br));

        // Add back the origin sampler in slot 1
        wgpu::BindingResource br2{.sampler = CreateUniqueSampler(42)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(1, &br2));
    }

    dispatch(table);
}

// On D3D12 the number of sampler descriptors in a GPU heap is limited to 2048. We deduplicate
// samplers, so test that we can add more than 2048 samplers to the resource table, as long as there
// are duplicates. We test this by creating a table of size 2*2048, add 2048 unique samplers in the
// first half of the table, then add the same set of sampers in the second half of the table.
TEST_P(ResourceTableTests, AddDuplicateSamplersTwice) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    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);
        }
    )");
    auto pipeline = device.CreateComputePipeline(&csDesc);

    auto dispatch = [&](wgpu::ResourceTable table) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    // Make a table with double the max number of unique samplers on D3D12.
    wgpu::ResourceTable table = MakeResourceTable(kD3D12MaxUniqueSamplers * 2);

    // Add samplers to slots 0..kD3D12MaxUniqueSamplers-1
    for (uint32_t i : Range(kD3D12MaxUniqueSamplers)) {
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(i)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(i, &br));
    }

    // Draw so that the CPU to GPU sampler heap creation and copy occurs.
    dispatch(table);

    // Add the same samplers to slots kD3D12MaxUniqueSamplers..kD3D12MaxUniqueSamplers*2-1
    for (uint32_t i : Range(kD3D12MaxUniqueSamplers)) {
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(i)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(i + kD3D12MaxUniqueSamplers, &br));
    }

    // Draw again. If we didn't handle removal of samplers correctly, this will fail
    // for surpassing the 2048 sampler descriptor per heap limit.
    dispatch(table);
}

// On D3D12 the number of sampler descriptors in a GPU heap is limited to 2048. This test
// allocates a resource table larger than that, adds 2048 unique samplers, draws, removes them all,
// then adds 2048 unique samplers (different from the first set) again in different slots,
// and draws again, making sure this is supported. Effectively, this tests that the resource table
// correctly handles removal of samplers.
TEST_P(ResourceTableTests, AddAndRemoveMaxSamplersTwice) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
    // TODO(https://issues.chromium.org/issues/512829734): Fails on Vulkan if
    // VkPhysicalDeviceLimits::maxSamplerAllocationCount <= 4K
    DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsWindows() && IsIntel());

    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);
        }
    )");
    auto pipeline = device.CreateComputePipeline(&csDesc);

    auto dispatch = [&](wgpu::ResourceTable table) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    // Make a table with double the max number of samplers on D3D12.
    wgpu::ResourceTable table = MakeResourceTable(kD3D12MaxUniqueSamplers * 2);

    // Add samplers to slots 0..kD3D12MaxUniqueSamplers-1
    for (uint32_t i : Range(kD3D12MaxUniqueSamplers)) {
        // Make samplers unique by making one of the values different for each
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(i)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(i, &br));
    }

    // Draw so that the CPU to GPU sampler heap creation and copy occurs.
    dispatch(table);

    // Remove all samplers
    for (uint32_t i : Range(kD3D12MaxUniqueSamplers)) {
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(i));
    }

    // Add different samplers to slots kD3D12MaxUniqueSamplers..kD3D12MaxUniqueSamplers*2-1
    for (uint32_t i : Range(kD3D12MaxUniqueSamplers)) {
        wgpu::BindingResource br{.sampler = CreateUniqueSampler(kD3D12MaxUniqueSamplers + i)};
        EXPECT_EQ(wgpu::Status::Success, table.Update(i + kD3D12MaxUniqueSamplers, &br));
    }

    // Draw again. If we didn't handle removal of samplers correctly, this will fail
    // for surpassing the 2048 sampler descriptor per heap limit.
    dispatch(table);
}

// Test that removing then adding a texture in a slot works as expected.
TEST_P(ResourceTableTests, RemoveThenAddTextureInSameSlot) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let t = getResource<texture_2d<f32>>(0);
            let s = getResource<sampler>(1);
            results[0] = textureSample(t, s, vec2f(0.5, 0.5));
            return vec4f(0);
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    // Create textures
    wgpu::Texture textureRed = CreateColorTexture(utils::RGBA8::kRed);
    wgpu::Texture textureGreen = CreateColorTexture(utils::RGBA8::kGreen);
    textureRed.Pin(wgpu::TextureUsage::TextureBinding);
    textureGreen.Pin(wgpu::TextureUsage::TextureBinding);

    // Create the result buffer resource
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(float) * 4,  // 1 vec4fs
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

    // Create resource table
    wgpu::ResourceTable table = MakeResourceTable(1);

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

    auto draw = [&]() {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, resultBG);
        pass.SetResourceTable(table);
        pass.Draw(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    wgpu::BindingResource res;
    float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};
    float expectedGreen[4] = {0.0, 1.0, 0.0, 1.0};

    // Add red texture and draw
    res = {.textureView = textureRed.CreateView()};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &res));
    draw();
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0, 4);

    // Now test removing and adding the green texture in the same slot
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    WaitForAllOperations();
    res = {.textureView = textureGreen.CreateView()};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &res));
    draw();
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedGreen, resultBuffer, 0, 4);
}

// Test that adding and removing textures in the same slot between draws ensure that
// backends only see the effective diff (first one added to last one added).
TEST_P(ResourceTableTests, RemoveThenAddTextureMultipleInSameSlot) {
    // TODO(https://issues.chromium.org/issues/490066027): Fails on Mali G78
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> results : array<vec4f>;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @fragment fn fs() -> @location(0) vec4f {
            let t = getResource<texture_2d<f32>>(0);
            let s = getResource<sampler>(1);
            results[0] = textureSample(t, s, vec2f(0.5, 0.5));
            return vec4f(0);
        }
    )");

    // Create the pipeline.
    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    pDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);

    // Create textures
    wgpu::Texture textureRed = CreateColorTexture(utils::RGBA8::kRed);
    wgpu::Texture textureGreen = CreateColorTexture(utils::RGBA8::kGreen);
    wgpu::Texture textureBlue = CreateColorTexture(utils::RGBA8::kBlue);
    textureRed.Pin(wgpu::TextureUsage::TextureBinding);
    textureGreen.Pin(wgpu::TextureUsage::TextureBinding);
    textureBlue.Pin(wgpu::TextureUsage::TextureBinding);

    // Create the result buffer resource
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(float) * 4,  // 1 vec4fs
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, resultBuffer}});

    // Create resource table
    wgpu::ResourceTable table = MakeResourceTable(1);

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

    auto draw = [&]() {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, resultBG);
        pass.SetResourceTable(table);
        pass.Draw(1);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    };

    wgpu::BindingResource res;
    float expectedRed[4] = {1.0, 0.0, 0.0, 1.0};
    float expectedBlue[4] = {0.0, 0.0, 1.0, 1.0};

    // Add red texture and draw
    res = {.textureView = textureRed.CreateView()};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &res));
    draw();
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedRed, resultBuffer, 0, 4);

    // Remove then add green texture (this could be done in a loop with multiple textures)
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    WaitForAllOperations();
    res = {.textureView = textureGreen.CreateView()};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &res));

    // Now test removing and adding the blue texture in the same slot
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    WaitForAllOperations();
    res = {.textureView = textureBlue.CreateView()};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &res));
    draw();
    EXPECT_BUFFER_FLOAT_RANGE_EQ(expectedBlue, resultBuffer, 0, 4);
}

// Check that Pin forces zero-initialization of the resources.
TEST_P(ResourceTableTests, PinDoesZeroInit) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create the pipeline reading back from the texture.
    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @group(0) @binding(0) var<storage, read_write> result : u32;

        @compute @workgroup_size(1) fn readbackPixel() {
            let errorIfNotPresent = u32(!hasResource<texture_2d<u32>>(0));
            let tex = getResource<texture_2d<u32>>(0);
            let texel = textureLoad(tex, vec2u(0), 0).r;
            result = errorIfNotPresent + texel;
        }
    )");

    wgpu::ComputePipelineDescriptor csDesc = {.compute = {
                                                  .module = module,
                                              }};
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    // Create the test resource table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R32Uint,
    };
    wgpu::TextureViewDescriptor vDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table =
        MakeResourceTable(1, {{0, {.textureView = tex.CreateView(&vDesc)}}});

    // Create the other test resources.
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(uint32_t),
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);

    wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                              {
                                                  {0, resultBuffer},
                                              });

    // Check that Pin does the initial zero init.
    {
        tex.Pin(wgpu::TextureUsage::TextureBinding);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetBindGroup(0, bg);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        EXPECT_BUFFER_U32_EQ(0, resultBuffer, 0);
    }

    // Use a render pass discard to mark the texture as uninitialized again. Use a LoadOp::Clear to
    // set some non-zero value in the texture which hopefully would tell us if the lazy clear didn't
    // happen.
    {
        tex.Unpin();

        wgpu::RenderPassColorAttachment attachment = {
            .view = tex.CreateView(),
            .loadOp = wgpu::LoadOp::Clear,
            .storeOp = wgpu::StoreOp::Discard,
            .clearValue = {.r = 1.0, .g = 0.0, .b = 0.0, .a = 0.0},
        };
        wgpu::RenderPassDescriptor rpDesc = {
            .colorAttachmentCount = 1,
            .colorAttachments = &attachment,
        };

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

    // Check that Pin does the zero init after a discard.
    {
        tex.Pin(wgpu::TextureUsage::TextureBinding);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetResourceTable(table);
        pass.SetBindGroup(0, bg);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        EXPECT_BUFFER_U32_EQ(0, resultBuffer, 0);
    }
}

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

    wgpu::ResourceTable table = MakeResourceTable(1);
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));

    // 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.
    bool updateValid = false;
    DoSomeWorkInSubmit();
    queue.OnSubmittedWorkDone(
        wgpu::CallbackMode::AllowSpontaneous,
        [&](wgpu::QueueWorkDoneStatus, wgpu::StringView) { updateValid = true; });
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));

    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 a resource table slot can be updated only after all commands submitted prior to
// RemoveBinding are completed.
TEST_P(ResourceTableTests, UpdateAfterRemoveRequiresGPUIsFinished_ErrorBindGroup) {
    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));

    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R32Uint,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);
    wgpu::BindingResource resource{.textureView = tex.CreateView()};

    // Make an error resource table.
    wgpu::RenderPassMaxDrawCount maxDraw;
    maxDraw.maxDrawCount = 1000;
    wgpu::ResourceTableDescriptor desc{
        .nextInChain = &maxDraw,
        .size = 1,
    };
    wgpu::ResourceTable table;
    ASSERT_DEVICE_ERROR(table = device.CreateResourceTable(&desc));

    {
        // Ignore all validation errors for this test as they are tested in other places, and we're
        // checking immediate validation returned as a wgpu::Status and supposed to be the same for
        // valid and invalid objects.
        utils::ScopedIgnoreValidationErrors ignoreErrors(device);

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

        // 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.
        bool updateValid = false;
        DoSomeWorkInSubmit();
        queue.OnSubmittedWorkDone(
            wgpu::CallbackMode::AllowSpontaneous,
            [&](wgpu::QueueWorkDoneStatus, wgpu::StringView) { updateValid = true; });
        EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));

        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 Update and InsertBinding make the new binding visible in the resource table.
TEST_P(ResourceTableTests, UpdateAndInsertBindingMakeBindingVisible) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    wgpu::ResourceTable table = MakeResourceTable(2);

    // Before we do anything, the table has no valid entries.
    TestHasU8BindingsAll(table, {{}, {}});

    // Update makes the entry visible.
    wgpu::BindingResource resource0 = {.textureView = MakePinnedU8View(17)};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource0));
    TestHasU8BindingsAll(table, {{17}, {}});

    // InsertBinding makes the entry visible.
    wgpu::BindingResource resource1 = {.textureView = MakePinnedU8View(42)};
    EXPECT_EQ(1u, table.InsertBinding(&resource1));
    TestHasU8BindingsAll(table, {{17}, {42}});
}

// Check that RemoveBinding instantly makes the binding not visible, both for entries added with
// Update and InsertBinding.
TEST_P(ResourceTableTests, RemoveBindingMakeBindingInvalid) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Fill a resource table with both Update and InsertBinding.
    wgpu::ResourceTable table = MakeResourceTable(2);

    wgpu::BindingResource resource0 = {.textureView = MakePinnedU8View(100)};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource0));

    wgpu::BindingResource resource1 = {.textureView = MakePinnedU8View(101)};
    EXPECT_EQ(1u, table.InsertBinding(&resource1));

    // Before we remove bindings, they are all valid.
    TestHasU8BindingsAll(table, {{100}, {101}});

    // RemoveBinding immediately makes bindings invalid.
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
    TestHasU8BindingsAll(table, {{100}, {}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8BindingsAll(table, {{}, {}});
}

// Check that removing a binding and adding a different one works.
TEST_P(ResourceTableTests, ReplaceBinding) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create the test resource table.
    wgpu::ResourceTable table = MakeResourceTable(1);
    wgpu::BindingResource resource = {.textureView = MakePinnedU8View(19)};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));

    // Test removing a binding that was previously there.
    TestHasU8BindingsAll(table, {{19}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8BindingsAll(table, {{}});

    /// Add it back a new entry, the shader should be seeing the updated entry.
    WaitForAllOperations();

    wgpu::BindingResource newResource = {.textureView = MakePinnedU8View(23)};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &newResource));
    TestHasU8BindingsAll(table, {{23}});
}

// Check that removing a binding and adding it back works.
TEST_P(ResourceTableTests, ReplaceWithSameBinding) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create the test resource table.
    wgpu::ResourceTable table = MakeResourceTable(1);
    wgpu::BindingResource resource = {.textureView = MakePinnedU8View(19)};
    EXPECT_EQ(wgpu::Status::Success, table.Update(0, &resource));

    // Test removing a binding that was previously there.
    TestHasU8BindingsAll(table, {{19}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8BindingsAll(table, {{}});

    /// Add it back a new entry, the shader should be seeing the updated entry.
    WaitForAllOperations();

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

// Check that setting multiple resource table, on per dispatch/draw/executebundle, on a single pass
// works.
TEST_P(ResourceTableTests, SinglePassMultipleResourceTables) {
    // TODO(crbug.com/385158827): Fails on older WARP 10.0.19041.5794
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    std::vector<wgpu::BindingResource> resources;

    wgpu::ResourceTable table0 = MakeResourceTable(2);
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(17)});
    EXPECT_EQ(wgpu::Status::Success, table0.Update(0, &resources.back()));
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(18)});
    EXPECT_EQ(wgpu::Status::Success, table0.Update(1, &resources.back()));

    wgpu::ResourceTable table1 = MakeResourceTable(3);
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(27)});
    EXPECT_EQ(wgpu::Status::Success, table1.Update(0, &resources.back()));
    // Leave slot 1 empty
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(29)});
    EXPECT_EQ(wgpu::Status::Success, table1.Update(2, &resources.back()));

    wgpu::ResourceTable table2 = MakeResourceTable(4);
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(37)});
    EXPECT_EQ(wgpu::Status::Success, table2.Update(0, &resources.back()));
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(38)});
    EXPECT_EQ(wgpu::Status::Success, table2.Update(1, &resources.back()));
    // Leave slot 2 empty
    resources.push_back(wgpu::BindingResource{.textureView = MakePinnedU8View(40)});
    EXPECT_EQ(wgpu::Status::Success, table2.Update(3, &resources.back()));

    auto case0 = TableAndExpected(table0, {{17, 18}});
    auto case1 = TableAndExpected(table1, {{27, {}, 29}});
    auto case2 = TableAndExpected(table2, {{37, 38, {}, 40}});

    TestHasU8BindingsAll({case0, case1, case2});
    TestHasU8BindingsAll({case1, case0, case2});
    TestHasU8BindingsAll({case2, case1, case0});
}

// Check that logic to dirty or reuse VkDescriptorSet takes into account the resource table in the
// Vulkan backend.
TEST_P(ResourceTableTests, SwitchUseResourceTableAndNot) {
    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_resource_table;

        @vertex fn vs() -> @builtin(position) vec4f {
            return vec4f(0, 0, 0.5, 0.5);
        }

        @group(0) @binding(0) var<storage, read_write> results : array<u32>;
        var<immediate> resultIndex : u32;

        @fragment fn yes_resource_table() -> @location(0) vec4f {
            results[resultIndex] = 10 + u32(hasResource<texture_2d<f32>>(resultIndex));
            return vec4();
        }

        @fragment fn no_resource_table() -> @location(0) vec4f {
            results[resultIndex] = 42;
            return vec4();
        }
    )");

    wgpu::BindGroupLayout resultBGL = utils::MakeBindGroupLayout(
        device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}});

    wgpu::RenderPipeline resourceTablePipeline;
    {
        utils::ComboRenderPipelineDescriptor desc;
        desc.layout = MakePipelineLayoutWithTable({resultBGL}, 4);
        desc.vertex.module = module;
        desc.cFragment.module = module;
        desc.cFragment.entryPoint = "yes_resource_table";
        desc.primitive.topology = wgpu::PrimitiveTopology::PointList;
        resourceTablePipeline = device.CreateRenderPipeline(&desc);
    }

    wgpu::RenderPipeline noResourceTablePipeline;
    {
        utils::ComboRenderPipelineDescriptor desc;
        desc.layout = utils::MakeBasicPipelineLayout(device, &resultBGL, 4);
        desc.vertex.module = module;
        desc.cFragment.module = module;
        desc.cFragment.entryPoint = "no_resource_table";
        desc.primitive.topology = wgpu::PrimitiveTopology::PointList;
        noResourceTablePipeline = device.CreateRenderPipeline(&desc);
    }

    // Create the result buffer resource.
    wgpu::BufferDescriptor bDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(uint32_t) * 3,
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&bDesc);
    wgpu::BindGroup resultBG = utils::MakeBindGroup(device, resultBGL, {{0, resultBuffer}});

    // Create and populate the resource table.
    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R32Uint,
    };
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::ResourceTable table = MakeResourceTable(0);

    // Encode render commands that switch between the two pipelines. The resultBGL index in the
    // Vulkan backend will be pushed by 1 if the pipeline uses the resource table, so we check that
    // the invalidation of VkDescriptorSet inheritance works correctly.
    uint32_t resultIndex = 0;
    auto rp = utils::CreateBasicRenderPass(device, 1, 1);
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
    pass.SetResourceTable(table);
    pass.SetBindGroup(0, resultBG);

    // Start by not using the resource table.
    pass.SetPipeline(noResourceTablePipeline);
    pass.SetImmediates(0, &resultIndex, sizeof(resultIndex));
    pass.Draw(1);
    resultIndex++;

    // Switch to using the resource table.
    pass.SetPipeline(resourceTablePipeline);
    pass.SetImmediates(0, &resultIndex, sizeof(resultIndex));
    pass.Draw(1);
    resultIndex++;

    // And back to not using it.
    pass.SetPipeline(noResourceTablePipeline);
    pass.SetImmediates(0, &resultIndex, sizeof(resultIndex));
    pass.Draw(1);
    resultIndex++;

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

    EXPECT_BUFFER_U32_EQ(42, resultBuffer, 0);
    EXPECT_BUFFER_U32_EQ(10, resultBuffer, 4);
    EXPECT_BUFFER_U32_EQ(42, resultBuffer, 8);
}

// TODO(479179409): Add tests for dynamic validation of filterability
//   - BGL has tex2d, shader has tex1d, swap in default tex1d
//   - BGL has sampler_comparison, shader has sampler, swap in sampler
//   - BGL has unfilterable texture and filtering sampler, swap sampler to non_filternig
//   - BGL has unfilterable texture, bind-less filtering sampler, swap texture
//   - bind-less unfilterable texture, BGL has filtering sampler, swap sampler

DAWN_INSTANTIATE_TEST(ResourceTableTests, D3D12Backend(), MetalBackend(), VulkanBackend());

}  // anonymous namespace
}  // namespace dawn
