// Copyright 2020 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_native/vulkan/QuerySetVk.h"

#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
#include "dawn_platform/DawnPlatform.h"

namespace dawn::native::vulkan {

    namespace {
        VkQueryType VulkanQueryType(wgpu::QueryType type) {
            switch (type) {
                case wgpu::QueryType::Occlusion:
                    return VK_QUERY_TYPE_OCCLUSION;
                case wgpu::QueryType::PipelineStatistics:
                    return VK_QUERY_TYPE_PIPELINE_STATISTICS;
                case wgpu::QueryType::Timestamp:
                    return VK_QUERY_TYPE_TIMESTAMP;
            }
            UNREACHABLE();
        }

        VkQueryPipelineStatisticFlags VulkanQueryPipelineStatisticFlags(
            std::vector<wgpu::PipelineStatisticName> pipelineStatisticsSet) {
            VkQueryPipelineStatisticFlags pipelineStatistics = 0;
            for (size_t i = 0; i < pipelineStatisticsSet.size(); ++i) {
                switch (pipelineStatisticsSet[i]) {
                    case wgpu::PipelineStatisticName::ClipperInvocations:
                        pipelineStatistics |= VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT;
                        break;
                    case wgpu::PipelineStatisticName::ClipperPrimitivesOut:
                        pipelineStatistics |= VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT;
                        break;
                    case wgpu::PipelineStatisticName::ComputeShaderInvocations:
                        pipelineStatistics |=
                            VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
                        break;
                    case wgpu::PipelineStatisticName::FragmentShaderInvocations:
                        pipelineStatistics |=
                            VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
                        break;
                    case wgpu::PipelineStatisticName::VertexShaderInvocations:
                        pipelineStatistics |=
                            VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT;
                        break;
                }
            }

            return pipelineStatistics;
        }
    }  // anonymous namespace

    // static
    ResultOrError<Ref<QuerySet>> QuerySet::Create(Device* device,
                                                  const QuerySetDescriptor* descriptor) {
        Ref<QuerySet> queryset = AcquireRef(new QuerySet(device, descriptor));
        DAWN_TRY(queryset->Initialize());
        return queryset;
    }

    MaybeError QuerySet::Initialize() {
        VkQueryPoolCreateInfo createInfo;
        createInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
        createInfo.pNext = NULL;
        createInfo.flags = 0;
        createInfo.queryType = VulkanQueryType(GetQueryType());
        createInfo.queryCount = std::max(GetQueryCount(), uint32_t(1u));
        if (GetQueryType() == wgpu::QueryType::PipelineStatistics) {
            createInfo.pipelineStatistics =
                VulkanQueryPipelineStatisticFlags(GetPipelineStatistics());
        }

        Device* device = ToBackend(GetDevice());
        DAWN_TRY(CheckVkOOMThenSuccess(
            device->fn.CreateQueryPool(device->GetVkDevice(), &createInfo, nullptr, &*mHandle),
            "vkCreateQueryPool"));

        SetLabelImpl();

        return {};
    }

    VkQueryPool QuerySet::GetHandle() const {
        return mHandle;
    }

    QuerySet::~QuerySet() = default;

    void QuerySet::DestroyImpl() {
        QuerySetBase::DestroyImpl();
        if (mHandle != VK_NULL_HANDLE) {
            ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
            mHandle = VK_NULL_HANDLE;
        }
    }

    void QuerySet::SetLabelImpl() {
        SetDebugName(ToBackend(GetDevice()), VK_OBJECT_TYPE_QUERY_POOL,
                     reinterpret_cast<uint64_t&>(mHandle), "Dawn_QuerySet", GetLabel());
    }

}  // namespace dawn::native::vulkan
