Files
zig-experiments/src/nu/Render.zig
David Allemang ccee3733b0 nu simplified; working swapchain, queue, and validators.
it compiles, but initialization is not done

create debug messenger

Use proxies

wip swapchain

wip swapchain - stub usage

get device queue

wip swapchain - scaffolded with segfault

wip swapchain - fix segfault

wip swapchain - working, but resize broken. semaphore issue with naive handling

satisfy validation
2024-11-24 21:44:21 -05:00

214 lines
6.5 KiB
Zig

//! 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);
}