// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tests/unittests/validation/ValidationTest.h"

#include "common/Constants.h"

#include "utils/ComboRenderBundleEncoderDescriptor.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/WGPUHelpers.h"

namespace {

    class RenderBundleValidationTest : public ValidationTest {
      protected:
        void SetUp() override {
            ValidationTest::SetUp();

            vsModule = utils::CreateShaderModule(device, R"(
                [[block]] struct S {
                    transform : mat2x2<f32>;
                };
                [[group(0), binding(0)]] var<uniform> uniforms : S;

                [[stage(vertex)]] fn main([[location(0)]] pos : vec2<f32>) -> [[builtin(position)]] vec4<f32> {
                    return vec4<f32>();
                })");

            fsModule = utils::CreateShaderModule(device, R"(
                [[block]] struct Uniforms {
                    color : vec4<f32>;
                };
                [[group(1), binding(0)]] var<uniform> uniforms : Uniforms;

                [[block]] struct Storage {
                    dummy : array<f32>;
                };
                [[group(1), binding(1)]] var<storage, read_write> ssbo : Storage;

                [[stage(fragment)]] fn main() {
                })");

            wgpu::BindGroupLayout bgls[] = {
                utils::MakeBindGroupLayout(
                    device, {{0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform}}),
                utils::MakeBindGroupLayout(
                    device, {
                                {0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform},
                                {1, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage},
                            })};

            wgpu::PipelineLayoutDescriptor pipelineLayoutDesc = {};
            pipelineLayoutDesc.bindGroupLayoutCount = 2;
            pipelineLayoutDesc.bindGroupLayouts = bgls;

            pipelineLayout = device.CreatePipelineLayout(&pipelineLayoutDesc);

            utils::ComboRenderPipelineDescriptor descriptor;
            InitializeRenderPipelineDescriptor(&descriptor);
            pipeline = device.CreateRenderPipeline(&descriptor);

            float data[8];
            wgpu::Buffer buffer = utils::CreateBufferFromData(device, data, 8 * sizeof(float),
                                                              wgpu::BufferUsage::Uniform);

            constexpr static float kVertices[] = {-1.f, 1.f, 1.f, -1.f, -1.f, 1.f};

            vertexBuffer = utils::CreateBufferFromData(device, kVertices, sizeof(kVertices),
                                                       wgpu::BufferUsage::Vertex);

            // Dummy storage buffer.
            wgpu::Buffer storageBuffer = utils::CreateBufferFromData(
                device, kVertices, sizeof(kVertices), wgpu::BufferUsage::Storage);

            // Vertex buffer with storage usage for testing read+write error usage.
            vertexStorageBuffer =
                utils::CreateBufferFromData(device, kVertices, sizeof(kVertices),
                                            wgpu::BufferUsage::Vertex | wgpu::BufferUsage::Storage);

            bg0 = utils::MakeBindGroup(device, bgls[0], {{0, buffer, 0, 8 * sizeof(float)}});
            bg1 = utils::MakeBindGroup(
                device, bgls[1],
                {{0, buffer, 0, 4 * sizeof(float)}, {1, storageBuffer, 0, sizeof(kVertices)}});

            bg1Vertex = utils::MakeBindGroup(device, bgls[1],
                                             {{0, buffer, 0, 8 * sizeof(float)},
                                              {1, vertexStorageBuffer, 0, sizeof(kVertices)}});
        }

        void InitializeRenderPipelineDescriptor(utils::ComboRenderPipelineDescriptor* descriptor) {
            descriptor->layout = pipelineLayout;
            descriptor->vertex.module = vsModule;
            descriptor->cFragment.module = fsModule;
            descriptor->cTargets[0].writeMask = wgpu::ColorWriteMask::None;
            descriptor->vertex.bufferCount = 1;
            descriptor->cBuffers[0].arrayStride = 2 * sizeof(float);
            descriptor->cBuffers[0].attributeCount = 1;
            descriptor->cAttributes[0].format = wgpu::VertexFormat::Float32x2;
            descriptor->cAttributes[0].shaderLocation = 0;
        }

