diff --git a/README.md b/README.md new file mode 100644 index 0000000..d196c0d --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Stroll Vulkan Driver + +
+

A driver as slow as Lance Stroll

+ +
diff --git a/src/soft/Instance.zig b/src/soft/Instance.zig index 4ce54da..95777a0 100644 --- a/src/soft/Instance.zig +++ b/src/soft/Instance.zig @@ -12,13 +12,8 @@ pub const Interface = base.Instance; 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(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) !?*Interface { - const self = try allocator.create(Self); +pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!*Interface { + const self = allocator.create(Self) catch return VkError.OutOfHostMemory; errdefer allocator.destroy(self); self.interface = try base.Instance.init(allocator, infos); diff --git a/src/soft/lib.zig b/src/soft/lib.zig index 78aba52..5bd0745 100644 --- a/src/soft/lib.zig +++ b/src/soft/lib.zig @@ -2,8 +2,8 @@ const std = @import("std"); const vk = @import("vulkan"); const base = @import("base"); +pub const Instance = @import("Instance.zig"); const Device = @import("Device.zig"); -const Instance = @import("Instance.zig"); const PhysicalDevice = @import("PhysicalDevice.zig"); pub const DRIVER_LOGS_ENV_NAME = base.DRIVER_LOGS_ENV_NAME; @@ -17,5 +17,4 @@ pub const std_options = base.std_options; comptime { _ = base; - _ = Instance; } diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index f4a134e..259578d 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -1,6 +1,6 @@ const std = @import("std"); const vk = @import("vulkan"); -const root = @import("lib.zig"); +const root = @import("root"); const logger = @import("logger.zig"); const error_set = @import("error_set.zig"); @@ -15,19 +15,20 @@ const Instance = @import("Instance.zig"); const Device = @import("Device.zig"); const PhysicalDevice = @import("PhysicalDevice.zig"); -extern fn __vkImplCreateInstance(*const std.mem.Allocator, *const vk.InstanceCreateInfo) ?*Instance; - // This file contains all exported Vulkan entrypoints. // // The use of official Vulkan function names is assumed // and is not a concern, given that this driver only implements Vulkan's API. -fn functionMapElement(name: []const u8) struct { []const u8, vk.PfnVoidFunction } { - if (!std.meta.hasFn(@This(), name)) { - std.log.scoped(.vkGetInstanceProcAddr).err("Could not find function {s}", .{name}); - return .{ name, null }; +fn functionMapElement(comptime name: []const u8) struct { []const u8, vk.PfnVoidFunction } { + const stroll_name = std.fmt.comptimePrint("stroll{s}", .{name[2..]}); + + if (std.meta.hasFn(@This(), name)) { + return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), name))) }; + } else if (std.meta.hasFn(@This(), stroll_name)) { + return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), stroll_name))) }; } - return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), name))) }; + return .{ name, null }; } const icd_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ @@ -66,7 +67,7 @@ const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ // ICD Interface ============================================================================================================================================= -pub export fn vk_icdNegotiateLoaderICDInterfaceVersion(p_version: *u32) callconv(vk.vulkan_call_conv) vk.Result { +pub export fn stroll_icdNegotiateLoaderICDInterfaceVersion(p_version: *u32) callconv(vk.vulkan_call_conv) vk.Result { p_version.* = 7; return .success; } @@ -83,7 +84,7 @@ pub export fn vk_icdGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]c return vkGetInstanceProcAddr(p_instance, p_name); } -pub export fn vk_icdGetPhysicalDeviceProcAddr(_: vk.Instance, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { +pub export fn stroll_icdGetPhysicalDeviceProcAddr(_: vk.Instance, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { if (p_name == null) return null; const name = std.mem.span(p_name.?); @@ -91,7 +92,10 @@ pub export fn vk_icdGetPhysicalDeviceProcAddr(_: vk.Instance, p_name: ?[*:0]cons logger.indent(); defer logger.unindent(); - return if (physical_device_pfn_map.get(name)) |pfn| pfn else null; + if (physical_device_pfn_map.get(name)) |pfn| return pfn; + + std.log.scoped(.vk_icdGetPhysicalDeviceProcAddr).err("Could not find function {s}", .{name}); + return null; } // Global functions ========================================================================================================================================== @@ -117,7 +121,7 @@ pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const return 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 strollCreateInstance(p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_instance: *vk.Instance) callconv(vk.vulkan_call_conv) vk.Result { const infos = p_infos orelse return .error_initialization_failed; if (infos.s_type != .instance_create_info) { return .error_initialization_failed; @@ -127,14 +131,16 @@ pub export fn vkCreateInstance(p_infos: ?*const vk.InstanceCreateInfo, callbacks defer logger.unindent(); const allocator = VulkanAllocator.init(callbacks, .instance).allocator(); - const instance = __vkImplCreateInstance(&allocator, infos) orelse return .error_initialization_failed; + + // Will call impl instead of interface as root refs the impl module + const instance = root.Instance.create(allocator, infos) catch |err| return toVkResult(err); instance.requestPhysicalDevices(allocator) catch |err| return toVkResult(err); p_instance.* = (Dispatchable(Instance).wrap(allocator, instance) catch |err| return toVkResult(err)).toVkHandle(vk.Instance); return .success; } -pub export fn vkEnumerateInstanceExtensionProperties(p_layer_name: ?[*:0]const u8, property_count: *u32, properties: ?*vk.ExtensionProperties) callconv(vk.vulkan_call_conv) vk.Result { +pub export fn strollEnumerateInstanceExtensionProperties(p_layer_name: ?[*:0]const u8, property_count: *u32, properties: ?*vk.ExtensionProperties) callconv(vk.vulkan_call_conv) vk.Result { var name: ?[]const u8 = null; if (p_layer_name) |layer_name| { name = std.mem.span(layer_name); @@ -143,14 +149,14 @@ pub export fn vkEnumerateInstanceExtensionProperties(p_layer_name: ?[*:0]const u return .success; } -pub export fn vkEnumerateInstanceVersion(version: *u32) callconv(vk.vulkan_call_conv) vk.Result { +pub export fn strollEnumerateInstanceVersion(version: *u32) callconv(vk.vulkan_call_conv) vk.Result { Instance.enumerateVersion(version) catch |err| return toVkResult(err); return .success; } // Instance functions ======================================================================================================================================== -pub export fn vkDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { +pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { std.log.scoped(.vkDestroyInstance).info("Destroying VkInstance", .{}); logger.indent(); defer logger.unindent(); @@ -161,7 +167,7 @@ pub export fn vkDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.A 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 strollEnumeratePhysicalDevices(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); count.* = @intCast(self.physical_devices.items.len); if (p_devices) |devices| { @@ -174,7 +180,7 @@ pub export fn vkEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p // Physical Device functions ================================================================================================================================= -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 { +pub export fn strollCreateDevice(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; @@ -190,7 +196,7 @@ pub export fn vkCreateDevice(p_physical_device: vk.PhysicalDevice, p_infos: ?*co return .success; } -pub export fn vkEnumerateDeviceExtensionProperties(p_physical_device: vk.PhysicalDevice, p_layer_name: ?[*:0]const u8, property_count: *u32, properties: ?*vk.ExtensionProperties) callconv(vk.vulkan_call_conv) vk.Result { +pub export fn strollEnumerateDeviceExtensionProperties(p_physical_device: vk.PhysicalDevice, p_layer_name: ?[*:0]const u8, property_count: *u32, properties: ?*vk.ExtensionProperties) callconv(vk.vulkan_call_conv) vk.Result { var name: ?[]const u8 = null; if (p_layer_name) |layer_name| { name = std.mem.span(layer_name); @@ -201,18 +207,18 @@ pub export fn vkEnumerateDeviceExtensionProperties(p_physical_device: vk.Physica return .success; } -pub export fn vkGetPhysicalDeviceFormatProperties(p_physical_device: vk.PhysicalDevice, format: vk.Format, properties: *vk.FormatProperties) callconv(vk.vulkan_call_conv) void { +pub export fn strollGetPhysicalDeviceFormatProperties(p_physical_device: vk.PhysicalDevice, format: vk.Format, properties: *vk.FormatProperties) callconv(vk.vulkan_call_conv) void { _ = format; const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; properties.* = self.format_props; } -pub export fn vkGetPhysicalDeviceFeatures(p_physical_device: vk.PhysicalDevice, features: *vk.PhysicalDeviceFeatures) callconv(vk.vulkan_call_conv) void { +pub export fn strollGetPhysicalDeviceFeatures(p_physical_device: vk.PhysicalDevice, features: *vk.PhysicalDeviceFeatures) callconv(vk.vulkan_call_conv) void { const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; features.* = self.features; } -pub export fn vkGetPhysicalDeviceImageFormatProperties(p_physical_device: vk.PhysicalDevice, format: vk.Format, image_type: vk.ImageType, tiling: vk.ImageTiling, usage: vk.ImageUsageFlags, flags: vk.ImageCreateFlags, properties: *vk.ImageFormatProperties) callconv(vk.vulkan_call_conv) vk.Result { +pub export fn strollGetPhysicalDeviceImageFormatProperties(p_physical_device: vk.PhysicalDevice, format: vk.Format, image_type: vk.ImageType, tiling: vk.ImageTiling, usage: vk.ImageUsageFlags, flags: vk.ImageCreateFlags, properties: *vk.ImageFormatProperties) callconv(vk.vulkan_call_conv) vk.Result { _ = p_physical_device; _ = format; _ = image_type; @@ -223,17 +229,17 @@ pub export fn vkGetPhysicalDeviceImageFormatProperties(p_physical_device: vk.Phy return .error_format_not_supported; } -pub export fn vkGetPhysicalDeviceProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceProperties) callconv(vk.vulkan_call_conv) void { +pub export fn strollGetPhysicalDeviceProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceProperties) callconv(vk.vulkan_call_conv) void { const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; properties.* = self.props; } -pub export fn vkGetPhysicalDeviceMemoryProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceMemoryProperties) callconv(vk.vulkan_call_conv) void { +pub export fn strollGetPhysicalDeviceMemoryProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceMemoryProperties) callconv(vk.vulkan_call_conv) void { const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; properties.* = self.mem_props; } -pub export fn vkGetPhysicalDeviceQueueFamilyProperties(p_physical_device: vk.PhysicalDevice, count: *u32, properties: ?[*]vk.QueueFamilyProperties) callconv(vk.vulkan_call_conv) void { +pub export fn strollGetPhysicalDeviceQueueFamilyProperties(p_physical_device: vk.PhysicalDevice, count: *u32, properties: ?[*]vk.QueueFamilyProperties) callconv(vk.vulkan_call_conv) void { _ = p_physical_device; _ = properties; count.* = 0; @@ -241,7 +247,7 @@ pub export fn vkGetPhysicalDeviceQueueFamilyProperties(p_physical_device: vk.Phy // Device functions ========================================================================================================================================== -pub export fn vkDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { +pub export fn strollDestroyDevice(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; std.log.scoped(.vkDestroyDevice).info("Destroying VkDevice created from {s}", .{dispatchable.object.physical_device.props.device_name}); @@ -252,7 +258,7 @@ pub export fn vkDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.Allocat dispatchable.destroy(allocator); } -pub export fn vkGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { +pub export fn strollGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { if (p_name == null) return null; const name = std.mem.span(p_name.?); @@ -261,5 +267,8 @@ pub export fn vkGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8) c defer logger.unindent(); if (p_device == .null_handle) return null; - return if (device_pfn_map.get(name)) |pfn| pfn else null; + if (device_pfn_map.get(name)) |pfn| return pfn; + + std.log.scoped(.vkGetDeviceProcAddr).err("Could not find entrypoint {s}", .{name}); + return null; }