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

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

namespace dawn {
namespace {

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

        // TODO(https://issues.chromium.org/435317394): The Subzero compiler used by Swiftshader
        // produces bad code and crashes on some VK_EXT_descriptor_indexing workloads. Skip tests on
        // it, but still run them with Swiftshader LLVM 10.0. On ARM64 the only supported compiler
        // is LLVM10.0 so use that signal to choose when Swiftshader can be tested.
        DAWN_SUPPRESS_TEST_IF(IsSwiftshader() && !DAWN_PLATFORM_IS(ARM64));
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        if (SupportsFeatures({wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable})) {
            return {wgpu::FeatureName::Float32Filterable,
                    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, filterable>") {
        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();
        encoder.SetResourceTable(table);
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        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();
    }

    // Test that `table` has a texture_2d<u32> iff the `expected` has a value, and that the textures
    // have the expected value, if any.
    void TestHasU8Bindings(wgpu::ResourceTable table,
                           std::vector<std::optional<uint8_t>> expected) {
        ASSERT_EQ(table.GetSize(), expected.size());

        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++) {
                    if !hasResource<texture_2d<u32>>(i) {
                        results[i] = 0xBEEF;
                    } else {
                        let tex = getResource<texture_2d<u32>>(i);
                        results[i] = textureLoad(tex, vec2(0), 0).x;
                    }
                }
            }
        )");

        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();
        encoder.SetResourceTable(table);
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        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 (auto optValue : expected) {
            expectedU32.push_back(optValue ? *optValue : 0xBEEFu);
        }

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

// 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, filterable>>(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, filterable>>(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, filterable>>(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::R32Float,
    };
    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) {
    // TODO(crbug.com/473354062): Implement on D3D12
    DAWN_SUPPRESS_TEST_IF(IsD3D12());

    wgpu::TextureDescriptor tDesc{
        .usage = wgpu::TextureUsage::TextureBinding,
        .size = {1, 1},
        .format = wgpu::TextureFormat::R32Float,
    };
    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, unfilterable>");
}

// 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::R32Float,
    };
    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::R32Float,
    };
    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::R32Float,
    };
    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::R32Float,
    };
    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::R32Float,
    };
    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, filterable>",
    "texture_1d<f32, unfilterable>",
    "texture_1d<i32>",
    "texture_1d<u32>",
    "texture_2d<f32, filterable>",
    "texture_2d<f32, unfilterable>",
    "texture_2d<i32>",
    "texture_2d<u32>",
    "texture_2d_array<f32, filterable>",
    "texture_2d_array<f32, unfilterable>",
    "texture_2d_array<i32>",
    "texture_2d_array<u32>",
    "texture_cube<f32, filterable>",
    "texture_cube<f32, unfilterable>",
    "texture_cube<i32>",
    "texture_cube<u32>",
    "texture_cube_array<f32, filterable>",
    "texture_cube_array<f32, unfilterable>",
    "texture_cube_array<i32>",
    "texture_cube_array<u32>",
    "texture_3d<f32, filterable>",
    "texture_3d<f32, unfilterable>",
    "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",
};

struct TextureDescForTypeIDCase {
    std::unordered_set<std::string_view> wgslTypes;
    wgpu::TextureFormat format;
    wgpu::TextureDimension dimension;
    wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::Undefined;
    uint32_t sampleCount = 1;
    wgpu::TextureAspect viewAspect = wgpu::TextureAspect::All;

