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

#include "dawn/common/NonMovable.h"
#include "dawn/tests/unittests/validation/ValidationTest.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

class PixelLocalStorageDisabledTest : public ValidationTest {};

// Check that creating a StorageAttachment texture is disallowed without the extension.
TEST_F(PixelLocalStorageDisabledTest, StorageAttachmentTextureNotAllowed) {
    wgpu::TextureDescriptor desc;
    desc.size = {1, 1, 1};
    desc.format = wgpu::TextureFormat::R32Uint;
    desc.usage = wgpu::TextureUsage::TextureBinding;

    // Control case: creating the texture without StorageAttachment is allowed.
    device.CreateTexture(&desc);

    // Error case: creating the texture without StorageAttachment is disallowed.
    desc.usage = wgpu::TextureUsage::StorageAttachment;
    ASSERT_DEVICE_ERROR(device.CreateTexture(&desc));
}

// Check that creating a pipeline layout with a PipelineLayoutPixelLocalStorage is disallowed
// without the extension.
TEST_F(PixelLocalStorageDisabledTest, PipelineLayoutPixelLocalStorageDisallowed) {
    wgpu::PipelineLayoutDescriptor desc;
    desc.bindGroupLayoutCount = 0;

    // Control case: creating the pipeline layout without the PLS is allowed.
    device.CreatePipelineLayout(&desc);

    // Error case: creating the pipeline layout with a PLS is disallowed even if it is empty.
    wgpu::PipelineLayoutPixelLocalStorage pls;
    pls.totalPixelLocalStorageSize = 0;
    pls.storageAttachmentCount = 0;
    desc.nextInChain = &pls;

    ASSERT_DEVICE_ERROR(device.CreatePipelineLayout(&desc));
}

// Check that a render pass with a RenderPassPixelLocalStorage is disallowed without the extension.
TEST_F(PixelLocalStorageDisabledTest, RenderPassPixelLocalStorageDisallowed) {
    utils::BasicRenderPass rp = utils::CreateBasicRenderPass(device, 1, 1);

    // Control case: beginning the render pass without the PLS is allowed.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
        pass.End();
        encoder.Finish();
    }

    // Error case: beginning the render pass without the PLS is disallowed, even if it is empty.
    {
        wgpu::RenderPassPixelLocalStorage pls;
        pls.totalPixelLocalStorageSize = 0;
        pls.storageAttachmentCount = 0;
        rp.renderPassInfo.nextInChain = &pls;

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

// Check that it is not possible to use the WGSL extension without the device extension enabled.
TEST_F(PixelLocalStorageDisabledTest, WGSLExtensionDisallowed) {
    ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, R"(
        enable chromium_experimental_pixel_local;
    )"));
}

// Check that PixelLocalStorageBarrier() is disallowed without the extension.
TEST_F(PixelLocalStorageDisabledTest, PixelLocalStorageBarrierDisallowed) {
    utils::BasicRenderPass rp = utils::CreateBasicRenderPass(device, 1, 1);

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

class PixelLocalStorageOtherExtensionTest : public ValidationTest {
  protected:
    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
                                wgpu::DeviceDescriptor descriptor) override {
        // Only test the coherent extension. The non-coherent one has the rest of the validation
        // tests.
        wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::PixelLocalStorageCoherent};
        descriptor.requiredFeatures = requiredFeatures;
        descriptor.requiredFeatureCount = 1;
        return dawnAdapter.CreateDevice(&descriptor);
    }
};

// Simple test checking all the various things that are normally validated out without PLS are
// available if the coherent PLS extension is enabled.
TEST_F(PixelLocalStorageOtherExtensionTest, SmokeTest) {
    // Creating a StorageAttachment texture is allowed.
    wgpu::TextureDescriptor textureDesc;
    textureDesc.size = {1, 1, 1};
    textureDesc.format = wgpu::TextureFormat::R32Uint;
    textureDesc.usage = wgpu::TextureUsage::StorageAttachment;
    wgpu::Texture tex = device.CreateTexture(&textureDesc);

    // Creating a pipeline layout with PLS is allowed.
    wgpu::PipelineLayoutPixelLocalStorage plPlsDesc;
    plPlsDesc.totalPixelLocalStorageSize = 0;
    plPlsDesc.storageAttachmentCount = 0;

    wgpu::PipelineLayoutDescriptor plDesc;
    plDesc.bindGroupLayoutCount = 0;
    plDesc.nextInChain = &plPlsDesc;
    device.CreatePipelineLayout(&plDesc);

    // Creating a PLS render pass is allowed.
    wgpu::RenderPassPixelLocalStorage rpPlsDesc;
    rpPlsDesc.totalPixelLocalStorageSize = 0;
    rpPlsDesc.storageAttachmentCount = 0;

    utils::BasicRenderPass rp = utils::CreateBasicRenderPass(device, 1, 1);
    rp.renderPassInfo.nextInChain = &rpPlsDesc;

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
    // Calling PixelLocalStorageBarrier is allowed.
    pass.PixelLocalStorageBarrier();
    pass.End();
    encoder.Finish();

    // Creating a shader with the extension is allowed.
    utils::CreateShaderModule(device, R"(
        enable chromium_experimental_pixel_local;
    )");
}

