// 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.

#ifndef DAWNNATIVE_VULKAN_UTILSVULKAN_H_
#define DAWNNATIVE_VULKAN_UTILSVULKAN_H_

#include "common/vulkan_platform.h"
#include "dawn_native/Commands.h"
#include "dawn_native/dawn_platform.h"

namespace dawn::native {
    struct ProgrammableStage;
    union OverridableConstantScalar;
}  // namespace dawn::native

namespace dawn::native::vulkan {

    class Device;

    // A Helper type used to build a pNext chain of extension structs.
    // Usage is:
    //   1) Create instance, passing the address of the first struct in the chain. This requires
    //      pNext to be nullptr. If you already have a chain you need to pass a pointer to the tail
    //      of it.
    //
    //   2) Call Add(&vk_struct) every time a new struct needs to be appended to the chain.
    //
    //   3) Alternatively, call Add(&vk_struct, VK_STRUCTURE_TYPE_XXX) to initialize the struct
    //      with a given VkStructureType value while appending it to the chain.
    //
    // Examples:
    //     VkPhysicalFeatures2 features2 = {
    //       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
    //       .pNext = nullptr,
    //     };
    //
    //     PNextChainBuilder featuresChain(&features2);
    //
    //     featuresChain.Add(&featuresExtensions.subgroupSizeControl,
    //                       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT);
    //
    struct PNextChainBuilder {
        // Constructor takes the address of a Vulkan structure instance, and
        // walks its pNext chain to record the current location of its tail.
        //
        // NOTE: Some VK_STRUCT_TYPEs define their pNext field as a const void*
        // which is why the VkBaseOutStructure* casts below are necessary.
        template <typename VK_STRUCT_TYPE>
        explicit PNextChainBuilder(VK_STRUCT_TYPE* head)
            : mCurrent(reinterpret_cast<VkBaseOutStructure*>(head)) {
            ASSERT(head->pNext == nullptr);
        }

        // Add one item to the chain. |vk_struct| must be a Vulkan structure
        // that is already initialized.
        template <typename VK_STRUCT_TYPE>
        void Add(VK_STRUCT_TYPE* vkStruct) {
            // Sanity checks to ensure proper type safety.
            static_assert(
                offsetof(VK_STRUCT_TYPE, sType) == offsetof(VkBaseOutStructure, sType) &&
                    offsetof(VK_STRUCT_TYPE, pNext) == offsetof(VkBaseOutStructure, pNext),
                "Argument type is not a proper Vulkan structure type");
            vkStruct->pNext = nullptr;

            mCurrent->pNext = reinterpret_cast<VkBaseOutStructure*>(vkStruct);
            mCurrent = mCurrent->pNext;
        }

        // A variant of Add() above that also initializes the |sType| field in |vk_struct|.
        template <typename VK_STRUCT_TYPE>
        void Add(VK_STRUCT_TYPE* vkStruct, VkStructureType sType) {
            vkStruct->sType = sType;
            Add(vkStruct);
        }

      private:
        VkBaseOutStructure* mCurrent;
    };

    VkCompareOp ToVulkanCompareOp(wgpu::CompareFunction op);

    VkImageAspectFlags VulkanAspectMask(const Aspect& aspects);

    Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy, const Extent3D& copySize);

    VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
                                                   const TextureCopy& textureCopy,
                                                   const Extent3D& copySize);
    VkBufferImageCopy ComputeBufferImageCopyRegion(const TextureDataLayout& dataLayout,
                                                   const TextureCopy& textureCopy,
                                                   const Extent3D& copySize);

    void SetDebugName(Device* device,
                      VkObjectType objectType,
                      uint64_t objectHandle,
                      const char* prefix,
                      std::string label = "");

    // Returns nullptr or &specializationInfo
    // specializationInfo, specializationDataEntries, specializationMapEntries needs to
    // be alive at least until VkSpecializationInfo is passed into Vulkan Create*Pipelines
    VkSpecializationInfo* GetVkSpecializationInfo(
        const ProgrammableStage& programmableStage,
        VkSpecializationInfo* specializationInfo,
        std::vector<OverridableConstantScalar>* specializationDataEntries,
        std::vector<VkSpecializationMapEntry>* specializationMapEntries);

}  // namespace dawn::native::vulkan

#endif  // DAWNNATIVE_VULKAN_UTILSVULKAN_H_
