From 64af182ecc62c8aaf968980ae4f59ab217029ffc Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 17 Dec 2025 17:39:20 +0100 Subject: [PATCH] adding VK_KHR_get_physical_device_properties2 and bug fixes --- build.zig | 4 +- build.zig.zon | 4 + src/soft/SoftCommandBuffer.zig | 4 +- src/soft/SoftInstance.zig | 25 +++- src/soft/SoftPhysicalDevice.zig | 30 +++- src/vulkan/CommandBuffer.zig | 8 +- src/vulkan/Device.zig | 4 +- src/vulkan/Instance.zig | 24 +-- src/vulkan/PhysicalDevice.zig | 26 +++- src/vulkan/commands.zig | 2 + src/vulkan/lib_vulkan.zig | 187 +++++++++++++++++++++--- src/vulkan/logger/ThreadSafeManager.zig | 20 ++- src/vulkan/logger/logger.zig | 24 +-- 13 files changed, 290 insertions(+), 72 deletions(-) diff --git a/build.zig b/build.zig index 640cb30..1c3ec39 100644 --- a/build.zig +++ b/build.zig @@ -31,6 +31,7 @@ pub fn build(b: *std.Build) !void { }); const zdt = b.dependency("zdt", .{}).module("zdt"); + const zigrc = b.dependency("zigrc", .{}).module("zigrc"); const vulkan_headers = b.dependency("vulkan_headers", .{}); const vulkan_utility_libraries = b.dependency("vulkan_utility_libraries", .{}); @@ -39,6 +40,7 @@ pub fn build(b: *std.Build) !void { }).module("vulkan-zig"); base_mod.addImport("zdt", zdt); + base_mod.addImport("zigrc", zigrc); base_mod.addImport("vulkan", vulkan); base_mod.addSystemIncludePath(vulkan_headers.path("include")); base_mod.addSystemIncludePath(vulkan_utility_libraries.path("include")); @@ -184,7 +186,7 @@ fn addCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *const Implemen })); const mustpass = try cts.path( - b.fmt("mustpass/{}.{}.0/vk-default.txt", .{ + b.fmt("mustpass/{}.{}.2/vk-default.txt", .{ impl.vulkan_version.major, impl.vulkan_version.minor, }), diff --git a/build.zig.zon b/build.zig.zon index 448b789..3afaaa4 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -29,6 +29,10 @@ .url = "git+https://github.com/Kbz-8/Vulkan-CTS-bin#19ce2da05f8176348064a9fc6688847e5f76a46e", .hash = "N-V-__8AAHDV0xtS93nAGaYd7YWxBLnvHDEplwIpC29izSGa", }, + .zigrc = .{ + .url = "https://github.com/Aandreba/zigrc/archive/refs/tags/1.1.0.tar.gz", + .hash = "zigrc-1.0.0-lENlWzvQAACulrbkL9PVhWjFsWSkYhi7AmfSbCM-2Xlh", + }, .cpuinfo = .{ .url = "git+https://github.com/Kbz-8/cpuinfo#4883954cfcec3f6c9ca9c4aaddfc26107e08726f", .hash = "cpuinfo-0.0.1-RLgIQTLRMgF4dLo8AJ-HvnpFsJe6jmXCJjMWWjil6RF1", diff --git a/src/soft/SoftCommandBuffer.zig b/src/soft/SoftCommandBuffer.zig index faa5561..ba02448 100644 --- a/src/soft/SoftCommandBuffer.zig +++ b/src/soft/SoftCommandBuffer.zig @@ -89,11 +89,13 @@ pub fn copyBuffer(interface: *Interface, src: *base.Buffer, dst: *base.Buffer, r _ = regions; } -pub fn copyImage(interface: *Interface, src: *base.Image, dst: *base.Image, regions: []const vk.ImageCopy) VkError!void { +pub fn copyImage(interface: *Interface, src: *base.Image, src_layout: vk.ImageLayout, dst: *base.Image, dst_layout: vk.ImageLayout, regions: []const vk.ImageCopy) VkError!void { // No-op _ = interface; _ = src; + _ = src_layout; _ = dst; + _ = dst_layout; _ = regions; } diff --git a/src/soft/SoftInstance.zig b/src/soft/SoftInstance.zig index aad8732..f4d1785 100644 --- a/src/soft/SoftInstance.zig +++ b/src/soft/SoftInstance.zig @@ -12,13 +12,26 @@ pub const Interface = base.Instance; interface: Interface, +fn castExtension(comptime ext: vk.ApiInfo) vk.ExtensionProperties { + var props: vk.ExtensionProperties = .{ + .extension_name = undefined, + .spec_version = @bitCast(ext.version), + }; + @memcpy(props.extension_name[0..ext.name.len], ext.name); + return props; +} + +pub const EXTENSIONS = [_]vk.ExtensionProperties{ + castExtension(vk.extensions.khr_get_physical_device_properties_2), +}; + 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); self.interface.dispatch_table = &.{ - .destroyInstance = destroyInstance, + .destroy = destroy, }; self.interface.vtable = &.{ .requestPhysicalDevices = requestPhysicalDevices, @@ -27,6 +40,11 @@ pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) return &self.interface; } +fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void { + const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); + allocator.destroy(self); +} + fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) VkError!void { // Software driver has only one physical device (the CPU) const physical_device = try SoftPhysicalDevice.create(allocator, interface); @@ -42,8 +60,3 @@ fn releasePhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) V interface.physical_devices.deinit(allocator); interface.physical_devices = .empty; } - -fn destroyInstance(interface: *Interface, allocator: std.mem.Allocator) VkError!void { - const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); - allocator.destroy(self); -} diff --git a/src/soft/SoftPhysicalDevice.zig b/src/soft/SoftPhysicalDevice.zig index b8c9f86..b589930 100644 --- a/src/soft/SoftPhysicalDevice.zig +++ b/src/soft/SoftPhysicalDevice.zig @@ -30,6 +30,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkEr .getFormatProperties = getFormatProperties, .getImageFormatProperties = getImageFormatProperties, .getSparseImageFormatProperties = getSparseImageFormatProperties, + .getSparseImageFormatProperties2 = getSparseImageFormatProperties2, .release = destroy, }; @@ -670,6 +671,7 @@ pub fn getImageFormatProperties( }; } +/// Soft does not support sparse images. pub fn getSparseImageFormatProperties( interface: *Interface, format: vk.Format, @@ -677,14 +679,34 @@ pub fn getSparseImageFormatProperties( samples: vk.SampleCountFlags, tiling: vk.ImageTiling, usage: vk.ImageUsageFlags, - flags: vk.ImageCreateFlags, -) VkError!vk.SparseImageFormatProperties { + properties: ?[*]vk.SparseImageFormatProperties, +) VkError!u32 { _ = interface; _ = format; _ = image_type; _ = samples; _ = tiling; _ = usage; - _ = flags; - return undefined; + _ = properties; + return 0; +} + +/// Soft does not support sparse images. +pub fn getSparseImageFormatProperties2( + interface: *Interface, + format: vk.Format, + image_type: vk.ImageType, + samples: vk.SampleCountFlags, + tiling: vk.ImageTiling, + usage: vk.ImageUsageFlags, + properties: ?[*]vk.SparseImageFormatProperties2, +) VkError!u32 { + _ = interface; + _ = format; + _ = image_type; + _ = samples; + _ = tiling; + _ = usage; + _ = properties; + return 0; } diff --git a/src/vulkan/CommandBuffer.zig b/src/vulkan/CommandBuffer.zig index 524add6..88aac56 100644 --- a/src/vulkan/CommandBuffer.zig +++ b/src/vulkan/CommandBuffer.zig @@ -42,7 +42,7 @@ pub const DispatchTable = struct { begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void, clearColorImage: *const fn (*Self, *Image, vk.ImageLayout, *const vk.ClearColorValue, []const vk.ImageSubresourceRange) VkError!void, copyBuffer: *const fn (*Self, *Buffer, *Buffer, []const vk.BufferCopy) VkError!void, - copyImage: *const fn (*Self, *Image, *Image, []const vk.ImageCopy) VkError!void, + copyImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageCopy) VkError!void, end: *const fn (*Self) VkError!void, fillBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, vk.DeviceSize, u32) VkError!void, reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void, @@ -153,14 +153,16 @@ pub inline fn copyBuffer(self: *Self, src: *Buffer, dst: *Buffer, regions: []con try self.dispatch_table.copyBuffer(self, src, dst, regions); } -pub inline fn copyImage(self: *Self, src: *Image, dst: *Image, regions: []const vk.ImageCopy) VkError!void { +pub inline fn copyImage(self: *Self, src: *Image, src_layout: vk.ImageLayout, dst: *Image, dst_layout: vk.ImageLayout, regions: []const vk.ImageCopy) VkError!void { const allocator = self.host_allocator.allocator(); self.commands.append(allocator, .{ .CopyImage = .{ .src = src, + .src_layout = src_layout, .dst = dst, + .dst_layout = dst_layout, .regions = allocator.dupe(vk.ImageCopy, regions) catch return VkError.OutOfHostMemory, } }) catch return VkError.OutOfHostMemory; - try self.dispatch_table.copyImage(self, src, dst, regions); + try self.dispatch_table.copyImage(self, src, src_layout, dst, dst_layout, regions); } pub inline fn fillBuffer(self: *Self, buffer: *Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void { diff --git a/src/vulkan/Device.zig b/src/vulkan/Device.zig index 5df9356..3d573f7 100644 --- a/src/vulkan/Device.zig +++ b/src/vulkan/Device.zig @@ -99,8 +99,8 @@ pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.D const queue = try self.vtable.createQueue(allocator, self, queue_info.queue_family_index, @intCast(family_ptr.items.len), queue_info.flags); - logger.manager.get().indent(); - defer logger.manager.get().unindent(); + logger.getManager().get().indent(); + defer logger.getManager().get().unindent(); const dispatchable_queue = try Dispatchable(Queue).wrap(allocator, queue); family_ptr.append(allocator, dispatchable_queue) catch return VkError.OutOfHostMemory; diff --git a/src/vulkan/Instance.zig b/src/vulkan/Instance.zig index 5c0d2ce..862cce1 100644 --- a/src/vulkan/Instance.zig +++ b/src/vulkan/Instance.zig @@ -15,6 +15,9 @@ comptime { if (!@hasDecl(root, "VULKAN_VERSION")) { @compileError("Missing VULKAN_VERSION in module root"); } + if (!@hasDecl(root.Instance, "EXTENSIONS")) { + @compileError("Missing EXTENSIONS in Instance's implementation"); + } } } @@ -31,7 +34,7 @@ pub const VTable = struct { }; pub const DispatchTable = struct { - destroyInstance: *const fn (*Self, std.mem.Allocator) VkError!void, + destroy: *const fn (*Self, std.mem.Allocator) VkError!void, }; pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!Self { @@ -53,18 +56,19 @@ pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) pub fn deinit(self: *Self, allocator: std.mem.Allocator) VkError!void { try self.releasePhysicalDevices(allocator); - try self.dispatch_table.destroyInstance(self, allocator); + try self.dispatch_table.destroy(self, allocator); } -pub fn enumerateExtensionProperties(layer_name: ?[]const u8, property_count: *u32, properties: ?*vk.ExtensionProperties) VkError!void { +pub fn enumerateExtensionProperties(layer_name: ?[]const u8, count: *u32, p_properties: ?[*]vk.ExtensionProperties) VkError!void { if (layer_name) |_| { return VkError.LayerNotPresent; } - - _ = properties; - _ = std.StaticStringMap(vk.ExtensionProperties).initComptime(.{}); - - property_count.* = 0; + count.* = root.Instance.EXTENSIONS.len; + if (p_properties) |properties| { + for (root.Instance.EXTENSIONS, 0..) |ext, i| { + properties[i] = ext; + } + } } pub fn enumerateVersion(version: *u32) VkError!void { @@ -80,8 +84,8 @@ pub fn releasePhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError } pub fn requestPhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void { - logger.manager.get().indent(); - defer logger.manager.get().unindent(); + logger.getManager().get().indent(); + defer logger.getManager().get().unindent(); try self.vtable.requestPhysicalDevices(self, allocator); if (self.physical_devices.items.len == 0) { diff --git a/src/vulkan/PhysicalDevice.zig b/src/vulkan/PhysicalDevice.zig index c58d82e..1f11135 100644 --- a/src/vulkan/PhysicalDevice.zig +++ b/src/vulkan/PhysicalDevice.zig @@ -20,7 +20,8 @@ pub const DispatchTable = struct { createDevice: *const fn (*Self, std.mem.Allocator, *const vk.DeviceCreateInfo) VkError!*Device, getFormatProperties: *const fn (*Self, vk.Format) VkError!vk.FormatProperties, getImageFormatProperties: *const fn (*Self, vk.Format, vk.ImageType, vk.ImageTiling, vk.ImageUsageFlags, vk.ImageCreateFlags) VkError!vk.ImageFormatProperties, - getSparseImageFormatProperties: *const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, vk.ImageCreateFlags) VkError!vk.SparseImageFormatProperties, + getSparseImageFormatProperties: *const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, ?[*]vk.SparseImageFormatProperties) VkError!u32, + getSparseImageFormatProperties2: ?*const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, ?[*]vk.SparseImageFormatProperties2) VkError!u32, release: *const fn (*Self, std.mem.Allocator) VkError!void, }; @@ -67,7 +68,7 @@ pub fn getImageFormatProperties( usage: vk.ImageUsageFlags, flags: vk.ImageCreateFlags, ) VkError!vk.ImageFormatProperties { - return try self.dispatch_table.getImageFormatProperties(self, format, image_type, tiling, usage, flags); + return self.dispatch_table.getImageFormatProperties(self, format, image_type, tiling, usage, flags); } pub fn getSparseImageFormatProperties( @@ -77,9 +78,24 @@ pub fn getSparseImageFormatProperties( samples: vk.SampleCountFlags, tiling: vk.ImageTiling, usage: vk.ImageUsageFlags, - flags: vk.ImageCreateFlags, -) VkError!vk.SparseImageFormatProperties { - return try self.dispatch_table.getSparseImageFormatProperties(self, format, image_type, samples, tiling, usage, flags); + properties: ?[*]vk.SparseImageFormatProperties, +) VkError!u32 { + return self.dispatch_table.getSparseImageFormatProperties(self, format, image_type, samples, tiling, usage, properties); +} + +pub fn getSparseImageFormatProperties2( + self: *Self, + format: vk.Format, + image_type: vk.ImageType, + samples: vk.SampleCountFlags, + tiling: vk.ImageTiling, + usage: vk.ImageUsageFlags, + properties: ?[*]vk.SparseImageFormatProperties2, +) VkError!u32 { + return if (self.dispatch_table.getSparseImageFormatProperties2) |pfn| + pfn(self, format, image_type, samples, tiling, usage, properties) + else + 0; } pub fn releasePhysicalDevice(self: *Self, allocator: std.mem.Allocator) VkError!void { diff --git a/src/vulkan/commands.zig b/src/vulkan/commands.zig index 2366744..273405a 100644 --- a/src/vulkan/commands.zig +++ b/src/vulkan/commands.zig @@ -38,7 +38,9 @@ pub const CommandCopyBuffer = struct { }; pub const CommandCopyImage = struct { src: *Image, + src_layout: vk.ImageLayout, dst: *Image, + dst_layout: vk.ImageLayout, regions: []const vk.ImageCopy, }; pub const CommandDraw = struct { diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index 8a92964..9290d1f 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -46,11 +46,11 @@ pub const ShaderModule = @import("ShaderModule.zig"); fn entryPointBeginLogTrace(comptime scope: @Type(.enum_literal)) void { std.log.scoped(scope).debug("Calling {s}...", .{@tagName(scope)}); - logger.manager.get().indent(); + logger.getManager().get().indent(); } fn entryPointEndLogTrace() void { - logger.manager.get().unindent(); + logger.getManager().get().unindent(); } fn entryPointNotFoundErrorLog(comptime scope: @Type(.enum_literal), name: []const u8) void { @@ -97,12 +97,19 @@ const physical_device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComp functionMapEntryPoint("vkCreateDevice"), functionMapEntryPoint("vkEnumerateDeviceExtensionProperties"), functionMapEntryPoint("vkGetPhysicalDeviceFeatures"), + functionMapEntryPoint("vkGetPhysicalDeviceFeatures2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceFormatProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceFormatProperties2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceImageFormatProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceImageFormatProperties2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceMemoryProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceMemoryProperties2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceProperties2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceQueueFamilyProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceQueueFamilyProperties2KHR"), functionMapEntryPoint("vkGetPhysicalDeviceSparseImageFormatProperties"), + functionMapEntryPoint("vkGetPhysicalDeviceSparseImageFormatProperties2KHR"), }); const device_pfn_map = block: { @@ -283,14 +290,11 @@ pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, p_name: ?[*:0]const const name = std.mem.span(p_name.?); if (global_pfn_map.get(name)) |pfn| return pfn; - if (p_instance == .null_handle) { - entryPointNotFoundErrorLog(.vkGetInstanceProcAddr, name); - return null; + if (p_instance != .null_handle) { + 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; } - 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; - entryPointNotFoundErrorLog(.vkGetInstanceProcAddr, name); return null; } @@ -315,7 +319,7 @@ pub export fn strollCreateInstance(info: *const vk.InstanceCreateInfo, callbacks return .success; } -pub export fn strollEnumerateInstanceExtensionProperties(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 { entryPointBeginLogTrace(.vkEnumerateInstanceExtensionProperties); defer entryPointEndLogTrace(); @@ -338,7 +342,7 @@ pub export fn strollEnumerateInstanceVersion(version: *u32) callconv(vk.vulkan_c // Instance functions ======================================================================================================================================== pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { - //defer logger.manager.deinit(); + defer logger.getManager().deinit(); entryPointBeginLogTrace(.vkDestroyInstance); defer entryPointEndLogTrace(); @@ -405,6 +409,16 @@ pub export fn strollGetPhysicalDeviceFormatProperties(p_physical_device: vk.Phys properties.* = physical_device.getFormatProperties(format) catch |err| return errorLogger(err); } +pub export fn strollGetPhysicalDeviceFormatProperties2KHR(p_physical_device: vk.PhysicalDevice, format: vk.Format, properties: *vk.FormatProperties2KHR) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkGetPhysicalDeviceFormatProperties2KHR); + defer entryPointEndLogTrace(); + + if (properties.s_type != .format_properties_2) return; + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return errorLogger(err); + properties.format_properties = physical_device.getFormatProperties(format) catch |err| return errorLogger(err); +} + pub export fn strollGetPhysicalDeviceFeatures(p_physical_device: vk.PhysicalDevice, features: *vk.PhysicalDeviceFeatures) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkGetPhysicalDeviceFeatures); defer entryPointEndLogTrace(); @@ -413,6 +427,16 @@ pub export fn strollGetPhysicalDeviceFeatures(p_physical_device: vk.PhysicalDevi features.* = physical_device.features; } +pub export fn strollGetPhysicalDeviceFeatures2KHR(p_physical_device: vk.PhysicalDevice, features: *vk.PhysicalDeviceFeatures2KHR) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkGetPhysicalDeviceFeatures2KHR); + defer entryPointEndLogTrace(); + + if (features.s_type != .physical_device_features_2) return; + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return errorLogger(err); + features.features = physical_device.features; +} + pub export fn strollGetPhysicalDeviceImageFormatProperties( p_physical_device: vk.PhysicalDevice, format: vk.Format, @@ -430,6 +454,24 @@ pub export fn strollGetPhysicalDeviceImageFormatProperties( return .success; } +pub export fn strollGetPhysicalDeviceImageFormatProperties2KHR(p_physical_device: vk.PhysicalDevice, format_info: *vk.PhysicalDeviceImageFormatInfo2KHR, properties: *vk.ImageFormatProperties2KHR) callconv(vk.vulkan_call_conv) vk.Result { + entryPointBeginLogTrace(.vkGetPhysicalDeviceImageFormatProperties2KHR); + defer entryPointEndLogTrace(); + + if (format_info.s_type != .physical_device_image_format_info_2) return .error_validation_failed; + if (properties.s_type != .image_format_properties_2) return .error_validation_failed; + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); + properties.image_format_properties = physical_device.getImageFormatProperties( + format_info.format, + format_info.type, + format_info.tiling, + format_info.usage, + format_info.flags, + ) catch |err| return toVkResult(err); + return .success; +} + pub export fn strollGetPhysicalDeviceProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceProperties) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkGetPhysicalDeviceProperties); defer entryPointEndLogTrace(); @@ -438,6 +480,16 @@ pub export fn strollGetPhysicalDeviceProperties(p_physical_device: vk.PhysicalDe properties.* = physical_device.props; } +pub export fn strollGetPhysicalDeviceProperties2KHR(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceProperties2KHR) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkGetPhysicalDeviceProperties2KHR); + defer entryPointEndLogTrace(); + + if (properties.s_type != .physical_device_properties_2) return; + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return errorLogger(err); + properties.properties = physical_device.props; +} + pub export fn strollGetPhysicalDeviceMemoryProperties(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceMemoryProperties) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkGetPhysicalDeviceMemoryProperties); defer entryPointEndLogTrace(); @@ -446,6 +498,16 @@ pub export fn strollGetPhysicalDeviceMemoryProperties(p_physical_device: vk.Phys properties.* = physical_device.mem_props; } +pub export fn strollGetPhysicalDeviceMemoryProperties2KHR(p_physical_device: vk.PhysicalDevice, properties: *vk.PhysicalDeviceMemoryProperties2KHR) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkGetPhysicalDeviceMemoryProperties2KHR); + defer entryPointEndLogTrace(); + + if (properties.s_type != .physical_device_memory_properties_2) return; + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return errorLogger(err); + properties.memory_properties = physical_device.mem_props; +} + pub export fn strollGetPhysicalDeviceQueueFamilyProperties(p_physical_device: vk.PhysicalDevice, count: *u32, properties: ?[*]vk.QueueFamilyProperties) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkGetPhysicalDeviceQueueFamilyProperties); defer entryPointEndLogTrace(); @@ -457,21 +519,56 @@ pub export fn strollGetPhysicalDeviceQueueFamilyProperties(p_physical_device: vk } } +pub export fn strollGetPhysicalDeviceQueueFamilyProperties2KHR(p_physical_device: vk.PhysicalDevice, count: *u32, properties: ?[*]vk.QueueFamilyProperties2KHR) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkGetPhysicalDeviceQueueFamilyProperties2KHR); + defer entryPointEndLogTrace(); + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return errorLogger(err); + count.* = @intCast(physical_device.queue_family_props.items.len); + if (properties) |p_props| { + for (p_props[0..], physical_device.queue_family_props.items[0..], 0..count.*) |*props, device_props, _| { + if (props.s_type != .queue_family_properties_2) continue; + props.queue_family_properties = device_props; + } + } +} + pub export fn strollGetPhysicalDeviceSparseImageFormatProperties( p_physical_device: vk.PhysicalDevice, format: vk.Format, image_type: vk.ImageType, samples: vk.SampleCountFlags, - tiling: vk.ImageTiling, usage: vk.ImageUsageFlags, - flags: vk.ImageCreateFlags, - properties: *vk.SparseImageFormatProperties, + tiling: vk.ImageTiling, + count: *u32, + properties: ?[*]vk.SparseImageFormatProperties, ) callconv(vk.vulkan_call_conv) vk.Result { entryPointBeginLogTrace(.vkGetPhysicalDeviceSparseImageFormatProperties); defer entryPointEndLogTrace(); const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); - properties.* = physical_device.getSparseImageFormatProperties(format, image_type, samples, tiling, usage, flags) catch |err| return toVkResult(err); + count.* = physical_device.getSparseImageFormatProperties(format, image_type, samples, tiling, usage, properties) catch |err| return toVkResult(err); + return .success; +} + +pub export fn strollGetPhysicalDeviceSparseImageFormatProperties2KHR( + p_physical_device: vk.PhysicalDevice, + format_info: *const vk.PhysicalDeviceSparseImageFormatInfo2KHR, + count: *u32, + properties: ?[*]vk.SparseImageFormatProperties2KHR, +) callconv(vk.vulkan_call_conv) vk.Result { + entryPointBeginLogTrace(.vkGetPhysicalDeviceSparseImageFormatProperties2KHR); + defer entryPointEndLogTrace(); + + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); + count.* = physical_device.getSparseImageFormatProperties2( + format_info.format, + format_info.type, + format_info.samples, + format_info.tiling, + format_info.usage, + properties, + ) catch |err| return toVkResult(err); return .success; } @@ -647,14 +744,35 @@ pub export fn strollCreateComputePipelines(p_device: vk.Device, p_cache: vk.Pipe const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); const cache = if (p_cache == .null_handle) null else NonDispatchable(PipelineCache).fromHandleObject(p_cache) catch |err| return toVkResult(err); + var global_res: vk.Result = .success; + for (p_pipelines, infos, 0..count) |*p_pipeline, *info, _| { if (info.s_type != .compute_pipeline_create_info) { return .error_validation_failed; } - const pipeline = device.createComputePipeline(allocator, cache, info) catch |err| return toVkResult(err); - p_pipeline.* = (NonDispatchable(Pipeline).wrap(allocator, pipeline) catch |err| return toVkResult(err)).toVkHandle(vk.Pipeline); + + // According to the Vulkan spec, section 9.4. Multiple Pipeline Creation + // "When an application attempts to create many pipelines in a single command, + // it is possible that some subset may fail creation. In that case, the + // corresponding entries in the pPipelines output array will be filled with + // VK_NULL_HANDLE values. If any pipeline fails creation (for example, due to + // out of memory errors), the vkCreate*Pipelines commands will return an + // error code. The implementation will attempt to create all pipelines, and + // only return VK_NULL_HANDLE values for those that actually failed." + p_pipeline.*, const local_res = blk: { + const pipeline = device.createComputePipeline(allocator, cache, info) catch |err| break :blk .{ .null_handle, toVkResult(err) }; + const handle = NonDispatchable(Pipeline).wrap(allocator, pipeline) catch |err| { + pipeline.destroy(allocator); + break :blk .{ .null_handle, toVkResult(err) }; + }; + break :blk .{ handle.toVkHandle(vk.Pipeline), .success }; + }; + + if (local_res != .success) { + global_res = local_res; + } } - return .success; + return global_res; } pub export fn strollCreateDescriptorPool(p_device: vk.Device, info: *const vk.DescriptorPoolCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_pool: *vk.DescriptorPool) callconv(vk.vulkan_call_conv) vk.Result { @@ -740,14 +858,35 @@ pub export fn strollCreateGraphicsPipelines(p_device: vk.Device, p_cache: vk.Pip const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); const cache = if (p_cache == .null_handle) null else NonDispatchable(PipelineCache).fromHandleObject(p_cache) catch |err| return toVkResult(err); + var global_res: vk.Result = .success; + for (p_pipelines, infos, 0..count) |*p_pipeline, *info, _| { if (info.s_type != .graphics_pipeline_create_info) { return .error_validation_failed; } - const pipeline = device.createGraphicsPipeline(allocator, cache, info) catch |err| return toVkResult(err); - p_pipeline.* = (NonDispatchable(Pipeline).wrap(allocator, pipeline) catch |err| return toVkResult(err)).toVkHandle(vk.Pipeline); + + // According to the Vulkan spec, section 9.4. Multiple Pipeline Creation + // "When an application attempts to create many pipelines in a single command, + // it is possible that some subset may fail creation. In that case, the + // corresponding entries in the pPipelines output array will be filled with + // VK_NULL_HANDLE values. If any pipeline fails creation (for example, due to + // out of memory errors), the vkCreate*Pipelines commands will return an + // error code. The implementation will attempt to create all pipelines, and + // only return VK_NULL_HANDLE values for those that actually failed." + p_pipeline.*, const local_res = blk: { + const pipeline = device.createGraphicsPipeline(allocator, cache, info) catch |err| break :blk .{ .null_handle, toVkResult(err) }; + const handle = NonDispatchable(Pipeline).wrap(allocator, pipeline) catch |err| { + pipeline.destroy(allocator); + break :blk .{ .null_handle, toVkResult(err) }; + }; + break :blk .{ handle.toVkHandle(vk.Pipeline), .success }; + }; + + if (local_res != .success) { + global_res = local_res; + } } - return .success; + return global_res; } pub export fn strollCreateImage(p_device: vk.Device, info: *const vk.ImageCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_image: *vk.Image) callconv(vk.vulkan_call_conv) vk.Result { @@ -1630,7 +1769,7 @@ pub export fn strollCmdClearAttachments(p_cmd: vk.CommandBuffer, attachment_coun } pub export fn strollCmdClearColorImage(p_cmd: vk.CommandBuffer, p_image: vk.Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, count: u32, ranges: [*]const vk.ImageSubresourceRange) callconv(vk.vulkan_call_conv) void { - entryPointBeginLogTrace(.vkCmdCopyImage); + entryPointBeginLogTrace(.vkCmdClearColorImage); defer entryPointEndLogTrace(); const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err); @@ -1683,14 +1822,14 @@ pub export fn strollCmdCopyBufferToImage(p_cmd: vk.CommandBuffer, p_src: vk.Buff _ = regions; } -pub export fn strollCmdCopyImage(p_cmd: vk.CommandBuffer, p_src: vk.Image, p_dst: vk.Image, count: u32, regions: [*]const vk.ImageCopy) callconv(vk.vulkan_call_conv) void { +pub export fn strollCmdCopyImage(p_cmd: vk.CommandBuffer, p_src: vk.Image, src_layout: vk.ImageLayout, p_dst: vk.Image, dst_layout: vk.ImageLayout, count: u32, regions: [*]const vk.ImageCopy) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkCmdCopyImage); defer entryPointEndLogTrace(); const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err); const src = NonDispatchable(Image).fromHandleObject(p_src) catch |err| return errorLogger(err); const dst = NonDispatchable(Image).fromHandleObject(p_dst) catch |err| return errorLogger(err); - cmd.copyImage(src, dst, regions[0..count]) catch |err| return errorLogger(err); + cmd.copyImage(src, src_layout, dst, dst_layout, regions[0..count]) catch |err| return errorLogger(err); } pub export fn strollCmdCopyImageToBuffer(p_cmd: vk.CommandBuffer, p_src: vk.Image, layout: vk.ImageLayout, p_dst: vk.Buffer, count: u32, regions: [*]const vk.BufferImageCopy) callconv(vk.vulkan_call_conv) void { diff --git a/src/vulkan/logger/ThreadSafeManager.zig b/src/vulkan/logger/ThreadSafeManager.zig index e06b913..de98227 100644 --- a/src/vulkan/logger/ThreadSafeManager.zig +++ b/src/vulkan/logger/ThreadSafeManager.zig @@ -23,12 +23,20 @@ pub fn get(self: *Self) *Manager { } pub fn deinit(self: *Self) void { - self.mutex.lock(); - defer self.mutex.unlock(); + { + self.mutex.lock(); + defer self.mutex.unlock(); - var it = self.managers.iterator(); - while (it.next()) |entry| { - entry.value_ptr.deinit(); + if (self.managers.getPtr(std.Thread.getCurrentId())) |manager| { + manager.deinit(); + _ = self.managers.orderedRemove(std.Thread.getCurrentId()); + } + } + if (self.managers.count() == 0) { + self.mutex.lock(); + self.mutex.unlock(); + + self.managers.deinit(self.allocator.allocator()); + self.* = .init; } - self.managers.deinit(self.allocator.allocator()); } diff --git a/src/vulkan/logger/logger.zig b/src/vulkan/logger/logger.zig index 3424a5a..898bd11 100644 --- a/src/vulkan/logger/logger.zig +++ b/src/vulkan/logger/logger.zig @@ -17,11 +17,15 @@ comptime { } } -pub var manager: ThreadSafeManager = .init; +var manager: ThreadSafeManager = .init; + +pub inline fn getManager() *ThreadSafeManager { + return &manager; +} pub inline fn fixme(comptime format: []const u8, args: anytype) void { - manager.get().disableIndent(); - defer manager.get().enableIndent(); + getManager().get().disableIndent(); + defer getManager().get().enableIndent(); nestedFixme(format, args); } @@ -93,8 +97,8 @@ pub fn log(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), out_config.setColor(&writer, .reset) catch {}; - if (manager.get().indent_enabled) { - for (0..manager.get().indent_level) |_| { + if (getManager().get().indent_enabled) { + for (0..getManager().get().indent_level) |_| { writer.print("> ", .{}) catch {}; } } @@ -102,17 +106,17 @@ pub fn log(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), writer.flush() catch return; if (level == .debug and lib.getLogVerboseLevel() == .Standard) { - manager.get().debug_stack.pushBack(.{ + getManager().get().debug_stack.pushBack(.{ .log = buffer, - .indent_level = manager.get().indent_level, + .indent_level = getManager().get().indent_level, .log_level = level, }) catch return; return; } - if (manager.get().indent_enabled) { - while (manager.get().debug_stack.len() != 0) { - const elem = manager.get().debug_stack.popFront(); + if (getManager().get().indent_enabled) { + while (getManager().get().debug_stack.len() != 0) { + const elem = getManager().get().debug_stack.popFront(); switch (elem.log_level) { .info, .debug => _ = stdout_file.write(&elem.log) catch {}, .warn, .err => _ = stderr_file.write(&elem.log) catch {},