struct OffsetAndFormat {
    uint64_t offset;
    wgpu::TextureFormat format;
};
struct PLSSpec {
    uint64_t totalSize;
    std::vector<OffsetAndFormat> attachments;
    bool active = true;
};

constexpr std::array<wgpu::TextureFormat, 3> kStorageAttachmentFormats = {
    wgpu::TextureFormat::R32Float,
    wgpu::TextureFormat::R32Uint,
    wgpu::TextureFormat::R32Sint,
};
bool IsStorageAttachmentFormat(wgpu::TextureFormat format) {
    return std::find(kStorageAttachmentFormats.begin(), kStorageAttachmentFormats.end(), format) !=
           kStorageAttachmentFormats.end();
}

struct ComboTestPLSRenderPassDescriptor : NonMovable {
    std::array<wgpu::RenderPassStorageAttachment, 8> storageAttachments;
    wgpu::RenderPassPixelLocalStorage pls;
    wgpu::RenderPassColorAttachment colorAttachment;
    wgpu::RenderPassDescriptor rpDesc;
};

class PixelLocalStorageTest : public ValidationTest {
  protected:
    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
                                wgpu::DeviceDescriptor descriptor) override {
        // Test only the non-coherent version, and assume that the same validation code paths are
        // taken for the coherent path.
        wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::PixelLocalStorageNonCoherent};
        descriptor.requiredFeatures = requiredFeatures;
        descriptor.requiredFeatureCount = 1;
        return dawnAdapter.CreateDevice(&descriptor);
    }

    void InitializePLSRenderPass(ComboTestPLSRenderPassDescriptor* desc) {
        // Set up a single storage attachment.
        wgpu::TextureDescriptor storageDesc;
        storageDesc.size = {1, 1};
        storageDesc.format = wgpu::TextureFormat::R32Uint;
        storageDesc.usage = wgpu::TextureUsage::StorageAttachment;
        wgpu::Texture storage = device.CreateTexture(&storageDesc);

        desc->storageAttachments[0].storage = storage.CreateView();
        desc->storageAttachments[0].offset = 0;
        desc->storageAttachments[0].loadOp = wgpu::LoadOp::Load;
        desc->storageAttachments[0].storeOp = wgpu::StoreOp::Store;

        desc->pls.totalPixelLocalStorageSize = 4;
        desc->pls.storageAttachmentCount = 1;
        desc->pls.storageAttachments = desc->storageAttachments.data();

        // Add at least one color attachment to make the render pass valid if there's no storage
        // attachment.
        wgpu::TextureDescriptor colorDesc;
        colorDesc.size = {1, 1};
        colorDesc.format = kColorAttachmentFormat;
        colorDesc.usage = wgpu::TextureUsage::RenderAttachment;
        wgpu::Texture color = device.CreateTexture(&colorDesc);

        desc->colorAttachment.view = color.CreateView();
        desc->colorAttachment.loadOp = wgpu::LoadOp::Load;
        desc->colorAttachment.storeOp = wgpu::StoreOp::Store;

        desc->rpDesc.nextInChain = &desc->pls;
        desc->rpDesc.colorAttachmentCount = 1;
        desc->rpDesc.colorAttachments = &desc->colorAttachment;
    }

    void RecordRenderPass(const wgpu::RenderPassDescriptor* desc,
                          wgpu::RenderPipeline pipeline = {}) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(desc);

        if (pipeline) {
            pass.SetPipeline(pipeline);
        }

        pass.End();
        encoder.Finish();
    }

    void RecordPLSRenderPass(const PLSSpec& spec, wgpu::RenderPipeline pipeline = {}) {
        ComboTestPLSRenderPassDescriptor desc;
        InitializePLSRenderPass(&desc);

        // Convert the PLSSpec to a RenderPassPLS
        for (size_t i = 0; i < spec.attachments.size(); i++) {
            wgpu::TextureDescriptor tDesc;
            tDesc.size = {1, 1};
            tDesc.format = spec.attachments[i].format;
            tDesc.usage = wgpu::TextureUsage::StorageAttachment;
            wgpu::Texture texture = device.CreateTexture(&tDesc);

            desc.storageAttachments[i].storage = texture.CreateView();
            desc.storageAttachments[i].offset = spec.attachments[i].offset;
            desc.storageAttachments[i].loadOp = wgpu::LoadOp::Load;
            desc.storageAttachments[i].storeOp = wgpu::StoreOp::Store;
        }

        desc.pls.totalPixelLocalStorageSize = spec.totalSize;
        desc.pls.storageAttachmentCount = spec.attachments.size();

        // Add the PLS if needed and record the render pass.
        if (!spec.active) {
            desc.rpDesc.nextInChain = nullptr;
        }

        RecordRenderPass(&desc.rpDesc, pipeline);
    }

    wgpu::PipelineLayout MakePipelineLayout(const PLSSpec& spec) {
        // Convert the PLSSpec to a PipelineLayoutPLS
        std::vector<wgpu::PipelineLayoutStorageAttachment> storageAttachments;
        for (const auto& attachmentSpec : spec.attachments) {
            wgpu::PipelineLayoutStorageAttachment attachment;
            attachment.format = attachmentSpec.format;
            attachment.offset = attachmentSpec.offset;
            storageAttachments.push_back(attachment);
        }

        wgpu::PipelineLayoutPixelLocalStorage pls;
        pls.totalPixelLocalStorageSize = spec.totalSize;
        pls.storageAttachmentCount = storageAttachments.size();
        pls.storageAttachments = storageAttachments.data();

        // Add the PLS if needed and make the pipeline layout.
        wgpu::PipelineLayoutDescriptor plDesc;
        plDesc.bindGroupLayoutCount = 0;
        if (spec.active) {
            plDesc.nextInChain = &pls;
        }
        return device.CreatePipelineLayout(&plDesc);
    }

    wgpu::RenderPipeline MakePipeline(const PLSSpec& spec) {
        std::vector<const char*> plsTypes;
        plsTypes.resize(spec.totalSize / kPLSSlotByteSize, "u32");
        for (const auto& attachment : spec.attachments) {
            switch (attachment.format) {
                case wgpu::TextureFormat::R32Uint:
                    plsTypes[attachment.offset / kPLSSlotByteSize] = "u32";
                    break;
                case wgpu::TextureFormat::R32Sint:
                    plsTypes[attachment.offset / kPLSSlotByteSize] = "i32";
                    break;
                case wgpu::TextureFormat::R32Float:
                    plsTypes[attachment.offset / kPLSSlotByteSize] = "f32";
                    break;
                default:
                    DAWN_UNREACHABLE();
            }
        }

        bool outputPLS = spec.active && !plsTypes.empty();

        std::ostringstream fsStream;
        fsStream << "enable chromium_experimental_pixel_local;\n";
        if (outputPLS) {
            fsStream << "struct PLS {\n";
            for (size_t i = 0; i < plsTypes.size(); i++) {
                fsStream << "  a" << i << " : " << plsTypes[i] << ",\n";
            }
            fsStream << "}\n";
            fsStream << "var<pixel_local> pls : PLS;\n";
        }
        fsStream << "@fragment fn fs() -> @location(0) u32 {\n";
        if (outputPLS) {
            fsStream << "  _ = pls;\n";
        }
        fsStream << "  return 0u;\n";
        fsStream << "}\n";

        utils::ComboRenderPipelineDescriptor desc;
        desc.layout = MakePipelineLayout(spec);
        desc.cFragment.module = utils::CreateShaderModule(device, fsStream.str().c_str());
        desc.vertex.module = utils::CreateShaderModule(device, R"(
            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f();
            }
        )");
        desc.cTargets[0].format = kColorAttachmentFormat;
        return device.CreateRenderPipeline(&desc);
    }

    void CheckPLSStateMatching(const PLSSpec& rpSpec, const PLSSpec& pipelineSpec, bool success) {
        wgpu::RenderPipeline pipeline = MakePipeline(pipelineSpec);

        if (success) {
            RecordPLSRenderPass(rpSpec, pipeline);
        } else {
            ASSERT_DEVICE_ERROR(RecordPLSRenderPass(rpSpec, pipeline));
        }
    }

    void TestFragmentAndLayoutCompat(const PLSSpec& layoutSpec,
                                     absl::string_view fs,
                                     bool success) {
        TestFragmentAndLayoutCompat(MakePipelineLayout(layoutSpec), fs, success);
    }

    void TestFragmentAndLayoutCompat(const wgpu::PipelineLayout& layout,
                                     absl::string_view fs,
                                     bool success) {
        wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, fs.data());
        wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
            @vertex fn vs() -> @builtin(position) vec4f {
                return vec4f();
            }
        )");

        utils::ComboRenderPipelineDescriptor desc;
        desc.layout = layout;
        desc.cFragment.module = fsModule;
        desc.vertex.module = vsModule;
        desc.cTargets[0].format = kColorAttachmentFormat;
        desc.cTargets[0].writeMask = wgpu::ColorWriteMask::None;

        if (success) {
            device.CreateRenderPipeline(&desc);
        } else {
            ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&desc));
        }
    }

    static constexpr wgpu::TextureFormat kColorAttachmentFormat = wgpu::TextureFormat::R32Uint;
};

