incremental - dropping swapchain

This commit is contained in:
David Allemang
2024-04-01 20:47:29 -04:00
parent 10dcd3125a
commit 1b3302cc99
2 changed files with 55 additions and 44 deletions

View File

@@ -246,6 +246,26 @@ fn create_device(
return error.NoSuitableDevice;
}
fn find_surface_format(
pdev: vk.PhysicalDevice,
surface: vk.SurfaceKHR,
preferred: vk.SurfaceFormatKHR,
vki: gfx.InstanceDispatch,
) !vk.SurfaceFormatKHR {
var formats_buf: [64]vk.SurfaceFormatKHR = undefined;
var formats_count: u32 = 64;
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &formats_count, &formats_buf);
const formats = formats_buf[0..formats_count];
for (formats) |format| {
if (std.meta.eql(format, preferred)) {
return format;
}
}
return formats[0];
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
@@ -278,6 +298,12 @@ pub fn main() !void {
try create_device(ally, instance, surface, vki);
defer vkd.destroyDevice(dev, null);
const preferred_format: vk.SurfaceFormatKHR = .{
.format = .b8g8r8a8_srgb,
.color_space = .srgb_nonlinear_khr,
};
const format = try find_surface_format(pdev, surface, preferred_format, vki);
const queue = vkd.getDeviceQueue(dev, family, 0);
const gc: Context = .{
@@ -290,7 +316,7 @@ pub fn main() !void {
.family = family,
};
var swapchain = try Swapchain.init(&gc, ally, extent);
var swapchain = try Swapchain.init(&gc, ally, extent, format);
defer swapchain.deinit();
const pipeline_layout = try gc.vkd.createPipelineLayout(gc.dev, &.{
@@ -302,7 +328,7 @@ pub fn main() !void {
}, null);
defer gc.vkd.destroyPipelineLayout(gc.dev, pipeline_layout, null);
const pipeline = try createPipeline(&gc, pipeline_layout, swapchain);
const pipeline = try createPipeline(&gc, pipeline_layout, format);
defer gc.vkd.destroyPipeline(gc.dev, pipeline, null);
const pool = try gc.vkd.createCommandPool(gc.dev, &.{
@@ -348,7 +374,6 @@ pub fn main() !void {
defer destroyCommandBuffers(&gc, pool, ally, cmdbufs);
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
std.log.debug("new frame", .{ });
var w: c_int = undefined;
var h: c_int = undefined;
c.glfwGetFramebufferSize(window, &w, &h);
@@ -366,18 +391,13 @@ pub fn main() !void {
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))) {
extent.width = @intCast(w);
extent.height = @intCast(h);
std.log.debug("about to recreate", .{ });
try swapchain.recreate(extent);
try swapchain.recreate(extent, format);
std.log.debug("about to destroy command buffers", .{ });
destroyCommandBuffers(&gc, pool, ally, cmdbufs);
std.log.debug("about to create command buffers", .{ });
cmdbufs = try createCommandBuffers(
&gc,
pool,
@@ -607,7 +627,7 @@ fn destroyCommandBuffers(gc: *const Context, pool: vk.CommandPool, allocator: Al
allocator.free(cmdbufs);
}
fn createPipeline(gc: *const Context, layout: vk.PipelineLayout, swapchain: Swapchain) !vk.Pipeline {
fn createPipeline(gc: *const Context, layout: vk.PipelineLayout, format: vk.SurfaceFormatKHR) !vk.Pipeline {
const vert = try gc.vkd.createShaderModule(gc.dev, &.{
.code_size = shaders.triangle_vert.len,
.p_code = @as([*]const u32, @ptrCast(&shaders.triangle_vert)),
@@ -701,7 +721,7 @@ fn createPipeline(gc: *const Context, layout: vk.PipelineLayout, swapchain: Swap
const prci = vk.PipelineRenderingCreateInfoKHR{
.color_attachment_count = 1,
.p_color_attachment_formats = @ptrCast(&swapchain.surface_format.format),
.p_color_attachment_formats = @ptrCast(&format),
.depth_attachment_format = .undefined,
.stencil_attachment_format = .undefined,
.view_mask = 0,

View File

@@ -52,7 +52,6 @@ pub const Swapchain = struct {
gc: *const Context,
allocator: Allocator,
surface_format: vk.SurfaceFormatKHR,
present_mode: vk.PresentModeKHR,
extent: vk.Extent2D,
handle: vk.SwapchainKHR,
@@ -61,18 +60,28 @@ pub const Swapchain = struct {
image_index: u32,
next_image_acquired: vk.Semaphore,
pub fn init(gc: *const Context, allocator: Allocator, extent: vk.Extent2D) !Swapchain {
return try initRecycle(gc, allocator, extent, .null_handle);
pub fn init(
gc: *const Context,
allocator: Allocator,
extent: vk.Extent2D,
format: vk.SurfaceFormatKHR,
) !Swapchain {
return try initRecycle(gc, allocator, extent, format, .null_handle);
}
pub fn initRecycle(gc: *const Context, allocator: Allocator, extent: vk.Extent2D, old_handle: vk.SwapchainKHR) !Swapchain {
pub fn initRecycle(
gc: *const Context,
allocator: Allocator,
extent: vk.Extent2D,
format: vk.SurfaceFormatKHR,
old_handle: vk.SwapchainKHR,
) !Swapchain {
const caps = try gc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(gc.pdev, gc.surface);
const actual_extent = findActualExtent(caps, extent);
if (actual_extent.width == 0 or actual_extent.height == 0) {
return error.InvalidSurfaceDimensions;
}
const surface_format = try findSurfaceFormat(gc, allocator);
const present_mode = try findPresentMode(gc, allocator);
var image_count = caps.min_image_count + 1;
@@ -83,8 +92,8 @@ pub const Swapchain = struct {
const handle = try gc.vkd.createSwapchainKHR(gc.dev, &.{
.surface = gc.surface,
.min_image_count = image_count,
.image_format = surface_format.format,
.image_color_space = surface_format.color_space,
.image_format = format.format,
.image_color_space = format.color_space,
.image_extent = actual_extent,
.image_array_layers = 1,
.image_usage = .{ .color_attachment_bit = true, .transfer_dst_bit = true },
@@ -102,7 +111,7 @@ pub const Swapchain = struct {
gc.vkd.destroySwapchainKHR(gc.dev, old_handle, null);
}
const swap_images = try initSwapchainImages(gc, handle, surface_format.format, allocator);
const swap_images = try initSwapchainImages(gc, handle, format.format, allocator);
errdefer {
for (swap_images) |si| si.deinit(gc);
allocator.free(swap_images);
@@ -129,7 +138,6 @@ pub const Swapchain = struct {
return Swapchain{
.gc = gc,
.allocator = allocator,
.surface_format = surface_format,
.present_mode = present_mode,
.extent = actual_extent,
.handle = handle,
@@ -154,12 +162,16 @@ pub const Swapchain = struct {
self.gc.vkd.destroySwapchainKHR(self.gc.dev, self.handle, null);
}
pub fn recreate(self: *Swapchain, new_extent: vk.Extent2D) !void {
pub fn recreate(
self: *Swapchain,
new_extent: vk.Extent2D,
format: vk.SurfaceFormatKHR,
) !void {
const gc = self.gc;
const allocator = self.allocator;
const old_handle = self.handle;
self.deinitExceptSwapchain();
self.* = try initRecycle(gc, allocator, new_extent, old_handle);
self.* = try initRecycle(gc, allocator, new_extent, format, old_handle);
}
pub fn currentImage(self: Swapchain) vk.Image {
@@ -318,27 +330,6 @@ fn initSwapchainImages(gc: *const Context, swapchain: vk.SwapchainKHR, format: v
return swap_images;
}
fn findSurfaceFormat(gc: *const Context, allocator: Allocator) !vk.SurfaceFormatKHR {
const preferred = vk.SurfaceFormatKHR{
.format = .b8g8r8a8_srgb,
.color_space = .srgb_nonlinear_khr,
};
var count: u32 = undefined;
_ = try gc.vki.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, null);
const surface_formats = try allocator.alloc(vk.SurfaceFormatKHR, count);
defer allocator.free(surface_formats);
_ = try gc.vki.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, surface_formats.ptr);
for (surface_formats) |sfmt| {
if (std.meta.eql(sfmt, preferred)) {
return preferred;
}
}
return surface_formats[0]; // There must always be at least one supported surface format
}
fn findPresentMode(gc: *const Context, allocator: Allocator) !vk.PresentModeKHR {
var count: u32 = undefined;
_ = try gc.vki.getPhysicalDeviceSurfacePresentModesKHR(gc.pdev, gc.surface, &count, null);