//
// Notice Regarding Standards.  AMD does not provide a license or sublicense to
// any Intellectual Property Rights relating to any standards, including but not
// limited to any audio and/or video codec technologies such as MPEG-2, MPEG-4;
// AVC/H.264; HEVC/H.265; AAC decode/FFMPEG; AAC encode/FFMPEG; VC-1; and MP3
// (collectively, the "Media Technologies"). For clarity, you will pay any
// royalties due for such third party technologies, which may include the Media
// Technologies that are owed as a result of AMD providing the Software to you.
//
// MIT license
//
// Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#ifndef __VulkanAMF_h__
#define __VulkanAMF_h__
#pragma once
#include "Platform.h"

#include "vulkan/vulkan.h"

#if defined(__cplusplus)
namespace amf
{
#endif
    typedef enum AMF_VULKAN_EXTENSION_TYPE
    {
        AMF_VULKAN_EXTENSION_UNKNOWN    = 0,
        AMF_VARIANT_TIMELINE_SEMAPHORE  = 1,
    } AMF_VULKAN_EXTENSION_TYPE;

    typedef struct AMFVulkanDevice
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanDevice)
        void*               pNext;              // reserved for extensions
        VkInstance          hInstance;
        VkPhysicalDevice    hPhysicalDevice;
        VkDevice            hDevice;
    } AMFVulkanDevice;

    typedef struct AMFVulkanSync
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanSync)
        void*               pNext;              // reserved for extensions
        VkSemaphore         hSemaphore;         // VkSemaphore; can be nullptr
        amf_bool            bSubmitted;         // if true - wait for hSemaphore. re-submit hSemaphore if not synced by other ways and set to true, ignored if timeline
        VkFence             hFence;             // To sync on CPU; can be nullptr. Submitted in vkQueueSubmit. If waited for hFence, null it, do not delete or reset.
    } AMFVulkanSync;

    typedef struct AMFVulkanTimeline // can be attached to AMFVulkanSync::pNext
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanTimeline)
        AMF_VULKAN_EXTENSION_TYPE eExtensionType;// identifies extensions to make extension chains in the future AMF_VARIANT_TIMELINE_SEMAPHORE
        void*               pNext;              // reserved for extensions
        amf_uint64          uiCount;             // count for timeline semaphores
    } AMFVulkanTimeline;

        typedef struct AMFVulkanBuffer
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanBuffer)
        void*               pNext;              // reserved for extensions
        VkBuffer            hBuffer;
        VkDeviceMemory      hMemory;
        amf_int64           iSize;
        amf_int64           iAllocatedSize;     // for reuse
        amf_uint32          eAccessFlags;       // VkAccessFlagBits
        amf_uint32          eUsage;             // AMF_BUFFER_USAGE
        amf_uint32          eAccess;            // AMF_MEMORY_CPU_ACCESS
        AMFVulkanSync       Sync;
    } AMFVulkanBuffer;

    typedef struct AMFVulkanSurface
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanSurface)
        void*               pNext;              // reserved for extensions
        // surface properties
        VkImage             hImage;             // vulkan native image for which the surface is created
        VkDeviceMemory      hMemory;            // memory for hImage, can be nullptr
        amf_int64           iSize;              // memory size
        amf_uint32          eFormat;            // VkFormat
        amf_int32           iWidth;             // image width
        amf_int32           iHeight;            // image height
        amf_uint32          eCurrentLayout;     // VkImageLayout
        amf_uint32          eUsage;             // AMF_SURFACE_USAGE
        amf_uint32          eAccess;            // AMF_MEMORY_CPU_ACCESS
        AMFVulkanSync       Sync;               // To sync on GPU
    } AMFVulkanSurface;

    typedef struct AMFVulkanSurface1
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanSurface)
        void*               pNext;              // reserved for extensions
        // surface properties
        amf_uint32          eTiling;            // VkImageTiling
    } AMFVulkanSurface1;

    typedef struct AMFVulkanView
    {
        amf_size            cbSizeof;           // sizeof(AMFVulkanView)
        void*               pNext;              // reserved for extensions
        // surface properties
        AMFVulkanSurface    *pSurface;
        VkImageView         hView;
        amf_int32           iPlaneWidth;
        amf_int32           iPlaneHeight;
        amf_int32           iPlaneWidthPitch;
        amf_int32           iPlaneHeightPitch;
    } AMFVulkanView;

#define AMF_CONTEXT_VULKAN_COMPUTE_QUEUE  L"VulkanComputeQueue" // amf_int64; default=0; Compute queue index in range [0, (VkQueueFamilyProperties.queueCount-1)] of the compute queue family.
#define AMF_CONTEXT_VULKAN_USE_TIMELINE_SEMAPHORES  L"VulkanTimelineSemaphores" //  amf_bool; default=false; Use timeline semaphores in Vulkan

#if defined(__cplusplus)
} // namespace amf
#endif
#endif // __VulkanAMF_h__