// Check that it is possible to use the WGSL extension when the device extension is enabled.
TEST_F(PixelLocalStorageTest, WGSLExtensionAllowed) {
    utils::CreateShaderModule(device, R"(
        enable chromium_experimental_pixel_local;
    )");
}

// Check that StorageAttachment textures must be one of the supported formats.
TEST_F(PixelLocalStorageTest, TextureFormatMustSupportStorageAttachment) {
    for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
        wgpu::TextureDescriptor desc;
        desc.size = {1, 1};
        desc.format = format;
        desc.usage = wgpu::TextureUsage::StorageAttachment;

        if (IsStorageAttachmentFormat(format)) {
            device.CreateTexture(&desc);
        } else {
            ASSERT_DEVICE_ERROR(device.CreateTexture(&desc));
        }
    }
}

// Check that StorageAttachment textures must have a sample count of 1.
TEST_F(PixelLocalStorageTest, TextureMustBeSingleSampled) {
    wgpu::TextureDescriptor desc;
    desc.size = {1, 1};
    desc.format = wgpu::TextureFormat::R32Uint;
    desc.usage = wgpu::TextureUsage::StorageAttachment;

    // Control case: sampleCount = 1 is valid.
    desc.sampleCount = 1;
    device.CreateTexture(&desc);

    // Error case: sampledCount != 1 is an error.
    desc.sampleCount = 4;
    ASSERT_DEVICE_ERROR(device.CreateTexture(&desc));
}

