adding queues and debug allocators
This commit is contained in:
@@ -13,10 +13,16 @@ const Self = @This();
|
||||
pub const ObjectType: vk.ObjectType = .device;
|
||||
|
||||
physical_device: *const PhysicalDevice,
|
||||
dispatch_table: *const DispatchTable,
|
||||
host_allocator: VulkanAllocator,
|
||||
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(*Dispatchable(Queue))),
|
||||
|
||||
dispatch_table: *const DispatchTable,
|
||||
vtable: *const VTable,
|
||||
|
||||
pub const VTable = struct {
|
||||
createQueue: *const fn (std.mem.Allocator, *const Self, u32, u32, vk.DeviceQueueCreateFlags) VkError!*Queue,
|
||||
destroyQueue: *const fn (*Queue, std.mem.Allocator) VkError!void,
|
||||
};
|
||||
|
||||
pub const DispatchTable = struct {
|
||||
allocateMemory: *const fn (*Self, std.mem.Allocator, *const vk.MemoryAllocateInfo) VkError!*DeviceMemory,
|
||||
createFence: *const fn (*Self, std.mem.Allocator, *const vk.FenceCreateInfo) VkError!*Fence,
|
||||
@@ -29,15 +35,14 @@ pub const DispatchTable = struct {
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
|
||||
const vulkan_allocator: *VulkanAllocator = @ptrCast(@alignCast(allocator.ptr));
|
||||
var self: Self = .{
|
||||
_ = allocator;
|
||||
_ = info;
|
||||
return .{
|
||||
.physical_device = physical_device,
|
||||
.dispatch_table = undefined,
|
||||
.host_allocator = vulkan_allocator.*,
|
||||
.queues = .empty,
|
||||
.dispatch_table = undefined,
|
||||
.vtable = undefined,
|
||||
};
|
||||
try self.createQueues(allocator, info);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!void {
|
||||
@@ -46,22 +51,31 @@ pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.D
|
||||
} else if (info.p_queue_create_infos == null) {
|
||||
return VkError.ValidationFailed;
|
||||
}
|
||||
var family_sizes: std.AutoHashMap(u32, usize) = .empty;
|
||||
defer family_sizes.deinit(allocator);
|
||||
|
||||
for (0..info.queue_create_info_count) |i| {
|
||||
const queue_info = info.p_queue_create_infos.?[i];
|
||||
const value = family_sizes.getOrPut(allocator, queue_info.queue_family_index) catch return VkError.OutOfHostMemory;
|
||||
value.value_ptr.* += @intCast(queue_info.queue_count);
|
||||
}
|
||||
const res = (self.queues.getOrPut(allocator, queue_info.queue_family_index) catch return VkError.OutOfHostMemory);
|
||||
const family_ptr = res.value_ptr;
|
||||
if (!res.found_existing) {
|
||||
family_ptr.* = .empty;
|
||||
}
|
||||
|
||||
var it = family_sizes.iterator();
|
||||
while (it.next()) |entry| {
|
||||
self.queues.put(allocator, entry.key_ptr.*, std.ArrayListUnmanaged(*Dispatchable(Queue)).initCapacity(allocator, entry.value_ptr.*)) catch return VkError.OutOfHostMemory;
|
||||
const queue = try self.vtable.createQueue(allocator, self, queue_info.queue_family_index, @intCast(family_ptr.items.len), queue_info.flags);
|
||||
const dispatchable_queue = try Dispatchable(Queue).wrap(allocator, queue);
|
||||
family_ptr.append(allocator, dispatchable_queue) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||
var it = self.queues.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const family = entry.value_ptr;
|
||||
for (family.items) |dispatchable_queue| {
|
||||
try self.vtable.destroyQueue(dispatchable_queue.object, allocator);
|
||||
dispatchable_queue.destroy(allocator);
|
||||
}
|
||||
family.deinit(allocator);
|
||||
}
|
||||
self.queues.deinit(allocator);
|
||||
try self.dispatch_table.destroy(self, allocator);
|
||||
}
|
||||
|
||||
@@ -20,11 +20,15 @@ pub const ObjectType: vk.ObjectType = .instance;
|
||||
|
||||
physical_devices: std.ArrayListUnmanaged(*Dispatchable(PhysicalDevice)),
|
||||
dispatch_table: *const DispatchTable,
|
||||
vtable: *const VTable,
|
||||
|
||||
pub const VTable = struct {
|
||||
releasePhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||
requestPhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||
};
|
||||
|
||||
pub const DispatchTable = struct {
|
||||
destroyInstance: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||
releasePhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||
requestPhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!Self {
|
||||
@@ -33,11 +37,12 @@ pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) V
|
||||
return .{
|
||||
.physical_devices = .empty,
|
||||
.dispatch_table = undefined,
|
||||
.vtable = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||
try self.dispatch_table.releasePhysicalDevices(self, allocator);
|
||||
try self.releasePhysicalDevices(allocator);
|
||||
try self.dispatch_table.destroyInstance(self, allocator);
|
||||
}
|
||||
|
||||
@@ -61,11 +66,11 @@ pub fn enumerateVersion(version: *u32) VkError!void {
|
||||
}
|
||||
|
||||
pub fn releasePhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||
try self.dispatch_table.releasePhysicalDevices(self, allocator);
|
||||
try self.vtable.releasePhysicalDevices(self, allocator);
|
||||
}
|
||||
|
||||
pub fn requestPhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||
try self.dispatch_table.requestPhysicalDevices(self, allocator);
|
||||
try self.vtable.requestPhysicalDevices(self, allocator);
|
||||
if (self.physical_devices.items.len == 0) {
|
||||
std.log.scoped(.vkCreateInstance).info("No VkPhysicalDevice found", .{});
|
||||
return;
|
||||
|
||||
@@ -22,6 +22,7 @@ pub const DispatchTable = struct {
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, device: *const Device, index: u32, family_index: u32, flags: vk.DeviceQueueCreateFlags) VkError!Self {
|
||||
std.log.scoped(.vkCreateDevice).info("Creating device queue with family index {d} and index {d}", .{ family_index, index });
|
||||
_ = allocator;
|
||||
return .{
|
||||
.owner = device,
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const builtin = @import("builtin");
|
||||
const DRIVER_DEBUG_ALLOCATOR_ENV_NAME = @import("lib.zig").DRIVER_DEBUG_ALLOCATOR_ENV_NAME;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Alignment = std.mem.Alignment;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
|
||||
|
||||
callbacks: ?vk.AllocationCallbacks,
|
||||
scope: vk.SystemAllocationScope,
|
||||
|
||||
@@ -21,22 +25,22 @@ pub fn init(callbacks: ?*const vk.AllocationCallbacks, scope: vk.SystemAllocatio
|
||||
}
|
||||
|
||||
pub fn allocator(self: *const Self) Allocator {
|
||||
if (self.callbacks == null) {
|
||||
if (self.callbacks != null) {
|
||||
return .{
|
||||
.ptr = @constCast(self),
|
||||
.vtable = std.heap.c_allocator.vtable,
|
||||
.vtable = &.{
|
||||
.alloc = alloc,
|
||||
.resize = resize,
|
||||
.remap = remap,
|
||||
.free = free,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return .{
|
||||
.ptr = @constCast(self),
|
||||
.vtable = &.{
|
||||
.alloc = alloc,
|
||||
.resize = resize,
|
||||
.remap = remap,
|
||||
.free = free,
|
||||
},
|
||||
};
|
||||
return if (std.process.hasEnvVarConstant(DRIVER_DEBUG_ALLOCATOR_ENV_NAME) or builtin.mode == std.builtin.OptimizeMode.Debug)
|
||||
debug_allocator.allocator()
|
||||
else
|
||||
std.heap.c_allocator;
|
||||
}
|
||||
|
||||
fn alloc(context: *anyopaque, len: usize, alignment: Alignment, _: usize) ?[*]u8 {
|
||||
|
||||
@@ -18,7 +18,9 @@ pub const DeviceMemory = @import("DeviceMemory.zig");
|
||||
pub const Fence = @import("Fence.zig");
|
||||
|
||||
pub const VULKAN_VENDOR_ID = @typeInfo(vk.VendorId).@"enum".fields[@typeInfo(vk.VendorId).@"enum".fields.len - 1].value + 1;
|
||||
|
||||
pub const DRIVER_LOGS_ENV_NAME = "STROLL_LOGS_LEVEL";
|
||||
pub const DRIVER_DEBUG_ALLOCATOR_ENV_NAME = "STROLL_DEBUG_ALLOCATOR";
|
||||
|
||||
pub const std_options: std.Options = .{
|
||||
.log_level = .debug,
|
||||
|
||||
@@ -75,6 +75,7 @@ const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
||||
functionMapEntryPoint("vkDestroyDevice"),
|
||||
functionMapEntryPoint("vkCreateFence"),
|
||||
functionMapEntryPoint("vkFreeMemory"),
|
||||
functionMapEntryPoint("vkGetDeviceQueue"),
|
||||
functionMapEntryPoint("vkGetFenceStatus"),
|
||||
functionMapEntryPoint("vkMapMemory"),
|
||||
functionMapEntryPoint("vkUnmapMemory"),
|
||||
@@ -173,6 +174,13 @@ pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const
|
||||
const dispatchable = Dispatchable(Instance).fromHandle(p_instance) catch return;
|
||||
dispatchable.object.deinit(allocator) catch {};
|
||||
dispatchable.destroy(allocator);
|
||||
|
||||
if (std.process.hasEnvVarConstant(lib.DRIVER_DEBUG_ALLOCATOR_ENV_NAME) or builtin.mode == std.builtin.OptimizeMode.Debug) {
|
||||
// All host memory allocations should've been freed by now
|
||||
if (!VulkanAllocator.debug_allocator.detectLeaks()) {
|
||||
std.log.scoped(.vkDestroyInstance).debug("No memory leaks detected", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub export fn strollEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p_devices: ?[*]vk.PhysicalDevice) callconv(vk.vulkan_call_conv) vk.Result {
|
||||
@@ -330,6 +338,22 @@ pub export fn strollGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u
|
||||
return null;
|
||||
}
|
||||
|
||||
pub export fn strollGetDeviceQueue(p_device: vk.Device, queue_family_index: u32, queue_index: u32, p_queue: *vk.Queue) callconv(vk.vulkan_call_conv) void {
|
||||
p_queue.* = .null_handle;
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
||||
if (device.queues.get(queue_family_index)) |family| {
|
||||
if (queue_index >= family.items.len) return;
|
||||
|
||||
const dispatchable_queue = family.items[queue_index];
|
||||
const queue = dispatchable_queue.object;
|
||||
|
||||
// https://docs.vulkan.org/refpages/latest/refpages/source/vkGetDeviceQueue.html#VUID-vkGetDeviceQueue-flags-01841
|
||||
if (queue.flags != @TypeOf(queue.flags){}) return;
|
||||
|
||||
p_queue.* = dispatchable_queue.toVkHandle(vk.Queue);
|
||||
}
|
||||
}
|
||||
|
||||
pub export fn strollGetFenceStatus(p_device: vk.Device, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result {
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||
const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
|
||||
|
||||
@@ -45,10 +45,9 @@ pub fn log(comptime level: std.log.Level, comptime scope: @Type(.enum_literal),
|
||||
const prefix = std.fmt.comptimePrint("{s: <8}", .{"[" ++ comptime level.asText() ++ "] "});
|
||||
|
||||
const level_color: std.Io.tty.Color = switch (level) {
|
||||
.info => .blue,
|
||||
.info, .debug => .blue,
|
||||
.warn => .yellow,
|
||||
.err => .red,
|
||||
.debug => .blue,
|
||||
};
|
||||
|
||||
std.debug.lockStdErr();
|
||||
|
||||
Reference in New Issue
Block a user