198 lines
6.1 KiB
Zig
198 lines
6.1 KiB
Zig
const std = @import("std");
|
|
const glfw = @import("zglfw");
|
|
const vk = @import("vulkan");
|
|
|
|
const context = @import("context.zig");
|
|
const device = @import("device.zig");
|
|
|
|
pub const SwapchainContext = struct {
|
|
swapchain: vk.SwapchainKHR,
|
|
images: []vk.Image,
|
|
image_views: []vk.ImageView,
|
|
format: vk.SurfaceFormatKHR,
|
|
present_mode: vk.PresentModeKHR,
|
|
extent: vk.Extent2D,
|
|
image_count: u32,
|
|
allocator: std.mem.Allocator,
|
|
|
|
pub fn destroy(self: *const SwapchainContext, ldc: *const device.LogicalDeviceContext) void {
|
|
for (self.image_views) |image_view| {
|
|
ldc.vkd.destroyImageView(ldc.device, image_view, null);
|
|
}
|
|
self.allocator.free(self.image_views);
|
|
self.allocator.free(self.images);
|
|
ldc.vkd.destroySwapchainKHR(ldc.device, self.swapchain, null);
|
|
}
|
|
};
|
|
|
|
pub fn initSwapchain(
|
|
vc: context.VulkanContext,
|
|
ldc: device.LogicalDeviceContext,
|
|
surface: vk.SurfaceKHR,
|
|
window: *glfw.Window,
|
|
allocator: std.mem.Allocator,
|
|
) !SwapchainContext {
|
|
const surface_caps = try vc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
|
ldc.physical_device,
|
|
surface,
|
|
);
|
|
|
|
std.debug.print(
|
|
"surface current extent: {}x{}\n",
|
|
.{
|
|
surface_caps.current_extent.width,
|
|
surface_caps.current_extent.height,
|
|
},
|
|
);
|
|
|
|
std.debug.print(
|
|
"surface min/max image count: {}/{}\n",
|
|
.{
|
|
surface_caps.min_image_count,
|
|
surface_caps.max_image_count,
|
|
},
|
|
);
|
|
|
|
const surface_formats = try vc.vki.getPhysicalDeviceSurfaceFormatsAllocKHR(
|
|
ldc.physical_device,
|
|
surface,
|
|
allocator,
|
|
);
|
|
defer allocator.free(surface_formats);
|
|
|
|
const present_modes = try vc.vki.getPhysicalDeviceSurfacePresentModesAllocKHR(
|
|
ldc.physical_device,
|
|
surface,
|
|
allocator,
|
|
);
|
|
defer allocator.free(present_modes);
|
|
|
|
var chosen_surface_format = surface_formats[0];
|
|
for (surface_formats) |format| {
|
|
if (format.format == .b8g8r8a8_srgb and
|
|
format.color_space == .srgb_nonlinear_khr)
|
|
{
|
|
chosen_surface_format = format;
|
|
break;
|
|
}
|
|
}
|
|
|
|
var chosen_present_mode: vk.PresentModeKHR = .fifo_khr;
|
|
for (present_modes) |mode| {
|
|
if (mode == .fifo_khr) {
|
|
chosen_present_mode = mode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const framebuffer_size = window.getFramebufferSize();
|
|
|
|
const chosen_extent = if (surface_caps.current_extent.width != std.math.maxInt(u32))
|
|
surface_caps.current_extent
|
|
else
|
|
vk.Extent2D{
|
|
.width = @intCast(framebuffer_size[0]),
|
|
.height = @intCast(framebuffer_size[1]),
|
|
};
|
|
|
|
var chosen_image_count = surface_caps.min_image_count + 1;
|
|
if (surface_caps.max_image_count != 0 and chosen_image_count > surface_caps.max_image_count) {
|
|
chosen_image_count = surface_caps.max_image_count;
|
|
}
|
|
|
|
std.debug.print(
|
|
"chosen swapchain format={any}, color_space={any}\n",
|
|
.{ chosen_surface_format.format, chosen_surface_format.color_space },
|
|
);
|
|
std.debug.print("chosen present mode={any}\n", .{chosen_present_mode});
|
|
std.debug.print(
|
|
"chosen extent={}x{}\n",
|
|
.{ chosen_extent.width, chosen_extent.height },
|
|
);
|
|
std.debug.print("chosen image count={}\n", .{chosen_image_count});
|
|
|
|
const swapchain_create_info = vk.SwapchainCreateInfoKHR{
|
|
.surface = surface,
|
|
.min_image_count = chosen_image_count,
|
|
.image_format = chosen_surface_format.format,
|
|
.image_color_space = chosen_surface_format.color_space,
|
|
.image_extent = chosen_extent,
|
|
.image_array_layers = 1,
|
|
.image_usage = .{
|
|
.color_attachment_bit = true,
|
|
},
|
|
.image_sharing_mode = .exclusive,
|
|
.pre_transform = surface_caps.current_transform,
|
|
.composite_alpha = .{
|
|
.opaque_bit_khr = true,
|
|
},
|
|
.present_mode = chosen_present_mode,
|
|
.clipped = .true,
|
|
};
|
|
|
|
const swapchain = try ldc.vkd.createSwapchainKHR(ldc.device, &swapchain_create_info, null);
|
|
errdefer ldc.vkd.destroySwapchainKHR(ldc.device, swapchain, null);
|
|
std.debug.print("created swapchain\n", .{});
|
|
|
|
const swapchain_images = try ldc.vkd.getSwapchainImagesAllocKHR(
|
|
ldc.device,
|
|
swapchain,
|
|
allocator,
|
|
);
|
|
errdefer allocator.free(swapchain_images);
|
|
std.debug.print("swapchain images: {}\n", .{swapchain_images.len});
|
|
|
|
const swapchain_image_views = try allocator.alloc(vk.ImageView, swapchain_images.len);
|
|
errdefer allocator.free(swapchain_image_views);
|
|
|
|
var created_image_view_count: usize = 0;
|
|
errdefer {
|
|
for (swapchain_image_views[0..created_image_view_count]) |image_view| {
|
|
ldc.vkd.destroyImageView(ldc.device, image_view, null);
|
|
}
|
|
}
|
|
|
|
for (swapchain_images, 0..) |image, i| {
|
|
const image_view_create_info = vk.ImageViewCreateInfo{
|
|
.image = image,
|
|
.view_type = .@"2d",
|
|
.format = chosen_surface_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,
|
|
},
|
|
};
|
|
|
|
swapchain_image_views[i] = try ldc.vkd.createImageView(
|
|
ldc.device,
|
|
&image_view_create_info,
|
|
null,
|
|
);
|
|
created_image_view_count += 1;
|
|
}
|
|
|
|
std.debug.print("created swapchain image views: {}\n", .{swapchain_image_views.len});
|
|
|
|
return .{
|
|
.swapchain = swapchain,
|
|
.images = swapchain_images,
|
|
.image_views = swapchain_image_views,
|
|
.format = chosen_surface_format,
|
|
.present_mode = chosen_present_mode,
|
|
.extent = chosen_extent,
|
|
.image_count = chosen_image_count,
|
|
.allocator = allocator,
|
|
};
|
|
}
|