// Copyright 2021 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 "dawn/common/GPUInfo.h"
#include "dawn/common/Log.h"
#include "dawn/common/Platform.h"
#include "dawn/common/SystemUtils.h"
#include "dawn/dawn_proc.h"
#include "dawn/native/DawnNative.h"
#include "dawn/tests/MockCallback.h"
#include "dawn/webgpu_cpp.h"

#if defined(DAWN_ENABLE_BACKEND_VULKAN)
#    include "dawn/native/VulkanBackend.h"
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)

#if defined(DAWN_ENABLE_BACKEND_D3D12)
#    include "dawn/native/D3D12Backend.h"
#endif  // defined(DAWN_ENABLE_BACKEND_D3D12)

#if defined(DAWN_ENABLE_BACKEND_METAL)
#    include "dawn/native/MetalBackend.h"
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) || defined(DAWN_ENABLE_BACKEND_OPENGLES)
#    include "GLFW/glfw3.h"
#    include "dawn/native/OpenGLBackend.h"
#endif  // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) || defined(DAWN_ENABLE_BACKEND_OPENGLES)

#include <gtest/gtest.h>

namespace {

    using namespace testing;

    class AdapterDiscoveryTests : public ::testing::Test {};

#if defined(DAWN_ENABLE_BACKEND_VULKAN)
    // Test only discovering the SwiftShader adapter
    TEST(AdapterDiscoveryTests, OnlySwiftShader) {
        dawn::native::Instance instance;

        dawn::native::vulkan::AdapterDiscoveryOptions options;
        options.forceSwiftShader = true;
        instance.DiscoverAdapters(&options);

        const auto& adapters = instance.GetAdapters();
        EXPECT_LE(adapters.size(), 1u);  // 0 or 1 SwiftShader adapters.
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::Vulkan);
            EXPECT_EQ(properties.adapterType, wgpu::AdapterType::CPU);
            EXPECT_TRUE(gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID));
        }
    }

    // Test discovering only Vulkan adapters
    TEST(AdapterDiscoveryTests, OnlyVulkan) {
        dawn::native::Instance instance;

        dawn::native::vulkan::AdapterDiscoveryOptions options;
        instance.DiscoverAdapters(&options);

        const auto& adapters = instance.GetAdapters();
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::Vulkan);
        }
    }
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)

#if defined(DAWN_ENABLE_BACKEND_D3D12)
    // Test discovering only D3D12 adapters
    TEST(AdapterDiscoveryTests, OnlyD3D12) {
        dawn::native::Instance instance;

        dawn::native::d3d12::AdapterDiscoveryOptions options;
        instance.DiscoverAdapters(&options);

        const auto& adapters = instance.GetAdapters();
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::D3D12);
        }
    }

    // Test discovering a D3D12 adapter from a prexisting DXGI adapter
    TEST(AdapterDiscoveryTests, MatchingDXGIAdapter) {
        using Microsoft::WRL::ComPtr;

        ComPtr<IDXGIFactory4> dxgiFactory;
        HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory));
        ASSERT_EQ(hr, S_OK);

        for (uint32_t adapterIndex = 0;; ++adapterIndex) {
            ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
            if (dxgiFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
                break;  // No more adapters to enumerate.
            }

            dawn::native::Instance instance;

            dawn::native::d3d12::AdapterDiscoveryOptions options;
            options.dxgiAdapter = std::move(dxgiAdapter);
            instance.DiscoverAdapters(&options);

            const auto& adapters = instance.GetAdapters();
            for (const auto& adapter : adapters) {
                wgpu::AdapterProperties properties;
                adapter.GetProperties(&properties);

                EXPECT_EQ(properties.backendType, wgpu::BackendType::D3D12);
            }
        }
    }
#endif  // defined(DAWN_ENABLE_BACKEND_D3D12)

