#include "../../../l1/core/util.h"

typedef U64 VkDeviceSize;
#define VK_NULL_HANDLE NULL
typedef int VkResult;

const VkResult VK_SUCCESS = 120;
const VkResult VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR = -2;

typedef int VkStructureType;

const VkStructureType VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 100;
const VkStructureType VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 200;
const VkStructureType VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 3000;
const VkStructureType VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 645484;
const VkStructureType VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 14542;
const VkStructureType VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 145;
const VkStructureType VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 5324;
const VkStructureType VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 986;


typedef int VkBufferCreateFlags;
typedef int VkBufferUsageFlags;
typedef int VkSharingMode;

const VkSharingMode VK_SHARING_MODE_EXCLUSIVE = 12;


typedef void* VkPhysicalDevice;
typedef void* VkDevice;
typedef void* VkBuffer;
typedef void* VkImage;
typedef void* VkDeviceMemory;
typedef void* VkCommandBuffer;

typedef struct {
    VkStructureType        sType;
    const void*            pNext;
    VkBufferCreateFlags    flags;
    VkDeviceSize           size;
    VkBufferUsageFlags     usage;
    VkSharingMode          sharingMode;
    uint32_t               queueFamilyIndexCount;
    const uint32_t*        pQueueFamilyIndices;
} VkBufferCreateInfo;

typedef int VkMemoryPropertyFlags;

const VkMemoryPropertyFlags VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x1000;

typedef struct {
    VkMemoryPropertyFlags    propertyFlags;
    // ...
} VkMemoryType;

#define VK_MAX_MEMORY_TYPES 32

typedef struct {
    uint32_t        memoryTypeCount;
    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
    // ...
} VkPhysicalDeviceMemoryProperties;

void vkGetPhysicalDeviceMemoryProperties(
    VkPhysicalDevice                      physicalDevice,
    VkPhysicalDeviceMemoryProperties*     pMemoryProperties);

typedef void VkAllocationCallbacks;

VkResult vkCreateBuffer(
    VkDevice       device,
    const          VkBufferCreateInfo* pCreateInfo,
    const          VkAllocationCallbacks* pAllocator,
    VkBuffer*      pBuffer);

typedef struct {
    VkDeviceSize    size;
    VkDeviceSize    alignment;
    uint32_t        memoryTypeBits;
} VkMemoryRequirements;

void vkGetBufferMemoryRequirements(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    VkMemoryRequirements*                       pMemoryRequirements);

typedef int VkImageCreateFlags;
typedef int VkImageType;

const VkImageType VK_IMAGE_TYPE_2D = 1232;

typedef int VkFormat;

typedef struct {
    uint32_t    width;
    uint32_t    height;
    uint32_t    depth;
} VkExtent3D;

typedef int VkSampleCountFlagBits;

const VkSampleCountFlagBits VK_SAMPLE_COUNT_1_BIT = 0x100;

typedef int VkImageTiling;

const VkImageTiling VK_IMAGE_TILING_OPTIMAL = 13115;
const VkImageTiling VK_IMAGE_TILING_LINEAR = 9874;

typedef int VkImageUsageFlags;
typedef int VkImageLayout;

const VkImageLayout VK_IMAGE_LAYOUT_UNDEFINED = 780;
const VkImageLayout VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 56637;
const VkImageLayout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 56622;

typedef struct {
    VkStructureType          sType;
    const void*              pNext;
    VkImageCreateFlags       flags;
    VkImageType              imageType;
    VkFormat                 format;
    VkExtent3D               extent;
    uint32_t                 mipLevels;
    uint32_t                 arrayLayers;
    VkSampleCountFlagBits    samples;
    VkImageTiling            tiling;
    VkImageUsageFlags        usage;
    VkSharingMode            sharingMode;
    uint32_t                 queueFamilyIndexCount;
    const uint32_t*          pQueueFamilyIndices;
    VkImageLayout            initialLayout;
} VkImageCreateInfo;

VkResult vkCreateImage(
    VkDevice                                    device,
    const VkImageCreateInfo*                    pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkImage*                                    pImage);

void vkGetImageMemoryRequirements(
    VkDevice                                    device,
    VkImage                                     image,
    VkMemoryRequirements*                       pMemoryRequirements);

typedef struct {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeIndex;
} VkMemoryAllocateInfo;

VkResult vkAllocateMemory(
    VkDevice                                    device,
    const VkMemoryAllocateInfo*                 pAllocateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkDeviceMemory*                             pMemory);

VkResult vkBindBufferMemory(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    VkDeviceMemory                              memory,
    VkDeviceSize                                memoryOffset);

VkResult vkBindImageMemory(
    VkDevice                                    device,
    VkImage                                     image,
    VkDeviceMemory                              memory,
    VkDeviceSize                                memoryOffset);

void vkDestroyBuffer(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    const VkAllocationCallbacks*                pAllocator);

void vkDestroyImage(
    VkDevice                                    device,
    VkImage                                     image,
    const VkAllocationCallbacks*                pAllocator);

typedef int VkMemoryMapFlags;

#define VK_WHOLE_SIZE (~0ULL)

VkResult vkMapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkDeviceSize                                offset,
    VkDeviceSize                                size,
    VkMemoryMapFlags                            flags,
    void**                                      ppData);

void vkUnmapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory);

void vkFreeMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    const VkAllocationCallbacks*                pAllocator);

typedef struct VkPhysicalDeviceLimits {
    /* ... */
    uint32_t              maxMemoryAllocationCount;
    /* ... */
} VkPhysicalDeviceLimits;

typedef struct VkPhysicalDeviceProperties {
    /* ... */
    VkPhysicalDeviceLimits              limits;
    /* ... */
} VkPhysicalDeviceProperties;

