diff --git a/src/common/profiler.zig b/src/common/profiler.zig index 0c02857..9b1243d 100644 --- a/src/common/profiler.zig +++ b/src/common/profiler.zig @@ -49,7 +49,7 @@ pub const ProfileMark = struct { }; } - pub fn begin(self: *const Self) !void { + pub fn begin(self: *const Self) void { const frame = time.getFrameCount(); if (frame != ctx.frame) { @@ -68,7 +68,7 @@ pub const ProfileMark = struct { if (ctx.count < node_limit and ctx.depth < depth_limit) { const parent = ctx.current orelse &ctx.root; - const next = try allocator.create(Node); + const next = allocator.create(Node) catch unreachable; next.mark = self; next.parent = parent; next.depth = ctx.depth; @@ -112,8 +112,8 @@ pub const ProfileMark = struct { const Testing = struct { const pm_slow_func = ProfileMark.init("Test.slow_func"); - fn slow_func() !void { - try pm_slow_func.begin(); + fn slow_func() void { + pm_slow_func.begin(); defer pm_slow_func.end(); std.time.sleep(100); @@ -121,7 +121,7 @@ const Testing = struct { }; test "profile test" { - try Testing.slow_func(); + Testing.slow_func(); const fchild = ctx.root.fchild orelse unreachable; try testing.expectEqual(std.math.Order.lt, fchild.begin.order(fchild.end)); diff --git a/src/main.zig b/src/main.zig index bf93d2e..27f3904 100644 --- a/src/main.zig +++ b/src/main.zig @@ -32,7 +32,7 @@ pub fn main() !void { while (!window.shouldClose()) { std.debug.print("hi", .{}); - renderer.update(); + try renderer.update(); try glfw.pollEvents(); } } diff --git a/src/rendering/vulkan/Command.zig b/src/rendering/vulkan/Command.zig index 8f4a366..e8752df 100644 --- a/src/rendering/vulkan/Command.zig +++ b/src/rendering/vulkan/Command.zig @@ -2,11 +2,13 @@ const assert = @import("std").debug.assert; const vk = @import("vulkan"); const settings = @import("settings.zig"); +const Context = @import("Context.zig"); const Device = @import("device.zig").Device; const ProfileMark = @import("../../common/profiler.zig").ProfileMark; const Renderer = @import("Renderer.zig"); const SubmitId = @import("swapchain.zig").SubmitId; const Fence = @import("sync.zig").Fence; +const Semaphore = @import("sync.zig").Semaphore; const queues = @import("queues.zig"); @@ -46,7 +48,7 @@ const read_access: vk.AccessFlags = .{ const pm_init = ProfileMark.init("Command.init"); pub fn init(device: *const Device, queue: *queues.Queue, id: queues.QueueId) !void { - try pm_init.begin(); + pm_init.begin(); defer pm_init.end(); assert(queue == queues.get(id)); @@ -70,7 +72,7 @@ pub fn init(device: *const Device, queue: *queues.Queue, id: queues.QueueId) !vo const pm_deinit = ProfileMark("Command.deinit"); pub fn deinit(device: *const Device, queue: *const queues.Queue) void { - pm_init.begin() catch {}; + pm_init.begin(); defer pm_init.end(); for (queue.cmd_fences) |fence| { @@ -80,18 +82,42 @@ pub fn deinit(device: *const Device, queue: *const queues.Queue) void { queue.cmd_pool.deinit(device); } +pub fn get(queue_id: queues.QueueId, device: *const Device) !*Buffer { + var ctx = Context.context; + var cmd = &ctx.cur_cmd_buf[@enumToInt(queue_id)]; + if (cmd.handle == .null_handle) { + try cmd.init(device, queues.get(queue_id)); + } + + if (!cmd.began) { + try device.dispatch.beginCommandBuffer(cmd.handle, &.{ + .s_type = .command_buffer_begin_info, + .flags = .{ .one_time_submit_bit = true }, + .p_inheritance_info = null, + }); + cmd.began = true; + ctx.most_recent_begin = queue_id; + } + + return cmd; +} + pub fn getHeadSubmit(id: queues.QueueId) SubmitId { // TODO _ = id; } -pub const Buffer = packed struct { +pub fn flush() void { + // TODO +} + +pub const Buffer = struct { const Self = @This(); - handle: vk.CommandBuffer, - fence: vk.Fence, + handle: vk.CommandBuffer = .null_handle, + fence: Fence, id: u32, - queue_id: queues.QueueId, + queue_id: u4, // indicates which types of cmds are legal in this cmdbuf gfx: bool, comp: bool, @@ -100,39 +126,36 @@ pub const Buffer = packed struct { // cmd state began: bool, ended: bool, - submit: bool, + submitted: bool, is_render_pass: bool, subpass: u8, queue_transfer_src: bool, queue_transfer_dst: bool, // XXX: I do not really understand this? - pub fn init(self: *Self, queue: queues.Queue) !void { + pub fn init(self: *Self, device: *const Device, queue: *queues.Queue) !void { const ring_mask: u32 = queue.cmds.len - 1; // TODO: decode meaning of SASSERT((NELEM(queue->cmds) & (NELEM(queue->cmds) - 1u)) == 0); const head_id = queue.head; queue.head += 1; - while (head_id - queue.tail >= queue.cmds.len) { + while (head_id - queue.tail >= queue.cmds.len) : (queue.tail += 1) { const tail_slot = queue.tail & ring_mask; assert(queue.cmd_ids[tail_slot] == queue.tail); - const tail_fence = queue.fences[tail_slot]; - try tail_fence.wait(); - queue.ids[tail_slot] = 0; - queue.tail += 1; + const tail_fence = queue.cmd_fences[tail_slot]; + try tail_fence.wait(device); + queue.cmd_ids[tail_slot] = 0; } const head_slot = head_id & ring_mask; - assert(!queue.ids[head_slot]); - queue.ids[head_slot] = head_id; + assert(queue.cmd_ids[head_slot] == 0); + queue.cmd_ids[head_slot] = head_id; const cmd = queue.cmds[head_slot]; - const fence = queue.fences[head_slot]; + const fence = queue.cmd_fences[head_slot]; - assert(fence); - assert(cmd); - assert(fence.stat() == .signaled); - fence.reset(); + assert((try fence.stat(device)) == .signaled); + try fence.reset(device); self.handle = cmd; self.fence = fence; @@ -143,6 +166,14 @@ pub const Buffer = packed struct { self.xfer = queue.xfer; self.pres = queue.pres; } + + pub fn submit(self: *const Self, wait_sema: Semaphore, wait_mask: vk.PipelineStageFlags, signal_sema: Semaphore) !SubmitId { + _ = self; + _ = wait_sema; + _ = wait_mask; + _ = signal_sema; + return undefined; + } }; pub const Pool = struct { diff --git a/src/rendering/vulkan/Renderer.zig b/src/rendering/vulkan/Renderer.zig index b2bacd1..dc4f3a3 100644 --- a/src/rendering/vulkan/Renderer.zig +++ b/src/rendering/vulkan/Renderer.zig @@ -71,13 +71,13 @@ pub fn init() !Self { }; } -pub fn update(self: Self) void { +pub fn update(self: *Self) !void { // TODO profiling // base system update { - try self.swapchain.acquireSync(&self.device); - self.swapchain.acquireImage(); + _ = self.swapchain.acquireSync(&self.device); + _ = try self.swapchain.acquireImage(&self.device); memory.update(); } @@ -98,7 +98,8 @@ pub fn update(self: Self) void { //self.main_pass.execute(); // present phase - self.swapchain.submit(Command.get()); + // currently only graphics queue + try self.swapchain.submit(try Command.get(.graphics, &self.device), &self.device); // background work { diff --git a/src/rendering/vulkan/image.zig b/src/rendering/vulkan/image.zig index 281323b..f303ab8 100644 --- a/src/rendering/vulkan/image.zig +++ b/src/rendering/vulkan/image.zig @@ -10,7 +10,7 @@ const settings = @import("settings.zig"); const memory = @import("memory.zig"); const Swapchain = @import("swapchain.zig").Swapchain; -pub const Image = packed struct { +pub const Image = struct { const Self = @This(); state: ImageState, @@ -80,13 +80,21 @@ pub const Image = packed struct { } }; -const ImageState = packed struct { +const ImageState = struct { + const Self = @This(); + owner: queues.QueueId, cmd_id: i32, stage: vk.PipelineStageFlags, access: vk.AccessFlags, layout: vk.ImageLayout, substates: [*]SubImageState, + + pub fn presentSrc(self: *Self, command: *const Command.Buffer) !void { + // TODO + _ = self; + _ = command; + } }; const ImageSet = struct { diff --git a/src/rendering/vulkan/memory.zig b/src/rendering/vulkan/memory.zig index 69fbccd..2eee51c 100644 --- a/src/rendering/vulkan/memory.zig +++ b/src/rendering/vulkan/memory.zig @@ -33,9 +33,11 @@ pub fn finalize(device: *const Device) !void { } } +pub fn update() void {} + const pm_imgnew = profiler.ProfileMark.init("memory.imageNew"); pub fn imageNew(img: *Image, info: *const vk.ImageCreateInfo, mem_usage: vma.MemoryUsage) !void { - try pm_imgnew.begin(); + pm_imgnew.begin(); defer pm_imgnew.end(); // memset needed? @@ -70,7 +72,7 @@ pub fn imageNew(img: *Image, info: *const vk.ImageCreateInfo, mem_usage: vma.Mem const pm_imagedel = profiler.ProfileMark.init("memory.imageDel"); pub fn imageDel(img: *const Image, device: *const Device) void { - pm_imagedel.begin() catch {}; + pm_imagedel.begin(); defer pm_imagedel.end(); device.dispatch.destroyImageView(device.handle, img.view, null); diff --git a/src/rendering/vulkan/queues.zig b/src/rendering/vulkan/queues.zig index 8a06b0a..c85c7df 100644 --- a/src/rendering/vulkan/queues.zig +++ b/src/rendering/vulkan/queues.zig @@ -268,7 +268,7 @@ pub const Queue = struct { index: QueueId = 0, access_mask: vk.AccessFlags = .{}, stage_mask: vk.PipelineStageFlags = .{}, - queueId: u4 = 0, + queue_id: u4 = 0, gfx: bool = false, comp: bool = false, xfer: bool = false, diff --git a/src/rendering/vulkan/render_pass.zig b/src/rendering/vulkan/render_pass.zig index 8e74081..04fa9ed 100644 --- a/src/rendering/vulkan/render_pass.zig +++ b/src/rendering/vulkan/render_pass.zig @@ -13,7 +13,7 @@ const s_cache = std.HashMap(Description, vk.RenderPass).init(allocator); const pm_get = profiler.ProfileMark.init("renderpass.get"); pub fn get(desc: *const Description) !vk.RenderPass { - try pm_get.begin(); + pm_get.begin(); defer pm_get.end(); const result = try s_cache.getOrPut(desc); diff --git a/src/rendering/vulkan/swapchain.zig b/src/rendering/vulkan/swapchain.zig index 53fadcc..95ed967 100644 --- a/src/rendering/vulkan/swapchain.zig +++ b/src/rendering/vulkan/swapchain.zig @@ -1,6 +1,7 @@ const std = @import("std"); const vk = @import("vulkan"); const math = @import("std").math; +const Command = @import("Command.zig"); const profiler = @import("../../common/profiler.zig"); const settings = @import("settings.zig"); const Instance = @import("instance.zig").Instance; @@ -121,7 +122,7 @@ pub const SubmitId = packed struct { const pm_wait = profiler.ProfileMark.init("swapchain.SubmitId.wait"); pub fn wait(self: *const SubmitId, device: *const Device) void { - pm_wait.begin() catch {}; + pm_wait.begin(); defer pm_wait.end(); std.debug.assert(self.valid); @@ -234,17 +235,19 @@ pub const Swapchain = struct { .length = img_count, }; + const color_format = format.format; + for (images) |img, i| { - try Image.import(&self.images[i], device, &.{ + try self.images[i].import(device, &.{ .s_type = .image_create_info, .flags = .{}, .image_type = .@"2d", - .format = self.color_format, .extent = .{ .width = ext.width, .height = ext.height, .depth = 1, }, + .format = color_format, .mip_levels = 1, .array_layers = 1, .samples = .{ .@"1_bit" = true }, @@ -281,18 +284,67 @@ pub const Swapchain = struct { } } - const pm_acquiresync = profiler.ProfileMark.init("Swapchain.acquireSync"); - pub fn acquireSync(self: *Self, device: *const Device) !usize { - try pm_acquiresync.begin(); + const pm_acquiresync = profiler.ProfileMark.init("swapchain.Swapchain.acquireSync"); + pub fn acquireSync(self: *Self, device: *const Device) usize { + pm_acquiresync.begin(); defer pm_acquiresync.end(); const sync_index = (self.sync_index + 1) % self.sync_submits.len; - const submit = self.sync_submits[sync_index]; - if (submit.valid) { - submit.wait(device); + const sub = self.sync_submits[sync_index]; + if (sub.valid) { + sub.wait(device); } self.sync_index = sync_index; return sync_index; } + + const pm_acquireimage = profiler.ProfileMark.init("swapchain.Swapchain.acquireImage"); + pub fn acquireImage(self: *Self, device: *const Device) !usize { + pm_acquireimage.begin(); + defer pm_acquireimage.end(); + + const timeout = std.math.maxInt(u64); + const result = try device.dispatch.acquireNextImageKHR(device.handle, self.handle, timeout, self.available_semas[self.sync_index].handle, .null_handle); + std.debug.assert(result.image_index < self.length); + const sub = self.image_submits[result.image_index]; + if (sub.valid) { + sub.wait(device); + } + + self.image_index = result.image_index; + return result.image_index; + } + + const pm_submit = profiler.ProfileMark.init("swapchain.Swapchain.submit"); + pub fn submit(self: *Self, command: *const Command.Buffer, device: *const Device) !void { + pm_submit.begin(); + defer pm_submit.end(); + + const image_index = self.image_index; + const sync_index = self.sync_index; + { + const backbuf = getBackBuffer(); + const prev_use = backbuf.state.stage; + try backbuf.state.presentSrc(command); + + const submit_id = try command.submit(self.available_semas[sync_index], prev_use, self.rendered_semas[sync_index]); + self.sync_submits[sync_index] = submit_id; + self.image_submits[image_index] = submit_id; + } + + { + var queue = queues.get(.graphics); + if (!queue.pres) { + queue = queues.get(.present); + } + + _ = try device.dispatch.queuePresentKHR(queue.handle, &.{ .s_type = .present_info_khr, .wait_semaphore_count = 1, .p_wait_semaphores = @ptrCast([*]const vk.Semaphore, &self.rendered_semas[sync_index]), .swapchain_count = 1, .p_swapchains = @ptrCast([*]const vk.SwapchainKHR, &self.handle), .p_results = null, .p_image_indices = @ptrCast([*]const u32, &self.image_index) }); + } + } + + pub fn getBackBuffer() *Image { + // TODO + return undefined; + } }; diff --git a/src/rendering/vulkan/sync.zig b/src/rendering/vulkan/sync.zig index 6e3a8af..9571d87 100644 --- a/src/rendering/vulkan/sync.zig +++ b/src/rendering/vulkan/sync.zig @@ -52,7 +52,7 @@ pub const Fence = struct { } pub fn reset(self: *const Self, device: *const Device) !void { - try device.dispatch.resetFences(device.handle, 1, &self.handle); + try device.dispatch.resetFences(device.handle, 1, @ptrCast([*]const vk.Fence, &self.handle)); } pub fn wait(self: *const Self, device: *const Device) !void {