package net.halbear.Terrain4J.EngineCore.Vulkan.Util;

import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.vma.VmaAllocatorCreateInfo;
import org.lwjgl.util.vma.VmaVulkanFunctions;

import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.util.vma.Vma.vmaCreateAllocator;
import static org.lwjgl.util.vma.Vma.vmaDestroyAllocator;
import static org.lwjgl.vulkan.VK13.VK_API_VERSION_1_3;

public class VulkanMemoryAllocator {
    private final long VmaAllocator;

    public VulkanMemoryAllocator(VulkanInstance Instance, PhysicalDevice physicalDevice, Device device){
        try(var MemStack = MemoryStack.stackPush()){
            PointerBuffer AllocatorPointer = MemStack.mallocPointer(1);
            var vmaVulkanFunctions = VmaVulkanFunctions.calloc(MemStack)
                    .set(Instance.getVkInstance(),device.FetchVulkanDevice());

            var AllocatorCreateInfo = VmaAllocatorCreateInfo.calloc(MemStack)
                    .instance(Instance.getVkInstance())
                    .vulkanApiVersion(VK_API_VERSION_1_3)
                    .device(device.FetchVulkanDevice())
                    .physicalDevice(physicalDevice.GetPhysicalDevice())
                    .pVulkanFunctions(vmaVulkanFunctions);
            vkCheck(vmaCreateAllocator(AllocatorCreateInfo,AllocatorPointer),"Failed to create Vulkan Memory Allocator");
            VmaAllocator = AllocatorPointer.get(0);
        }
    }
    public void CleanUp(){
        vmaDestroyAllocator(VmaAllocator);
    }
    public long GetVmaAllocator(){
        return VmaAllocator;
    }
}
