architectural rework

This commit is contained in:
2025-11-03 15:40:15 +01:00
parent a2948bd65d
commit 6b1d525e40
13 changed files with 281 additions and 121 deletions

View File

@@ -1,55 +1,40 @@
const std = @import("std");
const vk = @import("vulkan");
const common = @import("common");
const base = @import("base");
const PhysicalDevice = @import("PhysicalDevice.zig");
const dispatchable = common.dispatchable;
const dispatchable = base.dispatchable;
const VulkanAllocator = base.VulkanAllocator;
const Self = @This();
pub const ObjectType: vk.ObjectType = .instance;
common_instance: common.Instance,
physical_device: vk.PhysicalDevice, // Software driver only has one physical device (CPU)
export fn __vkImplInstanceInit(base_instance: *base.Instance, allocator: *const std.mem.Allocator) ?*anyopaque {
return realVkImplInstanceInit(base_instance, allocator.*) catch return null;
}
pub fn create(p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_instance: *vk.Instance) callconv(vk.vulkan_call_conv) vk.Result {
const allocator = std.heap.c_allocator;
const dispatchable_instance = dispatchable.Dispatchable(Self).create(allocator) catch return .error_out_of_host_memory;
const instance = dispatchable_instance.object;
common.Instance.init(&instance.common_instance, p_infos, callbacks) catch return .error_initialization_failed;
instance.common_instance.vtable = .{
.destroyInstance = destroy,
.enumeratePhysicalDevices = enumeratePhysicalDevices,
// Pure Zig implementation to leverage `errdefer` and avoid memory leaks or complex resources handling
fn realVkImplInstanceInit(base_instance: *base.Instance, allocator: std.mem.Allocator) !?*anyopaque {
base_instance.dispatch_table = .{
.destroyInstance = deinit,
.enumerateInstanceVersion = null,
//.enumerateInstanceLayerProperties = null,
.enumerateInstanceExtensionProperties = null,
.getPhysicalDeviceProperties = PhysicalDevice.getProperties,
};
const dispatchable_physical_device = dispatchable.Dispatchable(PhysicalDevice).create(allocator) catch return .error_out_of_host_memory;
PhysicalDevice.init(dispatchable_physical_device.object) catch return .error_initialization_failed;
instance.physical_device = @enumFromInt(dispatchable_physical_device.toHandle());
// Software driver only has one physical device (the CPU)
const dispatchable_physical_device = try PhysicalDevice.init(base_instance, allocator);
errdefer dispatchable_physical_device.destroy(allocator);
p_instance.* = @enumFromInt(dispatchable_instance.toHandle());
return .success;
try base_instance.physical_devices.append(allocator, @enumFromInt(dispatchable_physical_device.toHandle()));
const self = try allocator.create(Self);
errdefer allocator.destroy(self);
return @ptrCast(self);
}
pub fn enumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p_devices: ?[*]vk.PhysicalDevice) callconv(vk.vulkan_call_conv) vk.Result {
const instance = dispatchable.fromHandleObject(Self, @intFromEnum(p_instance)) catch return .error_initialization_failed;
count.* = 1;
if (p_devices) |devices| {
devices[0] = instance.physical_device;
pub fn deinit(base_instance: *const base.Instance, allocator: std.mem.Allocator) !void {
for (base_instance.physical_devices.items) |physical_device| {
const dispatchable_physical_device = try dispatchable.fromHandle(base.PhysicalDevice, @intFromEnum(physical_device));
dispatchable_physical_device.destroy(allocator);
}
return .success;
}
pub fn destroy(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
const allocator = std.heap.c_allocator;
_ = callbacks;
const dispatchable_instance = dispatchable.fromHandle(Self, @intFromEnum(p_instance)) catch return;
const dispatchable_physical_device = dispatchable.fromHandle(PhysicalDevice, @intFromEnum(dispatchable_instance.object.physical_device)) catch return;
dispatchable_physical_device.destroy(allocator);
dispatchable_instance.destroy(allocator);
}

View File

@@ -1,41 +1,30 @@
const std = @import("std");
const vk = @import("vulkan");
const Instance = @import("Instance.zig");
const common = @import("common");
const base = @import("base");
const root = @import("root");
const cpuinfo = @import("cpuinfo");
const dispatchable = common.dispatchable;
const dispatchable = base.dispatchable;
const Self = @This();
pub const ObjectType: vk.ObjectType = .physical_device;
instance: *const Instance,
common_physical_device: common.PhysicalDevice,
pub fn init(instance: *const base.Instance, allocator: std.mem.Allocator) !*dispatchable.Dispatchable(base.PhysicalDevice) {
const dispatchable_physical_device = try base.PhysicalDevice.init(instance, allocator);
errdefer dispatchable_physical_device.destroy(allocator);
pub fn init(self: *Self) !void {
const allocator = std.heap.c_allocator;
const base_physical_device = dispatchable_physical_device.object;
self.common_physical_device.props = .{
.api_version = @bitCast(root.VULKAN_VERSION),
.driver_version = @bitCast(root.DRIVER_VERSION),
.vendor_id = common.VULKAN_VENDOR_ID,
.device_id = root.DEVICE_ID,
.device_type = .cpu,
.device_name = [_]u8{0} ** vk.MAX_PHYSICAL_DEVICE_NAME_SIZE,
.pipeline_cache_uuid = undefined,
.limits = undefined,
.sparse_properties = undefined,
};
base_physical_device.props.api_version = @bitCast(root.VULKAN_VERSION);
base_physical_device.props.driver_version = @bitCast(root.DRIVER_VERSION);
base_physical_device.props.device_id = root.DEVICE_ID;
base_physical_device.props.device_type = .cpu;
const info = try cpuinfo.get(allocator);
defer info.deinit(allocator);
var writer = std.io.Writer.fixed(self.common_physical_device.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
var writer = std.io.Writer.fixed(base_physical_device.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
try writer.print("{s} [Soft Vulkan Driver]", .{info.name});
}
pub fn getProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceProperties) callconv(vk.vulkan_call_conv) void {
const physical_device = dispatchable.fromHandleObject(Self, @intFromEnum(p_physical_device)) catch return;
properties.* = physical_device.common_physical_device.props;
return dispatchable_physical_device;
}

View File

@@ -1,6 +1,6 @@
const std = @import("std");
const vk = @import("vulkan");
const common = @import("common");
const base = @import("base");
const Instance = @import("Instance.zig");
@@ -8,15 +8,7 @@ pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
pub const DEVICE_ID = 0x600DCAFE;
const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
.{ "vkGetInstanceProcAddr", @as(vk.PfnVoidFunction, @ptrCast(&common.icd.getInstanceProcAddr)) },
.{ "vkCreateInstance", @as(vk.PfnVoidFunction, @ptrCast(&Instance.create)) },
});
pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, pName: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction {
if (pName == null) {
return null;
}
const name = std.mem.span(pName.?);
return common.icd.getInstanceProcAddr(global_pfn_map, p_instance, name);
comptime {
_ = base;
_ = Instance;
}