From aaa22c058dbc7b8d2a21afe599cad196f9a2293b Mon Sep 17 00:00:00 2001 From: David Allemang Date: Thu, 27 Jun 2024 21:31:50 -0400 Subject: [PATCH] clear to red with one frame in flight --- src/au/SwapChain.zig | 27 +++- src/main.zig | 311 +++++++++++-------------------------------- 2 files changed, 101 insertions(+), 237 deletions(-) diff --git a/src/au/SwapChain.zig b/src/au/SwapChain.zig index 22a02a9..9f451d2 100644 --- a/src/au/SwapChain.zig +++ b/src/au/SwapChain.zig @@ -8,6 +8,7 @@ alloc: std.mem.Allocator, cinfo: vk.SwapchainCreateInfoKHR, handle: vk.SwapchainKHR = .null_handle, images: std.ArrayListUnmanaged(vk.Image) = .{}, +views: std.ArrayListUnmanaged(vk.ImageView) = .{}, pub fn init(alloc: std.mem.Allocator) !Self { const caps = try au.I.getPhysicalDeviceSurfaceCapabilitiesKHR(au.device_config.pdev, au.W.surface); @@ -41,7 +42,13 @@ pub fn init(alloc: std.mem.Allocator) !Self { } pub fn deinit(self: *Self) void { + for (self.views.items) |view| { + au.D.destroyImageView(view, null); + } + self.views.deinit(self.alloc); + self.images.deinit(self.alloc); + au.D.destroySwapchainKHR(self.handle, null); } @@ -68,11 +75,29 @@ pub fn rebuild(self: *Self) !bool { try self.images.resize(self.alloc, count); _ = try au.D.getSwapchainImagesKHR(self.handle, &count, self.images.items.ptr); + for (self.views.items) |view| { + au.D.destroyImageView(view, null); + } + try self.views.resize(self.alloc, count); + for (self.images.items, self.views.items) |image, *view| { + view.* = try au.D.createImageView(&vk.ImageViewCreateInfo{ .image = image, .view_type = .@"2d", .format = self.cinfo.image_format, .components = .{ .r = .identity, .g = .identity, .b = .identity, .a = .identity }, .subresource_range = .{ + .aspect_mask = .{ .color_bit = true }, + .base_mip_level = 0, + .level_count = 1, + .base_array_layer = 0, + .layer_count = 1, + } }, null); + } + // todo repopulate images and synchronization return true; } -pub fn get(self: Self, idx: u32) vk.Image { +pub fn getImage(self: Self, idx: u32) vk.Image { return self.images.items[idx]; } + +pub fn getView(self: Self, idx: u32) vk.ImageView { + return self.views.items[idx]; +} diff --git a/src/main.zig b/src/main.zig index 314190d..e080826 100644 --- a/src/main.zig +++ b/src/main.zig @@ -52,45 +52,6 @@ const vertices = [_]Vertex{ const indices = [_]Index{ 4, 5, 6, 6, 5, 7 }; -fn render( - dev: vk.Device, - vkd: gfx.Device.Wrapper, - swapchain: vk.SwapchainKHR, - frame: gfx.Swapchain.ChainImage, - queue: vk.Queue, -) !void { - _ = try vkd.waitForFences(dev, 1, @ptrCast(&frame.fence), vk.TRUE, std.math.maxInt(u64)); - - const result = try vkd.acquireNextImageKHR( - dev, - swapchain, - std.math.maxInt(u64), - frame.image_available, - .null_handle, - ); - - try vkd.resetFences(dev, 1, @ptrCast(&frame.fence)); - - try vkd.queueSubmit(queue, 1, @ptrCast(&vk.SubmitInfo{ - .wait_semaphore_count = 1, - .p_wait_semaphores = @ptrCast(&frame.image_available), - .p_wait_dst_stage_mask = @ptrCast(&vk.PipelineStageFlags{ .color_attachment_output_bit = true }), - .command_buffer_count = 1, - .p_command_buffers = @ptrCast(&frame.cmdbuf), - .signal_semaphore_count = 1, - .p_signal_semaphores = @ptrCast(&frame.render_finished), - }), frame.fence); - - _ = try vkd.queuePresentKHR(queue, &.{ - .wait_semaphore_count = 1, - .p_wait_semaphores = @ptrCast(&frame.render_finished), - .swapchain_count = 1, - .p_swapchains = @ptrCast(&swapchain), - .p_image_indices = @ptrCast(&result.image_index), - .p_results = null, - }); -} - pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.detectLeaks(); @@ -138,7 +99,8 @@ pub fn main() !void { sem_ready, .null_handle, ); - const image = sc.get(acq.image_index); + const image = sc.getImage(acq.image_index); + const view = sc.getView(acq.image_index); var cmd = au.CommandBufferProxy.init(.null_handle, au.D.wrapper); try au.D.allocateCommandBuffers(&.{ @@ -149,23 +111,9 @@ pub fn main() !void { try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } }); - // const clear = vk.ClearValue{ .color = .{ .float_32 = .{ 0, 0, 0, 1 } } }; - // const viewport = vk.Viewport{ - // .x = 0, - // .y = 0, - // .width = sc.cinfo.image_extent, - // .height = sc.cinfo.image_extent.height, - // .min_depth = 0, - // .max_depth = 1, - // }; - // const scissor = vk.Rect2D{ - // .offset = .{ .x = 0, .y = 0 }, - // .extent = sc.cinfo.image_extent, - // }; - cmd.pipelineBarrier( .{ .top_of_pipe_bit = true }, - .{ .bottom_of_pipe_bit = true }, + .{ .color_attachment_output_bit = true }, .{}, 0, null, @@ -174,8 +122,77 @@ pub fn main() !void { 1, @ptrCast(&vk.ImageMemoryBarrier{ .src_access_mask = .{}, - .dst_access_mask = .{}, + .dst_access_mask = .{ .color_attachment_write_bit = true }, .old_layout = .undefined, + .new_layout = .color_attachment_optimal, + .src_queue_family_index = 0, + .dst_queue_family_index = 0, + .image = image, + .subresource_range = .{ + .aspect_mask = .{ .color_bit = true }, + .base_mip_level = 0, + .level_count = 1, + .base_array_layer = 0, + .layer_count = 1, + }, + }), + ); + + const viewport = vk.Viewport{ + .x = 0, + .y = 0, + .width = @floatFromInt(sc.cinfo.image_extent.width), + .height = @floatFromInt(sc.cinfo.image_extent.height), + .min_depth = 0, + .max_depth = 1, + }; + const scissor = vk.Rect2D{ + .offset = .{ .x = 0, .y = 0 }, + .extent = sc.cinfo.image_extent, + }; + const info = vk.RenderingInfoKHR{ + .render_area = scissor, + .layer_count = 1, + .view_mask = 0, + .color_attachment_count = 1, + .p_color_attachments = &.{vk.RenderingAttachmentInfo{ + .image_view = view, + .image_layout = .color_attachment_optimal, + .resolve_mode = .{}, + .resolve_image_view = .null_handle, + .resolve_image_layout = .undefined, + .load_op = .clear, + .store_op = .store, + .clear_value = .{ .color = .{ .float_32 = .{ 1, 0, 0, 1 } } }, + }}, + }; + + cmd.setViewport(0, 1, &.{viewport}); + cmd.setScissor(0, 1, &.{scissor}); + cmd.beginRendering(&info); + + // todo + // vkd.cmdBindPipeline(cmdbuf, .graphics, pipeline); + // const offset = [_]vk.DeviceSize{0}; + // vkd.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&vertex_buffer), &offset); + // vkd.cmdBindIndexBuffer(cmdbuf, index_buffer, 0, .uint16); + // vkd.cmdDrawIndexed(cmdbuf, indices.len, 1, 0, 0, 0); + + cmd.endRendering(); + + cmd.pipelineBarrier( + .{ .color_attachment_output_bit = true }, + .{ .bottom_of_pipe_bit = true }, + .{}, + 0, + null, + 0, + null, + 1, + @ptrCast(&vk.ImageMemoryBarrier{ + .src_access_mask = .{ .color_attachment_write_bit = true }, + .dst_access_mask = .{}, + .old_layout = .color_attachment_optimal, .new_layout = .present_src_khr, .src_queue_family_index = 0, .dst_queue_family_index = 0, @@ -217,13 +234,6 @@ pub fn main() !void { try au.D.deviceWaitIdle(); - // // todo create command pool - // - // var sc = try gfx.Swapchain.create(ally, &dev); - // defer sc.deinit(); - // - // const device_local = gfx.VkAllocator.init(dev.pdev, inst.vki); - // // const pipeline_layout = try dev.vkd.createPipelineLayout(dev.dev, &.{ // .flags = .{}, // .set_layout_count = 0, @@ -235,7 +245,7 @@ pub fn main() !void { // // const pipeline = try createPipeline(dev.dev, pipeline_layout, dev.format, dev.vkd); // defer dev.vkd.destroyPipeline(dev.dev, pipeline, null); - // + // const vertex_buffer = try dev.vkd.createBuffer(dev.dev, &.{ // .size = @sizeOf(@TypeOf(vertices)), // .usage = .{ .transfer_dst_bit = true, .vertex_buffer_bit = true }, @@ -246,9 +256,8 @@ pub fn main() !void { // const vertex_memory = try device_local.alloc(dev.dev, dev.vkd, vertex_mem_reqs, .{ .device_local_bit = true }); // defer dev.vkd.freeMemory(dev.dev, vertex_memory, null); // try dev.vkd.bindBufferMemory(dev.dev, vertex_buffer, vertex_memory, 0); - // // try gfx.uploadData(Vertex, dev.pdev, inst.vki, dev.dev, dev.vkd, dev.queue, dev.pool, vertex_buffer, &vertices); - // + // const index_buffer = try dev.vkd.createBuffer(dev.dev, &.{ // .size = @sizeOf(@TypeOf(indices)), // .usage = .{ .transfer_dst_bit = true, .index_buffer_bit = true }, @@ -259,177 +268,7 @@ pub fn main() !void { // const index_memory = try device_local.alloc(dev.dev, dev.vkd, index_mem_reqs, .{ .device_local_bit = true }); // defer dev.vkd.freeMemory(dev.dev, index_memory, null); // try dev.vkd.bindBufferMemory(dev.dev, index_buffer, index_memory, 0); - // // try gfx.uploadData(Index, dev.pdev, inst.vki, dev.dev, dev.vkd, dev.queue, dev.pool, index_buffer, &indices); - // - // try sc.init(); - // for (sc.chain.items(.image), sc.chain.items(.view), sc.chain.items(.cmdbuf)) |image, view, cmdbuf| { - // try record_cmdbuf(cmdbuf, dev.vkd, image, view, sc.extent, pipeline, vertex_buffer, index_buffer); - // } - // - // var index: u32 = 0; - // - // while (c.glfwWindowShouldClose(win.ref) == c.GLFW_FALSE) { - // var w: c_int = undefined; - // var h: c_int = undefined; - // c.glfwGetFramebufferSize(win.ref, &w, &h); - // - // // Don't present or resize swapchain while the window is minimized - // if (w == 0 or h == 0) { - // c.glfwPollEvents(); - // continue; - // } - // - // const frame = sc.chain.get(index); - // - // render(dev.dev, dev.vkd, sc.ref, frame, dev.queue) catch |err| switch (err) { - // error.OutOfDateKHR => { - // // TODO: this is a hack to safely destroy sync primitives - // // don't do this. be smart about sync primitive reuse or - // // move them to "garbage" to be destroyed later. - // try dev.vkd.deviceWaitIdle(dev.dev); - // - // try sc.init(); - // for (sc.chain.items(.image), sc.chain.items(.view), sc.chain.items(.cmdbuf)) |image, view, cmdbuf| { - // try record_cmdbuf(cmdbuf, dev.vkd, image, view, sc.extent, pipeline, vertex_buffer, index_buffer); - // } - // - // index = 0; - // - // continue; - // }, - // else => |errx| return errx, - // }; - // - // c.glfwPollEvents(); - // - // index = @intCast((index + 1) % sc.chain.len); - // } - // - // try dev.vkd.deviceWaitIdle(dev.dev); -} - -fn record_cmdbuf( - cmdbuf: vk.CommandBuffer, - vkd: gfx.Device.Wrapper, - image: vk.Image, - view: vk.ImageView, - extent: vk.Extent2D, - pipeline: vk.Pipeline, - vertex_buffer: vk.Buffer, - index_buffer: vk.Buffer, -) !void { - const clear = vk.ClearValue{ - .color = .{ .float_32 = .{ 0, 0, 0, 1 } }, - }; - - const viewport = vk.Viewport{ - .x = 0, - .y = 0, - .width = @floatFromInt(extent.width), - .height = @floatFromInt(extent.height), - .min_depth = 0, - .max_depth = 1, - }; - - const scissor = vk.Rect2D{ - .offset = .{ .x = 0, .y = 0 }, - .extent = extent, - }; - - try vkd.beginCommandBuffer(cmdbuf, &.{}); - - vkd.cmdPipelineBarrier( - cmdbuf, - .{ .top_of_pipe_bit = true }, - .{ .color_attachment_output_bit = true }, - .{}, - 0, - null, - 0, - null, - 1, - @ptrCast(&vk.ImageMemoryBarrier{ - .src_access_mask = .{}, - .dst_access_mask = .{ .color_attachment_write_bit = true }, - .old_layout = .undefined, - .new_layout = .color_attachment_optimal, - .src_queue_family_index = 0, - .dst_queue_family_index = 0, - .image = image, - .subresource_range = .{ - .aspect_mask = .{ .color_bit = true }, - .base_mip_level = 0, - .level_count = 1, - .base_array_layer = 0, - .layer_count = 1, - }, - }), - ); - - vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport)); - vkd.cmdSetScissor(cmdbuf, 0, 1, @ptrCast(&scissor)); - - const color_attachments = [_]vk.RenderingAttachmentInfoKHR{ - .{ - .image_view = view, - .image_layout = .color_attachment_optimal, - .resolve_mode = .{}, - .resolve_image_view = .null_handle, - .resolve_image_layout = .undefined, - .load_op = .clear, - .store_op = .store, - .clear_value = clear, - }, - }; - - const render_info = vk.RenderingInfoKHR{ - .render_area = scissor, // since we always do full-frame changes - .layer_count = 1, - .view_mask = 0, - .color_attachment_count = color_attachments.len, - .p_color_attachments = &color_attachments, - }; - - vkd.cmdBeginRenderingKHR(cmdbuf, &render_info); - - vkd.cmdBindPipeline(cmdbuf, .graphics, pipeline); - const offset = [_]vk.DeviceSize{0}; - vkd.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&vertex_buffer), &offset); - vkd.cmdBindIndexBuffer(cmdbuf, index_buffer, 0, .uint16); - vkd.cmdDrawIndexed(cmdbuf, indices.len, 1, 0, 0, 0); - - vkd.cmdEndRenderingKHR(cmdbuf); - - vkd.cmdPipelineBarrier( - cmdbuf, - .{ .color_attachment_output_bit = true }, - .{ .bottom_of_pipe_bit = true }, - .{}, - 0, - null, - 0, - null, - 1, - @ptrCast(&vk.ImageMemoryBarrier{ - .src_access_mask = .{ .color_attachment_write_bit = true }, - .dst_access_mask = .{}, - .old_layout = .color_attachment_optimal, - .new_layout = .present_src_khr, - .src_queue_family_index = 0, - .dst_queue_family_index = 0, - .image = image, - .subresource_range = .{ - .aspect_mask = .{ .color_bit = true }, - .base_mip_level = 0, - .level_count = 1, - .base_array_layer = 0, - .layer_count = 1, - }, - }), - ); - - try vkd.endCommandBuffer(cmdbuf); } fn createPipeline(