improving architecture, adding logical device creation and destruction

This commit is contained in:
2025-11-04 13:02:47 +01:00
parent 0664c3e94b
commit 31c9234a99
13 changed files with 302 additions and 103 deletions

32
src/soft/Device.zig git.filemode.normal_file
View File

@@ -0,0 +1,32 @@
const std = @import("std");
const vk = @import("vulkan");
const Instance = @import("Instance.zig");
const base = @import("base");
const VkError = base.VkError;
const Self = @This();
pub const Interface = base.Device;
interface: Interface,
pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, infos: *const vk.DeviceCreateInfo) VkError!*Self {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(self);
var interface = try Interface.init(allocator, physical_device, infos);
interface.dispatch_table = &.{
.destroy = destroy,
};
self.* = .{
.interface = interface,
};
return self;
}
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self);
}

View File

@@ -1,30 +1,54 @@
const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const soft_physical_device = @import("physical_device.zig");
const PhysicalDevice = @import("PhysicalDevice.zig");
const Dispatchable = base.Dispatchable;
const VulkanAllocator = base.VulkanAllocator;
const VkError = base.VkError;
const Self = @This();
pub const Interface = base.Instance;
export fn __vkImplInstanceInit(base_instance: *base.Instance, allocator: *const std.mem.Allocator, infos: *const vk.InstanceCreateInfo) ?*anyopaque {
return realVkImplInstanceInit(base_instance, allocator.*, infos) catch return null;
interface: Interface,
export fn __vkImplCreateInstance(allocator: *const std.mem.Allocator, infos: *const vk.InstanceCreateInfo) ?*Interface {
return realVkImplInstanceInit(allocator.*, infos) catch return null;
}
// Pure Zig implementation to leverage `errdefer` and avoid memory leaks or complex resources handling
fn realVkImplInstanceInit(instance: *base.Instance, allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) !?*anyopaque {
_ = infos;
// Software driver only has one physical device (the CPU)
const physical_device = try Dispatchable(base.PhysicalDevice).create(allocator, .{instance});
errdefer physical_device.destroy(allocator);
try soft_physical_device.setup(allocator, physical_device.object);
try instance.physical_devices.append(allocator, physical_device.toVkHandle(vk.PhysicalDevice));
fn realVkImplInstanceInit(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) !?*Interface {
const self = try allocator.create(Self);
errdefer allocator.destroy(self);
return @ptrCast(self);
self.interface = try base.Instance.init(allocator, infos);
self.interface.dispatch_table = &.{
.requestPhysicalDevices = requestPhysicalDevices,
.releasePhysicalDevices = releasePhysicalDevices,
.destroyInstance = destroyInstance,
};
return &self.interface;
}
fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
// Software driver only has one physical device (the CPU)
const physical_device = try PhysicalDevice.create(allocator, interface);
errdefer physical_device.interface.releasePhysicalDevice(allocator) catch {};
interface.physical_devices.append(allocator, try Dispatchable(PhysicalDevice.Interface).wrap(allocator, &physical_device.interface)) catch return VkError.OutOfHostMemory;
}
fn releasePhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
defer {
interface.physical_devices.deinit(allocator);
interface.physical_devices = .empty;
}
const physical_device = interface.physical_devices.getLast();
try physical_device.object.releasePhysicalDevice(allocator);
physical_device.destroy(allocator);
}
fn destroyInstance(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self);
}

67
src/soft/PhysicalDevice.zig git.filemode.normal_file
View File

@@ -0,0 +1,67 @@
const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const root = @import("lib.zig");
const cpuinfo = @import("cpuinfo");
const Device = @import("Device.zig");
const Instance = @import("Instance.zig");
const VkError = base.VkError;
const Self = @This();
pub const Interface = base.PhysicalDevice;
interface: Interface,
pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkError!*Self {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(self);
var interface = try Interface.init(allocator, instance);
interface.dispatch_table = &.{
.createDevice = createDevice,
.release = destroy,
};
interface.props.api_version = @bitCast(root.VULKAN_VERSION);
interface.props.driver_version = @bitCast(root.DRIVER_VERSION);
interface.props.device_id = root.DEVICE_ID;
interface.props.device_type = .cpu;
interface.mem_props.memory_type_count = 1;
interface.mem_props.memory_types[0] = .{
.heap_index = 0,
.property_flags = .{
.host_visible_bit = true,
.host_coherent_bit = true,
},
};
interface.mem_props.memory_heap_count = 1;
interface.mem_props.memory_heaps[0] = .{
.size = std.process.totalSystemMemory() catch 0,
.flags = .{}, // Host memory
};
const info = cpuinfo.get(allocator) catch return VkError.InitializationFailed;
defer info.deinit(allocator);
var writer = std.io.Writer.fixed(interface.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
writer.print("{s} [Soft Vulkan Driver]", .{info.name}) catch return VkError.InitializationFailed;
self.* = .{
.interface = interface,
};
return self;
}
pub fn createDevice(interface: *Interface, allocator: std.mem.Allocator, infos: *const vk.DeviceCreateInfo) VkError!*Device.Interface {
const device = try Device.create(interface, allocator, infos);
return &device.interface;
}
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
allocator.destroy(self);
}

View File

@@ -2,12 +2,16 @@ const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const Device = @import("Device.zig");
const Instance = @import("Instance.zig");
const PhysicalDevice = @import("PhysicalDevice.zig");
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;
pub const std_options = base.std_options;
comptime {
_ = base;
_ = Instance;

View File

@@ -1,33 +0,0 @@
const std = @import("std");
const vk = @import("vulkan");
const Instance = @import("Instance.zig");
const base = @import("base");
const root = @import("lib.zig");
const cpuinfo = @import("cpuinfo");
pub fn setup(allocator: std.mem.Allocator, physical_device: *base.PhysicalDevice) !void {
physical_device.props.api_version = @bitCast(root.VULKAN_VERSION);
physical_device.props.driver_version = @bitCast(root.DRIVER_VERSION);
physical_device.props.device_id = root.DEVICE_ID;
physical_device.props.device_type = .cpu;
physical_device.mem_props.memory_type_count = 1;
physical_device.mem_props.memory_types[0] = .{
.heap_index = 0,
.property_flags = .{
.host_visible_bit = true,
.host_coherent_bit = true,
},
};
physical_device.mem_props.memory_heap_count = 1;
physical_device.mem_props.memory_heaps[0] = .{
.size = std.process.totalSystemMemory() catch 0,
.flags = .{}, // Host memory
};
const info = try cpuinfo.get(allocator);
defer info.deinit(allocator);
var writer = std.io.Writer.fixed(physical_device.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
try writer.print("{s} [Soft Vulkan Driver]", .{info.name});
}