#if defined(DAWN_ENABLE_BACKEND_METAL)
    // Test discovering only Metal adapters
    TEST(AdapterDiscoveryTests, OnlyMetal) {
        dawn::native::Instance instance;

        dawn::native::metal::AdapterDiscoveryOptions options;
        instance.DiscoverAdapters(&options);

        const auto& adapters = instance.GetAdapters();
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::Metal);
        }
    }
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
    // Test discovering only desktop OpenGL adapters
    TEST(AdapterDiscoveryTests, OnlyDesktopGL) {
        if (!glfwInit()) {
            GTEST_SKIP() << "glfwInit() failed";
        }
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

        GLFWwindow* window =
            glfwCreateWindow(400, 400, "Dawn OpenGL test window", nullptr, nullptr);
        glfwMakeContextCurrent(window);

        dawn::native::Instance instance;

        dawn::native::opengl::AdapterDiscoveryOptions options;
        options.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
        instance.DiscoverAdapters(&options);
        glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);

        const auto& adapters = instance.GetAdapters();
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::OpenGL);
        }

        glfwDestroyWindow(window);
    }
#endif  // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)

#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
    // Test discovering only OpenGLES adapters
    TEST(AdapterDiscoveryTests, OnlyOpenGLES) {
        ScopedEnvironmentVar angleDefaultPlatform;
        if (GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM").first.empty()) {
            angleDefaultPlatform.Set("ANGLE_DEFAULT_PLATFORM", "swiftshader");
        }

        if (!glfwInit()) {
            GTEST_SKIP() << "glfwInit() failed";
        }
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
        glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
        glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

        GLFWwindow* window =
            glfwCreateWindow(400, 400, "Dawn OpenGLES test window", nullptr, nullptr);
        glfwMakeContextCurrent(window);

        dawn::native::Instance instance;

        dawn::native::opengl::AdapterDiscoveryOptionsES options;
        options.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
        instance.DiscoverAdapters(&options);
        glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);

        const auto& adapters = instance.GetAdapters();
        for (const auto& adapter : adapters) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.backendType, wgpu::BackendType::OpenGLES);
        }

        glfwDestroyWindow(window);
    }
#endif  // defined(DAWN_ENABLE_BACKEND_OPENGLES)

