starting to test swapchain
This commit is contained in:
@@ -4,7 +4,8 @@ const builtin = @import("builtin");
|
|||||||
const vk = @import("vk");
|
const vk = @import("vk");
|
||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
|
|
||||||
const Bus = @import("au/Bus.zig");
|
pub const Bus = @import("au/Bus.zig");
|
||||||
|
pub const SwapChain = @import("au/SwapChain.zig");
|
||||||
|
|
||||||
pub const use_debug_messenger = switch (builtin.mode) {
|
pub const use_debug_messenger = switch (builtin.mode) {
|
||||||
.Debug, .ReleaseSafe => true,
|
.Debug, .ReleaseSafe => true,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const vk = @import("vk");
|
||||||
const c = @import("../c.zig");
|
const c = @import("../c.zig");
|
||||||
const Window = @import("../au.zig").Window;
|
const Window = @import("../au.zig").Window;
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
@@ -86,7 +87,7 @@ pub const Event = union(enum) {
|
|||||||
const WindowFocus = struct { focused: bool };
|
const WindowFocus = struct { focused: bool };
|
||||||
const WindowIconify = struct { iconified: bool };
|
const WindowIconify = struct { iconified: bool };
|
||||||
const WindowMaximize = struct { maximized: bool };
|
const WindowMaximize = struct { maximized: bool };
|
||||||
const FramebufferSize = struct { x: i32, y: i32 };
|
const FramebufferSize = struct { extent: vk.Extent2D };
|
||||||
const WindowContentScale = struct { x: f32, y: f32 };
|
const WindowContentScale = struct { x: f32, y: f32 };
|
||||||
const MouseButton = struct {
|
const MouseButton = struct {
|
||||||
button: c_int, // todo enum
|
button: c_int, // todo enum
|
||||||
@@ -193,12 +194,14 @@ fn onWindowMaximize(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.C) void
|
|||||||
}) catch unreachable; // todo circular queue; warn
|
}) catch unreachable; // todo circular queue; warn
|
||||||
}
|
}
|
||||||
|
|
||||||
fn onFramebufferSize(handle: ?*c.GLFWwindow, x: c_int, y: c_int) callconv(.C) void {
|
fn onFramebufferSize(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
|
||||||
const bus = getBus(handle);
|
const bus = getBus(handle);
|
||||||
bus.events.append(bus.alloc, .{
|
bus.events.append(bus.alloc, .{
|
||||||
.framebufferSize = .{
|
.framebufferSize = .{
|
||||||
.x = @intCast(x),
|
.extent = .{
|
||||||
.y = @intCast(y),
|
.width = @intCast(width),
|
||||||
|
.height = @intCast(height),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}) catch unreachable; // todo circular queue; warn
|
}) catch unreachable; // todo circular queue; warn
|
||||||
}
|
}
|
||||||
|
68
src/au/SwapChain.zig
Normal file
68
src/au/SwapChain.zig
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const au = @import("../au.zig");
|
||||||
|
const vk = @import("vk");
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
cinfo: vk.SwapchainCreateInfoKHR,
|
||||||
|
handle: vk.SwapchainKHR,
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) !Self {
|
||||||
|
const caps = try au.I.getPhysicalDeviceSurfaceCapabilitiesKHR(au.device_config.pdev, au.W.surface);
|
||||||
|
|
||||||
|
var min_image_count = @max(3, caps.min_image_count + 1); // todo magic numbers
|
||||||
|
if (caps.max_image_count > 0) {
|
||||||
|
min_image_count = @min(min_image_count, caps.max_image_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine format
|
||||||
|
const format = au.device_config.format;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.cinfo = .{
|
||||||
|
.surface = au.W.surface,
|
||||||
|
.min_image_count = min_image_count,
|
||||||
|
.image_format = format.format,
|
||||||
|
.image_color_space = format.color_space,
|
||||||
|
.image_extent = undefined, // set in rebuild
|
||||||
|
.image_array_layers = 1,
|
||||||
|
.image_usage = .{ .color_attachment_bit = true },
|
||||||
|
.image_sharing_mode = .exclusive,
|
||||||
|
.pre_transform = .{ .identity_bit_khr = true },
|
||||||
|
.composite_alpha = .{ .opaque_bit_khr = true },
|
||||||
|
.present_mode = au.device_config.mode,
|
||||||
|
.clipped = vk.TRUE,
|
||||||
|
.old_swapchain = .null_handle,
|
||||||
|
},
|
||||||
|
.handle = .null_handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
au.D.destroySwapchainKHR(self.handle, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// mark that the swapchain _should_ be rebuilt with the given extent
|
||||||
|
/// this function is reentrant, so the swapchain can be marked multiple times
|
||||||
|
/// and only one rebuild occur
|
||||||
|
pub fn mark(self: *Self) void {
|
||||||
|
self.handle = .null_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// rebuild the swapchain only if it is marked. return true if the swapchain was rebuilt.
|
||||||
|
pub fn rebuild(self: *Self) !bool {
|
||||||
|
if (self.handle != .null_handle) return false;
|
||||||
|
|
||||||
|
const caps = try au.I.getPhysicalDeviceSurfaceCapabilitiesKHR(au.device_config.pdev, self.cinfo.surface);
|
||||||
|
self.cinfo.image_extent = caps.current_extent;
|
||||||
|
|
||||||
|
self.handle = try au.D.createSwapchainKHR(&self.cinfo, null);
|
||||||
|
au.D.destroySwapchainKHR(self.cinfo.old_swapchain, null);
|
||||||
|
self.cinfo.old_swapchain = self.handle;
|
||||||
|
|
||||||
|
// todo repopulate images and synchronization
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
79
src/main.zig
79
src/main.zig
@@ -99,19 +99,86 @@ pub fn main() !void {
|
|||||||
try au.init(alloc);
|
try au.init(alloc);
|
||||||
defer au.deinit();
|
defer au.deinit();
|
||||||
|
|
||||||
|
var sc = try au.SwapChain.init(alloc);
|
||||||
|
defer sc.deinit();
|
||||||
|
|
||||||
|
const pool = try au.D.createCommandPool(&.{ .queue_family_index = au.device_config.family }, null);
|
||||||
|
defer au.D.destroyCommandPool(pool, null);
|
||||||
|
|
||||||
|
const fence: vk.Fence = try au.D.createFence(&.{ .flags = .{ .signaled_bit = true } }, null);
|
||||||
|
defer au.D.destroyFence(fence, null);
|
||||||
|
|
||||||
|
const sem_ready: vk.Semaphore = try au.D.createSemaphore(&.{}, null);
|
||||||
|
defer au.D.destroySemaphore(sem_ready, null);
|
||||||
|
|
||||||
|
const sem_done: vk.Semaphore = try au.D.createSemaphore(&.{}, null);
|
||||||
|
defer au.D.destroySemaphore(sem_done, null);
|
||||||
|
|
||||||
|
const cmdbufs: [1]vk.CommandBuffer = undefined;
|
||||||
|
try au.D.allocateCommandBuffers(
|
||||||
|
&.{ .command_pool = pool, .command_buffer_count = @intCast(cmdbufs.len), .level = .primary },
|
||||||
|
cmdbufs.ptr,
|
||||||
|
);
|
||||||
|
defer au.D.freeCommandBuffers(pool, @intCast(cmdbufs.len), cmdbufs.ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
const cmd = au.CommandBufferProxy.init(cmdbufs[0], au.D);
|
||||||
|
const clear = vk.ClearValue{ .color = .{ .float_32 = .{ 0, 0, 0, 1 } } };
|
||||||
|
const viewport = vk.Viewport{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = sc.cinfo.image_extent.width,
|
||||||
|
.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 };
|
||||||
|
|
||||||
|
try cmd.beginCommandBuffer(&.{});
|
||||||
|
cmd.pipelineBarrier(
|
||||||
|
.{ .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 = .null_handle, // todo this needs to point to the swapchain image, so I can't get away from recording a command buffer for each one.
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
while (!au.W.should_close()) {
|
while (!au.W.should_close()) {
|
||||||
// todo switch mode depending on if window is focused
|
// todo switch mode depending on if window is focused
|
||||||
const events = au.wait_events_timeout(0.10);
|
const events = au.wait_events_timeout(0.10);
|
||||||
|
|
||||||
for (events) |u| switch (u) {
|
for (events) |u| switch (u) {
|
||||||
.cursorPos,
|
.framebufferSize => sc.mark(),
|
||||||
.windowPos,
|
.cursorPos, .windowPos, .windowSize, .windowRefresh => {},
|
||||||
.windowSize,
|
|
||||||
.framebufferSize,
|
|
||||||
.windowRefresh,
|
|
||||||
=> {},
|
|
||||||
else => |e| std.debug.print("{any}\n", .{e}),
|
else => |e| std.debug.print("{any}\n", .{e}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_ = try sc.rebuild();
|
||||||
|
|
||||||
|
const acq = try au.D.acquireNextImageKHR(sc.handle, std.math.maxInt(u64), sem_ready, .null_handle);
|
||||||
|
|
||||||
|
const pre = try au.Q.presentKHR(&vk.PresentInfoKHR{
|
||||||
|
.wait_semaphore_count = 1,
|
||||||
|
.p_wait_semaphores = &.{sem_done},
|
||||||
|
.swapchain_count = 1,
|
||||||
|
.p_swapchains = &.{sc.handle},
|
||||||
|
.p_image_indices = &.{acq.image_index},
|
||||||
|
.p_results = null,
|
||||||
|
});
|
||||||
|
std.debug.print("present result: {}\n", .{pre});
|
||||||
}
|
}
|
||||||
|
|
||||||
try au.D.deviceWaitIdle();
|
try au.D.deviceWaitIdle();
|
||||||
|
Reference in New Issue
Block a user