swapchain recreation works, but buggy
This commit is contained in:
287
src/main.zig
287
src/main.zig
@@ -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];
|
||||
|
||||
|
Reference in New Issue
Block a user