//! Isolate vulkan code (except for ImGui) through this module. //! //! Requires that Window module already be initialized. const std = @import("std"); const builtin = @import("builtin"); const vk = @import("vk"); const nu = @import("../nu.zig"); // const au = @import("Render/au.zig"); const ctx = @import("Render/ctx.zig"); const swap_chain = @import("Render/swap_chain.zig"); pub const Config = struct { app_name: [*:0]const u8 = "nu-au-app", app_version: struct { variant: u3 = 0, major: u7 = 0, minor: u10 = 0, patch: u12 = 0, } = .{}, engine_name: [*:0]const u8 = "nu-au", engine_version: struct { variant: u3 = 0, major: u7 = 0, minor: u10 = 0, patch: u12 = 0, } = .{}, use_debug_messenger: bool = switch (builtin.mode) { .Debug, .ReleaseSafe => true, .ReleaseSmall, .ReleaseFast => false, }, }; const config = nu.config.render; pub const depends = .{nu.Window}; const SwapChain = swap_chain.SwapChain(Flight); const Flight = struct { pool: vk.CommandPool = .null_handle, cmd: vk.CommandBuffer = .null_handle, pub fn init() !Flight { const pool = try ctx.D.createCommandPool( &.{ .queue_family_index = ctx.family.* }, null, ); errdefer ctx.D.destroyCommandPool(pool, null); var cmds: [1]vk.CommandBuffer = undefined; try ctx.D.allocateCommandBuffers( &vk.CommandBufferAllocateInfo{ .command_buffer_count = 1, .command_pool = pool, .level = .primary, }, &cmds, ); errdefer ctx.D.freeCommandBuffers(pool, 1, &cmds); return .{ .pool = pool, .cmd = cmds[0], }; } pub fn deinit(self: Flight) void { const cmds: [1]vk.CommandBuffer = .{self.cmd}; ctx.D.freeCommandBuffers(self.pool, 1, &cmds); ctx.D.destroyCommandPool(self.pool, null); } }; var _sc: SwapChain = undefined; var _flights: []Flight = undefined; pub fn setup(alloc: std.mem.Allocator) !void { try ctx.init(alloc); errdefer ctx.deinit(); _flights = try alloc.alloc(Flight, 3); errdefer alloc.free(_flights); errdefer for (_flights) |flight| flight.deinit(); for (_flights) |*flight| flight.* = try Flight.init(); _sc = try SwapChain.init(alloc, _flights); errdefer _sc.deinit(); } pub fn teardown() void { _sc.deinit(); for (_flights) |flight| flight.deinit(); ctx.deinit(); } pub fn render() !void { const target = try _sc.acquire(); const render_area: vk.Rect2D = .{ .offset = .{ .x = 0, .y = 0 }, .extent = _sc.cinfo.image_extent, }; try ctx.D.resetCommandPool(target.flight.pool, .{}); var cmd = ctx.CommandBufferProxy.init(target.flight.cmd, ctx.dw); try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } }); { cmd.pipelineBarrier( .{ .top_of_pipe_bit = true }, .{ .color_attachment_output_bit = true }, .{}, 0, null, 0, null, 1, &.{ 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, // values are the same; no transfer occurs .dst_queue_family_index = 0, .image = target.image, .subresource_range = .{ .aspect_mask = .{ .color_bit = true }, .base_mip_level = 0, .level_count = 1, .base_array_layer = 0, .layer_count = 1, }, }, }, ); cmd.beginRendering(&vk.RenderingInfo{ .render_area = render_area, .layer_count = 1, .view_mask = 0, .color_attachment_count = 1, .p_color_attachments = &.{ vk.RenderingAttachmentInfo{ .image_view = target.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.endRendering(); cmd.pipelineBarrier( .{ .color_attachment_output_bit = true }, .{ .bottom_of_pipe_bit = true }, .{}, 0, null, 0, null, 1, &.{ 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, // values are the same; no transfer occurs. .dst_queue_family_index = 0, .image = target.image, .subresource_range = .{ .aspect_mask = .{ .color_bit = true }, .base_mip_level = 0, .level_count = 1, .base_array_layer = 0, .layer_count = 1, }, }, }, ); } try cmd.endCommandBuffer(); try ctx.Q.submit( 1, &.{ vk.SubmitInfo{ .wait_semaphore_count = 1, // don't start writing to color attachment until the swapchain image has been acquired. .p_wait_semaphores = &.{ target.acquired, }, .p_wait_dst_stage_mask = &.{ vk.PipelineStageFlags{ .color_attachment_output_bit = true }, }, .command_buffer_count = 1, .p_command_buffers = &.{target.flight.cmd}, .signal_semaphore_count = 1, .p_signal_semaphores = &.{target.complete}, }, }, target.available, // target will become available again once these finish ); try _sc.present(target); }