const std = @import("std"); const log = std.log.scoped(.graphics); const vk = @import("vulkan"); const commands = @import("commands.zig"); const device = @import("device.zig"); const swapchain = @import("swapchain.zig"); const sync = @import("sync.zig"); pub const FrameResult = enum { OK, Recreate, }; pub fn drawFrame( ldc: device.LogicalDeviceContext, swapchain_context: swapchain.SwapchainContext, command_context: commands.CommandContext, sync_context: sync.SyncContext, ) !FrameResult { const wait_fences = [_]vk.Fence{sync_context.in_flight_fence}; _ = try ldc.vkd.waitForFences(ldc.device, &wait_fences, .true, std.math.maxInt(u64)); const image_result = ldc.vkd.acquireNextImageKHR( ldc.device, swapchain_context.swapchain, std.math.maxInt(u64), sync_context.image_available_semaphore, .null_handle, ) catch |err| switch (err) { error.OutOfDateKHR => return .Recreate, else => return err, }; const image_index = image_result.image_index; const should_recreate_after_present = image_result.result == .suboptimal_khr; log.debug("Acquired swapchain image: {}", .{image_index}); try ldc.vkd.resetFences(ldc.device, &wait_fences); const wait_semaphores = [_]vk.Semaphore{sync_context.image_available_semaphore}; const wait_stages = [_]vk.PipelineStageFlags{ .{ .color_attachment_output_bit = true, }, }; const signal_semaphores = [_]vk.Semaphore{sync_context.render_finished_semaphore}; const submit_command_buffers = [_]vk.CommandBuffer{ command_context.command_buffers[image_index], }; const submit_info = vk.SubmitInfo{ .wait_semaphore_count = wait_semaphores.len, .p_wait_semaphores = &wait_semaphores, .p_wait_dst_stage_mask = &wait_stages, .command_buffer_count = submit_command_buffers.len, .p_command_buffers = &submit_command_buffers, .signal_semaphore_count = signal_semaphores.len, .p_signal_semaphores = &signal_semaphores, }; try ldc.vkd.queueSubmit(ldc.graphics_queue, &[_]vk.SubmitInfo{submit_info}, sync_context.in_flight_fence); const present_swapchains = [_]vk.SwapchainKHR{swapchain_context.swapchain}; const present_image_indices = [_]u32{image_index}; const present_info = vk.PresentInfoKHR{ .wait_semaphore_count = signal_semaphores.len, .p_wait_semaphores = &signal_semaphores, .swapchain_count = present_swapchains.len, .p_swapchains = &present_swapchains, .p_image_indices = &present_image_indices, }; const present_result = ldc.vkd.queuePresentKHR(ldc.graphics_queue, &present_info) catch |err| switch (err) { error.OutOfDateKHR => return .Recreate, else => return err, }; log.debug("Presented one frame", .{}); if (should_recreate_after_present or present_result == .suboptimal_khr) { return FrameResult.Recreate; } return FrameResult.OK; }