/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This is a GPU-backend specific test. It relies on static intializers to work

#include "SkTypes.h"

#if defined(SK_VULKAN)

#include "vk/GrVkVulkan.h"

#include "GrBackendSurface.h"
#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrTexture.h"
#include "Test.h"
#include "vk/GrVkCopyPipeline.h"
#include "vk/GrVkGpu.h"
#include "vk/GrVkRenderTarget.h"
#include "vk/GrVkUtil.h"

using sk_gpu_test::GrContextFactory;

class TestVkCopyProgram {
public:
    TestVkCopyProgram()
            : fVertShaderModule(VK_NULL_HANDLE)
            , fFragShaderModule(VK_NULL_HANDLE)
            , fPipelineLayout(VK_NULL_HANDLE) {}

    void test(GrVkGpu* gpu, skiatest::Reporter* reporter) {
        const char vertShaderText[] =
            "#extension GL_ARB_separate_shader_objects : enable\n"
            "#extension GL_ARB_shading_language_420pack : enable\n"

            "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
            "half4 uPosXform;"
            "half4 uTexCoordXform;"
            "};"
            "layout(location = 0) in float2 inPosition;"
            "layout(location = 1) out half2 vTexCoord;"

            "// Copy Program VS\n"
            "void main() {"
            "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
            "sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
            "sk_Position.zw = half2(0, 1);"
            "}";

        const char fragShaderText[] =
            "#extension GL_ARB_separate_shader_objects : enable\n"
            "#extension GL_ARB_shading_language_420pack : enable\n"

            "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
            "layout(location = 1) in half2 vTexCoord;"

            "// Copy Program FS\n"
            "void main() {"
            "sk_FragColor = texture(uTextureSampler, vTexCoord);"
            "}";

        SkSL::Program::Settings settings;
        SkSL::String spirv;
        SkSL::Program::Inputs inputs;
        if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
                                     &fVertShaderModule, &fShaderStageInfo[0], settings,
                                     &spirv, &inputs)) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }
        SkASSERT(inputs.isEmpty());

        if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
                                     &fFragShaderModule, &fShaderStageInfo[1], settings,
                                     &spirv, &inputs)) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }

        VkDescriptorSetLayout dsLayout[2];

        GrVkResourceProvider& resourceProvider = gpu->resourceProvider();

        dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();

        uint32_t samplerVisibility = kFragment_GrShaderFlag;
        SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);

        resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                                                       visibilityArray, &fSamplerDSHandle);
        dsLayout[GrVkUniformHandler::kSamplerDescSet] =
                resourceProvider.getSamplerDSLayout(fSamplerDSHandle);

        // Create the VkPipelineLayout
        VkPipelineLayoutCreateInfo layoutCreateInfo;
        memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
        layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        layoutCreateInfo.pNext = 0;
        layoutCreateInfo.flags = 0;
        layoutCreateInfo.setLayoutCount = 2;
        layoutCreateInfo.pSetLayouts = dsLayout;
        layoutCreateInfo.pushConstantRangeCount = 0;
        layoutCreateInfo.pPushConstantRanges = nullptr;

        VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
                                                                           &layoutCreateInfo,
                                                                           nullptr,
                                                                           &fPipelineLayout));
        if (err) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }

        GrSurfaceDesc surfDesc;
        surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
        surfDesc.fWidth = 16;
        surfDesc.fHeight = 16;
        surfDesc.fConfig = kRGBA_8888_GrPixelConfig;
        surfDesc.fSampleCnt = 1;
        sk_sp<GrTexture> tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
        if (!tex) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, tex.get());
            return;

        }
        GrRenderTarget* rt = tex->asRenderTarget();
        REPORTER_ASSERT(reporter, rt);
        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);

        GrVkCopyPipeline* copyPipeline = GrVkCopyPipeline::Create(gpu,
                                                                  fShaderStageInfo,
                                                                  fPipelineLayout,
                                                                  1,
                                                                  *vkRT->simpleRenderPass(),
                                                                  VK_NULL_HANDLE);

        REPORTER_ASSERT(reporter, copyPipeline);
        if (copyPipeline) {
            copyPipeline->unref(gpu);
        }

        this->destroyResources(gpu);
    }

    void destroyResources(GrVkGpu* gpu) {
        if (VK_NULL_HANDLE != fVertShaderModule) {
            GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
                                                               nullptr));
            fVertShaderModule = VK_NULL_HANDLE;
        }

        if (VK_NULL_HANDLE != fFragShaderModule) {
            GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
                                                               nullptr));
            fFragShaderModule = VK_NULL_HANDLE;
        }

        if (VK_NULL_HANDLE != fPipelineLayout) {
            GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
                                                                 nullptr));
            fPipelineLayout = VK_NULL_HANDLE;
        }
    }

    VkShaderModule fVertShaderModule;
    VkShaderModule fFragShaderModule;
    VkPipelineShaderStageCreateInfo fShaderStageInfo[2];

    GrVkDescriptorSetManager::Handle fSamplerDSHandle;
    VkPipelineLayout fPipelineLayout;

};

DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());

    TestVkCopyProgram copyProgram;
    copyProgram.test(gpu, reporter);
}

#endif
