diff --git a/examples/graphics_context.zig b/examples/graphics_context.zig index e2b2c74..852f0c8 100644 --- a/examples/graphics_context.zig +++ b/examples/graphics_context.zig @@ -46,6 +46,15 @@ const DeviceDispatch = struct { vkResetFences: vk.PfnResetFences, vkQueueSubmit: vk.PfnQueueSubmit, vkQueuePresentKHR: vk.PfnQueuePresentKHR, + vkCreateCommandPool: vk.PfnCreateCommandPool, + vkDestroyCommandPool: vk.PfnDestroyCommandPool, + vkAllocateCommandBuffers: vk.PfnAllocateCommandBuffers, + vkFreeCommandBuffers: vk.PfnFreeCommandBuffers, + vkBeginCommandBuffer: vk.PfnBeginCommandBuffer, + vkCmdClearColorImage: vk.PfnCmdClearColorImage, + vkEndCommandBuffer: vk.PfnEndCommandBuffer, + vkQueueWaitIdle: vk.PfnQueueWaitIdle, + vkCmdPipelineBarrier: vk.PfnCmdPipelineBarrier, usingnamespace vk.DeviceWrapper(@This()); }; diff --git a/examples/main.zig b/examples/main.zig index 21a2bd9..4ad3502 100644 --- a/examples/main.zig +++ b/examples/main.zig @@ -34,11 +34,116 @@ pub fn main() !void { std.debug.print("Using device: {}\n", .{gc.deviceName()}); - const swapchain = try Swapchain.init(&gc, std.heap.page_allocator, extent); + var swapchain = try Swapchain.init(&gc, std.heap.page_allocator, extent); defer swapchain.deinit(); + const pool = try gc.vkd.createCommandPool(gc.dev, .{ + .flags = .{}, + .queue_family_index = gc.graphics_queue.family, + }, null); + defer gc.vkd.destroyCommandPool(gc.dev, pool, null); + while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) { + var cmdbuf: vk.CommandBuffer = undefined; + try gc.vkd.allocateCommandBuffers(gc.dev, .{ + .command_pool = pool, + .level = .primary, + .command_buffer_count = 1, + }, @ptrCast([*]vk.CommandBuffer, &cmdbuf)); + defer gc.vkd.freeCommandBuffers(gc.dev, pool, 1, @ptrCast([*]const vk.CommandBuffer, &cmdbuf)); + + try gc.vkd.beginCommandBuffer(cmdbuf, .{ + .flags = .{.one_time_submit_bit = true}, + .p_inheritance_info = null, + }); + + const subresource_range = vk.ImageSubresourceRange{ + .aspect_mask = .{.color_bit = true}, + .base_mip_level = 0, + .level_count = 1, + .base_array_layer = 0, + .layer_count = 1, + }; + + const color = vk.ClearColorValue{.float_32 = .{1, 0, 1, 1}}; + + imageTransition( + &gc, + cmdbuf, + swapchain.currentImage(), + subresource_range, + .{.layout = .@"undefined", .stage = .{.top_of_pipe_bit = true}}, + .{.layout = .general, .stage = .{.top_of_pipe_bit = true}}, + ); + + gc.vkd.cmdClearColorImage( + cmdbuf, + swapchain.currentImage(), + .general, + color, + 1, + @ptrCast([*]const vk.ImageSubresourceRange, &subresource_range), + ); + + imageTransition( + &gc, + cmdbuf, + swapchain.currentImage(), + subresource_range, + .{.layout = .general, .stage = .{.top_of_pipe_bit = true}}, + .{.layout = .present_src_khr, .stage = .{.bottom_of_pipe_bit = true}}, + ); + + try gc.vkd.endCommandBuffer(cmdbuf); + const result = swapchain.present(cmdbuf); + try gc.vkd.queueWaitIdle(gc.graphics_queue.handle); + const state = result catch |err| switch (err) { + error.OutOfDateKHR => Swapchain.PresentState.suboptimal, + else => |narrow| return narrow, + }; + + if (state == .suboptimal) { + var w: c_int = undefined; + var h: c_int = undefined; + c.glfwGetWindowSize(window, &w, &h); + + try swapchain.recreate(.{.width = @intCast(u32, w), .height = @intCast(u32, h)}); + } + c.glfwSwapBuffers(window); c.glfwPollEvents(); } } + +const ImageState = struct { + layout: vk.ImageLayout, + stage: vk.PipelineStageFlags, + access_mask: vk.AccessFlags = .{}, +}; + +fn imageTransition( + gc: *const GraphicsContext, + cmdbuf: vk.CommandBuffer, + image: vk.Image, + subresource_range: vk.ImageSubresourceRange, + src: ImageState, + dst: ImageState +) void { + const barrier = vk.ImageMemoryBarrier{ + .src_access_mask = src.access_mask, + .dst_access_mask = dst.access_mask, + .old_layout = src.layout, + .new_layout = dst.layout, + .src_queue_family_index = vk.QUEUE_FAMILY_IGNORED, + .dst_queue_family_index = vk.QUEUE_FAMILY_IGNORED, + .image = image, + .subresource_range = subresource_range, + }; + + gc.vkd.cmdPipelineBarrier( + cmdbuf, src.stage, dst.stage, .{}, + 0, undefined, + 0, undefined, + 1, @ptrCast([*]const vk.ImageMemoryBarrier, &barrier) + ); +} diff --git a/examples/swapchain.zig b/examples/swapchain.zig index 37e1af9..b6208ac 100644 --- a/examples/swapchain.zig +++ b/examples/swapchain.zig @@ -100,7 +100,7 @@ pub const Swapchain = struct { self.gc.vkd.destroySwapchainKHR(self.gc.dev, self.handle, null); } - pub fn recreate(self: *Swapchain, new_extent: vk.Extnet2D) !void { + pub fn recreate(self: *Swapchain, new_extent: vk.Extent2D) !void { const gc = self.gc; const allocator = self.allocator; const old_handle = self.handle; @@ -142,22 +142,22 @@ pub const Swapchain = struct { // Step 2: Submit the command buffer const wait_stage = [_]vk.PipelineStageFlags{.{.top_of_pipe_bit = true}}; - try self.gc.vkd.queueSubmit(self.gc.graphics_queue.handle, 1, .{ + try self.gc.vkd.queueSubmit(self.gc.graphics_queue.handle, 1, &[_]vk.SubmitInfo{.{ .wait_semaphore_count = 1, .p_wait_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.image_acquired), .p_wait_dst_stage_mask = &wait_stage, .command_buffer_count = 1, - .p_command_buffers = @ptrCast([*]const CommandBuffer, &cmdbuf), + .p_command_buffers = @ptrCast([*]const vk.CommandBuffer, &cmdbuf), .signal_semaphore_count = 1, .p_signal_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished), - }, current_swap_image.frame_fence); + }}, current.frame_fence); // Step 3: Present the current frame _ = try self.gc.vkd.queuePresentKHR(self.gc.present_queue.handle, .{ .wait_semaphore_count = 1, - .p_signal_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished), + .p_wait_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished), .swapchain_count = 1, - .p_swapchains = @ptrCast([*]const vk.Swapchain, &self.handle), + .p_swapchains = @ptrCast([*]const vk.SwapchainKHR, &self.handle), .p_image_indices = @ptrCast([*]const u32, &self.image_index), .p_results = null, }); @@ -174,9 +174,10 @@ pub const Swapchain = struct { std.mem.swap(vk.Semaphore, &self.swap_images[result.image_index].image_acquired, &self.next_image_acquired); self.image_index = result.image_index; - return switch (result) { + return switch (result.result) { .success => .optimal, .suboptimal_khr => .suboptimal, + else => unreachable, }; } }; diff --git a/generator/render.zig b/generator/render.zig index 8b038a3..93343db 100644 --- a/generator/render.zig +++ b/generator/render.zig @@ -211,6 +211,13 @@ fn Renderer(comptime WriterType: type) type { }; } + fn isFlags(self: Self, name: []const u8) bool { + const tag = util.getAuthorTag(name, self.registry.tags); + const base_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name; + + return mem.endsWith(u8, base_name, "Flags"); + } + fn classifyParam(self: Self, param: reg.Command.Param) !ParamType { switch (param.param_type) { .pointer => |ptr| { @@ -240,7 +247,7 @@ fn Renderer(comptime WriterType: type) type { } }, .name => |name| { - if (self.extractBitflagName(param.param_type.name) != null) { + if (self.extractBitflagName(param.param_type.name) != null or self.isFlags(param.param_type.name)) { return .bitflags; } }, @@ -440,6 +447,10 @@ fn Renderer(comptime WriterType: type) type { }); try self.writer.writeAll(".IntType"); break :blk; + } else if (self.isFlags(param.param_type.name)) { + try self.renderTypeInfo(param.param_type); + try self.writer.writeAll(".IntType"); + break :blk; } } @@ -870,7 +881,7 @@ fn Renderer(comptime WriterType: type) type { }, .bitflags => { try self.writeIdentifierWithCase(.snake, param.name); - try self.writer.writeAll(".toInt()"); // TODO: Generate wrapper + try self.writer.writeAll(".toInt()"); }, .buffer_len, .mut_buffer_len, .other => { try self.writeIdentifierWithCase(.snake, param.name);