        wgpu::ShaderModule vsModule;
        wgpu::ShaderModule fsModule;
        wgpu::PipelineLayout pipelineLayout;
        wgpu::RenderPipeline pipeline;
        wgpu::Buffer vertexBuffer;
        wgpu::Buffer vertexStorageBuffer;
        wgpu::BindGroup bg0;
        wgpu::BindGroup bg1;
        wgpu::BindGroup bg1Vertex;
    };

}  // anonymous namespace

// Test creating and encoding an empty render bundle.
TEST_F(RenderBundleValidationTest, Empty) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(1, &renderBundle);
    pass.EndPass();
    commandEncoder.Finish();
}

// Test that an empty error bundle encoder produces an error bundle.
// This is a regression test for error render bundle encoders containing no commands would
// produce non-error render bundles.
TEST_F(RenderBundleValidationTest, EmptyErrorEncoderProducesErrorBundle) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    // Having 0 attachments is invalid!
    desc.colorFormatsCount = 0;

    wgpu::RenderBundleEncoder renderBundleEncoder;
    ASSERT_DEVICE_ERROR(renderBundleEncoder = device.CreateRenderBundleEncoder(&desc));
    wgpu::RenderBundle renderBundle;
    ASSERT_DEVICE_ERROR(renderBundle = renderBundleEncoder.Finish());

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(1, &renderBundle);
    pass.EndPass();
    ASSERT_DEVICE_ERROR(commandEncoder.Finish());
}

// Test executing zero render bundles.
TEST_F(RenderBundleValidationTest, ZeroBundles) {
    DummyRenderPass renderPass(device);

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(0, nullptr);
    pass.EndPass();
    commandEncoder.Finish();
}

// Test successfully creating and encoding a render bundle into a command buffer.
TEST_F(RenderBundleValidationTest, SimpleSuccess) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
    renderBundleEncoder.SetPipeline(pipeline);
    renderBundleEncoder.SetBindGroup(0, bg0);
    renderBundleEncoder.SetBindGroup(1, bg1);
    renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
    renderBundleEncoder.Draw(3);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(1, &renderBundle);
    pass.EndPass();
    commandEncoder.Finish();
}

// Test that render bundle debug groups must be well nested.
TEST_F(RenderBundleValidationTest, DebugGroups) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    // Test a single debug group works.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PushDebugGroup("group");
        renderBundleEncoder.PopDebugGroup();
        renderBundleEncoder.Finish();
    }

    // Test nested debug groups work.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PushDebugGroup("group");
        renderBundleEncoder.PushDebugGroup("group2");
        renderBundleEncoder.PopDebugGroup();
        renderBundleEncoder.PopDebugGroup();
        renderBundleEncoder.Finish();
    }

    // Test popping when no group is pushed is invalid.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PopDebugGroup();
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // Test popping too many times is invalid.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PushDebugGroup("group");
        renderBundleEncoder.PopDebugGroup();
        renderBundleEncoder.PopDebugGroup();
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // Test that a single debug group must be popped.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PushDebugGroup("group");
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // Test that all debug groups must be popped.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.PushDebugGroup("group");
        renderBundleEncoder.PushDebugGroup("group2");
        renderBundleEncoder.PopDebugGroup();
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }
}

// Test render bundles do not inherit command buffer state
TEST_F(RenderBundleValidationTest, StateInheritance) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    // Render bundle does not inherit pipeline so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);

        pass.SetPipeline(pipeline);

        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1);
        renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
        renderBundleEncoder.Draw(3);
        ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish());

        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not inherit bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);

        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);

        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
        renderBundleEncoder.Draw(3);
        ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish());

        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not inherit pipeline and bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);

        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);

        renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
        renderBundleEncoder.Draw(3);
        ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish());

        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not inherit buffers so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);

        pass.SetVertexBuffer(0, vertexBuffer);

        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1);
        renderBundleEncoder.Draw(3);
        ASSERT_DEVICE_ERROR(wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish());

        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test render bundles do not persist command buffer state
TEST_F(RenderBundleValidationTest, StatePersistence) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    // Render bundle does not persist pipeline so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

        pass.ExecuteBundles(1, &renderBundle);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not persist bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1);
        wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipeline);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not persist pipeline and bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1);
        wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

        pass.ExecuteBundles(1, &renderBundle);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle does not persist buffers so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
        wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test executing render bundles clears command buffer state