// Check that the format in PLS must be one of the enabled ones.
TEST_F(PixelLocalStorageTest, PLSStateFormatMustSupportStorageAttachment) {
    for (wgpu::TextureFormat format : utils::kFormatsInCoreSpec) {
        PLSSpec spec = {4, {{0, format}}};

        // Note that BeginRenderPass is not tested here as a different test checks that the
        // StorageAttachment texture must indeed have been created with the StorageAttachment usage.
        if (IsStorageAttachmentFormat(format)) {
            MakePipelineLayout(spec);
        } else {
            ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        }
    }
}

// Check that the total size must be a multiple of 4.
TEST_F(PixelLocalStorageTest, PLSStateTotalSizeMultipleOf4) {
    // Control case: total size is a multiple of 4.
    {
        PLSSpec spec = {4, {}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }

    // Control case: total size isn't a multiple of 4.
    {
        PLSSpec spec = {2, {}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
}

// Check that the total size must be less than 16.
// TODO(dawn:1704): Have a proper limit for totalSize.
TEST_F(PixelLocalStorageTest, PLSStateTotalLessThan16) {
    // Control case: total size is 16.
    {
        PLSSpec spec = {16, {}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }

    // Control case: total size is greater than 16.
    {
        PLSSpec spec = {20, {}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
}

// Check that the offset of a storage attachment must be a multiple of 4.
TEST_F(PixelLocalStorageTest, PLSStateOffsetMultipleOf4) {
    // Control case: offset is a multiple of 4.
    {
        PLSSpec spec = {8, {{4, wgpu::TextureFormat::R32Uint}}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }

    // Error case: offset isn't a multiple of 4.
    {
        PLSSpec spec = {8, {{2, wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
}

// Check that the storage attachment is in bounds of the total size.
TEST_F(PixelLocalStorageTest, PLSStateAttachmentInBoundsOfTotalSize) {
    // Note that all storage attachment formats are currently 4 byte wide.

    // Control case: 0 + 4 <= 4
    {
        PLSSpec spec = {4, {{0, wgpu::TextureFormat::R32Uint}}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }

    // Error case: 4 + 4 > 4
    {
        PLSSpec spec = {4, {{4, wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }

    // Control case: 8 + 4 <= 12
    {
        PLSSpec spec = {12, {{8, wgpu::TextureFormat::R32Uint}}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }

    // Error case: 12 + 4 > 12
    {
        PLSSpec spec = {4, {{12, wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }

    // Check that overflows don't incorrectly pass the validation.
    {
        PLSSpec spec = {4, {{uint64_t(0) - uint64_t(4), wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
}

// Check that collisions between storage attachments are not allowed.
TEST_F(PixelLocalStorageTest, PLSStateCollisionsDisallowed) {
    // Control case: no collisions, all is good!
    {
        PLSSpec spec = {8, {{0, wgpu::TextureFormat::R32Uint}, {4, wgpu::TextureFormat::R32Uint}}};
        MakePipelineLayout(spec);
        RecordPLSRenderPass(spec);
    }
    // Error case: collisions, boo!
    {
        PLSSpec spec = {8, {{0, wgpu::TextureFormat::R32Uint}, {0, wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
    {
        PLSSpec spec = {8,
                        {{0, wgpu::TextureFormat::R32Uint},
                         {4, wgpu::TextureFormat::R32Uint},
                         {0, wgpu::TextureFormat::R32Uint}}};
        ASSERT_DEVICE_ERROR(MakePipelineLayout(spec));
        ASSERT_DEVICE_ERROR(RecordPLSRenderPass(spec));
    }
}

// Check that using an error view as storage attachment is an error.
TEST_F(PixelLocalStorageTest, RenderPassStorageAttachmentErrorView) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    tDesc.format = wgpu::TextureFormat::R32Uint;
    wgpu::Texture t = device.CreateTexture(&tDesc);

    wgpu::TextureViewDescriptor viewDesc;

    // Control case: valid texture view.
    desc.storageAttachments[0].storage = t.CreateView(&viewDesc);
    RecordRenderPass(&desc.rpDesc);

    // Error case: invalid texture view because of the base array layer.
    viewDesc.baseArrayLayer = 10;
    ASSERT_DEVICE_ERROR(desc.storageAttachments[0].storage = t.CreateView(&viewDesc));
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that using a multi-subresource view as a storage attachment is an error (layers and levels
// cases).
TEST_F(PixelLocalStorageTest, RenderPassStorageAttachmentSingleSubresource) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    wgpu::TextureDescriptor colorDesc;
    colorDesc.size = {2, 2};
    colorDesc.usage = wgpu::TextureUsage::RenderAttachment;
    colorDesc.format = kColorAttachmentFormat;

    // Replace the render pass attachment with a 2x2 texture for mip level testing.
    desc.colorAttachment.view = device.CreateTexture(&colorDesc).CreateView();

    // Control case: single subresource view.
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {2, 2};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    tDesc.format = wgpu::TextureFormat::R32Uint;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    RecordRenderPass(&desc.rpDesc);

    // Error case: two array layers.
    tDesc.size.depthOrArrayLayers = 2;
    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));

    // Error case: two mip levels.
    tDesc.size.depthOrArrayLayers = 1;
    tDesc.mipLevelCount = 2;
    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that the size of storage attachments must match the size of other attachments.
TEST_F(PixelLocalStorageTest, RenderPassStorageAttachmentSizeMustMatch) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Explicitly set the color attachment to a 1x1 texture.
    wgpu::TextureDescriptor colorDesc;
    colorDesc.size = {1, 1};
    colorDesc.usage = wgpu::TextureUsage::RenderAttachment;
    colorDesc.format = kColorAttachmentFormat;
    desc.colorAttachment.view = device.CreateTexture(&colorDesc).CreateView();

    // Control case: the storage attachment size matches
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    tDesc.format = wgpu::TextureFormat::R32Uint;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    RecordRenderPass(&desc.rpDesc);

    // Error case: width doesn't match.
    tDesc.size = {2, 1};
    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));

    // Error case: height doesn't match.
    tDesc.size = {1, 2};
    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that the textures used as storage attachment must have the StorageAttachment TextureUsage.
TEST_F(PixelLocalStorageTest, RenderPassStorageAttachmentUsage) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: the storage attachment has the correct usage.
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    tDesc.format = wgpu::TextureFormat::R32Uint;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    RecordRenderPass(&desc.rpDesc);

    // Error case: the storage attachment doesn't have the usage.
    tDesc.usage = wgpu::TextureUsage::RenderAttachment;
    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that the same texture subresource cannot be used twice as a storage attachment.
TEST_F(PixelLocalStorageTest, RenderPassSubresourceUsedTwiceAsStorage) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: two different subresources for two storage attachments.
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    tDesc.format = wgpu::TextureFormat::R32Uint;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();

    desc.storageAttachments[1].storage = device.CreateTexture(&tDesc).CreateView();
    desc.storageAttachments[1].offset = 4;
    desc.storageAttachments[1].loadOp = wgpu::LoadOp::Load;
    desc.storageAttachments[1].storeOp = wgpu::StoreOp::Store;
    desc.pls.storageAttachmentCount = 2;
    desc.pls.totalPixelLocalStorageSize = 8;

    RecordRenderPass(&desc.rpDesc);

    // Error case: the same subresource is used twice as a storage attachment.
    desc.storageAttachments[0].storage = desc.storageAttachments[1].storage;
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that the same texture subresource cannot be used twice as a storage and render attachment.
TEST_F(PixelLocalStorageTest, RenderPassSubresourceUsedAsStorageAndRender) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: two different subresources for storage and render attachments.
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment | wgpu::TextureUsage::RenderAttachment;
    tDesc.format = kColorAttachmentFormat;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();
    RecordRenderPass(&desc.rpDesc);

    // Error case: the same view is used twice, once as storage, once as render attachment.
    desc.colorAttachment.view = desc.storageAttachments[0].storage;
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that using a subresource as storage attachment prevents other usages in the render pass.
TEST_F(PixelLocalStorageTest, RenderPassSubresourceUsedInsidePass) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment | wgpu::TextureUsage::TextureBinding;
    tDesc.format = wgpu::TextureFormat::R32Uint;

    desc.storageAttachments[0].storage = device.CreateTexture(&tDesc).CreateView();

    // Control case: the storage attachment is used only as storage attachment.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc.rpDesc);
        pass.End();
        encoder.Finish();
    }

    // Error case: the storage attachment is also used as a texture binding in a bind group.
    {
        wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
            device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Uint}});
        wgpu::BindGroup bg =
            utils::MakeBindGroup(device, bgl, {{0, desc.storageAttachments[0].storage}});

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc.rpDesc);
        pass.SetBindGroup(0, bg);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Check that the load and store op must not be undefined.
TEST_F(PixelLocalStorageTest, RenderPassLoadAndStoreOpNotUndefined) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: ops are not undefined.
    RecordRenderPass(&desc.rpDesc);

    // Error case: LoadOp::Undefined
    desc.storageAttachments[0].loadOp = wgpu::LoadOp::Undefined;
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
    desc.storageAttachments[0].loadOp = wgpu::LoadOp::Load;

    // Error case: StoreOp::Undefined
    desc.storageAttachments[0].storeOp = wgpu::StoreOp::Undefined;
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that the clear value, if used, must not have NaNs.
TEST_F(PixelLocalStorageTest, RenderPassClearValueNaNs) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    const float kNaN = std::nan("");

    // Check that NaNs are allowed if the loadOp is not Clear.
    desc.storageAttachments[0].loadOp = wgpu::LoadOp::Load;
    desc.storageAttachments[0].clearValue = {kNaN, kNaN, kNaN, kNaN};
    RecordRenderPass(&desc.rpDesc);

    // Control case, a non-NaN clear value is allowed.
    desc.storageAttachments[0].loadOp = wgpu::LoadOp::Clear;
    desc.storageAttachments[0].clearValue = {0, 0, 0, 0};
    RecordRenderPass(&desc.rpDesc);

    // Error case: NaN in one of the components of clearValue.
    desc.storageAttachments[0].clearValue = {kNaN, 0, 0, 0};
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));

    desc.storageAttachments[0].clearValue = {0, kNaN, 0, 0};
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));

    desc.storageAttachments[0].clearValue = {0, 0, kNaN, 0};
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));

    desc.storageAttachments[0].clearValue = {0, 0, 0, kNaN};
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

// Check that using a subresource as storage attachment prevents other usages in the render pass.
TEST_F(PixelLocalStorageTest, PixelLocalStorageBarrierRequiresPLS) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: there is a PLS, the barrier is allowed.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc.rpDesc);
        pass.PixelLocalStorageBarrier();
        pass.End();
        encoder.Finish();
    }

    // Error case: there is no PLS (it is unlinked from chained structs), the barrier is not
    // allowed.
    {
        desc.rpDesc.nextInChain = nullptr;

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc.rpDesc);
        pass.PixelLocalStorageBarrier();
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Check that PLS state differs between no PLS and empty PLS
TEST_F(PixelLocalStorageTest, PLSStateMatching_EmptyPLSVsNoPLS) {
    PLSSpec emptyPLS = {0, {}, true};
    PLSSpec noPLS = {0, {}, false};

    CheckPLSStateMatching(emptyPLS, emptyPLS, true);
    CheckPLSStateMatching(noPLS, noPLS, true);
    CheckPLSStateMatching(emptyPLS, noPLS, false);
    CheckPLSStateMatching(noPLS, emptyPLS, false);
}

// Check that PLS state differs between empty PLS and non-empty PLS with no storage attachments
TEST_F(PixelLocalStorageTest, PLSStateMatching_EmptyPLSVsNotEmpty) {
    PLSSpec emptyPLS = {0, {}};
    PLSSpec notEmptyPLS = {4, {}};

    CheckPLSStateMatching(emptyPLS, emptyPLS, true);
    CheckPLSStateMatching(notEmptyPLS, notEmptyPLS, true);
    CheckPLSStateMatching(emptyPLS, notEmptyPLS, false);
    CheckPLSStateMatching(notEmptyPLS, emptyPLS, false);
}

// Check that PLS state differs between implicit PLS vs storage attachment
TEST_F(PixelLocalStorageTest, PLSStateMatching_AttachmentVsImplicit) {
    PLSSpec implicitPLS = {4, {}};
    PLSSpec storagePLS = {4, {{0, wgpu::TextureFormat::R32Uint}}};

    CheckPLSStateMatching(implicitPLS, implicitPLS, true);
    CheckPLSStateMatching(storagePLS, storagePLS, true);
    CheckPLSStateMatching(implicitPLS, storagePLS, false);
    CheckPLSStateMatching(storagePLS, implicitPLS, false);
}

// Check that PLS state differs between storage attachment formats
TEST_F(PixelLocalStorageTest, PLSStateMatching_Format) {
    PLSSpec intPLS = {4, {{0, wgpu::TextureFormat::R32Sint}}};
    PLSSpec uintPLS = {4, {{0, wgpu::TextureFormat::R32Uint}}};

    CheckPLSStateMatching(intPLS, intPLS, true);
    CheckPLSStateMatching(uintPLS, uintPLS, true);
    CheckPLSStateMatching(intPLS, uintPLS, false);
    CheckPLSStateMatching(uintPLS, intPLS, false);
}

// Check that PLS state are equal even if attachments are specified in different orders
TEST_F(PixelLocalStorageTest, PLSStateMatching_StorageAttachmentOrder) {
    PLSSpec pls1 = {8, {{4, wgpu::TextureFormat::R32Uint}, {0, wgpu::TextureFormat::R32Sint}}};
    PLSSpec pls2 = {8, {{0, wgpu::TextureFormat::R32Sint}, {4, wgpu::TextureFormat::R32Uint}}};

    CheckPLSStateMatching(pls1, pls2, true);
}

// Check that a shader using pixel_local cannot be used for an implicit layout.
TEST_F(PixelLocalStorageTest, ImplicitLayoutDisallowed) {
    // Control case: not using a pixel_local block is ok.
    TestFragmentAndLayoutCompat(nullptr, R"(
        enable chromium_experimental_pixel_local;
        @fragment fn fs() {}
    )",
                                true);

    // Error case: using a pixel_local block is not ok.
    TestFragmentAndLayoutCompat(nullptr, R"(
        enable chromium_experimental_pixel_local;
        struct PLS { a : u32 }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                false);
}

// Check that the FS can have PLS iff the layout has it.
TEST_F(PixelLocalStorageTest, Reflection_PLSPresenceMatches) {
    // Control case: both without PLS is ok.
    TestFragmentAndLayoutCompat({0, {}, false}, R"(
        enable chromium_experimental_pixel_local;
        @fragment fn fs() {}
    )",
                                true);

    // Control case: both with PLS is ok.
    TestFragmentAndLayoutCompat({4, {}}, R"(
        enable chromium_experimental_pixel_local;
        struct PLS { a : u32 }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                true);

    // Error case: only shader has PLS
    TestFragmentAndLayoutCompat({0, {}, false}, R"(
        enable chromium_experimental_pixel_local;
        struct PLS { a : u32 }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                false);

    // Error case: only layout has PLS
    TestFragmentAndLayoutCompat({4, {}}, R"(
        enable chromium_experimental_pixel_local;
        @fragment fn fs() {
        }
    )",
                                false);

    // Special valid case: shader doesn't have PLS but the layout's PLS is empty
    TestFragmentAndLayoutCompat({0, {}}, R"(
        enable chromium_experimental_pixel_local;
        @fragment fn fs() {
        }
    )",
                                true);
}

// Check that layout's total PLS size must match the shader's pixel_local block size.
TEST_F(PixelLocalStorageTest, Reflection_PLSSize) {
    // Control case: 8 bytes for both!
    TestFragmentAndLayoutCompat({8, {}}, R"(
        enable chromium_experimental_pixel_local;
        struct PLS {
            a : u32,
            b : u32,
        }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                true);

    // Error case: shader PLS is 4 bytes smaller.
    TestFragmentAndLayoutCompat({8, {}}, R"(
        enable chromium_experimental_pixel_local;
        struct PLS { a : u32 }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                false);

    // Error case: layout PLS is 4 bytes smaller.
    TestFragmentAndLayoutCompat({4, {}}, R"(
        enable chromium_experimental_pixel_local;
        struct PLS {
            a : u32,
            b : u32,
        }
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            _ = pls;
        }
    )",
                                false);
}

// Check the validation of the layout's PLS format with the shader types.
TEST_F(PixelLocalStorageTest, Reflection_FormatMatching) {
    std::array<wgpu::TextureFormat, 4> testFormats = {
        wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint, wgpu::TextureFormat::R32Float,
        wgpu::TextureFormat::Undefined,  // No storageAttachment.
    };

    std::array<std::string, 3> shaderTypes = {"f32", "i32", "u32"};

    for (wgpu::TextureFormat format : testFormats) {
        for (const std::string& type : shaderTypes) {
            PLSSpec spec = {4, {}};
            if (format != wgpu::TextureFormat::Undefined) {
                spec = PLSSpec{4, {{0, format}}};
            }

            std::string shader = R"(
                enable chromium_experimental_pixel_local;
                struct PLS { a : )" +
                                 type + R"(}
                var<pixel_local> pls : PLS;
                @fragment fn fs() {
                    _ = pls;
                })";

            // List valid combinations to avoid writing the exact same switch statement as in
            // ShaderModule.cpp
            bool success = (format == wgpu::TextureFormat::R32Uint && type == "u32") ||
                           (format == wgpu::TextureFormat::R32Sint && type == "i32") ||
                           (format == wgpu::TextureFormat::R32Float && type == "f32") ||
                           (format == wgpu::TextureFormat::Undefined && type == "u32");
            TestFragmentAndLayoutCompat(spec, shader, success);
        }
    }
}

// Check that it is allowed to create render passes with only a storage attachment.
TEST_F(PixelLocalStorageTest, RenderPassOnlyStorageAttachment) {
    wgpu::TextureDescriptor tDesc;
    tDesc.format = wgpu::TextureFormat::R32Uint;
    tDesc.size = {1, 1};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::RenderPassStorageAttachment rpAttachment;
    rpAttachment.storage = tex.CreateView();
    rpAttachment.offset = 0;
    rpAttachment.loadOp = wgpu::LoadOp::Load;
    rpAttachment.storeOp = wgpu::StoreOp::Store;

    wgpu::RenderPassPixelLocalStorage rpPlsDesc;
    rpPlsDesc.totalPixelLocalStorageSize = 4;
    rpPlsDesc.storageAttachmentCount = 1;
    rpPlsDesc.storageAttachments = &rpAttachment;

    wgpu::RenderPassDescriptor rpDesc;
    rpDesc.nextInChain = &rpPlsDesc;
    rpDesc.colorAttachmentCount = 0;
    rpDesc.depthStencilAttachment = nullptr;

    // Success case: a render pass with just a storage attachment is valid.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.End();
        encoder.Finish();
    }

    // Error case: a render pass with PLS but no attachments is invalid.
    {
        rpPlsDesc.storageAttachmentCount = 0;
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

// Check that it is allowed to create render pipelines with only a storage attachment.
TEST_F(PixelLocalStorageTest, RenderPipelineOnlyStorageAttachment) {
    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        enable chromium_experimental_pixel_local;

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

        struct PLS {
            value : u32,
        };
        var<pixel_local> pls : PLS;
        @fragment fn fs() {
            pls.value = pls.value + 1;
        }
    )");

    wgpu::PipelineLayoutStorageAttachment plAttachment;
    plAttachment.offset = 0;
    plAttachment.format = wgpu::TextureFormat::R32Uint;

    wgpu::PipelineLayoutPixelLocalStorage plPlsDesc;
    plPlsDesc.totalPixelLocalStorageSize = 4;
    plPlsDesc.storageAttachmentCount = 1;
    plPlsDesc.storageAttachments = &plAttachment;

    wgpu::PipelineLayoutDescriptor plDesc;
    plDesc.nextInChain = &plPlsDesc;
    plDesc.bindGroupLayoutCount = 0;
    wgpu::PipelineLayout pl = device.CreatePipelineLayout(&plDesc);

    utils::ComboRenderPipelineDescriptor pDesc;
    pDesc.layout = pl;
    pDesc.vertex.module = module;
    pDesc.cFragment.module = module;
    pDesc.cFragment.targetCount = 0;

    // Success case: a render pipeline with just a storage attachment is valid.
    device.CreateRenderPipeline(&pDesc);

    // Error case: a render pass with PLS but no attachments is invalid.
    plPlsDesc.storageAttachmentCount = 0;
    pDesc.layout = device.CreatePipelineLayout(&plDesc);
    ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&pDesc));
}

// Check that the size of the render pass is correctly deduced when there is only a storage
// attachment. Use the SetViewport validation to check this.
TEST_F(PixelLocalStorageTest, RenderPassSizeDetectionWithOnlyStorageAttachment) {
    wgpu::TextureDescriptor tDesc;
    tDesc.format = wgpu::TextureFormat::R32Uint;
    tDesc.size = {7, 11};
    tDesc.usage = wgpu::TextureUsage::StorageAttachment;
    wgpu::Texture tex = device.CreateTexture(&tDesc);

    wgpu::RenderPassStorageAttachment rpAttachment;
    rpAttachment.storage = tex.CreateView();
    rpAttachment.offset = 0;
    rpAttachment.loadOp = wgpu::LoadOp::Load;
    rpAttachment.storeOp = wgpu::StoreOp::Store;

    wgpu::RenderPassPixelLocalStorage rpPlsDesc;
    rpPlsDesc.totalPixelLocalStorageSize = 4;
    rpPlsDesc.storageAttachmentCount = 1;
    rpPlsDesc.storageAttachments = &rpAttachment;

    wgpu::RenderPassDescriptor rpDesc;
    rpDesc.nextInChain = &rpPlsDesc;
    rpDesc.colorAttachmentCount = 0;
    rpDesc.depthStencilAttachment = nullptr;

    // Success case: viewport is exactly the size of the render pass.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.SetViewport(0, 0, tDesc.size.width, tDesc.size.height, 0.0, 1.0);
        pass.End();
        encoder.Finish();
    }

    // Error case: viewport width is larger than the render pass's.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.SetViewport(0, 0, tDesc.size.width + 1, tDesc.size.height, 0.0, 1.0);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }

    // Error case: viewport width is larger than the render pass's.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.SetViewport(0, 0, tDesc.size.width, tDesc.size.height + 1, 0.0, 1.0);
        pass.End();
        ASSERT_DEVICE_ERROR(encoder.Finish());
    }
}

class PixelLocalStorageAndRenderToSingleSampledTest : public PixelLocalStorageTest {
  protected:
    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
                                wgpu::DeviceDescriptor descriptor) override {
        wgpu::FeatureName requiredFeatures[2] = {wgpu::FeatureName::PixelLocalStorageNonCoherent,
                                                 wgpu::FeatureName::MSAARenderToSingleSampled};
        descriptor.requiredFeatures = requiredFeatures;
        descriptor.requiredFeatureCount = 2;
        return dawnAdapter.CreateDevice(&descriptor);
    }
};

