diff --git a/README.md b/README.md index 736b0db..bbf6c16 100644 --- a/README.md +++ b/README.md @@ -96,10 +96,10 @@ vkCmdWaitEvents | ❌ Not implemented vkCmdWriteTimestamp | ❌ Not implemented vkCreateBuffer | ✅ Implemented vkCreateBufferView | ❌ Not implemented -vkCreateCommandPool | ❌ Not implemented +vkCreateCommandPool | ✅ Implemented vkCreateComputePipelines | ❌ Not implemented -vkCreateDescriptorPool | ❌ Not implemented -vkCreateDescriptorSetLayout | ❌ Not implemented +vkCreateDescriptorPool | ⚙️ WIP +vkCreateDescriptorSetLayout | ⚙️ WIP vkCreateDevice | ✅ Implemented vkCreateEvent | ❌ Not implemented vkCreateFence | ✅ Implemented @@ -117,9 +117,9 @@ vkCreateSemaphore | ❌ Not implemented vkCreateShaderModule | ❌ Not implemented vkDestroyBuffer | ✅ Implemented vkDestroyBufferView | ❌ Not implemented -vkDestroyCommandPool | ❌ Not implemented -vkDestroyDescriptorPool | ❌ Not implemented -vkDestroyDescriptorSetLayout | ❌ Not implemented +vkDestroyCommandPool | ✅ Implemented +vkDestroyDescriptorPool | ⚙️ WIP +vkDestroyDescriptorSetLayout | ⚙️ WIP vkDestroyDevice | ✅ Implemented vkDestroyEvent | ❌ Not implemented vkDestroyFence | ✅ Implemented @@ -144,7 +144,7 @@ vkEnumerateInstanceLayerProperties | ⚙️ WIP vkEnumeratePhysicalDevices | ✅ Implemented vkFlushMappedMemoryRanges | ❌ Not implemented vkFreeCommandBuffers | ✅ Implemented -vkFreeDescriptorSets | ❌ Not implemented +vkFreeDescriptorSets | ⚙️ WIP vkFreeMemory | ✅ Implemented vkGetBufferMemoryRequirements | ✅ Implemented vkGetDeviceMemoryCommitment | ❌ Not implemented diff --git a/src/soft/SoftDescriptorPool.zig b/src/soft/SoftDescriptorPool.zig new file mode 100644 index 0000000..0b809b3 --- /dev/null +++ b/src/soft/SoftDescriptorPool.zig @@ -0,0 +1,38 @@ +const std = @import("std"); +const vk = @import("vulkan"); +const base = @import("base"); + +const VkError = base.VkError; +const Device = base.Device; + +const Self = @This(); +pub const Interface = base.DescriptorPool; + +interface: Interface, + +pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.DescriptorPoolCreateInfo) VkError!*Self { + const self = allocator.create(Self) catch return VkError.OutOfHostMemory; + errdefer allocator.destroy(self); + + var interface = try Interface.init(device, allocator, info); + + interface.vtable = &.{ + .destroy = destroy, + .freeDescriptorSets = freeDescriptorSets, + }; + + self.* = .{ + .interface = interface, + }; + return self; +} + +pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void { + const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); + allocator.destroy(self); +} + +pub fn freeDescriptorSets(interface: *Interface, sets: []*base.Dispatchable(base.DescriptorSet)) VkError!void { + _ = interface; + _ = sets; +} diff --git a/src/soft/SoftDescriptorSetLayout.zig b/src/soft/SoftDescriptorSetLayout.zig new file mode 100644 index 0000000..b2d706e --- /dev/null +++ b/src/soft/SoftDescriptorSetLayout.zig @@ -0,0 +1,32 @@ +const std = @import("std"); +const vk = @import("vulkan"); +const base = @import("base"); + +const VkError = base.VkError; +const Device = base.Device; + +const Self = @This(); +pub const Interface = base.DescriptorSetLayout; + +interface: Interface, + +pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.DescriptorSetLayoutCreateInfo) VkError!*Self { + const self = allocator.create(Self) catch return VkError.OutOfHostMemory; + errdefer allocator.destroy(self); + + var interface = try Interface.init(device, allocator, info); + + interface.vtable = &.{ + .destroy = destroy, + }; + + self.* = .{ + .interface = interface, + }; + return self; +} + +pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void { + const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); + allocator.destroy(self); +} diff --git a/src/soft/SoftDevice.zig b/src/soft/SoftDevice.zig index ddf0f87..a719aeb 100644 --- a/src/soft/SoftDevice.zig +++ b/src/soft/SoftDevice.zig @@ -10,6 +10,8 @@ const SoftQueue = @import("SoftQueue.zig"); const SoftBuffer = @import("SoftBuffer.zig"); const SoftDeviceMemory = @import("SoftDeviceMemory.zig"); +const SoftDescriptorPool = @import("SoftDescriptorPool.zig"); +const SoftDescriptorSetLayout = @import("SoftDescriptorSetLayout.zig"); const SoftFence = @import("SoftFence.zig"); const SoftImage = @import("SoftImage.zig"); const SoftImageView = @import("SoftImageView.zig"); @@ -40,6 +42,8 @@ pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocato .allocateMemory = allocateMemory, .createBuffer = createBuffer, .createCommandPool = createCommandPool, + .createDescriptorPool = createDescriptorPool, + .createDescriptorSetLayout = createDescriptorSetLayout, .createFence = createFence, .createImage = createImage, .createImageView = createImageView, @@ -86,6 +90,16 @@ pub fn createBuffer(interface: *Interface, allocator: std.mem.Allocator, info: * return &buffer.interface; } +pub fn createDescriptorPool(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.DescriptorPoolCreateInfo) VkError!*base.DescriptorPool { + const pool = try SoftDescriptorPool.create(interface, allocator, info); + return &pool.interface; +} + +pub fn createDescriptorSetLayout(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.DescriptorSetLayoutCreateInfo) VkError!*base.DescriptorSetLayout { + const layout = try SoftDescriptorSetLayout.create(interface, allocator, info); + return &layout.interface; +} + pub fn createFence(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.FenceCreateInfo) VkError!*base.Fence { const fence = try SoftFence.create(interface, allocator, info); return &fence.interface; diff --git a/src/soft/lib.zig b/src/soft/lib.zig index 035ec5b..58095de 100644 --- a/src/soft/lib.zig +++ b/src/soft/lib.zig @@ -13,6 +13,8 @@ pub const SoftBuffer = @import("SoftBuffer.zig"); pub const SoftCommandBuffer = @import("SoftCommandBuffer.zig"); pub const SoftCommandPool = @import("SoftCommandPool.zig"); pub const SoftDeviceMemory = @import("SoftDeviceMemory.zig"); +pub const SoftDescriptorPool = @import("SoftDescriptorPool.zig"); +pub const SoftDescriptorSetLayout = @import("SoftDescriptorSetLayout.zig"); pub const SoftFence = @import("SoftFence.zig"); pub const SoftImage = @import("SoftImage.zig"); pub const SoftImageView = @import("SoftImageView.zig"); diff --git a/src/vulkan/DescriptorPool.zig b/src/vulkan/DescriptorPool.zig index 2ea2a31..59d315a 100644 --- a/src/vulkan/DescriptorPool.zig +++ b/src/vulkan/DescriptorPool.zig @@ -2,9 +2,12 @@ const std = @import("std"); const vk = @import("vulkan"); const VkError = @import("error_set.zig").VkError; +const Dispatchable = @import("Dispatchable.zig").Dispatchable; const Device = @import("Device.zig"); +const DescriptorSet = @import("DescriptorSet.zig"); + const Self = @This(); pub const ObjectType: vk.ObjectType = .descriptor_pool; @@ -15,6 +18,7 @@ vtable: *const VTable, pub const VTable = struct { destroy: *const fn (*Self, std.mem.Allocator) void, + freeDescriptorSets: *const fn (*Self, []*Dispatchable(DescriptorSet)) VkError!void, }; pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.DescriptorPoolCreateInfo) VkError!Self { @@ -22,9 +26,14 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Descr return .{ .owner = device, .flags = info.flags, + .vtable = undefined, }; } pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void { self.vtable.destroy(self, allocator); } + +pub inline fn freeDescriptorSets(self: *Self, sets: []*Dispatchable(DescriptorSet)) VkError!void { + try self.vtable.freeDescriptorSets(self, sets); +} diff --git a/src/vulkan/DescriptorSet.zig b/src/vulkan/DescriptorSet.zig index 4d8aa05..dc1b6fb 100644 --- a/src/vulkan/DescriptorSet.zig +++ b/src/vulkan/DescriptorSet.zig @@ -32,6 +32,7 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Descr return .{ .owner = device, .layouts = layouts, + .vtable = undefined, }; } diff --git a/src/vulkan/DescriptorSetLayout.zig b/src/vulkan/DescriptorSetLayout.zig index a50ccc3..c247ca3 100644 --- a/src/vulkan/DescriptorSetLayout.zig +++ b/src/vulkan/DescriptorSetLayout.zig @@ -8,7 +8,7 @@ const Self = @This(); pub const ObjectType: vk.ObjectType = .descriptor_set_layout; owner: *Device, -bindings: []const vk.DescriptorSetLayoutBinding, +bindings: ?[]const vk.DescriptorSetLayoutBinding, vtable: *const VTable, @@ -17,9 +17,15 @@ pub const VTable = struct { }; pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.DescriptorSetLayoutCreateInfo) VkError!Self { + const bindings = if (info.p_bindings) |bindings| + allocator.dupe(vk.DescriptorSetLayoutBinding, bindings[0..info.binding_count]) catch return VkError.OutOfHostMemory + else + null; + return .{ .owner = device, - .bindings = allocator.dupe(info.bindings[0..info.binding_count]) catch return VkError.OutOfHostMemory, + .bindings = bindings, + .vtable = undefined, }; } diff --git a/src/vulkan/Device.zig b/src/vulkan/Device.zig index 1868059..5d8db6a 100644 --- a/src/vulkan/Device.zig +++ b/src/vulkan/Device.zig @@ -13,6 +13,9 @@ const Buffer = @import("Buffer.zig"); const CommandBuffer = @import("CommandBuffer.zig"); const CommandPool = @import("CommandPool.zig"); const DeviceMemory = @import("DeviceMemory.zig"); +const DescriptorPool = @import("DescriptorPool.zig"); +const DescriptorSet = @import("DescriptorSet.zig"); +const DescriptorSetLayout = @import("DescriptorSetLayout.zig"); const Fence = @import("Fence.zig"); const Image = @import("Image.zig"); const ImageView = @import("ImageView.zig"); @@ -36,6 +39,8 @@ pub const DispatchTable = struct { allocateMemory: *const fn (*Self, std.mem.Allocator, *const vk.MemoryAllocateInfo) VkError!*DeviceMemory, createBuffer: *const fn (*Self, std.mem.Allocator, *const vk.BufferCreateInfo) VkError!*Buffer, createCommandPool: *const fn (*Self, std.mem.Allocator, *const vk.CommandPoolCreateInfo) VkError!*CommandPool, + createDescriptorPool: *const fn (*Self, std.mem.Allocator, *const vk.DescriptorPoolCreateInfo) VkError!*DescriptorPool, + createDescriptorSetLayout: *const fn (*Self, std.mem.Allocator, *const vk.DescriptorSetLayoutCreateInfo) VkError!*DescriptorSetLayout, createFence: *const fn (*Self, std.mem.Allocator, *const vk.FenceCreateInfo) VkError!*Fence, createImage: *const fn (*Self, std.mem.Allocator, *const vk.ImageCreateInfo) VkError!*Image, createImageView: *const fn (*Self, std.mem.Allocator, *const vk.ImageViewCreateInfo) VkError!*ImageView, @@ -96,6 +101,14 @@ pub inline fn createBuffer(self: *Self, allocator: std.mem.Allocator, info: *con return self.dispatch_table.createBuffer(self, allocator, info); } +pub inline fn createDescriptorPool(self: *Self, allocator: std.mem.Allocator, info: *const vk.DescriptorPoolCreateInfo) VkError!*DescriptorPool { + return self.dispatch_table.createDescriptorPool(self, allocator, info); +} + +pub inline fn createDescriptorSetLayout(self: *Self, allocator: std.mem.Allocator, info: *const vk.DescriptorSetLayoutCreateInfo) VkError!*DescriptorSetLayout { + return self.dispatch_table.createDescriptorSetLayout(self, allocator, info); +} + pub inline fn createFence(self: *Self, allocator: std.mem.Allocator, info: *const vk.FenceCreateInfo) VkError!*Fence { return self.dispatch_table.createFence(self, allocator, info); } diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index 1790a4a..4ca1488 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -94,54 +94,63 @@ const physical_device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComp functionMapEntryPoint("vkGetPhysicalDeviceSparseImageFormatProperties"), }); -const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ - functionMapEntryPoint("vkAllocateCommandBuffers"), - functionMapEntryPoint("vkAllocateDescriptorSets"), - functionMapEntryPoint("vkAllocateMemory"), - functionMapEntryPoint("vkBeginCommandBuffer"), - functionMapEntryPoint("vkBindBufferMemory"), - functionMapEntryPoint("vkBindImageMemory"), - functionMapEntryPoint("vkCmdBeginQuery"), - functionMapEntryPoint("vkCmdBeginRenderPass"), - functionMapEntryPoint("vkCmdBindDescriptorSets"), - functionMapEntryPoint("vkCmdBindIndexBuffer"), - functionMapEntryPoint("vkCmdBindPipeline"), - functionMapEntryPoint("vkCmdBindVertexBuffers"), - functionMapEntryPoint("vkCmdBlitImage"), - functionMapEntryPoint("vkCmdClearAttachments"), - functionMapEntryPoint("vkCmdClearColorImage"), - functionMapEntryPoint("vkCmdClearDepthStencilImage"), - functionMapEntryPoint("vkCmdCopyBuffer"), - functionMapEntryPoint("vkCmdCopyBufferToImage"), - functionMapEntryPoint("vkCmdCopyImage"), - functionMapEntryPoint("vkCmdFillBuffer"), - functionMapEntryPoint("vkCreateBuffer"), - functionMapEntryPoint("vkCreateCommandPool"), - functionMapEntryPoint("vkCreateFence"), - functionMapEntryPoint("vkCreateImage"), - functionMapEntryPoint("vkCreateImageView"), - functionMapEntryPoint("vkDestroyBuffer"), - functionMapEntryPoint("vkDestroyCommandPool"), - functionMapEntryPoint("vkDestroyDevice"), - functionMapEntryPoint("vkDestroyFence"), - functionMapEntryPoint("vkDestroyImage"), - functionMapEntryPoint("vkDestroyImageView"), - functionMapEntryPoint("vkEndCommandBuffer"), - functionMapEntryPoint("vkFreeCommandBuffers"), - functionMapEntryPoint("vkFreeMemory"), - functionMapEntryPoint("vkGetBufferMemoryRequirements"), - functionMapEntryPoint("vkGetDeviceQueue"), - functionMapEntryPoint("vkGetFenceStatus"), - functionMapEntryPoint("vkGetImageMemoryRequirements"), - functionMapEntryPoint("vkMapMemory"), - functionMapEntryPoint("vkQueueBindSparse"), - functionMapEntryPoint("vkQueueSubmit"), - functionMapEntryPoint("vkQueueWaitIdle"), - functionMapEntryPoint("vkResetCommandBuffer"), - functionMapEntryPoint("vkResetFences"), - functionMapEntryPoint("vkUnmapMemory"), - functionMapEntryPoint("vkWaitForFences"), -}); +const device_pfn_map = block: { + @setEvalBranchQuota(65535); + break :block std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ + functionMapEntryPoint("vkAllocateCommandBuffers"), + functionMapEntryPoint("vkAllocateDescriptorSets"), + functionMapEntryPoint("vkAllocateDescriptorSets"), + functionMapEntryPoint("vkAllocateMemory"), + functionMapEntryPoint("vkBeginCommandBuffer"), + functionMapEntryPoint("vkBindBufferMemory"), + functionMapEntryPoint("vkBindImageMemory"), + functionMapEntryPoint("vkCmdBeginQuery"), + functionMapEntryPoint("vkCmdBeginRenderPass"), + functionMapEntryPoint("vkCmdBindDescriptorSets"), + functionMapEntryPoint("vkCmdBindIndexBuffer"), + functionMapEntryPoint("vkCmdBindPipeline"), + functionMapEntryPoint("vkCmdBindVertexBuffers"), + functionMapEntryPoint("vkCmdBlitImage"), + functionMapEntryPoint("vkCmdClearAttachments"), + functionMapEntryPoint("vkCmdClearColorImage"), + functionMapEntryPoint("vkCmdClearDepthStencilImage"), + functionMapEntryPoint("vkCmdCopyBuffer"), + functionMapEntryPoint("vkCmdCopyBufferToImage"), + functionMapEntryPoint("vkCmdCopyImage"), + functionMapEntryPoint("vkCmdFillBuffer"), + functionMapEntryPoint("vkCreateBuffer"), + functionMapEntryPoint("vkCreateCommandPool"), + functionMapEntryPoint("vkCreateDescriptorPool"), + functionMapEntryPoint("vkCreateDescriptorSetLayout"), + functionMapEntryPoint("vkCreateFence"), + functionMapEntryPoint("vkCreateImage"), + functionMapEntryPoint("vkCreateImageView"), + functionMapEntryPoint("vkDestroyBuffer"), + functionMapEntryPoint("vkDestroyCommandPool"), + functionMapEntryPoint("vkDestroyDescriptorPool"), + functionMapEntryPoint("vkDestroyDescriptorSetLayout"), + functionMapEntryPoint("vkDestroyDevice"), + functionMapEntryPoint("vkDestroyFence"), + functionMapEntryPoint("vkDestroyImage"), + functionMapEntryPoint("vkDestroyImageView"), + functionMapEntryPoint("vkEndCommandBuffer"), + functionMapEntryPoint("vkFreeCommandBuffers"), + functionMapEntryPoint("vkFreeDescriptorSets"), + functionMapEntryPoint("vkFreeMemory"), + functionMapEntryPoint("vkGetBufferMemoryRequirements"), + functionMapEntryPoint("vkGetDeviceQueue"), + functionMapEntryPoint("vkGetFenceStatus"), + functionMapEntryPoint("vkGetImageMemoryRequirements"), + functionMapEntryPoint("vkMapMemory"), + functionMapEntryPoint("vkQueueBindSparse"), + functionMapEntryPoint("vkQueueSubmit"), + functionMapEntryPoint("vkQueueWaitIdle"), + functionMapEntryPoint("vkResetCommandBuffer"), + functionMapEntryPoint("vkResetFences"), + functionMapEntryPoint("vkUnmapMemory"), + functionMapEntryPoint("vkWaitForFences"), + }); +}; // ICD Interface ============================================================================================================================================= @@ -540,6 +549,36 @@ pub export fn strollCreateCommandPool(p_device: vk.Device, info: *const vk.Comma return .success; } +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 { + entryPointBeginLogTrace(.vkCreateDescriptorPool); + defer entryPointEndLogTrace(); + + if (info.s_type != .descriptor_pool_create_info) { + return .error_validation_failed; + } + + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); + const pool = device.createDescriptorPool(allocator, info) catch |err| return toVkResult(err); + p_pool.* = (NonDispatchable(DescriptorPool).wrap(allocator, pool) catch |err| return toVkResult(err)).toVkHandle(vk.DescriptorPool); + return .success; +} + +pub export fn strollCreateDescriptorSetLayout(p_device: vk.Device, info: *const vk.DescriptorSetLayoutCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_layout: *vk.DescriptorSetLayout) callconv(vk.vulkan_call_conv) vk.Result { + entryPointBeginLogTrace(.vkCreateDescriptorSetLayout); + defer entryPointEndLogTrace(); + + if (info.s_type != .descriptor_set_layout_create_info) { + return .error_validation_failed; + } + + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); + const layout = device.createDescriptorSetLayout(allocator, info) catch |err| return toVkResult(err); + p_layout.* = (NonDispatchable(DescriptorSetLayout).wrap(allocator, layout) catch |err| return toVkResult(err)).toVkHandle(vk.DescriptorSetLayout); + return .success; +} + pub export fn strollCreateFence(p_device: vk.Device, info: *const vk.FenceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_fence: *vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { entryPointBeginLogTrace(.vkCreateFence); defer entryPointEndLogTrace(); @@ -618,6 +657,28 @@ pub export fn strollDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.All dispatchable.destroy(allocator); } +pub export fn strollDestroyDescriptorPool(p_device: vk.Device, p_pool: vk.DescriptorPool, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkDestroyDescriptorPool); + defer entryPointEndLogTrace(); + + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return errorLogger(err); + + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(DescriptorPool).fromHandle(p_pool) catch |err| return errorLogger(err); + non_dispatchable.intrusiveDestroy(allocator); +} + +pub export fn strollDestroyDescriptorSetLayout(p_device: vk.Device, p_layout: vk.DescriptorSetLayout, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkDestroyDescriptorLayout); + defer entryPointEndLogTrace(); + + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return errorLogger(err); + + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(DescriptorSetLayout).fromHandle(p_layout) catch |err| return errorLogger(err); + non_dispatchable.intrusiveDestroy(allocator); +} + pub export fn strollDestroyFence(p_device: vk.Device, p_fence: vk.Fence, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkDestroyFence); defer entryPointEndLogTrace(); @@ -662,6 +723,17 @@ pub export fn strollFreeCommandBuffers(p_device: vk.Device, p_pool: vk.CommandPo pool.freeCommandBuffers(cmds[0..count]) catch |err| return errorLogger(err); } +pub export fn strollFreeDescriptorSets(p_device: vk.Device, p_pool: vk.CommandPool, count: u32, p_sets: [*]const vk.DescriptorSet) callconv(vk.vulkan_call_conv) void { + entryPointBeginLogTrace(.vkFreeDescriptorSets); + defer entryPointEndLogTrace(); + + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return errorLogger(err); + + const pool = NonDispatchable(DescriptorPool).fromHandleObject(p_pool) catch |err| return errorLogger(err); + const sets: [*]*Dispatchable(DescriptorSet) = @ptrCast(@constCast(p_sets)); + pool.freeDescriptorSets(sets[0..count]) catch |err| return errorLogger(err); +} + pub export fn strollFreeMemory(p_device: vk.Device, p_memory: vk.DeviceMemory, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { entryPointBeginLogTrace(.vkFreeMemory); defer entryPointEndLogTrace();