TEST_F(RenderBundleValidationTest, ClearsState) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    // Render bundle clears pipeline so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetPipeline(pipeline);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle clears bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipeline);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle clears pipeline and bind groups so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Render bundle clears buffers so the draw is invalid.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetVertexBuffer(0, vertexBuffer);
        pass.ExecuteBundles(1, &renderBundle);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.Draw(3);
        pass.EndPass();

        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Test executing 0 bundles still clears command buffer state.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.ExecuteBundles(0, nullptr);
        pass.Draw(3);

        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test creating and encoding multiple render bundles.
TEST_F(RenderBundleValidationTest, MultipleBundles) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundle renderBundles[2] = {};

    wgpu::RenderBundleEncoder renderBundleEncoder0 = device.CreateRenderBundleEncoder(&desc);
    renderBundleEncoder0.SetPipeline(pipeline);
    renderBundleEncoder0.SetBindGroup(0, bg0);
    renderBundleEncoder0.SetBindGroup(1, bg1);
    renderBundleEncoder0.SetVertexBuffer(0, vertexBuffer);
    renderBundleEncoder0.Draw(3);
    renderBundles[0] = renderBundleEncoder0.Finish();

    wgpu::RenderBundleEncoder renderBundleEncoder1 = device.CreateRenderBundleEncoder(&desc);
    renderBundleEncoder1.SetPipeline(pipeline);
    renderBundleEncoder1.SetBindGroup(0, bg0);
    renderBundleEncoder1.SetBindGroup(1, bg1);
    renderBundleEncoder1.SetVertexBuffer(0, vertexBuffer);
    renderBundleEncoder1.Draw(3);
    renderBundles[1] = renderBundleEncoder1.Finish();

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(2, renderBundles);
    pass.EndPass();
    commandEncoder.Finish();
}

// Test that is is valid to execute a render bundle more than once.
TEST_F(RenderBundleValidationTest, ExecuteMultipleTimes) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
    renderBundleEncoder.SetPipeline(pipeline);
    renderBundleEncoder.SetBindGroup(0, bg0);
    renderBundleEncoder.SetBindGroup(1, bg1);
    renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
    renderBundleEncoder.Draw(3);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
    pass.ExecuteBundles(1, &renderBundle);
    pass.ExecuteBundles(1, &renderBundle);
    pass.ExecuteBundles(1, &renderBundle);
    pass.EndPass();
    commandEncoder.Finish();
}

// Test that it is an error to call Finish() on a render bundle encoder twice.
TEST_F(RenderBundleValidationTest, FinishTwice) {
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Uint;

    wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
    renderBundleEncoder.Finish();
    ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
}

// Test that it is invalid to create a render bundle with no texture formats
TEST_F(RenderBundleValidationTest, RequiresAtLeastOneTextureFormat) {
    // Test failure case.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
    }

    // Test success with one color format.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.colorFormatsCount = 1;
        desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Uint;
        device.CreateRenderBundleEncoder(&desc);
    }

    // Test success with a depth stencil format.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.depthStencilFormat = wgpu::TextureFormat::Depth24PlusStencil8;
        device.CreateRenderBundleEncoder(&desc);
    }
}

// Test that it is invalid to create a render bundle with no texture formats
TEST_F(RenderBundleValidationTest, ColorFormatsCountOutOfBounds) {
    std::array<wgpu::TextureFormat, kMaxColorAttachments + 1> colorFormats;
    for (uint32_t i = 0; i < colorFormats.size(); ++i) {
        colorFormats[i] = wgpu::TextureFormat::RGBA8Unorm;
    }

    // colorFormatsCount <= kMaxColorAttachments is valid.
    {
        wgpu::RenderBundleEncoderDescriptor desc;
        desc.colorFormatsCount = kMaxColorAttachments;
        desc.colorFormats = colorFormats.data();
        device.CreateRenderBundleEncoder(&desc);
    }

    // colorFormatsCount > kMaxColorAttachments is invalid.
    {
        wgpu::RenderBundleEncoderDescriptor desc;
        desc.colorFormatsCount = kMaxColorAttachments + 1;
        desc.colorFormats = colorFormats.data();
        ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
    }
}

