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 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 {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
@@ -94,7 +231,6 @@ pub fn main() !void {
|
|||||||
.color_space = .srgb_nonlinear_khr,
|
.color_space = .srgb_nonlinear_khr,
|
||||||
};
|
};
|
||||||
const format = try gfx.find_surface_format(pdev, vki, surface, preferred_format);
|
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);
|
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;
|
var swapchain: vk.SwapchainKHR = .null_handle;
|
||||||
defer vkd.destroySwapchainKHR(dev, swapchain, null);
|
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){};
|
var chain = std.MultiArrayList(ChainImage){};
|
||||||
defer chain.deinit(ally);
|
defer chain.deinit(ally);
|
||||||
defer vkd.freeCommandBuffers(dev, pool, @intCast(chain.len), chain.items(.cmdbuf).ptr);
|
defer deinit_chain(chain, dev, vkd, pool);
|
||||||
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);
|
|
||||||
|
|
||||||
const pipeline_layout = try vkd.createPipelineLayout(dev, &.{
|
const pipeline_layout = try vkd.createPipelineLayout(dev, &.{
|
||||||
.flags = .{},
|
.flags = .{},
|
||||||
@@ -213,6 +281,22 @@ pub fn main() !void {
|
|||||||
|
|
||||||
try gfx.uploadData(Index, pdev, vki, dev, vkd, queue, pool, index_buffer, &indices);
|
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| {
|
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);
|
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 frame: ChainImage = chain.get(index);
|
||||||
// const next_frame: ChainImage = chain.get((index + 1) % chain.len);
|
// const next_frame: ChainImage = chain.get((index + 1) % chain.len);
|
||||||
|
|
||||||
_ = try vkd.waitForFences(dev, 1, @ptrCast(&frame.fence), vk.TRUE, std.math.maxInt(u64));
|
render(dev, vkd, swapchain, frame, queue) catch |err| switch (err) {
|
||||||
try vkd.resetFences(dev, 1, @ptrCast(&frame.fence));
|
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;
|
// var index: u32 = undefined;
|
||||||
// try vkd.acquireNextImageKHR(dev, swapchain, std.math.maxInt(u64), frame., fence);
|
// 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];
|
// const cmdbuf = cmdbufs[swapchain.image_index];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user