debugging the swapchain recreate bugs
This commit is contained in:
@@ -93,6 +93,8 @@ pub fn main() !void {
|
|||||||
std.debug.print("type: {any}\n", .{props.device_type});
|
std.debug.print("type: {any}\n", .{props.device_type});
|
||||||
// props.device_type
|
// props.device_type
|
||||||
|
|
||||||
|
std.debug.print("max_push_constants_size: {d}\n", .{props.limits.max_push_constants_size});
|
||||||
|
|
||||||
var family_count: u32 = undefined;
|
var family_count: u32 = undefined;
|
||||||
vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null);
|
vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null);
|
||||||
const families = try ally.alloc(vk.QueueFamilyProperties, family_count);
|
const families = try ally.alloc(vk.QueueFamilyProperties, family_count);
|
||||||
|
63
src/main.zig
63
src/main.zig
@@ -164,7 +164,7 @@ fn create_device(
|
|||||||
|
|
||||||
pdev_search: for (pdevs) |pdev| {
|
pdev_search: for (pdevs) |pdev| {
|
||||||
const props = vki.getPhysicalDeviceProperties(pdev);
|
const props = vki.getPhysicalDeviceProperties(pdev);
|
||||||
// if (props.device_type != .discrete_gpu) continue :pdev_search;
|
if (props.device_type != .discrete_gpu) continue :pdev_search;
|
||||||
|
|
||||||
var format_count: u32 = undefined;
|
var format_count: u32 = undefined;
|
||||||
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &format_count, null);
|
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &format_count, null);
|
||||||
@@ -348,6 +348,7 @@ pub fn main() !void {
|
|||||||
defer destroyCommandBuffers(&gc, pool, ally, cmdbufs);
|
defer destroyCommandBuffers(&gc, pool, ally, cmdbufs);
|
||||||
|
|
||||||
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
|
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
|
||||||
|
std.log.debug("new frame", .{ });
|
||||||
var w: c_int = undefined;
|
var w: c_int = undefined;
|
||||||
var h: c_int = undefined;
|
var h: c_int = undefined;
|
||||||
c.glfwGetFramebufferSize(window, &w, &h);
|
c.glfwGetFramebufferSize(window, &w, &h);
|
||||||
@@ -364,13 +365,19 @@ pub fn main() !void {
|
|||||||
error.OutOfDateKHR => Swapchain.PresentState.suboptimal,
|
error.OutOfDateKHR => Swapchain.PresentState.suboptimal,
|
||||||
else => |narrow| return narrow,
|
else => |narrow| return narrow,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std.log.debug("state: {}", .{state});
|
||||||
|
|
||||||
if (state == .suboptimal or extent.width != @as(u32, @intCast(w)) or extent.height != @as(u32, @intCast(h))) {
|
if (state == .suboptimal or extent.width != @as(u32, @intCast(w)) or extent.height != @as(u32, @intCast(h))) {
|
||||||
extent.width = @intCast(w);
|
extent.width = @intCast(w);
|
||||||
extent.height = @intCast(h);
|
extent.height = @intCast(h);
|
||||||
|
std.log.debug("about to recreate", .{ });
|
||||||
try swapchain.recreate(extent);
|
try swapchain.recreate(extent);
|
||||||
|
|
||||||
|
std.log.debug("about to destroy command buffers", .{ });
|
||||||
destroyCommandBuffers(&gc, pool, ally, cmdbufs);
|
destroyCommandBuffers(&gc, pool, ally, cmdbufs);
|
||||||
|
|
||||||
|
std.log.debug("about to create command buffers", .{ });
|
||||||
cmdbufs = try createCommandBuffers(
|
cmdbufs = try createCommandBuffers(
|
||||||
&gc,
|
&gc,
|
||||||
pool,
|
pool,
|
||||||
@@ -499,8 +506,17 @@ fn createCommandBuffers(
|
|||||||
for (cmdbufs, swapchain.swap_images) |cmdbuf, image| {
|
for (cmdbufs, swapchain.swap_images) |cmdbuf, image| {
|
||||||
try gc.vkd.beginCommandBuffer(cmdbuf, &.{});
|
try gc.vkd.beginCommandBuffer(cmdbuf, &.{});
|
||||||
|
|
||||||
const pre_render_barriers: []const vk.ImageMemoryBarrier = &.{
|
gc.vkd.cmdPipelineBarrier(
|
||||||
vk.ImageMemoryBarrier{
|
cmdbuf,
|
||||||
|
.{ .top_of_pipe_bit = true },
|
||||||
|
.{ .color_attachment_output_bit = true },
|
||||||
|
.{},
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
@ptrCast(&vk.ImageMemoryBarrier{
|
||||||
.src_access_mask = .{},
|
.src_access_mask = .{},
|
||||||
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||||
.old_layout = .undefined,
|
.old_layout = .undefined,
|
||||||
@@ -515,19 +531,7 @@ fn createCommandBuffers(
|
|||||||
.base_array_layer = 0,
|
.base_array_layer = 0,
|
||||||
.layer_count = 1,
|
.layer_count = 1,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
};
|
|
||||||
gc.vkd.cmdPipelineBarrier(
|
|
||||||
cmdbuf,
|
|
||||||
.{ .top_of_pipe_bit = true },
|
|
||||||
.{ .color_attachment_output_bit = true },
|
|
||||||
.{},
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
@intCast(pre_render_barriers.len),
|
|
||||||
pre_render_barriers.ptr,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
gc.vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport));
|
gc.vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport));
|
||||||
@@ -564,8 +568,17 @@ fn createCommandBuffers(
|
|||||||
|
|
||||||
gc.vkd.cmdEndRenderingKHR(cmdbuf);
|
gc.vkd.cmdEndRenderingKHR(cmdbuf);
|
||||||
|
|
||||||
const post_render_barriers: []const vk.ImageMemoryBarrier = &.{
|
gc.vkd.cmdPipelineBarrier(
|
||||||
vk.ImageMemoryBarrier{
|
cmdbuf,
|
||||||
|
.{ .color_attachment_output_bit = true },
|
||||||
|
.{ .bottom_of_pipe_bit = true },
|
||||||
|
.{},
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
@ptrCast(&vk.ImageMemoryBarrier{
|
||||||
.src_access_mask = .{ .color_attachment_write_bit = true },
|
.src_access_mask = .{ .color_attachment_write_bit = true },
|
||||||
.dst_access_mask = .{},
|
.dst_access_mask = .{},
|
||||||
.old_layout = .color_attachment_optimal,
|
.old_layout = .color_attachment_optimal,
|
||||||
@@ -580,19 +593,7 @@ fn createCommandBuffers(
|
|||||||
.base_array_layer = 0,
|
.base_array_layer = 0,
|
||||||
.layer_count = 1,
|
.layer_count = 1,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
};
|
|
||||||
gc.vkd.cmdPipelineBarrier(
|
|
||||||
cmdbuf,
|
|
||||||
.{ .color_attachment_output_bit = true },
|
|
||||||
.{ .bottom_of_pipe_bit = true },
|
|
||||||
.{},
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
@intCast(post_render_barriers.len),
|
|
||||||
post_render_barriers.ptr,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
try gc.vkd.endCommandBuffer(cmdbuf);
|
try gc.vkd.endCommandBuffer(cmdbuf);
|
||||||
|
@@ -111,9 +111,18 @@ pub const Swapchain = struct {
|
|||||||
var next_image_acquired = try gc.vkd.createSemaphore(gc.dev, &.{}, null);
|
var next_image_acquired = try gc.vkd.createSemaphore(gc.dev, &.{}, null);
|
||||||
errdefer gc.vkd.destroySemaphore(gc.dev, next_image_acquired, null);
|
errdefer gc.vkd.destroySemaphore(gc.dev, next_image_acquired, null);
|
||||||
|
|
||||||
const result = try gc.vkd.acquireNextImageKHR(gc.dev, handle, std.math.maxInt(u64), next_image_acquired, .null_handle);
|
const result = try gc.vkd.acquireNextImageKHR(
|
||||||
if (result.result != .success) {
|
gc.dev,
|
||||||
return error.ImageAcquireFailed;
|
handle,
|
||||||
|
std.math.maxInt(u64),
|
||||||
|
next_image_acquired,
|
||||||
|
.null_handle,
|
||||||
|
);
|
||||||
|
switch (result.result) {
|
||||||
|
vk.Result.success, vk.Result.suboptimal_khr => {},
|
||||||
|
vk.Result.timeout => return error.Timeout,
|
||||||
|
vk.Result.not_ready => return error.NotReady,
|
||||||
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
std.mem.swap(vk.Semaphore, &swap_images[result.image_index].image_acquired, &next_image_acquired);
|
std.mem.swap(vk.Semaphore, &swap_images[result.image_index].image_acquired, &next_image_acquired);
|
||||||
@@ -267,6 +276,15 @@ const SwapImage = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: SwapImage, gc: *const Context) void {
|
fn deinit(self: SwapImage, gc: *const Context) void {
|
||||||
|
// todo critical: this waitForFence deadlocks when recreating swapchain on nvidia.
|
||||||
|
// Something about the main "present" loop is fucked. Can't just ignore the fence; validation layers show errors
|
||||||
|
// that you can't destroy a fence while a queue depends on it (details may be wrong... I don't fully understand)
|
||||||
|
// I suspect this is more an issue with the vulkan-zig example, so I probably need to revisit vulkan-tutorial or
|
||||||
|
// try to rebuild the swapchain infrastructure myself.
|
||||||
|
//
|
||||||
|
// I do think it's clunky how the swapchain is created and recreated; duplicate logic in creation and recreation
|
||||||
|
// that could maybe be avoided with .null_handle? Maybe there's some more straightforward way to handle it.
|
||||||
|
|
||||||
self.waitForFence(gc) catch return;
|
self.waitForFence(gc) catch return;
|
||||||
gc.vkd.destroyImageView(gc.dev, self.view, null);
|
gc.vkd.destroyImageView(gc.dev, self.view, null);
|
||||||
gc.vkd.destroySemaphore(gc.dev, self.image_acquired, null);
|
gc.vkd.destroySemaphore(gc.dev, self.image_acquired, null);
|
||||||
|
Reference in New Issue
Block a user