// Test that render bundle color formats cannot be set to undefined.
TEST_F(RenderBundleValidationTest, ColorFormatUndefined) {
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = wgpu::TextureFormat::Undefined;
    ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
}

// Test that the render bundle depth stencil format cannot be set to undefined.
TEST_F(RenderBundleValidationTest, DepthStencilFormatUndefined) {
    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.depthStencilFormat = wgpu::TextureFormat::Undefined;
    ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
}

// Test that depthReadOnly must be equal to stencilReadOnly if depth stencil format contain
// both depth and stencil formats.
TEST_F(RenderBundleValidationTest, DepthStencilReadOnly) {
    for (wgpu::TextureFormat format :
         {wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureFormat::Depth32Float}) {
        for (bool depthReadOnly : {true, false}) {
            for (bool stencilReadOnly : {true, false}) {
                utils::ComboRenderBundleEncoderDescriptor desc = {};
                desc.depthStencilFormat = format;
                desc.depthReadOnly = depthReadOnly;
                desc.stencilReadOnly = stencilReadOnly;
                if (format == wgpu::TextureFormat::Depth24PlusStencil8 &&
                    depthReadOnly != stencilReadOnly) {
                    ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
                } else {
                    device.CreateRenderBundleEncoder(&desc);
                }
            }
        }
    }
}
// Test that resource usages are validated inside render bundles.
TEST_F(RenderBundleValidationTest, UsageTracking) {
    DummyRenderPass renderPass(device);

    utils::ComboRenderBundleEncoderDescriptor desc = {};
    desc.colorFormatsCount = 1;
    desc.cColorFormats[0] = renderPass.attachmentFormat;

    wgpu::RenderBundle renderBundle0;
    wgpu::RenderBundle renderBundle1;

    // First base case is successful. |bg1Vertex| does not reference |vertexBuffer|.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1Vertex);
        renderBundleEncoder.SetVertexBuffer(0, vertexBuffer);
        renderBundleEncoder.Draw(3);
        renderBundle0 = renderBundleEncoder.Finish();
    }

    // Second base case is successful. |bg1| does not reference |vertexStorageBuffer|
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1);
        renderBundleEncoder.SetVertexBuffer(0, vertexStorageBuffer);
        renderBundleEncoder.Draw(3);
        renderBundle1 = renderBundleEncoder.Finish();
    }

    // Test that a render bundle which sets a buffer as both vertex and storage is invalid.
    // |bg1Vertex| references |vertexStorageBuffer|
    {
        wgpu::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.SetBindGroup(0, bg0);
        renderBundleEncoder.SetBindGroup(1, bg1Vertex);
        renderBundleEncoder.SetVertexBuffer(0, vertexStorageBuffer);
        renderBundleEncoder.Draw(3);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // When both render bundles are in the same pass, |vertexStorageBuffer| is used
    // as both read and write usage. This is invalid.
    // renderBundle0 uses |vertexStorageBuffer| as a storage buffer.
    // renderBundle1 uses |vertexStorageBuffer| as a vertex buffer.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle0);
        pass.ExecuteBundles(1, &renderBundle1);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // |vertexStorageBuffer| is used as both read and write usage. This is invalid.
    // The render pass uses |vertexStorageBuffer| as a storage buffer.
    // renderBundle1 uses |vertexStorageBuffer| as a vertex buffer.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1Vertex);
        pass.SetVertexBuffer(0, vertexBuffer);
        pass.Draw(3);

        pass.ExecuteBundles(1, &renderBundle1);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // |vertexStorageBuffer| is used as both read and write usage. This is invalid.
    // renderBundle0 uses |vertexStorageBuffer| as a storage buffer.
    // The render pass uses |vertexStorageBuffer| as a vertex buffer.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);

        pass.ExecuteBundles(1, &renderBundle0);

        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.SetVertexBuffer(0, vertexStorageBuffer);
        pass.Draw(3);

        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test that encoding SetPipline with an incompatible color format produces an error.
TEST_F(RenderBundleValidationTest, PipelineColorFormatMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 3;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    renderBundleDesc.cColorFormats[1] = wgpu::TextureFormat::RG16Float;
    renderBundleDesc.cColorFormats[2] = wgpu::TextureFormat::R16Sint;

    auto SetupRenderPipelineDescForTest = [this](utils::ComboRenderPipelineDescriptor* desc) {
        InitializeRenderPipelineDescriptor(desc);
        desc->cFragment.targetCount = 3;
        desc->cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
        desc->cTargets[1].format = wgpu::TextureFormat::RG16Float;
        desc->cTargets[2].format = wgpu::TextureFormat::R16Sint;
        desc->cTargets[0].writeMask = wgpu::ColorWriteMask::None;
        desc->cTargets[1].writeMask = wgpu::ColorWriteMask::None;
        desc->cTargets[2].writeMask = wgpu::ColorWriteMask::None;
    };

    // Test the success case.
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.Finish();
    }

    // Test the failure case for mismatched format types.
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);
        desc.cTargets[1].format = wgpu::TextureFormat::RGBA8Unorm;

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // Test the failure case for missing format
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);
        desc.cFragment.targetCount = 2;

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }
}

