swapchain recreation works, but buggy

This commit is contained in:
David Allemang
2024-04-02 00:37:52 -04:00
parent 0bcc87adc3
commit 2300e6e301

View File

@@ -50,6 +50,143 @@ const vertices = [_]Vertex{
const indices = [_]Index{ 4, 5, 6, 6, 5, 7 };
const ChainImage = struct {
image: vk.Image = .null_handle,
view: vk.ImageView = .null_handle,
cmdbuf: vk.CommandBuffer = .null_handle,
fence: vk.Fence = .null_handle,
image_available: vk.Semaphore = .null_handle,
render_finished: vk.Semaphore = .null_handle,
};
pub fn create_swapchain(
chain: *std.MultiArrayList(ChainImage),
swapchain: *vk.SwapchainKHR,
ally: std.mem.Allocator,
pdev: vk.PhysicalDevice,
vki: gfx.InstanceDispatch,
window: *c.GLFWwindow,
dev: vk.Device,
vkd: gfx.DeviceDispatch,
pool: vk.CommandPool,
surface: vk.SurfaceKHR,
swap_image_count: u32,
format: vk.SurfaceFormatKHR,
present_mode: vk.PresentModeKHR,
) !vk.Extent2D {
const extent = try gfx.find_swap_extent(pdev, vki, surface, window);
swapchain.* = try vkd.createSwapchainKHR(dev, &.{
.surface = surface,
.min_image_count = swap_image_count,
.image_format = format.format,
.image_color_space = format.color_space,
.image_extent = extent,
.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 = present_mode,
.clipped = vk.TRUE,
.old_swapchain = swapchain.*,
}, null);
var image_count: u32 = undefined;
_ = try vkd.getSwapchainImagesKHR(dev, swapchain.*, &image_count, null);
try chain.resize(ally, image_count);
_ = try vkd.getSwapchainImagesKHR(dev, swapchain.*, &image_count, chain.items(.image).ptr);
// memset so that deinit_chain will succeed with .null_handle if error part-way through a loop.
@memset(chain.items(.view), .null_handle);
@memset(chain.items(.cmdbuf), .null_handle);
@memset(chain.items(.fence), .null_handle);
@memset(chain.items(.image_available), .null_handle);
errdefer deinit_chain(chain.*, dev, vkd, pool);
for (chain.items(.image), chain.items(.view)) |image, *view| {
view.* = try vkd.createImageView(dev, &.{
.image = image,
.view_type = .@"2d",
.format = format.format,
.components = .{ .r = .identity, .g = .identity, .b = .identity, .a = .identity },
.subresource_range = .{
.aspect_mask = .{ .color_bit = true },
.base_mip_level = 0,
.level_count = 1,
.base_array_layer = 0,
.layer_count = 1,
},
}, null);
}
for (chain.items(.fence)) |*fence| {
fence.* = try vkd.createFence(dev, &.{ .flags = .{ .signaled_bit = true } }, null);
}
for (chain.items(.image_available)) |*sem| {
sem.* = try vkd.createSemaphore(dev, &.{}, null);
}
for (chain.items(.render_finished)) |*sem| {
sem.* = try vkd.createSemaphore(dev, &.{}, null);
}
try vkd.allocateCommandBuffers(dev, &.{
.command_buffer_count = @intCast(chain.len),
.command_pool = pool,
.level = .primary,
}, chain.items(.cmdbuf).ptr);
return extent;
}
pub fn deinit_chain(
chain: std.MultiArrayList(ChainImage),
dev: vk.Device,
vkd: gfx.DeviceDispatch,
pool: vk.CommandPool,
) void {
vkd.freeCommandBuffers(dev, pool, @intCast(chain.len), chain.items(.cmdbuf).ptr);
for (chain.items(.view)) |view| vkd.destroyImageView(dev, view, null);
for (chain.items(.fence)) |fence| vkd.destroyFence(dev, fence, null);
for (chain.items(.image_available)) |sem| vkd.destroySemaphore(dev, sem, null);
for (chain.items(.render_finished)) |sem| vkd.destroySemaphore(dev, sem, null);
}
fn render(dev: vk.Device, vkd: gfx.DeviceDispatch, swapchain: vk.SwapchainKHR, frame: ChainImage, queue: vk.Queue) !void {
_ = try vkd.waitForFences(dev, 1, @ptrCast(&frame.fence), vk.TRUE, std.math.maxInt(u64));
const result = try vkd.acquireNextImageKHR(
dev,
swapchain,
std.math.maxInt(u64),
frame.image_available,
.null_handle,
);
try vkd.resetFences(dev, 1, @ptrCast(&frame.fence));
try vkd.queueSubmit(queue, 1, @ptrCast(&vk.SubmitInfo{
.wait_semaphore_count = 1,
.p_wait_semaphores = @ptrCast(&frame.image_available),
.p_wait_dst_stage_mask = @ptrCast(&vk.PipelineStageFlags{ .color_attachment_output_bit = true }),
.command_buffer_count = 1,
.p_command_buffers = @ptrCast(&frame.cmdbuf),
.signal_semaphore_count = 1,
.p_signal_semaphores = @ptrCast(&frame.render_finished),
}), frame.fence);
_ = try vkd.queuePresentKHR(queue, &.{
.wait_semaphore_count = 1,
.p_wait_semaphores = @ptrCast(&frame.render_finished),
.swapchain_count = 1,
.p_swapchains = @ptrCast(&swapchain),
.p_image_indices = @ptrCast(&result.image_index),
.p_results = null,
});
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
@@ -94,7 +231,6 @@ pub fn main() !void {
.color_space = .srgb_nonlinear_khr,
};
const format = try gfx.find_surface_format(pdev, vki, surface, preferred_format);
extent = try gfx.find_swap_extent(pdev, vki, surface, window);
const present_mode = try gfx.find_present_mode(pdev, vki, surface, .mailbox_khr);
@@ -103,77 +239,9 @@ pub fn main() !void {
var swapchain: vk.SwapchainKHR = .null_handle;
defer vkd.destroySwapchainKHR(dev, swapchain, null);
const ChainImage = struct {
image: vk.Image = .null_handle,
view: vk.ImageView = .null_handle,
cmdbuf: vk.CommandBuffer = .null_handle,
fence: vk.Fence = .null_handle,
image_available: vk.Semaphore = .null_handle,
render_finished: vk.Semaphore = .null_handle,
};
var chain = std.MultiArrayList(ChainImage){};
defer chain.deinit(ally);
defer vkd.freeCommandBuffers(dev, pool, @intCast(chain.len), chain.items(.cmdbuf).ptr);
defer for (chain.items(.view)) |view| vkd.destroyImageView(dev, view, null);
defer for (chain.items(.fence)) |fence| vkd.destroyFence(dev, fence, null);
defer for (chain.items(.image_available)) |sem| vkd.destroySemaphore(dev, sem, null);
defer for (chain.items(.render_finished)) |sem| vkd.destroySemaphore(dev, sem, null);
swapchain = try vkd.createSwapchainKHR(dev, &.{
.surface = surface,
.min_image_count = swap_image_count,
.image_format = format.format,
.image_color_space = format.color_space,
.image_extent = extent,
.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 = present_mode,
.clipped = vk.TRUE,
.old_swapchain = swapchain,
}, null);
var image_count: u32 = undefined;
_ = try vkd.getSwapchainImagesKHR(dev, swapchain, &image_count, null);
try chain.resize(ally, image_count);
_ = try vkd.getSwapchainImagesKHR(dev, swapchain, &image_count, chain.items(.image).ptr);
for (chain.items(.image), chain.items(.view)) |image, *view| {
view.* = try vkd.createImageView(dev, &.{
.image = image,
.view_type = .@"2d",
.format = format.format,
.components = .{ .r = .identity, .g = .identity, .b = .identity, .a = .identity },
.subresource_range = .{
.aspect_mask = .{ .color_bit = true },
.base_mip_level = 0,
.level_count = 1,
.base_array_layer = 0,
.layer_count = 1,
},
}, null);
}
for (chain.items(.fence)) |*fence| {
fence.* = try vkd.createFence(dev, &.{ .flags = .{ .signaled_bit = true } }, null);
}
for (chain.items(.image_available)) |*sem| {
sem.* = try vkd.createSemaphore(dev, &.{}, null);
}
for (chain.items(.render_finished)) |*sem| {
sem.* = try vkd.createSemaphore(dev, &.{}, null);
}
try vkd.allocateCommandBuffers(dev, &.{
.command_buffer_count = @intCast(chain.len),
.command_pool = pool,
.level = .primary,
}, chain.items(.cmdbuf).ptr);
defer deinit_chain(chain, dev, vkd, pool);
const pipeline_layout = try vkd.createPipelineLayout(dev, &.{
.flags = .{},
@@ -213,6 +281,22 @@ pub fn main() !void {
try gfx.uploadData(Index, pdev, vki, dev, vkd, queue, pool, index_buffer, &indices);
extent = try create_swapchain(
&chain,
&swapchain,
ally,
pdev,
vki,
window,
dev,
vkd,
pool,
surface,
swap_image_count,
format,
present_mode,
);
for (chain.items(.image), chain.items(.view), chain.items(.cmdbuf)) |image, view, cmdbuf| {
try record_cmdbuf(cmdbuf, vkd, image, view, extent, pipeline, vertex_buffer, index_buffer);
}
@@ -233,34 +317,47 @@ pub fn main() !void {
const frame: ChainImage = chain.get(index);
// const next_frame: ChainImage = chain.get((index + 1) % chain.len);
_ = try vkd.waitForFences(dev, 1, @ptrCast(&frame.fence), vk.TRUE, std.math.maxInt(u64));
try vkd.resetFences(dev, 1, @ptrCast(&frame.fence));
render(dev, vkd, swapchain, frame, queue) catch |err| switch (err) {
error.OutOfDateKHR => {
// try vkd.deviceWaitIdle(dev);
// _ = try vkd.waitForFences(
// dev,
// @intCast(chain.len),
// chain.items(.fence).ptr,
// vk.TRUE,
// std.math.maxInt(u64),
// );
try vkd.deviceWaitIdle(dev);
deinit_chain(chain, dev, vkd, pool);
extent = try create_swapchain(
&chain,
&swapchain,
ally,
pdev,
vki,
window,
dev,
vkd,
pool,
surface,
swap_image_count,
format,
present_mode,
);
for (chain.items(.image), chain.items(.view), chain.items(.cmdbuf)) |image, view, cmdbuf| {
try record_cmdbuf(cmdbuf, vkd, image, view, extent, pipeline, vertex_buffer, index_buffer);
}
continue;
},
else => |errx| return errx,
};
// var index: u32 = undefined;
// try vkd.acquireNextImageKHR(dev, swapchain, std.math.maxInt(u64), frame., fence);
const result = try vkd.acquireNextImageKHR(dev, swapchain, std.math.maxInt(u64), frame.image_available, .null_handle);
// std.log.debug("frame {d}", .{result.image_index});
// const frame = chain.get(result.image_index);
try vkd.queueSubmit(queue, 1, @ptrCast(&vk.SubmitInfo{
.wait_semaphore_count = 1,
.p_wait_semaphores = @ptrCast(&frame.image_available),
.p_wait_dst_stage_mask = @ptrCast(&vk.PipelineStageFlags{ .color_attachment_output_bit = true }),
.command_buffer_count = 1,
.p_command_buffers = @ptrCast(&frame.cmdbuf),
.signal_semaphore_count = 1,
.p_signal_semaphores = @ptrCast(&frame.render_finished),
}), frame.fence);
_ = try vkd.queuePresentKHR(queue, &.{
.wait_semaphore_count = 1,
.p_wait_semaphores = @ptrCast(&frame.render_finished),
.swapchain_count = 1,
.p_swapchains = @ptrCast(&swapchain),
.p_image_indices = @ptrCast(&result.image_index),
.p_results = null,
});
// const cmdbuf = cmdbufs[swapchain.image_index];