// todo look into Vulkan Memory Allocator

const std = @import("std");
const vk = @import("vk");
const au = @import("../au.zig");

const Self = @This();

props: vk.PhysicalDeviceMemoryProperties,

pub fn init() Self {
    return .{
        .props = au.I.getPhysicalDeviceMemoryProperties(au.device_config.pdev),
    };
}

pub fn heaps(self: Self) []const vk.MemoryHeap {
    return self.props.memory_heaps[0..self.props.memory_heap_count];
}

pub fn types(self: Self) []const vk.MemoryType {
    return self.props.memory_types[0..self.props.memory_type_count];
}

pub fn alloc(self: Self, reqs: vk.MemoryRequirements, flags: vk.MemoryPropertyFlags) !vk.DeviceMemory {
    const memory_type_bits: std.bit_set.IntegerBitSet(vk.MAX_MEMORY_TYPES) = .{
        .mask = reqs.memory_type_bits,
    };

    for (self.types(), 0..) |typ, idx| {
        if (!memory_type_bits.isSet(idx)) continue;
        if (!typ.property_flags.contains(flags)) continue;

        return try au.D.allocateMemory(&.{
            .allocation_size = reqs.size,
            .memory_type_index = @intCast(idx),
        }, null);
    }

    return error.NoSuitableMemoryType;
}

pub fn free(_: Self, memory: vk.DeviceMemory) void {
    au.D.freeMemory(memory, null);
}