// Test that encoding SetPipline with an incompatible depth stencil format produces an error.
TEST_F(RenderBundleValidationTest, PipelineDepthStencilFormatMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 1;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    renderBundleDesc.depthStencilFormat = wgpu::TextureFormat::Depth24PlusStencil8;

    auto SetupRenderPipelineDescForTest = [this](utils::ComboRenderPipelineDescriptor* desc) {
        InitializeRenderPipelineDescriptor(desc);
        desc->cFragment.targetCount = 1;
        desc->cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    };

    // Test the success case.
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);
        desc.EnableDepthStencil(wgpu::TextureFormat::Depth24PlusStencil8);

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.Finish();
    }

    // Test the failure case for mismatched format.
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);
        desc.EnableDepthStencil(wgpu::TextureFormat::Depth24Plus);

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }

    // Test the failure case for missing format.
    {
        utils::ComboRenderPipelineDescriptor desc;
        SetupRenderPipelineDescForTest(&desc);
        desc.depthStencil = nullptr;

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
        renderBundleEncoder.SetPipeline(pipeline);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }
}

// Test that encoding SetPipline with an incompatible sample count produces an error.
TEST_F(RenderBundleValidationTest, PipelineSampleCountMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 1;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    renderBundleDesc.sampleCount = 4;

    utils::ComboRenderPipelineDescriptor renderPipelineDesc;
    InitializeRenderPipelineDescriptor(&renderPipelineDesc);
    renderPipelineDesc.cFragment.targetCount = 1;
    renderPipelineDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
    renderPipelineDesc.multisample.count = 4;

    // Test the success case.
    {
        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);
        renderBundleEncoder.SetPipeline(pipeline);
        renderBundleEncoder.Finish();
    }

    // Test the failure case.
    {
        renderPipelineDesc.multisample.count = 1;

        wgpu::RenderBundleEncoder renderBundleEncoder =
            device.CreateRenderBundleEncoder(&renderBundleDesc);
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);
        renderBundleEncoder.SetPipeline(pipeline);
        ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
    }
}

