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 std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
const soft_physical_device = @import("physical_device.zig");
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|
||||||
const Dispatchable = base.Dispatchable;
|
const Dispatchable = base.Dispatchable;
|
||||||
const VulkanAllocator = base.VulkanAllocator;
|
|
||||||
|
const VkError = base.VkError;
|
||||||
|
|
||||||
const Self = @This();
|
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 {
|
interface: Interface,
|
||||||
return realVkImplInstanceInit(base_instance, allocator.*, infos) catch return null;
|
|
||||||
|
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
|
// 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 {
|
fn realVkImplInstanceInit(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) !?*Interface {
|
||||||
_ = 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));
|
|
||||||
|
|
||||||
const self = try allocator.create(Self);
|
const self = try allocator.create(Self);
|
||||||
errdefer allocator.destroy(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 vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
|
|
||||||
|
const Device = @import("Device.zig");
|
||||||
const Instance = @import("Instance.zig");
|
const Instance = @import("Instance.zig");
|
||||||
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|
||||||
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
||||||
pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
|
pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
|
||||||
pub const DEVICE_ID = 0x600DCAFE;
|
pub const DEVICE_ID = 0x600DCAFE;
|
||||||
|
|
||||||
|
pub const std_options = base.std_options;
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
_ = base;
|
_ = base;
|
||||||
_ = Instance;
|
_ = 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});
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,28 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
|
||||||
|
const VkError = @import("error_set.zig").VkError;
|
||||||
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const ObjectType: vk.ObjectType = .device;
|
pub const ObjectType: vk.ObjectType = .device;
|
||||||
|
|
||||||
physical_device: *const PhysicalDevice,
|
physical_device: *const PhysicalDevice,
|
||||||
dispatch_table: DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
driver_data: ?*anyopaque,
|
|
||||||
|
|
||||||
pub const DispatchTable = struct {};
|
pub const DispatchTable = struct {
|
||||||
|
destroy: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn createImplDevice(physical_device: *base.PhysicalDevice, infos: vk.DeviceCreateInfo, allocator: std.mem.Allocator) !*anyopaque {
|
pub fn init(allocator: std.mem.Allocator, physical_device: *const PhysicalDevice, infos: *const vk.DeviceCreateInfo) VkError!Self {
|
||||||
|
_ = allocator;
|
||||||
|
_ = infos;
|
||||||
|
return .{
|
||||||
|
.physical_device = physical_device,
|
||||||
|
.dispatch_table = undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||||
|
try self.dispatch_table.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ pub fn Dispatchable(comptime T: type) type {
|
|||||||
loader_data: c.VK_LOADER_DATA,
|
loader_data: c.VK_LOADER_DATA,
|
||||||
object_type: vk.ObjectType,
|
object_type: vk.ObjectType,
|
||||||
object: *T,
|
object: *T,
|
||||||
|
is_owner: bool = false,
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator, args: anytype) VkError!*Self {
|
pub fn create(allocator: std.mem.Allocator, args: anytype) VkError!*Self {
|
||||||
comptime {
|
comptime {
|
||||||
@@ -33,7 +34,12 @@ pub fn Dispatchable(comptime T: type) type {
|
|||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
const object = allocator.create(T) catch return VkError.OutOfHostMemory;
|
const object = allocator.create(T) catch return VkError.OutOfHostMemory;
|
||||||
object.* = try @call(.auto, T.init, .{allocator} ++ args);
|
object.* = try @call(.auto, T.init, .{allocator} ++ args);
|
||||||
|
self.is_owner = true;
|
||||||
|
return self.wrap(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wrap(allocator: std.mem.Allocator, object: *T) VkError!*Self {
|
||||||
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.loader_data = .{ .loaderMagic = c.ICD_LOADER_MAGIC },
|
.loader_data = .{ .loaderMagic = c.ICD_LOADER_MAGIC },
|
||||||
.object_type = T.ObjectType,
|
.object_type = T.ObjectType,
|
||||||
@@ -43,10 +49,9 @@ pub fn Dispatchable(comptime T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
if (std.meta.hasMethod(T, "deinit")) {
|
if (self.is_owner) {
|
||||||
self.object.deinit(allocator);
|
allocator.destroy(self.object);
|
||||||
}
|
}
|
||||||
allocator.destroy(self.object);
|
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,31 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const root = @import("lib.zig");
|
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
|
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
extern fn __vkImplInstanceInit(*Self, *const std.mem.Allocator, *const vk.InstanceCreateInfo) ?*anyopaque;
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const ObjectType: vk.ObjectType = .instance;
|
pub const ObjectType: vk.ObjectType = .instance;
|
||||||
|
|
||||||
physical_devices: std.ArrayList(vk.PhysicalDevice),
|
physical_devices: std.ArrayList(*Dispatchable(PhysicalDevice)),
|
||||||
dispatch_table: DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
driver_data: ?*anyopaque,
|
|
||||||
|
|
||||||
pub const DispatchTable = struct {
|
pub const DispatchTable = struct {
|
||||||
destroyInstance: ?*const fn (*const Self, std.mem.Allocator) anyerror!void = null,
|
requestPhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||||
|
releasePhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||||
|
destroyInstance: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!Self {
|
pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!Self {
|
||||||
var self: Self = .{
|
_ = allocator;
|
||||||
.dispatch_table = .{},
|
_ = infos;
|
||||||
|
return .{
|
||||||
.physical_devices = .empty,
|
.physical_devices = .empty,
|
||||||
.driver_data = null,
|
.dispatch_table = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.driver_data = __vkImplInstanceInit(&self, &allocator, infos) orelse return VkError.InitializationFailed;
|
|
||||||
std.debug.assert(self.physical_devices.items.len != 0);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||||
if (self.dispatch_table.destroyInstance) |pfnDestroyInstance| {
|
try self.dispatch_table.releasePhysicalDevices(self, allocator);
|
||||||
pfnDestroyInstance(self, allocator) catch return;
|
try self.dispatch_table.destroyInstance(self, allocator);
|
||||||
} else if (std.process.hasEnvVar(allocator, root.DRIVER_LOGS_ENV_NAME) catch false) {
|
|
||||||
std.log.scoped(.vkDestroyInstance).warn("Missing dispatch implementation", .{});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const root = @import("lib.zig");
|
const root = @import("lib.zig");
|
||||||
|
|
||||||
const Instance = @import("Instance.zig");
|
const Instance = @import("Instance.zig");
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
|
const Device = @import("Device.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const ObjectType: vk.ObjectType = .physical_device;
|
pub const ObjectType: vk.ObjectType = .physical_device;
|
||||||
@@ -10,10 +12,12 @@ pub const ObjectType: vk.ObjectType = .physical_device;
|
|||||||
props: vk.PhysicalDeviceProperties,
|
props: vk.PhysicalDeviceProperties,
|
||||||
mem_props: vk.PhysicalDeviceMemoryProperties,
|
mem_props: vk.PhysicalDeviceMemoryProperties,
|
||||||
instance: *const Instance,
|
instance: *const Instance,
|
||||||
dispatch_table: DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
driver_data: ?*anyopaque,
|
|
||||||
|
|
||||||
pub const DispatchTable = struct {};
|
pub const DispatchTable = struct {
|
||||||
|
createDevice: *const fn (*Self, std.mem.Allocator, *const vk.DeviceCreateInfo) VkError!*Device,
|
||||||
|
release: *const fn (*Self, std.mem.Allocator) VkError!void,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, instance: *const Instance) VkError!Self {
|
pub fn init(allocator: std.mem.Allocator, instance: *const Instance) VkError!Self {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
@@ -35,8 +39,15 @@ pub fn init(allocator: std.mem.Allocator, instance: *const Instance) VkError!Sel
|
|||||||
.memory_heap_count = 0,
|
.memory_heap_count = 0,
|
||||||
.memory_heaps = undefined,
|
.memory_heaps = undefined,
|
||||||
},
|
},
|
||||||
.driver_data = null,
|
|
||||||
.instance = instance,
|
.instance = instance,
|
||||||
.dispatch_table = .{},
|
.dispatch_table = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn createDevice(self: *Self, allocator: std.mem.Allocator, infos: *const vk.DeviceCreateInfo) VkError!*Device {
|
||||||
|
return try self.dispatch_table.createDevice(self, allocator, infos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn releasePhysicalDevice(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
||||||
|
try self.dispatch_table.release(self, allocator);
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ const std = @import("std");
|
|||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
pub const lib_vulkan = @import("lib_vulkan.zig");
|
pub const lib_vulkan = @import("lib_vulkan.zig");
|
||||||
|
pub const logs = @import("logs.zig");
|
||||||
|
|
||||||
pub const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
pub const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
pub const VkError = @import("error_set.zig").VkError;
|
pub const VkError = @import("error_set.zig").VkError;
|
||||||
|
|
||||||
pub const Instance = @import("Instance.zig");
|
pub const Instance = @import("Instance.zig");
|
||||||
|
pub const Device = @import("Device.zig");
|
||||||
pub const PhysicalDevice = @import("PhysicalDevice.zig");
|
pub const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
pub const VulkanAllocator = @import("VulkanAllocator.zig");
|
pub const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||||
//pub const Device = @import("Device.zig");
|
//pub const Device = @import("Device.zig");
|
||||||
@@ -15,19 +17,10 @@ pub const VULKAN_VENDOR_ID = @typeInfo(vk.VendorId).@"enum".fields[@typeInfo(vk.
|
|||||||
pub const DRIVER_LOGS_ENV_NAME = "DRIVER_LOGS";
|
pub const DRIVER_LOGS_ENV_NAME = "DRIVER_LOGS";
|
||||||
|
|
||||||
pub const std_options: std.Options = .{
|
pub const std_options: std.Options = .{
|
||||||
.log_level = .info,
|
.log_level = .debug,
|
||||||
.logFn = logFn,
|
.logFn = logs.logger,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn logFn(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), comptime format: []const u8, args: anytype) void {
|
|
||||||
_ = level;
|
|
||||||
_ = scope;
|
|
||||||
std.debug.lockStdErr();
|
|
||||||
defer std.debug.unlockStdErr();
|
|
||||||
const stderr = std.fs.File.stderr().deprecatedWriter();
|
|
||||||
nosuspend stderr.print(format ++ "\n", args) catch return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retrieveDriverDataAs(handle: anytype, comptime T: type) !*T {
|
pub fn retrieveDriverDataAs(handle: anytype, comptime T: type) !*T {
|
||||||
comptime {
|
comptime {
|
||||||
switch (@typeInfo(@TypeOf(handle))) {
|
switch (@typeInfo(@TypeOf(handle))) {
|
||||||
|
|||||||
@@ -11,11 +11,14 @@ const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
|||||||
const VulkanAllocator = @import("VulkanAllocator.zig");
|
const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||||
|
|
||||||
const Instance = @import("Instance.zig");
|
const Instance = @import("Instance.zig");
|
||||||
|
const Device = @import("Device.zig");
|
||||||
const PhysicalDevice = @import("PhysicalDevice.zig");
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|
||||||
|
extern fn __vkImplCreateInstance(*const std.mem.Allocator, *const vk.InstanceCreateInfo) ?*Instance;
|
||||||
|
|
||||||
fn functionMapElement(name: []const u8) struct { []const u8, vk.PfnVoidFunction } {
|
fn functionMapElement(name: []const u8) struct { []const u8, vk.PfnVoidFunction } {
|
||||||
if (!std.meta.hasFn(@This(), name)) {
|
if (!std.meta.hasFn(@This(), name)) {
|
||||||
std.log.scoped(.functionMapElement).err("Could not find function {s}", .{name});
|
std.log.scoped(.vkGetInstanceProcAddr).err("Could not find function {s}", .{name});
|
||||||
return .{ name, null };
|
return .{ name, null };
|
||||||
}
|
}
|
||||||
return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), name))) };
|
return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), name))) };
|
||||||
@@ -28,24 +31,27 @@ pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const
|
|||||||
});
|
});
|
||||||
|
|
||||||
const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
||||||
|
functionMapElement("vkCreateDevice"),
|
||||||
functionMapElement("vkDestroyInstance"),
|
functionMapElement("vkDestroyInstance"),
|
||||||
functionMapElement("vkEnumeratePhysicalDevices"),
|
functionMapElement("vkEnumeratePhysicalDevices"),
|
||||||
functionMapElement("vkGetPhysicalDeviceProperties"),
|
functionMapElement("vkGetPhysicalDeviceProperties"),
|
||||||
functionMapElement("vkGetPhysicalDeviceProperties"),
|
functionMapElement("vkGetPhysicalDeviceProperties"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
||||||
|
functionMapElement("vkDestroyDevice"),
|
||||||
|
});
|
||||||
|
|
||||||
if (p_name == null) {
|
if (p_name == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const name = std.mem.span(p_name.?);
|
const name = std.mem.span(p_name.?);
|
||||||
|
std.log.scoped(.vkGetInstanceProcAddr).info("Loading {s}...", .{name});
|
||||||
if (std.process.hasEnvVarConstant(root.DRIVER_LOGS_ENV_NAME)) {
|
|
||||||
std.log.scoped(.vkGetInstanceProcAddr).info("Loading {s}...", .{name});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (global_pfn_map.get(name)) |pfn| return pfn;
|
if (global_pfn_map.get(name)) |pfn| return pfn;
|
||||||
if (p_instance == .null_handle) return null;
|
if (p_instance == .null_handle) return null;
|
||||||
return if (instance_pfn_map.get(name)) |pfn| pfn else null;
|
if (instance_pfn_map.get(name)) |pfn| return pfn;
|
||||||
|
return if (device_pfn_map.get(name)) |pfn| pfn else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn vkCreateInstance(p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_instance: *vk.Instance) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn vkCreateInstance(p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_instance: *vk.Instance) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
@@ -54,20 +60,27 @@ pub export fn vkCreateInstance(p_infos: ?*const vk.InstanceCreateInfo, callbacks
|
|||||||
return .error_initialization_failed;
|
return .error_initialization_failed;
|
||||||
}
|
}
|
||||||
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
||||||
p_instance.* = (Dispatchable(Instance).create(allocator, .{infos}) catch |err| return toVkResult(err)).toVkHandle(vk.Instance);
|
const handler = __vkImplCreateInstance(&allocator, infos) orelse return .error_initialization_failed;
|
||||||
|
handler.dispatch_table.requestPhysicalDevices(handler, allocator) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
|
p_instance.* = (Dispatchable(Instance).wrap(allocator, handler) catch |err| return toVkResult(err)).toVkHandle(vk.Instance);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn vkDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
pub export fn vkDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||||
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
||||||
(Dispatchable(Instance).fromHandle(p_instance) catch return).destroy(allocator);
|
const dispatchable = Dispatchable(Instance).fromHandle(p_instance) catch return;
|
||||||
|
dispatchable.object.deinit(allocator) catch {};
|
||||||
|
dispatchable.destroy(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn vkEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p_devices: ?[*]vk.PhysicalDevice) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn vkEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p_devices: ?[*]vk.PhysicalDevice) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
const self = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
const self = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
||||||
count.* = @intCast(self.physical_devices.items.len);
|
count.* = @intCast(self.physical_devices.items.len);
|
||||||
if (p_devices) |devices| {
|
if (p_devices) |devices| {
|
||||||
@memcpy(devices[0..self.physical_devices.items.len], self.physical_devices.items);
|
for (0..count.*) |i| {
|
||||||
|
devices[i] = self.physical_devices.items[i].toVkHandle(vk.PhysicalDevice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
@@ -81,3 +94,22 @@ pub export fn vkGetPhysicalDeviceMemoryProperties(p_physical_device: vk.Physical
|
|||||||
const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return;
|
const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return;
|
||||||
properties.* = self.mem_props;
|
properties.* = self.mem_props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub export fn vkCreateDevice(p_physical_device: vk.PhysicalDevice, p_infos: ?*const vk.DeviceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_device: *vk.Device) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
|
const infos = p_infos orelse return .error_initialization_failed;
|
||||||
|
if (infos.s_type != .device_create_info) {
|
||||||
|
return .error_initialization_failed;
|
||||||
|
}
|
||||||
|
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
||||||
|
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
|
||||||
|
const device = physical_device.createDevice(allocator, infos) catch |err| return toVkResult(err);
|
||||||
|
p_device.* = (Dispatchable(Device).wrap(allocator, device) catch |err| return toVkResult(err)).toVkHandle(vk.Device);
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub export fn vkDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||||
|
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
||||||
|
const dispatchable = Dispatchable(Device).fromHandle(p_device) catch return;
|
||||||
|
dispatchable.object.destroy(allocator) catch return;
|
||||||
|
dispatchable.destroy(allocator);
|
||||||
|
}
|
||||||
|
|||||||
48
src/vulkan/logs.zig
git.filemode.normal_file
48
src/vulkan/logs.zig
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const root = @import("lib.zig");
|
||||||
|
|
||||||
|
const is_posix = switch (builtin.os.tag) {
|
||||||
|
.windows, .uefi, .wasi => false,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn logger(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), comptime format: []const u8, args: anytype) void {
|
||||||
|
if (!std.process.hasEnvVarConstant(root.DRIVER_LOGS_ENV_NAME)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const scope_prefix = "(" ++ @tagName(scope) ++ "): ";
|
||||||
|
const prefix = "[" ++ comptime level.asText() ++ "] ";
|
||||||
|
|
||||||
|
const level_color: std.Io.tty.Color = switch (level) {
|
||||||
|
.info => .blue,
|
||||||
|
.warn => .yellow,
|
||||||
|
.err => .red,
|
||||||
|
.debug => .blue,
|
||||||
|
};
|
||||||
|
|
||||||
|
const instant = std.time.Instant.now() catch return;
|
||||||
|
const now = if (is_posix) instant.timestamp.nsec else instant.timestamp;
|
||||||
|
|
||||||
|
std.debug.lockStdErr();
|
||||||
|
defer std.debug.unlockStdErr();
|
||||||
|
|
||||||
|
var stderr_buffer: [512]u8 = undefined;
|
||||||
|
var stderr_file = std.fs.File.stderr();
|
||||||
|
var stderr_writer = stderr_file.writer(&stderr_buffer);
|
||||||
|
var writer: *std.Io.Writer = &stderr_writer.interface;
|
||||||
|
|
||||||
|
var out_config = std.Io.tty.Config.detect(stderr_file);
|
||||||
|
nosuspend {
|
||||||
|
out_config.setColor(writer, .magenta) catch {};
|
||||||
|
writer.print("[Driver log {}:{}:{}]", .{ @divFloor(now, std.time.ns_per_min), @divFloor(now, std.time.ns_per_s), @divFloor(now, std.time.ns_per_ms) }) catch return;
|
||||||
|
out_config.setColor(writer, level_color) catch {};
|
||||||
|
writer.print(prefix, .{}) catch return;
|
||||||
|
out_config.setColor(writer, .green) catch {};
|
||||||
|
writer.print(scope_prefix, .{}) catch return;
|
||||||
|
out_config.setColor(writer, .reset) catch {};
|
||||||
|
|
||||||
|
writer.print(format ++ "\n", args) catch return;
|
||||||
|
writer.flush() catch return;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,8 @@ int main(void)
|
|||||||
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
|
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
|
||||||
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
|
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
|
||||||
VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
|
VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
|
||||||
|
VULKAN_INSTANCE_FUNCTION(vkCreateDevice)
|
||||||
|
VULKAN_INSTANCE_FUNCTION(vkDestroyDevice)
|
||||||
|
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
vkEnumeratePhysicalDevices(instance, &count, NULL);
|
vkEnumeratePhysicalDevices(instance, &count, NULL);
|
||||||
@@ -58,6 +60,14 @@ int main(void)
|
|||||||
vkGetPhysicalDeviceProperties(physical_devices[0], &props);
|
vkGetPhysicalDeviceProperties(physical_devices[0], &props);
|
||||||
printf("VkPhysicalDevice name %s\n", props.deviceName);
|
printf("VkPhysicalDevice name %s\n", props.deviceName);
|
||||||
|
|
||||||
|
VkDeviceCreateInfo device_create_info = {0};
|
||||||
|
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
|
||||||
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
|
CheckVk(vkCreateDevice(physical_devices[0], &device_create_info, NULL, &device));
|
||||||
|
printf("VkDevice %p\n", device);
|
||||||
|
|
||||||
|
vkDestroyDevice(device, NULL);
|
||||||
vkDestroyInstance(instance, NULL);
|
vkDestroyInstance(instance, NULL);
|
||||||
|
|
||||||
free(physical_devices);
|
free(physical_devices);
|
||||||
|
|||||||
Reference in New Issue
Block a user