diff --git a/build.zig.zon b/build.zig.zon index 3a560e7..41847a1 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -32,8 +32,8 @@ .lazy = true, }, .kvf = .{ - .url = "git+https://github.com/Kbz-8/KVF#e69f907a96b9e636378288a973f23625177356c0", - .hash = "N-V-__8AAPaHAgA811W_sWLhxkbbE6uYWqaSQq9l36M_nMdY", + .url = "git+https://github.com/Kbz-8/KVF#f633db3070033db1a9358fd4b5cae7b35245ed9d", + .hash = "N-V-__8AAPaHAgCFo6mTsjpxuOdPZSpYtFZlDOlRXeu499mJ", .lazy = true, }, }, diff --git a/src/soft/SoftBuffer.zig b/src/soft/SoftBuffer.zig new file mode 100644 index 0000000..80e6eef --- /dev/null +++ b/src/soft/SoftBuffer.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.Buffer; + +interface: Interface, + +pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.BufferCreateInfo) 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, + .getMemoryRequirements = getMemoryRequirements, + }; + + 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 getMemoryRequirements(interface: *Interface, requirements: *vk.MemoryRequirements) void { + _ = interface; + _ = requirements; +} diff --git a/src/soft/SoftDevice.zig b/src/soft/SoftDevice.zig index e623eaa..aaa1566 100644 --- a/src/soft/SoftDevice.zig +++ b/src/soft/SoftDevice.zig @@ -5,9 +5,10 @@ const builtin = @import("builtin"); const Debug = std.builtin.OptimizeMode.Debug; +const SoftCommandPool = @import("SoftCommandPool.zig"); const SoftQueue = @import("SoftQueue.zig"); -const SoftCommandPool = @import("SoftCommandPool.zig"); +const SoftBuffer = @import("SoftBuffer.zig"); const SoftDeviceMemory = @import("SoftDeviceMemory.zig"); const SoftFence = @import("SoftFence.zig"); @@ -36,18 +37,11 @@ pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocato }; interface.dispatch_table = &.{ - .allocateCommandBuffers = allocateCommandBuffers, .allocateMemory = allocateMemory, + .createBuffer = createBuffer, .createCommandPool = createCommandPool, .createFence = createFence, .destroy = destroy, - .destroyCommandPool = destroyCommandPool, - .destroyFence = destroyFence, - .freeCommandBuffers = freeCommandBuffers, - .freeMemory = freeMemory, - .getFenceStatus = getFenceStatus, - .resetFences = resetFences, - .waitForFences = waitForFences, }; self.* = .{ @@ -79,62 +73,23 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void allocator.destroy(self); } -// Fence functions =================================================================================================================================== +pub fn createBuffer(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.BufferCreateInfo) VkError!*base.Buffer { + const buffer = try SoftBuffer.create(interface, allocator, info); + return &buffer.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; } -pub fn destroyFence(_: *Interface, allocator: std.mem.Allocator, fence: *base.Fence) VkError!void { - fence.destroy(allocator); -} - -pub fn getFenceStatus(_: *Interface, fence: *base.Fence) VkError!void { - try fence.getStatus(); -} - -pub fn resetFences(_: *Interface, fences: []*base.Fence) VkError!void { - for (fences) |fence| { - try fence.reset(); - } -} - -pub fn waitForFences(_: *Interface, fences: []*base.Fence, waitForAll: bool, timeout: u64) VkError!void { - for (fences) |fence| { - try fence.wait(timeout); - if (!waitForAll) return; - } -} - -// Command Pool functions ============================================================================================================================ - -pub fn allocateCommandBuffers(_: *Interface, info: *const vk.CommandBufferAllocateInfo) VkError![]*Dispatchable(base.CommandBuffer) { - const pool = try NonDispatchable(base.CommandPool).fromHandleObject(info.command_pool); - return pool.allocateCommandBuffers(info); -} - pub fn createCommandPool(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.CommandPoolCreateInfo) VkError!*base.CommandPool { const pool = try SoftCommandPool.create(interface, allocator, info); return &pool.interface; } -pub fn destroyCommandPool(_: *Interface, allocator: std.mem.Allocator, pool: *base.CommandPool) VkError!void { - pool.destroy(allocator); -} - -pub fn freeCommandBuffers(_: *Interface, pool: *base.CommandPool, cmds: []*Dispatchable(base.CommandBuffer)) VkError!void { - try pool.freeCommandBuffers(cmds); -} - -// Memory functions ================================================================================================================================== - pub fn allocateMemory(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.MemoryAllocateInfo) VkError!*base.DeviceMemory { const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); const device_memory = try SoftDeviceMemory.create(self, allocator, info.allocation_size, info.memory_type_index); return &device_memory.interface; } - -pub fn freeMemory(_: *Interface, allocator: std.mem.Allocator, device_memory: *base.DeviceMemory) VkError!void { - device_memory.destroy(allocator); -} diff --git a/src/soft/lib.zig b/src/soft/lib.zig index 9df45f0..141fb17 100644 --- a/src/soft/lib.zig +++ b/src/soft/lib.zig @@ -7,6 +7,7 @@ pub const SoftDevice = @import("SoftDevice.zig"); pub const SoftPhysicalDevice = @import("SoftPhysicalDevice.zig"); pub const SoftQueue = @import("SoftQueue.zig"); +pub const SoftBuffer = @import("SoftBuffer.zig"); pub const SoftCommandBuffer = @import("SoftCommandBuffer.zig"); pub const SoftCommandPool = @import("SoftCommandPool.zig"); pub const SoftDeviceMemory = @import("SoftDeviceMemory.zig"); diff --git a/src/vulkan/Buffer.zig b/src/vulkan/Buffer.zig index 77b1c97..a1828c0 100644 --- a/src/vulkan/Buffer.zig +++ b/src/vulkan/Buffer.zig @@ -18,6 +18,7 @@ allowed_memory_types: u32, vtable: *const VTable, pub const VTable = struct { + destroy: *const fn (*Self, std.mem.Allocator) void, getMemoryRequirements: *const fn (*Self, *vk.MemoryRequirements) void, }; @@ -34,6 +35,10 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Buffe }; } +pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void { + self.vtable.destroy(self, allocator); +} + pub inline fn bindMemory(self: *Self, memory: *DeviceMemory, offset: vk.DeviceSize) VkError!void { if (offset >= self.size or self.allowed_memory_types & memory.memory_type_index == 0) { return VkError.ValidationFailed; @@ -41,3 +46,9 @@ pub inline fn bindMemory(self: *Self, memory: *DeviceMemory, offset: vk.DeviceSi self.memory = memory; self.offset = offset; } + +pub inline fn getMemoryRequirements(self: *Self, requirements: *vk.MemoryRequirements) void { + requirements.size = self.size; + requirements.memory_type_bits = self.allowed_memory_types; + self.vtable.getMemoryRequirements(self, requirements); +} diff --git a/src/vulkan/Device.zig b/src/vulkan/Device.zig index ba15edc..0e45cd8 100644 --- a/src/vulkan/Device.zig +++ b/src/vulkan/Device.zig @@ -9,6 +9,7 @@ const VkError = @import("error_set.zig").VkError; const PhysicalDevice = @import("PhysicalDevice.zig"); const Queue = @import("Queue.zig"); +const Buffer = @import("Buffer.zig"); const CommandBuffer = @import("CommandBuffer.zig"); const CommandPool = @import("CommandPool.zig"); const DeviceMemory = @import("DeviceMemory.zig"); @@ -30,18 +31,11 @@ pub const VTable = struct { }; pub const DispatchTable = struct { - allocateCommandBuffers: *const fn (*Self, *const vk.CommandBufferAllocateInfo) VkError![]*Dispatchable(CommandBuffer), 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, createFence: *const fn (*Self, std.mem.Allocator, *const vk.FenceCreateInfo) VkError!*Fence, destroy: *const fn (*Self, std.mem.Allocator) VkError!void, - destroyCommandPool: *const fn (*Self, std.mem.Allocator, *CommandPool) VkError!void, - destroyFence: *const fn (*Self, std.mem.Allocator, *Fence) VkError!void, - freeCommandBuffers: *const fn (*Self, *CommandPool, []*Dispatchable(CommandBuffer)) VkError!void, - freeMemory: *const fn (*Self, std.mem.Allocator, *DeviceMemory) VkError!void, - getFenceStatus: *const fn (*Self, *Fence) VkError!void, - resetFences: *const fn (*Self, []*Fence) VkError!void, - waitForFences: *const fn (*Self, []*Fence, bool, u64) VkError!void, }; pub fn init(allocator: std.mem.Allocator, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self { @@ -90,60 +84,18 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) VkError!void { try self.dispatch_table.destroy(self, allocator); } -// Fence functions =================================================================================================================================== +pub inline fn createBuffer(self: *Self, allocator: std.mem.Allocator, info: *const vk.BufferCreateInfo) VkError!*Buffer { + return self.dispatch_table.createBuffer(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); } -pub inline fn destroyFence(self: *Self, allocator: std.mem.Allocator, fence: *Fence) VkError!void { - try self.dispatch_table.destroyFence(self, allocator, fence); -} - -pub inline fn getFenceStatus(self: *Self, fence: *Fence) VkError!void { - try self.dispatch_table.getFenceStatus(self, fence); -} - -pub inline fn resetFences(self: *Self, fences: []*Fence) VkError!void { - try self.dispatch_table.resetFences(self, fences); -} - -pub inline fn waitForFences(self: *Self, fences: []*Fence, waitForAll: bool, timeout: u64) VkError!void { - try self.dispatch_table.waitForFences(self, fences, waitForAll, timeout); -} - -// Command Pool functions ============================================================================================================================ - -pub inline fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*Dispatchable(CommandBuffer) { - return self.dispatch_table.allocateCommandBuffers(self, info); -} - pub inline fn createCommandPool(self: *Self, allocator: std.mem.Allocator, info: *const vk.CommandPoolCreateInfo) VkError!*CommandPool { return self.dispatch_table.createCommandPool(self, allocator, info); } -pub inline fn destroyCommandPool(self: *Self, allocator: std.mem.Allocator, pool: *CommandPool) VkError!void { - try self.dispatch_table.destroyCommandPool(self, allocator, pool); -} - -pub inline fn freeCommandBuffers(self: *Self, pool: *CommandPool, cmds: []*Dispatchable(CommandBuffer)) VkError!void { - try self.dispatch_table.freeCommandBuffers(self, pool, cmds); -} - -// Memory functions ================================================================================================================================== - pub inline fn allocateMemory(self: *Self, allocator: std.mem.Allocator, info: *const vk.MemoryAllocateInfo) VkError!*DeviceMemory { return self.dispatch_table.allocateMemory(self, allocator, info); } - -pub inline fn freeMemory(self: *Self, allocator: std.mem.Allocator, device_memory: *DeviceMemory) VkError!void { - try self.dispatch_table.freeMemory(self, allocator, device_memory); -} - -pub inline fn mapMemory(_: *Self, device_memory: *DeviceMemory, offset: vk.DeviceSize, size: vk.DeviceSize) VkError!?*anyopaque { - return device_memory.map(offset, size); -} - -pub inline fn unmapMemory(_: *Self, device_memory: *DeviceMemory) void { - return device_memory.unmap(); -} diff --git a/src/vulkan/Dispatchable.zig b/src/vulkan/Dispatchable.zig index 43da6e4..2eb4197 100644 --- a/src/vulkan/Dispatchable.zig +++ b/src/vulkan/Dispatchable.zig @@ -24,6 +24,11 @@ pub fn Dispatchable(comptime T: type) type { return self; } + pub inline fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void { + self.object.destroy(allocator); + allocator.destroy(self); + } + pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void { allocator.destroy(self); } @@ -52,5 +57,9 @@ pub fn Dispatchable(comptime T: type) type { const dispatchable_handle = try Self.fromHandle(handle); return dispatchable_handle.object; } + + pub inline fn checkHandleValidity(handle: anytype) VkError!void { + _ = try Self.fromHandle(handle); + } }; } diff --git a/src/vulkan/NonDispatchable.zig b/src/vulkan/NonDispatchable.zig index a75806d..6b0e93e 100644 --- a/src/vulkan/NonDispatchable.zig +++ b/src/vulkan/NonDispatchable.zig @@ -19,6 +19,11 @@ pub fn NonDispatchable(comptime T: type) type { return self; } + pub inline fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void { + self.object.destroy(allocator); + allocator.destroy(self); + } + pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void { allocator.destroy(self); } @@ -47,5 +52,9 @@ pub fn NonDispatchable(comptime T: type) type { const non_dispatchable_handle = try Self.fromHandle(handle); return non_dispatchable_handle.object; } + + pub inline fn checkHandleValidity(handle: anytype) VkError!void { + _ = try Self.fromHandle(handle); + } }; } diff --git a/src/vulkan/lib.zig b/src/vulkan/lib.zig index 79d2911..632922c 100644 --- a/src/vulkan/lib.zig +++ b/src/vulkan/lib.zig @@ -1,6 +1,7 @@ const std = @import("std"); const vk = @import("vulkan"); +pub const commands = @import("commands.zig"); pub const lib_vulkan = @import("lib_vulkan.zig"); pub const logger = @import("logger.zig"); @@ -14,6 +15,7 @@ pub const Device = @import("Device.zig"); pub const PhysicalDevice = @import("PhysicalDevice.zig"); pub const Queue = @import("Queue.zig"); +pub const Buffer = @import("Buffer.zig"); pub const CommandBuffer = @import("CommandBuffer.zig"); pub const CommandPool = @import("CommandPool.zig"); pub const DeviceMemory = @import("DeviceMemory.zig"); diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index a376d0c..e4223d6 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -21,6 +21,7 @@ const Device = @import("Device.zig"); const PhysicalDevice = @import("PhysicalDevice.zig"); const Queue = @import("Queue.zig"); +const Buffer = @import("Buffer.zig"); const CommandBuffer = @import("CommandBuffer.zig"); const CommandPool = @import("CommandPool.zig"); const DeviceMemory = @import("DeviceMemory.zig"); @@ -77,8 +78,11 @@ const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ functionMapEntryPoint("vkAllocateCommandBuffers"), functionMapEntryPoint("vkAllocateMemory"), functionMapEntryPoint("vkBeginCommandBuffer"), + functionMapEntryPoint("vkBindBufferMemory"), functionMapEntryPoint("vkCreateCommandPool"), + functionMapEntryPoint("vkCreateBuffer"), functionMapEntryPoint("vkCreateFence"), + functionMapEntryPoint("vkDestroyBuffer"), functionMapEntryPoint("vkDestroyCommandPool"), functionMapEntryPoint("vkDestroyFence"), functionMapEntryPoint("vkDestroyDevice"), @@ -87,6 +91,7 @@ const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{ functionMapEntryPoint("vkFreeMemory"), functionMapEntryPoint("vkGetDeviceQueue"), functionMapEntryPoint("vkGetFenceStatus"), + functionMapEntryPoint("vkGetBufferMemoryRequirements"), functionMapEntryPoint("vkMapMemory"), functionMapEntryPoint("vkUnmapMemory"), functionMapEntryPoint("vkResetCommandBuffer"), @@ -186,7 +191,7 @@ pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const const allocator = VulkanAllocator.init(callbacks, .instance).allocator(); const dispatchable = Dispatchable(Instance).fromHandle(p_instance) catch return; - dispatchable.object.deinit(allocator) catch {}; + dispatchable.object.deinit(allocator) catch return; dispatchable.destroy(allocator); if (std.process.hasEnvVarConstant(lib.DRIVER_DEBUG_ALLOCATOR_ENV_NAME) or builtin.mode == std.builtin.OptimizeMode.Debug) { @@ -198,11 +203,11 @@ pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const } 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); + const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err); + count.* = @intCast(instance.physical_devices.items.len); if (p_devices) |devices| { for (0..count.*) |i| { - devices[i] = self.physical_devices.items[i].toVkHandle(vk.PhysicalDevice); + devices[i] = instance.physical_devices.items[i].toVkHandle(vk.PhysicalDevice); } } return .success; @@ -238,36 +243,36 @@ pub export fn strollEnumerateDeviceExtensionProperties(p_physical_device: vk.Phy } pub export fn strollGetPhysicalDeviceFormatProperties(p_physical_device: vk.PhysicalDevice, format: vk.Format, properties: *vk.FormatProperties) callconv(vk.vulkan_call_conv) void { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; - properties.* = self.getFormatProperties(format) catch return; + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; + properties.* = physical_device.getFormatProperties(format) catch return; } 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; + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; + features.* = physical_device.features; } 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 { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); - properties.* = self.getImageFormatProperties(format, image_type, tiling, usage, flags) catch |err| return toVkResult(err); + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); + properties.* = physical_device.getImageFormatProperties(format, image_type, tiling, usage, 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 { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; - properties.* = self.props; + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; + properties.* = physical_device.props; } 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; + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; + 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 { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; - count.* = @intCast(self.queue_family_props.items.len); + const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch return; + count.* = @intCast(physical_device.queue_family_props.items.len); if (properties) |props| { - @memcpy(props[0..count.*], self.queue_family_props.items[0..count.*]); + @memcpy(props[0..count.*], physical_device.queue_family_props.items[0..count.*]); } } @@ -281,20 +286,45 @@ pub export fn strollGetPhysicalDeviceSparseImageFormatProperties( flags: vk.ImageCreateFlags, properties: *vk.SparseImageFormatProperties, ) callconv(vk.vulkan_call_conv) vk.Result { - const self = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err); - properties.* = self.getSparseImageFormatProperties(format, image_type, samples, tiling, usage, flags) catch |err| return toVkResult(err); + 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); + return .success; +} + +// Queue functions =========================================================================================================================================== + +pub export fn strollQueueBindSparse(p_queue: vk.Queue, count: u32, info: [*]vk.BindSparseInfo, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { + const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); + const fence = if (p_fence != .null_handle) NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err) else null; + queue.bindSparse(info[0..count], fence) catch |err| return toVkResult(err); + return .success; +} + +pub export fn strollQueueSubmit(p_queue: vk.Queue, count: u32, info: [*]const vk.SubmitInfo, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { + const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); + const fence = if (p_fence != .null_handle) NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err) else null; + queue.submit(info[0..count], fence) catch |err| return toVkResult(err); + return .success; +} + +pub export fn strollQueueWaitIdle(p_queue: vk.Queue) callconv(vk.vulkan_call_conv) vk.Result { + const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); + queue.waitIdle() catch |err| return toVkResult(err); return .success; } // Device functions ========================================================================================================================================== pub export fn strollAllocateCommandBuffers(p_device: vk.Device, p_info: ?*const vk.CommandBufferAllocateInfo, p_cmds: [*]vk.CommandBuffer) callconv(vk.vulkan_call_conv) vk.Result { + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); + const info = p_info orelse return .error_validation_failed; if (info.s_type != .command_buffer_allocate_info) { return .error_validation_failed; } - const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); - const cmds = device.allocateCommandBuffers(info) catch |err| return toVkResult(err); + + const pool = NonDispatchable(CommandPool).fromHandleObject(info.command_pool) catch |err| return toVkResult(err); + const cmds = pool.allocateCommandBuffers(info) catch |err| return toVkResult(err); for (cmds[0..info.command_buffer_count], 0..) |cmd, i| { p_cmds[i] = cmd.toVkHandle(vk.CommandBuffer); } @@ -313,6 +343,27 @@ pub export fn strollAllocateMemory(p_device: vk.Device, p_info: ?*const vk.Memor return .success; } +pub export fn strollBindBufferMemory(p_device: vk.Device, p_buffer: vk.Buffer, p_memory: vk.DeviceMemory, offset: vk.DeviceSize) callconv(vk.vulkan_call_conv) vk.Result { + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); + + const buffer = NonDispatchable(Buffer).fromHandleObject(p_buffer) catch |err| return toVkResult(err); + const memory = NonDispatchable(DeviceMemory).fromHandleObject(p_memory) catch |err| return toVkResult(err); + buffer.bindMemory(memory, offset) catch |err| return toVkResult(err); + return .success; +} + +pub export fn strollCreateBuffer(p_device: vk.Device, p_info: ?*const vk.BufferCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_buffer: *vk.Buffer) callconv(vk.vulkan_call_conv) vk.Result { + const info = p_info orelse return .error_validation_failed; + if (info.s_type != .buffer_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 buffer = device.createBuffer(allocator, info) catch |err| return toVkResult(err); + p_buffer.* = (NonDispatchable(Buffer).wrap(allocator, buffer) catch |err| return toVkResult(err)).toVkHandle(vk.Buffer); + return .success; +} + pub export fn strollCreateCommandPool(p_device: vk.Device, p_info: ?*const vk.CommandPoolCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_pool: *vk.CommandPool) callconv(vk.vulkan_call_conv) vk.Result { const info = p_info orelse return .error_validation_failed; if (info.s_type != .command_pool_create_info) { @@ -337,13 +388,20 @@ pub export fn strollCreateFence(p_device: vk.Device, p_info: ?*const vk.FenceCre return .success; } -pub export fn strollDestroyCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { - const allocator = VulkanAllocator.init(callbacks, .object).allocator(); - const device = Dispatchable(Device).fromHandleObject(p_device) catch return; - const non_dispatchable_pool = NonDispatchable(CommandPool).fromHandle(p_pool) catch return; +pub export fn strollDestroyBuffer(p_device: vk.Device, p_buffer: vk.Buffer, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { + Dispatchable(Device).checkHandleValidity(p_device) catch return; - device.destroyCommandPool(allocator, non_dispatchable_pool.object) catch return; - non_dispatchable_pool.destroy(allocator); + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(Buffer).fromHandle(p_buffer) catch return; + non_dispatchable.intrusiveDestroy(allocator); +} + +pub export fn strollDestroyCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { + Dispatchable(Device).checkHandleValidity(p_device) catch return; + + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(CommandPool).fromHandle(p_pool) catch return; + non_dispatchable.intrusiveDestroy(allocator); } pub export fn strollDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { @@ -358,28 +416,27 @@ pub export fn strollDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.All } pub export fn strollDestroyFence(p_device: vk.Device, p_fence: vk.Fence, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { - const allocator = VulkanAllocator.init(callbacks, .object).allocator(); - const device = Dispatchable(Device).fromHandleObject(p_device) catch return; - const non_dispatchable_fence = NonDispatchable(Fence).fromHandle(p_fence) catch return; + Dispatchable(Device).checkHandleValidity(p_device) catch return; - device.destroyFence(allocator, non_dispatchable_fence.object) catch return; - non_dispatchable_fence.destroy(allocator); + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(Fence).fromHandle(p_fence) catch return; + non_dispatchable.intrusiveDestroy(allocator); } pub export fn strollFreeCommandBuffers(p_device: vk.Device, p_pool: vk.CommandPool, count: u32, p_cmds: [*]const vk.CommandBuffer) callconv(vk.vulkan_call_conv) void { - const device = Dispatchable(Device).fromHandleObject(p_device) catch return; + Dispatchable(Device).checkHandleValidity(p_device) catch return; + const pool = NonDispatchable(CommandPool).fromHandleObject(p_pool) catch return; const cmds: [*]*Dispatchable(CommandBuffer) = @ptrCast(@constCast(p_cmds)); - device.freeCommandBuffers(pool, cmds[0..count]) catch return; + pool.freeCommandBuffers(cmds[0..count]) catch return; } pub export fn strollFreeMemory(p_device: vk.Device, p_memory: vk.DeviceMemory, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void { - const allocator = VulkanAllocator.init(callbacks, .object).allocator(); - const device = Dispatchable(Device).fromHandleObject(p_device) catch return; - const non_dispatchable_device_memory = NonDispatchable(DeviceMemory).fromHandle(p_memory) catch return; + Dispatchable(Device).checkHandleValidity(p_device) catch return; - device.freeMemory(allocator, non_dispatchable_device_memory.object) catch return; - non_dispatchable_device_memory.destroy(allocator); + const allocator = VulkanAllocator.init(callbacks, .object).allocator(); + const non_dispatchable = NonDispatchable(DeviceMemory).fromHandle(p_memory) catch return; + non_dispatchable.intrusiveDestroy(allocator); } pub export fn strollGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction { @@ -410,72 +467,53 @@ pub export fn strollGetDeviceQueue(p_device: vk.Device, queue_family_index: u32, } pub export fn strollGetFenceStatus(p_device: vk.Device, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { - const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); + const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err); - device.getFenceStatus(fence) catch |err| return toVkResult(err); + fence.getStatus() catch |err| return toVkResult(err); return .success; } +pub export fn strollGetBufferMemoryRequirements(p_device: vk.Device, p_buffer: vk.Buffer, requirements: *vk.MemoryRequirements) callconv(vk.vulkan_call_conv) void { + Dispatchable(Device).checkHandleValidity(p_device) catch return; + + const buffer = NonDispatchable(Buffer).fromHandleObject(p_buffer) catch return; + buffer.getMemoryRequirements(requirements); +} + pub export fn strollMapMemory(p_device: vk.Device, p_memory: vk.DeviceMemory, offset: vk.DeviceSize, size: vk.DeviceSize, _: vk.MemoryMapFlags, pp_data: *?*anyopaque) callconv(vk.vulkan_call_conv) vk.Result { - const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); + const device_memory = NonDispatchable(DeviceMemory).fromHandleObject(p_memory) catch |err| return toVkResult(err); - pp_data.* = device.mapMemory(device_memory, offset, size) catch |err| return toVkResult(err); + pp_data.* = device_memory.map(offset, size) catch |err| return toVkResult(err); return .success; } pub export fn strollUnmapMemory(p_device: vk.Device, p_memory: vk.DeviceMemory) callconv(vk.vulkan_call_conv) void { - const device = Dispatchable(Device).fromHandleObject(p_device) catch return; + Dispatchable(Device).checkHandleValidity(p_device) catch return; + const device_memory = NonDispatchable(DeviceMemory).fromHandleObject(p_memory) catch return; - device.unmapMemory(device_memory); + device_memory.unmap(); } pub export fn strollResetFences(p_device: vk.Device, count: u32, p_fences: [*]const vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { - const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); - const allocator = device.host_allocator.cloneWithScope(.command).allocator(); + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); - const fences: []*Fence = allocator.alloc(*Fence, count) catch return .error_unknown; - defer allocator.free(fences); - - for (p_fences, 0..count) |fence, i| { - fences[i] = NonDispatchable(Fence).fromHandleObject(fence) catch |err| return toVkResult(err); + for (p_fences, 0..count) |p_fence, _| { + const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err); + fence.reset() catch |err| return toVkResult(err); } - - device.resetFences(fences) catch |err| return toVkResult(err); - return .success; -} - -pub export fn strollQueueBindSparse(p_queue: vk.Queue, count: u32, info: [*]vk.BindSparseInfo, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { - const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); - const fence = if (p_fence != .null_handle) NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err) else null; - queue.bindSparse(info[0..count], fence) catch |err| return toVkResult(err); - return .success; -} - -pub export fn strollQueueSubmit(p_queue: vk.Queue, count: u32, info: [*]const vk.SubmitInfo, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result { - const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); - const fence = if (p_fence != .null_handle) NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err) else null; - queue.submit(info[0..count], fence) catch |err| return toVkResult(err); - return .success; -} - -pub export fn strollQueueWaitIdle(p_queue: vk.Queue) callconv(vk.vulkan_call_conv) vk.Result { - const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err); - queue.waitIdle() catch |err| return toVkResult(err); return .success; } pub export fn strollWaitForFences(p_device: vk.Device, count: u32, p_fences: [*]const vk.Fence, waitForAll: vk.Bool32, timeout: u64) callconv(vk.vulkan_call_conv) vk.Result { - const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err); - const allocator = device.host_allocator.cloneWithScope(.command).allocator(); + Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err); - const fences: []*Fence = allocator.alloc(*Fence, count) catch return .error_unknown; - defer allocator.free(fences); - - for (p_fences, 0..count) |fence, i| { - fences[i] = NonDispatchable(Fence).fromHandleObject(fence) catch |err| return toVkResult(err); + loop: for (p_fences, 0..count) |p_fence, _| { + const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err); + fence.wait(timeout) catch |err| return toVkResult(err); + if (waitForAll == .false) break :loop; } - - device.waitForFences(fences, (waitForAll == .true), timeout) catch |err| return toVkResult(err); return .success; } diff --git a/test/c/main.c b/test/c/main.c index 1dc8784..1e34dac 100644 --- a/test/c/main.c +++ b/test/c/main.c @@ -52,6 +52,8 @@ int main(void) VkDevice device = kvfCreateDevice(physical_device, NULL, 0, NULL); volkLoadDevice(device); + VkBuffer buffer = kvfCreateBuffer(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 256); + VkQueue queue = kvfGetDeviceQueue(device, KVF_GRAPHICS_QUEUE); VkFence fence = kvfCreateFence(device); VkCommandBuffer cmd = kvfCreateCommandBuffer(device); @@ -65,6 +67,7 @@ int main(void) kvfWaitForFence(device, fence); kvfDestroyFence(device, fence); + kvfDestroyBuffer(device, buffer); kvfDestroyDevice(device); kvfDestroyInstance(instance);