// Check that PLS + MSAA render to single sampled is not allowed
TEST_F(PixelLocalStorageAndRenderToSingleSampledTest, CombinationIsNotAllowed) {
    ComboTestPLSRenderPassDescriptor desc;
    InitializePLSRenderPass(&desc);

    // Control case: no MSAA render to single sampled.
    RecordRenderPass(&desc.rpDesc);

    // Error case: MSAA render to single sampled is added to the color attachment.
    wgpu::DawnRenderPassColorAttachmentRenderToSingleSampled msaaRenderToSingleSampledDesc;
    msaaRenderToSingleSampledDesc.implicitSampleCount = 4;
    desc.colorAttachment.nextInChain = &msaaRenderToSingleSampledDesc;
    ASSERT_DEVICE_ERROR(RecordRenderPass(&desc.rpDesc));
}

class PixelLocalStorageAndTransientAttachmentTest : public PixelLocalStorageTest {
    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
                                wgpu::DeviceDescriptor descriptor) override {
        wgpu::FeatureName requiredFeatures[2] = {wgpu::FeatureName::PixelLocalStorageNonCoherent,
                                                 wgpu::FeatureName::TransientAttachments};
        descriptor.requiredFeatures = requiredFeatures;
        descriptor.requiredFeatureCount = 2;
        return dawnAdapter.CreateDevice(&descriptor);
    }
};

// Check that a transient + storage attachment is allowed.
TEST_F(PixelLocalStorageAndTransientAttachmentTest, TransientStorageAttachment) {
    wgpu::TextureDescriptor desc;
    desc.size = {1, 1};
    desc.format = wgpu::TextureFormat::R32Uint;
    desc.usage = wgpu::TextureUsage::StorageAttachment | wgpu::TextureUsage::TransientAttachment;
    device.CreateTexture(&desc);

    desc.usage |= wgpu::TextureUsage::RenderAttachment;
    device.CreateTexture(&desc);
}

// TODO(dawn:1704): Add tests for limits
// TODO(dawn:1704): Add tests for load/store op validation with transient.
// TODO(dawn:1704): Allow multisampled storage attachments

}  // anonymous namespace
}  // namespace dawn