    // Create a view for a pinned texture for this case.
    wgpu::TextureView CreateTestView(const wgpu::Device& device) {
        wgpu::TextureDescriptor tDesc = {
            .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc,
            .dimension = dimension,
            .size = {1, 1, 1},
            .format = format,
            .sampleCount = sampleCount,
        };
        if (viewDimension == wgpu::TextureViewDimension::Cube ||
            viewDimension == wgpu::TextureViewDimension::CubeArray) {
            tDesc.size.depthOrArrayLayers = 6;
        }
        if (sampleCount != 1) {
            tDesc.usage |= wgpu::TextureUsage::RenderAttachment;
        }

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

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

std::vector<TextureDescForTypeIDCase> MakeTextureDescForTypeIDCases() {
    std::vector<TextureDescForTypeIDCase> cases;

    // TODO(https://issues.chromium.org/484770625): Add tests for the unorm unfilterable
    // formats that they only match a unfilterable texture.

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

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

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

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

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

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

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

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

    // Stencil textures can be used as 2D.
    cases.push_back({
        .wgslTypes = {{"texture_2d<u32>"}},
        .format = wgpu::TextureFormat::Stencil8,
        .dimension = wgpu::TextureDimension::e2D,
    });
    cases.push_back({
        .wgslTypes = {{"texture_2d_array<u32>"}},
        .format = wgpu::TextureFormat::Stencil8,
        .dimension = wgpu::TextureDimension::e2D,
        .viewDimension = wgpu::TextureViewDimension::e2DArray,
    });
    cases.push_back({
        .wgslTypes = {{"texture_cube<u32>"}},
        .format = wgpu::TextureFormat::Stencil8,
        .dimension = wgpu::TextureDimension::e2D,
        .viewDimension = wgpu::TextureViewDimension::Cube,
    });
    cases.push_back({
        .wgslTypes = {{"texture_cube_array<u32>"}},
        .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, unfilterable>"}},
        .format = wgpu::TextureFormat::Depth24PlusStencil8,
        .dimension = wgpu::TextureDimension::e2D,
        .viewAspect = wgpu::TextureAspect::DepthOnly,
    });
    cases.push_back({
        .wgslTypes = {{"texture_2d<u32>"}},
        .format = wgpu::TextureFormat::Depth24PlusStencil8,
        .dimension = wgpu::TextureDimension::e2D,
        .viewAspect = wgpu::TextureAspect::StencilOnly,
    });

    return cases;
}

// Test that hasResource() works as expected for all supported types in WGSL.
TEST_P(ResourceTableTests, HasResourceTextureCompatibilityAllTypes) {
    auto textureCases = MakeTextureDescForTypeIDCases();

    // Make a resource table with all of our test texture views.
    wgpu::ResourceTable table = MakeResourceTable(textureCases.size());
    for (auto [i, textureCase] : Enumerate(textureCases)) {
        wgpu::BindingResource resource = {.textureView = textureCase.CreateTestView(device)};
        table.Update(i, &resource);
    }

    // Test hasResource returning for each of the supported WGSL types, against each texture.
    for (auto wgslType : kWgslSampledTextureTypes) {
        std::vector<bool> expected;
        for (auto textureCase : textureCases) {
            expected.push_back(textureCase.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, filterable>>(resourceCount - 1));
            result[1] = u32(hasResource<texture_2d<f32, filterable>>(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, filterable>>(resourceCount + i));
            }
            result[2] = result2;

            result[3] = u32(hasResource<texture_2d<f32, filterable>>(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::R32Float,
    };
    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();
    encoder.SetResourceTable(table);
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    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, filterable>
            {
                check(!hasResource<texture_2d<f32, filterable>>(0));
                let t = getResource<texture_2d<f32, filterable>>(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();
    encoder.SetResourceTable(table);
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    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);
}

// 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();
        encoder.SetResourceTable(table);
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        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();
        encoder.SetResourceTable(table);
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        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.
    TestHasU8Bindings(table, {{}, {}});

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

    // InsertBinding makes the entry visible.
    wgpu::BindingResource resource1 = {.textureView = MakePinnedU8View(42)};
    EXPECT_EQ(1u, table.InsertBinding(&resource1));
    TestHasU8Bindings(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.
    TestHasU8Bindings(table, {{100}, {101}});

    // RemoveBinding immediately makes bindings invalid.
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(1));
    TestHasU8Bindings(table, {{100}, {}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8Bindings(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.
    TestHasU8Bindings(table, {{19}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8Bindings(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));
    TestHasU8Bindings(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.
    TestHasU8Bindings(table, {{19}});
    EXPECT_EQ(wgpu::Status::Success, table.RemoveBinding(0));
    TestHasU8Bindings(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));
    TestHasU8Bindings(table, {{19}});
}

// Check that logic to dirty or reuse VkDescriptorSet takes into account the resource table in the
// Vulkan backend.
TEST_P(ResourceTableTests, SwitchUseResourceTableAndNot) {
    // 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());

    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, filterable>>(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();
    encoder.SetResourceTable(table);
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
    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);
}

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

}  // anonymous namespace
}  // namespace dawn