#if defined(DAWN_ENABLE_BACKEND_METAL) && defined(DAWN_ENABLE_BACKEND_VULKAN)
    // Test discovering the Metal backend, then the Vulkan backend
    // does not duplicate adapters.
    TEST(AdapterDiscoveryTests, OneBackendThenTheOther) {
        dawn::native::Instance instance;
        uint32_t metalAdapterCount = 0;
        {
            dawn::native::metal::AdapterDiscoveryOptions options;
            instance.DiscoverAdapters(&options);

            const auto& adapters = instance.GetAdapters();
            metalAdapterCount = adapters.size();
            for (const auto& adapter : adapters) {
                wgpu::AdapterProperties properties;
                adapter.GetProperties(&properties);

                ASSERT_EQ(properties.backendType, wgpu::BackendType::Metal);
            }
        }
        {
            dawn::native::vulkan::AdapterDiscoveryOptions options;
            instance.DiscoverAdapters(&options);

            uint32_t metalAdapterCount2 = 0;
            const auto& adapters = instance.GetAdapters();
            for (const auto& adapter : adapters) {
                wgpu::AdapterProperties properties;
                adapter.GetProperties(&properties);

                EXPECT_TRUE(properties.backendType == wgpu::BackendType::Metal ||
                            properties.backendType == wgpu::BackendType::Vulkan);
                if (properties.backendType == wgpu::BackendType::Metal) {
                    metalAdapterCount2++;
                }
            }
            EXPECT_EQ(metalAdapterCount, metalAdapterCount2);
        }
    }
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN) && defined(DAWN_ENABLE_BACKEND_METAL)

    class AdapterCreationTest : public ::testing::Test {
      protected:
        void SetUp() override {
            dawnProcSetProcs(&dawn_native::GetProcs());

            {
                auto nativeInstance = std::make_unique<dawn_native::Instance>();
                nativeInstance->DiscoverDefaultAdapters();
                for (dawn_native::Adapter& nativeAdapter : nativeInstance->GetAdapters()) {
                    anyAdapterAvailable = true;

                    wgpu::AdapterProperties properties;
                    nativeAdapter.GetProperties(&properties);
                    swiftShaderAvailable =
                        swiftShaderAvailable ||
                        gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID);
                    discreteGPUAvailable = discreteGPUAvailable ||
                                           properties.adapterType == wgpu::AdapterType::DiscreteGPU;
                    integratedGPUAvailable =
                        integratedGPUAvailable ||
                        properties.adapterType == wgpu::AdapterType::IntegratedGPU;
                }
            }

            instance = wgpu::CreateInstance();
        }

        void TearDown() override {
            instance = nullptr;
            dawnProcSetProcs(nullptr);
        }

        wgpu::Instance instance;
        bool anyAdapterAvailable = false;
        bool swiftShaderAvailable = false;
        bool discreteGPUAvailable = false;
        bool integratedGPUAvailable = false;
    };

    // Test that requesting the default adapter works
    TEST_F(AdapterCreationTest, DefaultAdapter) {
        wgpu::RequestAdapterOptions options = {};

        MockCallback<WGPURequestAdapterCallback> cb;

        WGPUAdapter cAdapter = nullptr;
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));

        wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
    }

    // Test that passing nullptr for the options gets the default adapter
    TEST_F(AdapterCreationTest, NullGivesDefaultAdapter) {
        wgpu::RequestAdapterOptions options = {};

        MockCallback<WGPURequestAdapterCallback> cb;

        WGPUAdapter cAdapter = nullptr;
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));

        wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);

        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this + 1))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(nullptr, cb.Callback(), cb.MakeUserdata(this + 1));

        wgpu::Adapter adapter2 = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter.Get(), adapter2.Get());
    }

    // Test that requesting the fallback adapter returns SwiftShader.
    TEST_F(AdapterCreationTest, FallbackAdapter) {
        wgpu::RequestAdapterOptions options = {};
        options.forceFallbackAdapter = true;

        MockCallback<WGPURequestAdapterCallback> cb;

        WGPUAdapter cAdapter = nullptr;
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));

        wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter != nullptr, swiftShaderAvailable);
        if (adapter != nullptr) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);

            EXPECT_EQ(properties.adapterType, wgpu::AdapterType::CPU);
            EXPECT_TRUE(gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID));
        }
    }

    // Test that requesting a high performance GPU works
    TEST_F(AdapterCreationTest, PreferHighPerformance) {
        wgpu::RequestAdapterOptions options = {};
        options.powerPreference = wgpu::PowerPreference::HighPerformance;

        MockCallback<WGPURequestAdapterCallback> cb;

        WGPUAdapter cAdapter = nullptr;
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));

        wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
        if (discreteGPUAvailable) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);
            EXPECT_EQ(properties.adapterType, wgpu::AdapterType::DiscreteGPU);
        }
    }

    // Test that requesting a low power GPU works
    TEST_F(AdapterCreationTest, PreferLowPower) {
        wgpu::RequestAdapterOptions options = {};
        options.powerPreference = wgpu::PowerPreference::LowPower;

        MockCallback<WGPURequestAdapterCallback> cb;

        WGPUAdapter cAdapter = nullptr;
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
            .WillOnce(SaveArg<1>(&cAdapter));
        instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));

        wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
        EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
        if (integratedGPUAvailable) {
            wgpu::AdapterProperties properties;
            adapter.GetProperties(&properties);
            EXPECT_EQ(properties.adapterType, wgpu::AdapterType::IntegratedGPU);
        }
    }

}  // anonymous namespace
