diff --git a/src/vulkan/Instance.zig b/src/vulkan/Instance.zig index 31ac56a..753eac8 100644 --- a/src/vulkan/Instance.zig +++ b/src/vulkan/Instance.zig @@ -4,6 +4,14 @@ const VkError = @import("error_set.zig").VkError; const Dispatchable = @import("Dispatchable.zig").Dispatchable; const PhysicalDevice = @import("PhysicalDevice.zig"); +const root = @import("root"); + +comptime { + if (!@hasDecl(root, "VULKAN_VERSION")) { + @compileError("Missing VULKAN_VERSION in module root"); + } +} + const Self = @This(); pub const ObjectType: vk.ObjectType = .instance; @@ -41,6 +49,10 @@ pub fn enumerateExtensionProperties(layer_name: ?[]const u8, property_count: *u3 property_count.* = 0; } +pub fn enumerateVersion(version: *u32) VkError!void { + version.* = @bitCast(root.VULKAN_VERSION); +} + pub fn releasePhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void { try self.dispatch_table.releasePhysicalDevices(self, allocator); } diff --git a/src/vulkan/PhysicalDevice.zig b/src/vulkan/PhysicalDevice.zig index afe54e9..f4e40d4 100644 --- a/src/vulkan/PhysicalDevice.zig +++ b/src/vulkan/PhysicalDevice.zig @@ -11,6 +11,8 @@ pub const ObjectType: vk.ObjectType = .physical_device; props: vk.PhysicalDeviceProperties, mem_props: vk.PhysicalDeviceMemoryProperties, +format_props: vk.FormatProperties, +features: vk.PhysicalDeviceFeatures, instance: *const Instance, dispatch_table: *const DispatchTable, @@ -39,6 +41,8 @@ pub fn init(allocator: std.mem.Allocator, instance: *const Instance) VkError!Sel .memory_heap_count = 0, .memory_heaps = undefined, }, + .format_props = .{}, + .features = .{}, .instance = instance, .dispatch_table = undefined, }; diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index afb33b6..20ac7ca 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -21,6 +21,38 @@ extern fn __vkImplCreateInstance(*const std.mem.Allocator, *const vk.InstanceCre /// /// The use of official Vulkan function names is assumed /// and is not a concern, given that this driver only implements Vulkan's API. +const icd_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapElement("vk_icdGetInstanceProcAddr"), + functionMapElement("vk_icdGetPhysicalDeviceProcAddr"), + functionMapElement("vk_icdNegotiateLoaderICDInterfaceVersion"), +}); + +const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapElement("vkCreateInstance"), + functionMapElement("vkGetInstanceProcAddr"), + functionMapElement("vkEnumerateInstanceExtensionProperties"), + functionMapElement("vkEnumerateInstanceVersion"), +}); + +const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapElement("vkDestroyInstance"), + functionMapElement("vkEnumeratePhysicalDevices"), + functionMapElement("vkGetDeviceProcAddr"), +}); + +const physical_device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapElement("vkCreateDevice"), + functionMapElement("vkGetPhysicalDeviceFormatProperties"), + functionMapElement("vkGetPhysicalDeviceFeatures"), + functionMapElement("vkGetPhysicalDeviceImageFormatProperties"), + functionMapElement("vkGetPhysicalDeviceProperties"), + functionMapElement("vkGetPhysicalDeviceMemoryProperties"), + functionMapElement("vkGetPhysicalDeviceQueueFamilyProperties"), +}); + +const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapElement("vkDestroyDevice"), +}); // ICD Interface ============================================================================================================================================= @@ -30,23 +62,28 @@ pub export fn vk_icdNegotiateLoaderICDInterfaceVersion(p_version: *u32) callconv } pub export fn vk_icdGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { - if (p_name == null) { - return null; - } + if (p_name == null) return null; const name = std.mem.span(p_name.?); std.log.scoped(.vk_icdGetInstanceProcAddr).info("Loading {s}...", .{name}); logger.indent(); defer logger.unindent(); - const icd_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ - functionMapElement("vk_icdGetInstanceProcAddr"), - functionMapElement("vk_icdNegotiateLoaderICDInterfaceVersion"), - }); if (icd_pfn_map.get(name)) |pfn| return pfn; 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 { + if (p_name == null) return null; + const name = std.mem.span(p_name.?); + + std.log.scoped(.vk_icdGetPhysicalDeviceProcAddr).info("Loading {s}...", .{name}); + logger.indent(); + defer logger.unindent(); + + return if (physical_device_pfn_map.get(name)) |pfn| pfn else null; +} + // Global functions ========================================================================================================================================== fn functionMapElement(name: []const u8) struct { []const u8, vk.PfnVoidFunction } { @@ -57,31 +94,10 @@ fn functionMapElement(name: []const u8) struct { []const u8, vk.PfnVoidFunction return .{ name, @as(vk.PfnVoidFunction, @ptrCast(&@field(@This(), name))) }; } -const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ - functionMapElement("vkDestroyDevice"), -}); - pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { - if (p_name == null) { - return null; - } + if (p_name == null) return null; const name = std.mem.span(p_name.?); - const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ - functionMapElement("vkCreateInstance"), - functionMapElement("vkGetInstanceProcAddr"), - functionMapElement("vkEnumerateInstanceExtensionProperties"), - }); - - const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ - functionMapElement("vkCreateDevice"), - functionMapElement("vkDestroyInstance"), - functionMapElement("vkEnumeratePhysicalDevices"), - functionMapElement("vkGetDeviceProcAddr"), - functionMapElement("vkGetPhysicalDeviceProperties"), - functionMapElement("vkGetPhysicalDeviceProperties"), - }); - std.log.scoped(.vkGetInstanceProcAddr).info("Loading {s}...", .{name}); logger.indent(); defer logger.unindent(); @@ -92,6 +108,7 @@ pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const return null; } if (instance_pfn_map.get(name)) |pfn| return pfn; + if (physical_device_pfn_map.get(name)) |pfn| return pfn; if (device_pfn_map.get(name)) |pfn| return pfn; std.log.scoped(.vkGetInstanceProcAddr).err("Could not find entrypoint {s}", .{name}); @@ -124,6 +141,11 @@ 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 { + 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 { @@ -148,15 +170,7 @@ pub export fn vkEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, p return .success; } -pub export fn vkGetPhysicalDeviceProperties(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 { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; - properties.* = self.mem_props; -} +// 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 { const infos = p_infos orelse return .error_initialization_failed; @@ -174,6 +188,44 @@ pub export fn vkCreateDevice(p_physical_device: vk.PhysicalDevice, p_infos: ?*co return .success; } +pub export fn vkGetPhysicalDeviceFormatProperties(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 { + 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 { + _ = p_physical_device; + _ = format; + _ = image_type; + _ = tiling; + _ = usage; + _ = flags; + _ = properties; + return .error_format_not_supported; +} + +pub export fn vkGetPhysicalDeviceProperties(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 { + 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 { + _ = p_physical_device; + _ = properties; + count.* = 0; +} + // Device functions ========================================================================================================================================== pub export fn vkDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { @@ -188,9 +240,7 @@ pub export fn vkDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.Allocat } pub export fn vkGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { - if (p_name == null) { - return null; - } + if (p_name == null) return null; const name = std.mem.span(p_name.?); std.log.scoped(.vkGetDeviceProcAddr).info("Loading {s}...", .{name}); diff --git a/src/vulkan/logger.zig b/src/vulkan/logger.zig index f65b38c..2308f00 100644 --- a/src/vulkan/logger.zig +++ b/src/vulkan/logger.zig @@ -78,7 +78,7 @@ pub fn log(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), out_config.setColor(writer, level_color) catch {}; writer.print(prefix, .{}) catch return; - out_config.setColor(writer, .green) catch {}; + out_config.setColor(writer, if (level == .err) .red else .green) catch {}; writer.print("{s: >30}", .{scope_prefix}) catch return; out_config.setColor(writer, .reset) catch {}; diff --git a/test/c/main.c b/test/c/main.c index ee6b046..5db4974 100644 --- a/test/c/main.c +++ b/test/c/main.c @@ -19,13 +19,15 @@ do { \ if((x) != VK_SUCCESS) \ { \ - fprintf(stderr, "Vulkan call failed\n"); \ + fprintf(stderr, "Vulkan call failed %d\n", (x)); \ abort(); \ } \ } while(0) int main(void) { + volkInitialize(); + void* lib = dlopen("./zig-out/lib/lib" LIBVK ".so", RTLD_NOW | RTLD_LOCAL); if(!lib) { @@ -34,17 +36,15 @@ int main(void) } puts("openned ./zig-out/lib/lib" LIBVK ".so"); - volkInitialize(); + VkDirectDriverLoadingInfoLUNARG direct_loading_info = {}; + direct_loading_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG; + direct_loading_info.pfnGetInstanceProcAddr = (PFN_vkGetInstanceProcAddrLUNARG)(dlsym(lib, "vk_icdGetInstanceProcAddr")); - VkDirectDriverLoadingInfoLUNARG directLoadingInfo = {}; - directLoadingInfo.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG; - directLoadingInfo.pfnGetInstanceProcAddr = (PFN_vkGetInstanceProcAddrLUNARG)(dlsym(lib, "vk_icdGetInstanceProcAddr")); - - VkDirectDriverLoadingListLUNARG directDriverList = {}; - directDriverList.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG; - directDriverList.mode = VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG; - directDriverList.driverCount = 1; - directDriverList.pDrivers = &directLoadingInfo; + VkDirectDriverLoadingListLUNARG direct_driver_list = {}; + direct_driver_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG; + direct_driver_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG; + direct_driver_list.driverCount = 1; + direct_driver_list.pDrivers = &direct_loading_info; const char* extensions[] = { VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME }; @@ -53,7 +53,7 @@ int main(void) instance_create_info.pApplicationInfo = NULL; instance_create_info.enabledExtensionCount = 1; instance_create_info.ppEnabledExtensionNames = extensions; - instance_create_info.pNext = &directDriverList; + instance_create_info.pNext = &direct_driver_list; VkInstance instance = VK_NULL_HANDLE; CheckVk(vkCreateInstance(&instance_create_info, NULL, &instance));