// Copyright 2017 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/NXTTest.h"

#include "utils/NXTHelpers.h"

#include <array>

constexpr static unsigned int kRTSize = 16;

class DrawQuad {
    public:
        DrawQuad() {}
        DrawQuad(nxt::Device* device, const char* vsSource, const char* fsSource)
            : device(device) {
                vsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Vertex, vsSource);
                fsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Fragment, fsSource);

                pipelineLayout = utils::MakeBasicPipelineLayout(*device, nullptr);
            }

        void Draw(nxt::CommandBufferBuilder* builder) {
            auto renderPipeline = device->CreateRenderPipelineBuilder()
                .SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
                .SetLayout(pipelineLayout)
                .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
                .SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
                .GetResult();

            builder->SetRenderPipeline(renderPipeline);
            builder->DrawArrays(6, 1, 0, 0);
        }

    private:
        nxt::Device* device = nullptr;
        nxt::ShaderModule vsModule = {};
        nxt::ShaderModule fsModule = {};
        nxt::PipelineLayout pipelineLayout = {};
};

class RenderPassLoadOpTests : public NXTTest {
    protected:
        void SetUp() override {
            NXTTest::SetUp();

            renderTarget = device.CreateTextureBuilder()
                .SetDimension(nxt::TextureDimension::e2D)
                .SetExtent(kRTSize, kRTSize, 1)
                .SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
                .SetMipLevels(1)
                .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
                .GetResult();

            renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();

            RGBA8 zero(0, 0, 0, 0);
            std::fill(expectZero.begin(), expectZero.end(), zero);

            RGBA8 green(0, 255, 0, 255);
            std::fill(expectGreen.begin(), expectGreen.end(), green);

            RGBA8 blue(0, 0, 255, 255);
            std::fill(expectBlue.begin(), expectBlue.end(), blue);

            // draws a blue quad on the right half of the screen
            const char* vsSource = R"(
                #version 450
                void main() {
                    const vec2 pos[6] = vec2[6](
                        vec2(0, -1), vec2(1, -1), vec2(0, 1),
                        vec2(0,  1), vec2(1, -1), vec2(1, 1));
                    gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
                }
                )";
            const char* fsSource = R"(
                #version 450
                layout(location = 0) out vec4 color;
                void main() {
                    color = vec4(0.f, 0.f, 1.f, 1.f);
                }
                )";
            blueQuad = DrawQuad(&device, vsSource, fsSource);
        }

        nxt::Texture renderTarget;
        nxt::TextureView renderTargetView;

        std::array<RGBA8, kRTSize * kRTSize> expectZero;
        std::array<RGBA8, kRTSize * kRTSize> expectGreen;
        std::array<RGBA8, kRTSize * kRTSize> expectBlue;

        DrawQuad blueQuad = {};
};

// Tests clearing, loading, and drawing into color attachments
TEST_P(RenderPassLoadOpTests, ColorClearThenLoadAndDraw) {

    // Part 1: clear once, check to make sure it's cleared

    auto renderPassClearZero = device.CreateRenderPassDescriptorBuilder()
        .SetColorAttachment(0, renderTargetView, nxt::LoadOp::Clear)
        .SetColorAttachmentClearColor(0, 0.0f, 0.0f, 0.0f, 0.0f)
        .GetResult();

    auto commandsClearZero = device.CreateCommandBufferBuilder()
        .BeginRenderPass(renderPassClearZero)
            // Clear should occur implicitly
            // Store should occur implicitly
        .EndRenderPass()
        .GetResult();

    auto renderPassClearGreen = device.CreateRenderPassDescriptorBuilder()
        .SetColorAttachment(0, renderTargetView, nxt::LoadOp::Clear)
        .SetColorAttachmentClearColor(0, 0.0f, 1.0f, 0.0f, 1.0f)
        .GetResult();

    auto commandsClearGreen = device.CreateCommandBufferBuilder()
        .BeginRenderPass(renderPassClearGreen)
            // Clear should occur implicitly
            // Store should occur implicitly
        .EndRenderPass()
        .GetResult();

    queue.Submit(1, &commandsClearZero);
    EXPECT_TEXTURE_RGBA8_EQ(expectZero.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);

    queue.Submit(1, &commandsClearGreen);
    EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);

    // Part 2: draw a blue quad into the right half of the render target, and check result

    auto renderPassLoad = device.CreateRenderPassDescriptorBuilder()
        .SetColorAttachment(0, renderTargetView, nxt::LoadOp::Load)
        .GetResult();

    nxt::CommandBuffer commandsLoad;
    {
        auto builder = device.CreateCommandBufferBuilder()
            .BeginRenderPass(renderPassLoad)
                // Load should occur implicitly
            .Clone();
        blueQuad.Draw(&builder);
        commandsLoad = builder
                // Store should occur implicitly
            .EndRenderPass()
            .GetResult();
    }

    queue.Submit(1, &commandsLoad);
    // Left half should still be green
    EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize / 2, kRTSize, 0);
    // Right half should now be blue
    EXPECT_TEXTURE_RGBA8_EQ(expectBlue.data(), renderTarget, kRTSize / 2, 0, kRTSize / 2, kRTSize, 0);
}

NXT_INSTANTIATE_TEST(RenderPassLoadOpTests, D3D12Backend, MetalBackend, OpenGLBackend)
