diff --git a/src/soft/SoftCommandBuffer.zig b/src/soft/SoftCommandBuffer.zig index 7cc7f4e..fd5930c 100644 --- a/src/soft/SoftCommandBuffer.zig +++ b/src/soft/SoftCommandBuffer.zig @@ -49,6 +49,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v .dispatch = dispatch, .dispatchIndirect = dispatchIndirect, .end = end, + .executeCommands = executeCommands, .fillBuffer = fillBuffer, .pipelineBarrier = pipelineBarrier, .reset = reset, @@ -69,6 +70,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void { const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); allocator.destroy(self); + _ = self.command_allocator.reset(.free_all); } pub fn execute(self: *Self, device: *ExecutionDevice) void { @@ -98,8 +100,7 @@ pub fn end(interface: *Interface) VkError!void { pub fn reset(interface: *Interface, _: vk.CommandBufferResetFlags) VkError!void { const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); - const allocator = self.command_allocator.allocator(); - self.commands.clearAndFree(allocator); + self.commands.clearAndFree(self.command_allocator.allocator()); _ = self.command_allocator.reset(.free_all); } @@ -345,9 +346,6 @@ pub fn dispatchIndirect(interface: *Interface, buffer: *base.Buffer, offset: vk. const size = 3 * @sizeOf(u32); const memory = if (impl.buffer.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; const map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(impl.offset, size))))[0..3]; - - std.debug.print("{any}\n", .{map}); - try device.compute_routines.dispatch(map[0], map[1], map[2]); } }; @@ -361,6 +359,28 @@ pub fn dispatchIndirect(interface: *Interface, buffer: *base.Buffer, offset: vk. self.commands.append(allocator, Command.from(cmd)) catch return VkError.OutOfHostMemory; } +pub fn executeCommands(interface: *Interface, commands: *Interface) VkError!void { + const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); + const allocator = self.command_allocator.allocator(); + + const CommandImpl = struct { + const Impl = @This(); + + cmd: *Self, + + pub fn execute(impl: *const Impl, device: *ExecutionDevice) VkError!void { + impl.cmd.execute(device); + } + }; + + const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory; + errdefer allocator.destroy(cmd); + cmd.* = .{ + .cmd = @alignCast(@fieldParentPtr("interface", commands)), + }; + self.commands.append(allocator, Command.from(cmd)) catch return VkError.OutOfHostMemory; +} + pub fn fillBuffer(interface: *Interface, buffer: *base.Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void { const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); const allocator = self.command_allocator.allocator(); @@ -397,7 +417,7 @@ pub fn pipelineBarrier(interface: *Interface, src_stage: vk.PipelineStageFlags, const Impl = @This(); pub fn execute(_: *const Impl, _: *ExecutionDevice) VkError!void { - // TODO: implement synchronization for rasterizations stages + // TODO: implement synchronization for rasterization stages } }; diff --git a/src/vulkan/CommandBuffer.zig b/src/vulkan/CommandBuffer.zig index 9fb34c0..5d6be7b 100644 --- a/src/vulkan/CommandBuffer.zig +++ b/src/vulkan/CommandBuffer.zig @@ -48,6 +48,7 @@ pub const DispatchTable = struct { dispatch: *const fn (*Self, u32, u32, u32) VkError!void, dispatchIndirect: *const fn (*Self, *Buffer, vk.DeviceSize) VkError!void, end: *const fn (*Self) VkError!void, + executeCommands: *const fn (*Self, *Self) VkError!void, fillBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, vk.DeviceSize, u32) VkError!void, pipelineBarrier: *const fn (*Self, vk.PipelineStageFlags, vk.PipelineStageFlags, vk.DependencyFlags, []const vk.MemoryBarrier, []const vk.BufferMemoryBarrier, []const vk.ImageMemoryBarrier) VkError!void, reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void, @@ -99,6 +100,7 @@ pub inline fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError pub inline fn end(self: *Self) VkError!void { self.transitionState(.Executable, &.{.Recording}) catch return VkError.ValidationFailed; try self.dispatch_table.end(self); + self.begin_info = null; } pub inline fn reset(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void { @@ -133,6 +135,7 @@ pub inline fn finish(self: *Self) VkError!void { // Commands ==================================================================================================== pub inline fn bindDescriptorSets(self: *Self, bind_point: vk.PipelineBindPoint, first_set: u32, sets: []const vk.DescriptorSet, dynamic_offsets: []const u32) VkError!void { + std.debug.assert(sets.len < lib.VULKAN_MAX_DESCRIPTOR_SETS); var inner_sets = [_]?*DescriptorSet{null} ** lib.VULKAN_MAX_DESCRIPTOR_SETS; for (sets, inner_sets[0..sets.len]) |set, *inner_set| { inner_set.* = try NonDispatchable(DescriptorSet).fromHandleObject(set); @@ -174,6 +177,10 @@ pub inline fn dispatchIndirect(self: *Self, buffer: *Buffer, offset: vk.DeviceSi try self.dispatch_table.dispatchIndirect(self, buffer, offset); } +pub inline fn executeCommands(self: *Self, commands: *Self) VkError!void { + try self.dispatch_table.executeCommands(self, commands); +} + pub inline fn fillBuffer(self: *Self, buffer: *Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void { try self.dispatch_table.fillBuffer(self, buffer, offset, size, data); } diff --git a/src/vulkan/CommandPool.zig b/src/vulkan/CommandPool.zig index 7458ab0..acce024 100644 --- a/src/vulkan/CommandPool.zig +++ b/src/vulkan/CommandPool.zig @@ -72,9 +72,8 @@ pub fn freeCommandBuffers(self: *Self, cmds: []*Dispatchable(CommandBuffer)) VkE // Ugly method but it works well var len: usize = 0; for (cmds) |cmd| { - if (std.mem.indexOf(*Dispatchable(CommandBuffer), self.buffers.items, &[_]*Dispatchable(CommandBuffer){cmd})) |i| { + if (std.mem.indexOfScalar(*Dispatchable(CommandBuffer), self.buffers.items, cmd)) |i| { const save = self.buffers.orderedRemove(i); - // Append the now free command buffer at the end of the pool self.buffers.appendAssumeCapacity(save); len += 1; } @@ -82,8 +81,6 @@ pub fn freeCommandBuffers(self: *Self, cmds: []*Dispatchable(CommandBuffer)) VkE const new_first_free_buffer_index, const has_overflown = @subWithOverflow(self.first_free_buffer_index, len); if (has_overflown == 0) { self.first_free_buffer_index = new_first_free_buffer_index; - } else { - std.log.scoped(.CommandPool).warn("Avoided an underflow. This should not happen, please fill an issue.", .{}); } } diff --git a/src/vulkan/Queue.zig b/src/vulkan/Queue.zig index d307b68..176a3a6 100644 --- a/src/vulkan/Queue.zig +++ b/src/vulkan/Queue.zig @@ -53,9 +53,8 @@ pub const SubmitInfo = struct { } fn deinitBlob(allocator: std.mem.Allocator, self: *std.ArrayList(SubmitInfo)) void { - for (self.items) |submit_info| { - const command_buffers = &submit_info.command_buffers; - @constCast(command_buffers).deinit(allocator); + for (self.items) |*submit_info| { + submit_info.command_buffers.deinit(allocator); } self.deinit(allocator); } diff --git a/src/vulkan/error_set.zig b/src/vulkan/error_set.zig index 85faa45..eeb57b4 100644 --- a/src/vulkan/error_set.zig +++ b/src/vulkan/error_set.zig @@ -50,7 +50,7 @@ pub const VkError = error{ IncompatibleShaderBinaryExt, PipelineBinaryMissingKhr, NotEnoughSpaceKhr, - // ====== Internal errors + // == Set of internal errors for better debugging. They map to VK_UNKNOWN_ERROR InvalidHandleDrv, InvalidPipelineDrv, InvalidDeviceMemoryDrv, diff --git a/src/vulkan/lib_vulkan.zig b/src/vulkan/lib_vulkan.zig index f741199..3b99ded 100644 --- a/src/vulkan/lib_vulkan.zig +++ b/src/vulkan/lib_vulkan.zig @@ -1957,12 +1957,10 @@ pub export fn strollCmdExecuteCommands(p_cmd: vk.CommandBuffer, count: u32, p_cm defer entryPointEndLogTrace(); const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err); - - notImplementedWarning(); - - _ = cmd; - _ = count; - _ = p_cmds; + for (p_cmds, 0..count) |p_sec_cmd, _| { + const sec_cmd = Dispatchable(CommandBuffer).fromHandleObject(p_sec_cmd) catch |err| return errorLogger(err); + cmd.executeCommands(sec_cmd) catch |err| return errorLogger(err); + } } pub export fn strollCmdFillBuffer(p_cmd: vk.CommandBuffer, p_buffer: vk.Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) callconv(vk.vulkan_call_conv) void {