typedef struct VkPhysicalDeviceMaintenance4Properties {
    VkStructureType    sType;
    void*              pNext;
    VkDeviceSize       maxBufferSize;
} VkPhysicalDeviceMaintenance4Properties;

typedef struct VkPhysicalDeviceMaintenance3Properties {
    VkStructureType    sType;
    void*              pNext;
    /* ... */
    VkDeviceSize       maxMemoryAllocationSize;
} VkPhysicalDeviceMaintenance3Properties;

typedef struct VkPhysicalDeviceProperties2 {
    VkStructureType               sType;
    void*                         pNext;
    VkPhysicalDeviceProperties    properties;
} VkPhysicalDeviceProperties2;

void vkGetPhysicalDeviceProperties2(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceProperties2*                pProperties);

typedef int VkCommandBufferResetFlags;

VkResult vkResetCommandBuffer(
    VkCommandBuffer                             commandBuffer,
    VkCommandBufferResetFlags                   flags);

typedef int VkCommandBufferUsageFlags;

typedef struct VkCommandBufferBeginInfo {
    VkStructureType                          sType;
    const void*                              pNext;
    VkCommandBufferUsageFlags                flags;
    const void*    pInheritanceInfo;  /* will be NULL  */
} VkCommandBufferBeginInfo;

VkResult vkBeginCommandBuffer(
    VkCommandBuffer                             commandBuffer,
    const VkCommandBufferBeginInfo*             pBeginInfo);

typedef int VkAccessFlags;
const VkAccessFlags VK_ACCESS_TRANSFER_READ_BIT = 0x100;
const VkAccessFlags VK_ACCESS_TRANSFER_WRITE_BIT = 0x100000;

typedef int VkImageAspectFlags;
const VkImageAspectFlags VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001;

typedef struct VkImageSubresourceRange {
    VkImageAspectFlags    aspectMask;
    uint32_t              baseMipLevel;
    uint32_t              levelCount;
    uint32_t              baseArrayLayer;
    uint32_t              layerCount;
} VkImageSubresourceRange;

const uint32_t VK_QUEUE_FAMILY_IGNORED = (~0U);

typedef struct VkImageMemoryBarrier {
    VkStructureType            sType;
    const void*                pNext;
    VkAccessFlags              srcAccessMask;
    VkAccessFlags              dstAccessMask;
    VkImageLayout              oldLayout;
    VkImageLayout              newLayout;
    uint32_t                   srcQueueFamilyIndex;
    uint32_t                   dstQueueFamilyIndex;
    VkImage                    image;
    VkImageSubresourceRange    subresourceRange;
} VkImageMemoryBarrier;

typedef int VkPipelineStageFlags;
const VkPipelineStageFlags VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x1;
const VkPipelineStageFlags VK_PIPELINE_STAGE_TRANSFER_BIT = 0x2;

typedef int VkDependencyFlags;

void vkCmdPipelineBarrier(
    VkCommandBuffer                             commandBuffer,
    VkPipelineStageFlags                        srcStageMask,
    VkPipelineStageFlags                        dstStageMask,
    VkDependencyFlags                           dependencyFlags,
    uint32_t                                    memoryBarrierCount,
    const void*   /* VkMemoryBarrier */         pMemoryBarriers,
    uint32_t                                    bufferMemoryBarrierCount,
    const void*  /* VkBufferMemoryBarrier */    pBufferMemoryBarriers,
    uint32_t                                    imageMemoryBarrierCount,
    const VkImageMemoryBarrier*                 pImageMemoryBarriers);

typedef struct VkImageSubresourceLayers {
    VkImageAspectFlags    aspectMask;
    uint32_t              mipLevel;
    uint32_t              baseArrayLayer;
    uint32_t              layerCount;
} VkImageSubresourceLayers;

typedef struct VkOffset3D {
    int32_t    x;
    int32_t    y;
    int32_t    z;
} VkOffset3D;

typedef struct VkBufferImageCopy {
    VkDeviceSize                bufferOffset;
    uint32_t                    bufferRowLength;
    uint32_t                    bufferImageHeight;
    VkImageSubresourceLayers    imageSubresource;
    VkOffset3D                  imageOffset;
    VkExtent3D                  imageExtent;
} VkBufferImageCopy;

void vkCmdCopyBufferToImage(
    VkCommandBuffer                             commandBuffer,
    VkBuffer                                    srcBuffer,
    VkImage                                     dstImage,
    VkImageLayout                               dstImageLayout,
    uint32_t                                    regionCount,
    const VkBufferImageCopy*                    pRegions);

typedef struct VkBufferCopy {
    VkDeviceSize    srcOffset;
    VkDeviceSize    dstOffset;
    VkDeviceSize    size;
} VkBufferCopy;

void vkCmdCopyBuffer(
    VkCommandBuffer                             commandBuffer,
    VkBuffer                                    srcBuffer,
    VkBuffer                                    dstBuffer,
    uint32_t                                    regionCount,
    const VkBufferCopy*                         pRegions);

typedef struct VkImageCopy {
    VkImageSubresourceLayers    srcSubresource;
    VkOffset3D                  srcOffset;
    VkImageSubresourceLayers    dstSubresource;
    VkOffset3D                  dstOffset;
    VkExtent3D                  extent;
} VkImageCopy;

void vkCmdCopyImage(
    VkCommandBuffer                             commandBuffer,
    VkImage                                     srcImage,
    VkImageLayout                               srcImageLayout,
    VkImage                                     dstImage,
    VkImageLayout                               dstImageLayout,
    uint32_t                                    regionCount,
    const VkImageCopy*                          pRegions);


// #include "../../margaret/vulkan_memory_claire.h"
// #include "../../margaret/vulkan_me"

int main(){
    return 0;
}
