improving architecture, adding logical device creation and destruction
This commit is contained in:
32
src/soft/Device.zig
git.filemode.normal_file
32
src/soft/Device.zig
git.filemode.normal_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);
|
||||
}
|
||||
@@ -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
67
src/soft/PhysicalDevice.zig
git.filemode.normal_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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
Reference in New Issue
Block a user