// Test that encoding ExecuteBundles with an incompatible color format produces an error.
TEST_F(RenderBundleValidationTest, RenderPassColorFormatMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 3;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    renderBundleDesc.cColorFormats[1] = wgpu::TextureFormat::RG16Float;
    renderBundleDesc.cColorFormats[2] = wgpu::TextureFormat::R16Sint;

    wgpu::RenderBundleEncoder renderBundleEncoder =
        device.CreateRenderBundleEncoder(&renderBundleDesc);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::TextureDescriptor textureDesc = {};
    textureDesc.usage = wgpu::TextureUsage::RenderAttachment;
    textureDesc.size = wgpu::Extent3D({400, 400, 1});

    textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
    wgpu::Texture tex0 = device.CreateTexture(&textureDesc);

    textureDesc.format = wgpu::TextureFormat::RG16Float;
    wgpu::Texture tex1 = device.CreateTexture(&textureDesc);

    textureDesc.format = wgpu::TextureFormat::R16Sint;
    wgpu::Texture tex2 = device.CreateTexture(&textureDesc);

    // Test the success case
    {
        utils::ComboRenderPassDescriptor renderPass({
            tex0.CreateView(),
            tex1.CreateView(),
            tex2.CreateView(),
        });

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        commandEncoder.Finish();
    }

    // Test the failure case for mismatched format
    {
        utils::ComboRenderPassDescriptor renderPass({
            tex0.CreateView(),
            tex1.CreateView(),
            tex0.CreateView(),
        });

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Test the failure case for missing format
    {
        utils::ComboRenderPassDescriptor renderPass({
            tex0.CreateView(),
            tex1.CreateView(),
        });

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test that encoding ExecuteBundles with an incompatible depth stencil format produces an
// error.
TEST_F(RenderBundleValidationTest, RenderPassDepthStencilFormatMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 1;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
    renderBundleDesc.depthStencilFormat = wgpu::TextureFormat::Depth24Plus;

    wgpu::RenderBundleEncoder renderBundleEncoder =
        device.CreateRenderBundleEncoder(&renderBundleDesc);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::TextureDescriptor textureDesc = {};
    textureDesc.usage = wgpu::TextureUsage::RenderAttachment;
    textureDesc.size = wgpu::Extent3D({400, 400, 1});

    textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
    wgpu::Texture tex0 = device.CreateTexture(&textureDesc);

    textureDesc.format = wgpu::TextureFormat::Depth24Plus;
    wgpu::Texture tex1 = device.CreateTexture(&textureDesc);

    textureDesc.format = wgpu::TextureFormat::Depth32Float;
    wgpu::Texture tex2 = device.CreateTexture(&textureDesc);

    // Test the success case
    {
        utils::ComboRenderPassDescriptor renderPass({tex0.CreateView()}, tex1.CreateView());

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        commandEncoder.Finish();
    }

    // Test the failure case for mismatched format
    {
        utils::ComboRenderPassDescriptor renderPass({tex0.CreateView()}, tex2.CreateView());

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }

    // Test the failure case for missing format
    {
        utils::ComboRenderPassDescriptor renderPass({tex0.CreateView()});

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test that encoding ExecuteBundles with an incompatible sample count produces an error.
TEST_F(RenderBundleValidationTest, RenderPassSampleCountMismatch) {
    utils::ComboRenderBundleEncoderDescriptor renderBundleDesc = {};
    renderBundleDesc.colorFormatsCount = 1;
    renderBundleDesc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;

    wgpu::RenderBundleEncoder renderBundleEncoder =
        device.CreateRenderBundleEncoder(&renderBundleDesc);
    wgpu::RenderBundle renderBundle = renderBundleEncoder.Finish();

    wgpu::TextureDescriptor textureDesc = {};
    textureDesc.usage = wgpu::TextureUsage::RenderAttachment;
    textureDesc.size = wgpu::Extent3D({400, 400, 1});

    textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
    wgpu::Texture tex0 = device.CreateTexture(&textureDesc);

    textureDesc.sampleCount = 4;
    wgpu::Texture tex1 = device.CreateTexture(&textureDesc);

    // Test the success case
    {
        utils::ComboRenderPassDescriptor renderPass({tex0.CreateView()});

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        commandEncoder.Finish();
    }

    // Test the failure case
    {
        utils::ComboRenderPassDescriptor renderPass({tex1.CreateView()});

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
        pass.ExecuteBundles(1, &renderBundle);
        pass.EndPass();
        ASSERT_DEVICE_ERROR(commandEncoder.Finish());
    }
}

// Test that color attachment texture formats must be color renderable and
// depth stencil texture formats must be depth/stencil.
TEST_F(RenderBundleValidationTest, TextureFormats) {
    // Test that color formats are validated as color.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.colorFormatsCount = 1;
        desc.cColorFormats[0] = wgpu::TextureFormat::Depth24PlusStencil8;
        ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
    }

    // Test that color formats are validated as renderable.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.colorFormatsCount = 1;
        desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Snorm;
        ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
    }

    // Test that depth/stencil formats are validated as depth/stencil.
    {
        utils::ComboRenderBundleEncoderDescriptor desc = {};
        desc.depthStencilFormat = wgpu::TextureFormat::RGBA8Unorm;
        ASSERT_DEVICE_ERROR(device.CreateRenderBundleEncoder(&desc));
    }

    // Don't test non-renerable depth/stencil formats because we don't have any.
}
