Complete all Vulkan wrappers. Maybe worth it.
This commit is contained in:
@@ -16,7 +16,8 @@ extent: vk.Extent2D = .{ .width = 0, .height = 0 },
|
||||
swapchain: vk.SwapchainKHR = .null_handle,
|
||||
swapchain_images: []SwapchainImage = &.{},
|
||||
depth_texture: ?Texture = null,
|
||||
image_index: u32 = 0,
|
||||
image_index: ?u32 = null,
|
||||
fence: vk.Fence = .null_handle,
|
||||
semaphore_image_acquired: vk.Semaphore = .null_handle,
|
||||
|
||||
pub const PresentResult = enum {
|
||||
@@ -27,8 +28,8 @@ pub const PresentResult = enum {
|
||||
pub fn init(engine: *Engine) !Swapchain {
|
||||
const params: Params = try .init(engine);
|
||||
|
||||
const render_pass = blk: {
|
||||
const attachments = [_]vk.AttachmentDescription{
|
||||
const render_pass = try engine.createRenderPass(.{
|
||||
.attachments = &.{
|
||||
.{
|
||||
.format = params.surface_format.format,
|
||||
.samples = .{ .@"1_bit" = true },
|
||||
@@ -49,30 +50,23 @@ pub fn init(engine: *Engine) !Swapchain {
|
||||
.initial_layout = .undefined,
|
||||
.final_layout = .depth_stencil_attachment_optimal,
|
||||
},
|
||||
};
|
||||
|
||||
const color_attachments = [_]vk.AttachmentReference{
|
||||
.{
|
||||
.attachment = 0,
|
||||
.layout = .color_attachment_optimal,
|
||||
},
|
||||
};
|
||||
|
||||
const depth_stencil_attachment: vk.AttachmentReference = .{
|
||||
.attachment = 1,
|
||||
.layout = .depth_stencil_attachment_optimal,
|
||||
};
|
||||
|
||||
const subpasses = [_]vk.SubpassDescription{
|
||||
},
|
||||
.subpasses = &.{
|
||||
.{
|
||||
.pipeline_bind_point = .graphics,
|
||||
.color_attachment_count = color_attachments.len,
|
||||
.p_color_attachments = &color_attachments,
|
||||
.p_depth_stencil_attachment = &depth_stencil_attachment,
|
||||
.color_attachments = &.{
|
||||
.{
|
||||
.attachment = 0,
|
||||
.layout = .color_attachment_optimal,
|
||||
},
|
||||
},
|
||||
.depth_stencil_attachment = .{
|
||||
.attachment = 1,
|
||||
.layout = .depth_stencil_attachment_optimal,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const dependencies = [_]vk.SubpassDependency{
|
||||
},
|
||||
.dependencies = &.{
|
||||
.{
|
||||
.src_subpass = 0,
|
||||
.dst_subpass = 0,
|
||||
@@ -92,18 +86,9 @@ pub fn init(engine: *Engine) !Swapchain {
|
||||
.depth_stencil_attachment_write_bit = true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
break :blk try engine.device.createRenderPass(&.{
|
||||
.attachment_count = attachments.len,
|
||||
.p_attachments = &attachments,
|
||||
.subpass_count = subpasses.len,
|
||||
.p_subpasses = &subpasses,
|
||||
.dependency_count = dependencies.len,
|
||||
.p_dependencies = &dependencies,
|
||||
}, &engine.vk_allocator.interface);
|
||||
};
|
||||
errdefer engine.device.destroyRenderPass(render_pass, &engine.vk_allocator.interface);
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyRenderPass(render_pass);
|
||||
engine.setObjectName(render_pass, "RP", .{});
|
||||
|
||||
var swapchain: Swapchain = .{
|
||||
@@ -130,11 +115,12 @@ pub fn deinit(self: *Swapchain, engine: *Engine) void {
|
||||
}
|
||||
|
||||
if (self.swapchain != .null_handle) {
|
||||
engine.device.destroySwapchainKHR(self.swapchain, &engine.vk_allocator.interface);
|
||||
engine.destroySwapchain(self.swapchain);
|
||||
}
|
||||
|
||||
engine.device.destroyRenderPass(self.render_pass, &engine.vk_allocator.interface);
|
||||
engine.destroyRenderPass(self.render_pass);
|
||||
engine.destroySemaphore(self.semaphore_image_acquired);
|
||||
engine.destroyFence(self.fence);
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
@@ -145,8 +131,9 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
const old_swapchain = self.swapchain;
|
||||
const old_swapchain_images = self.swapchain_images;
|
||||
var old_depth_texture = self.depth_texture;
|
||||
const old_depth_texture = &self.depth_texture;
|
||||
const old_semaphore_image_acquired = self.semaphore_image_acquired;
|
||||
const old_fence = self.fence;
|
||||
|
||||
const extent = try getCurrentExtent(engine);
|
||||
|
||||
@@ -154,10 +141,8 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
// --- CREATE NEW SWAPCHAIN ------------------------------------------------
|
||||
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
|
||||
const qsm = QSM.resolve(engine.graphics_queue.allocation.family, mode.presentation_queue.allocation.family);
|
||||
const new_swapchain = try engine.device.createSwapchainKHR(&.{
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
const new_swapchain = try engine.createSwapchain(.{
|
||||
.surface = mode.surface,
|
||||
.min_image_count = self.params.image_count,
|
||||
.image_format = self.params.surface_format.format,
|
||||
@@ -165,16 +150,17 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
.image_extent = extent,
|
||||
.image_array_layers = 1,
|
||||
.image_usage = .{ .color_attachment_bit = true },
|
||||
.image_sharing_mode = qsm.sharing_mode,
|
||||
.queue_family_index_count = qsm.queue_family_index_count,
|
||||
.p_queue_family_indices = qsm.p_queue_family_indices,
|
||||
.queue_family_indices = &.{
|
||||
engine.graphics_queue.allocation.family,
|
||||
mode.presentation_queue.allocation.family,
|
||||
},
|
||||
.pre_transform = surface_capabilities.current_transform,
|
||||
.composite_alpha = .{ .opaque_bit_khr = true },
|
||||
.present_mode = .fifo_khr,
|
||||
.clipped = .true,
|
||||
.old_swapchain = old_swapchain,
|
||||
}, &engine.vk_allocator.interface);
|
||||
errdefer engine.device.destroySwapchainKHR(new_swapchain, &engine.vk_allocator.interface);
|
||||
});
|
||||
errdefer engine.destroySwapchain(new_swapchain);
|
||||
engine.setObjectName(new_swapchain, "SC {d}×{d}", .{ extent.width, extent.height });
|
||||
|
||||
// --- DESTROY OLD SWAPCHAIN AND ITS IMAGES --------------------------------
|
||||
@@ -189,22 +175,28 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
allocator.free(self.swapchain_images);
|
||||
self.swapchain_images = &.{};
|
||||
|
||||
if (old_depth_texture) |*depth_texture| {
|
||||
if (old_depth_texture.*) |*depth_texture| {
|
||||
depth_texture.deinit(engine);
|
||||
}
|
||||
|
||||
if (old_swapchain != .null_handle) {
|
||||
engine.device.destroySwapchainKHR(old_swapchain, &engine.vk_allocator.interface);
|
||||
engine.destroySwapchain(old_swapchain);
|
||||
self.swapchain = .null_handle;
|
||||
}
|
||||
|
||||
self.extent = .{ .width = 0, .height = 0 };
|
||||
self.image_index = null;
|
||||
|
||||
if (old_semaphore_image_acquired != .null_handle) {
|
||||
engine.destroySemaphore(old_semaphore_image_acquired);
|
||||
self.semaphore_image_acquired = .null_handle;
|
||||
}
|
||||
|
||||
if (old_fence != .null_handle) {
|
||||
engine.destroyFence(old_fence);
|
||||
self.fence = .null_handle;
|
||||
}
|
||||
|
||||
// --- CREATE DEPTH TEXTURE ------------------------------------------------
|
||||
|
||||
var new_depth_texture = try Texture.init(engine, .{
|
||||
@@ -219,7 +211,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
// --- CREATE NEW SWAPCHAIN IMAGES -----------------------------------------
|
||||
|
||||
const new_swapchain_images = blk: {
|
||||
const images = try engine.device.getSwapchainImagesAllocKHR(new_swapchain, allocator);
|
||||
const images = try engine.getSwapchainImagesAlloc(new_swapchain, allocator);
|
||||
defer allocator.free(images);
|
||||
|
||||
var swapchain_images: std.ArrayList(SwapchainImage) = try .initCapacity(allocator, images.len);
|
||||
@@ -247,18 +239,17 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
allocator.free(new_swapchain_images);
|
||||
}
|
||||
|
||||
// --- ACQUIRE NEXT IMAGE --------------------------------------------------
|
||||
// --- CREATE SEMAPHORES AND FENCES ----------------------------------------
|
||||
|
||||
var semaphore_image_acquired = try engine.createSemaphore();
|
||||
const semaphore_image_acquired = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(semaphore_image_acquired);
|
||||
engine.setObjectName(semaphore_image_acquired, "S Acquired[E]", .{});
|
||||
|
||||
const res = try engine.device.acquireNextImageKHR(new_swapchain, std.math.maxInt(u64), semaphore_image_acquired, .null_handle);
|
||||
if (res.result == .not_ready or res.result == .timeout) {
|
||||
return error.ImageAcquireFailed;
|
||||
}
|
||||
|
||||
std.mem.swap(vk.Semaphore, &new_swapchain_images[res.image_index].semaphore_image_acquired, &semaphore_image_acquired);
|
||||
const fence = try engine.createFence(.{
|
||||
.flags = .{ .signaled_bit = true },
|
||||
});
|
||||
errdefer engine.destroyFence(fence);
|
||||
engine.setObjectName(fence, "F", .{});
|
||||
|
||||
// --- COMMIT --------------------------------------------------------------
|
||||
|
||||
@@ -266,8 +257,20 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
self.swapchain = new_swapchain;
|
||||
self.swapchain_images = new_swapchain_images;
|
||||
self.depth_texture = new_depth_texture;
|
||||
self.image_index = res.image_index;
|
||||
self.image_index = null;
|
||||
self.semaphore_image_acquired = semaphore_image_acquired;
|
||||
self.fence = fence;
|
||||
}
|
||||
|
||||
pub fn acquire(self: *Swapchain, engine: *Engine) !void {
|
||||
try engine.waitForFence(self.fence);
|
||||
try engine.resetFence(self.fence);
|
||||
|
||||
const res = try engine.acquireNextImage(self.swapchain, .{
|
||||
.semaphore = self.semaphore_image_acquired,
|
||||
});
|
||||
std.mem.swap(vk.Semaphore, &self.swapchain_images[res.image_index].semaphore_image_acquired, &self.semaphore_image_acquired);
|
||||
self.image_index = res.image_index;
|
||||
}
|
||||
|
||||
pub const PresentInfo = struct {
|
||||
@@ -275,20 +278,9 @@ pub const PresentInfo = struct {
|
||||
wait_semaphores: []const WaitSemaphore = &.{},
|
||||
};
|
||||
|
||||
pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !PresentResult {
|
||||
pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !void {
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
const device = engine.device;
|
||||
const mode = &engine.mode.surface;
|
||||
|
||||
// --- WAIT FOR CURRENT FRAME TO FINISH ------------------------------------
|
||||
|
||||
const current_swapchain_image = &self.swapchain_images[self.image_index];
|
||||
try engine.waitForFence(current_swapchain_image.fence);
|
||||
if (current_swapchain_image.command_buffer) |*command_buffer| {
|
||||
command_buffer.deinit(engine);
|
||||
current_swapchain_image.command_buffer = null;
|
||||
}
|
||||
try engine.resetFence(current_swapchain_image.fence);
|
||||
const current_swapchain_image = &self.swapchain_images[self.image_index.?];
|
||||
|
||||
// --- SUBMIT COMMAND BUFFER -----------------------------------------------
|
||||
|
||||
@@ -301,45 +293,24 @@ pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !Pr
|
||||
});
|
||||
wait_semaphores.appendSliceAssumeCapacity(present_info.wait_semaphores);
|
||||
|
||||
current_swapchain_image.command_buffer = present_info.command_buffer;
|
||||
try present_info.command_buffer.submit(engine, .{
|
||||
.wait_semaphores = wait_semaphores.items,
|
||||
.signal_semaphores = &.{current_swapchain_image.semaphore_render_finished},
|
||||
.fence = current_swapchain_image.fence,
|
||||
.fence = self.fence,
|
||||
});
|
||||
|
||||
// --- PRESENT CURRENT FRAME -----------------------------------------------
|
||||
|
||||
_ = device.queuePresentKHR(mode.presentation_queue.handle, &.{
|
||||
.wait_semaphore_count = 1,
|
||||
.p_wait_semaphores = @ptrCast(¤t_swapchain_image.semaphore_render_finished),
|
||||
.swapchain_count = 1,
|
||||
.p_swapchains = @ptrCast(&self.swapchain),
|
||||
.p_image_indices = @ptrCast(&self.image_index),
|
||||
}) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return .suboptimal,
|
||||
else => return err,
|
||||
};
|
||||
|
||||
// --- ACQUIRE NEXT FRAME --------------------------------------------------
|
||||
|
||||
const res = device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), self.semaphore_image_acquired, .null_handle) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return .suboptimal,
|
||||
else => return err,
|
||||
};
|
||||
std.mem.swap(vk.Semaphore, &self.swapchain_images[res.image_index].semaphore_image_acquired, &self.semaphore_image_acquired);
|
||||
self.image_index = res.image_index;
|
||||
|
||||
return switch (res.result) {
|
||||
.success => .optimal,
|
||||
.suboptimal_khr => .suboptimal,
|
||||
else => unreachable,
|
||||
};
|
||||
_ = try engine.queuePresent(.{
|
||||
.wait_semaphores = &.{current_swapchain_image.semaphore_render_finished},
|
||||
.swapchain = self.swapchain,
|
||||
.image_index = self.image_index.?,
|
||||
});
|
||||
}
|
||||
|
||||
fn getCurrentExtent(engine: *Engine) !vk.Extent2D {
|
||||
const mode = &engine.mode.surface;
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
|
||||
if (surface_capabilities.current_extent.width != std.math.maxInt(u32) and surface_capabilities.current_extent.height != std.math.maxInt(u32)) {
|
||||
return surface_capabilities.current_extent;
|
||||
@@ -366,13 +337,12 @@ const Params = struct {
|
||||
image_count: u32,
|
||||
|
||||
pub fn init(engine: *Engine) !Params {
|
||||
const mode = &engine.mode.surface;
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
|
||||
const surface_format = blk: {
|
||||
const surface_formats = try engine.instance.getPhysicalDeviceSurfaceFormatsAllocKHR(engine.physical_device, mode.surface, allocator);
|
||||
const surface_formats = try engine.getPhysicalDeviceSurfaceFormatsAlloc(allocator);
|
||||
defer allocator.free(surface_formats);
|
||||
|
||||
// Look for 8-bit BGRA sRGB surface format.
|
||||
@@ -409,9 +379,7 @@ const SwapchainImage = struct {
|
||||
image_view: vk.ImageView,
|
||||
semaphore_image_acquired: vk.Semaphore,
|
||||
semaphore_render_finished: vk.Semaphore,
|
||||
fence: vk.Fence,
|
||||
framebuffer: vk.Framebuffer,
|
||||
command_buffer: ?CommandBuffer,
|
||||
|
||||
const InitProps = struct {
|
||||
image: vk.Image,
|
||||
@@ -447,12 +415,6 @@ const SwapchainImage = struct {
|
||||
errdefer engine.destroySemaphore(semaphore_render_finished);
|
||||
engine.setObjectName(image_view, "S Rendered[{d}]", .{props.index});
|
||||
|
||||
const fence = try engine.createFence(.{
|
||||
.flags = .{ .signaled_bit = true },
|
||||
});
|
||||
errdefer engine.destroyFence(fence);
|
||||
engine.setObjectName(image_view, "F Rendered[{d}]", .{props.index});
|
||||
|
||||
const framebuffer = try engine.createFramebuffer(.{
|
||||
.render_pass = props.render_pass,
|
||||
.attachments = &.{ image_view, props.depth_stencil_image_view },
|
||||
@@ -468,21 +430,14 @@ const SwapchainImage = struct {
|
||||
.image_view = image_view,
|
||||
.semaphore_image_acquired = semaphore_image_acquired,
|
||||
.semaphore_render_finished = semaphore_render_finished,
|
||||
.fence = fence,
|
||||
.framebuffer = framebuffer,
|
||||
.command_buffer = null,
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *SwapchainImage, engine: *Engine) void {
|
||||
std.log.scoped(.deinit).debug("Deinitializing {*} with {*}", .{ self, engine });
|
||||
|
||||
engine.waitForFence(self.fence) catch {};
|
||||
if (self.command_buffer) |*command_buffer| {
|
||||
command_buffer.deinit(engine);
|
||||
}
|
||||
engine.destroyFramebuffer(self.framebuffer);
|
||||
engine.destroyFence(self.fence);
|
||||
engine.destroySemaphore(self.semaphore_render_finished);
|
||||
engine.destroySemaphore(self.semaphore_image_acquired);
|
||||
engine.destroyImageView(self.image_view);
|
||||
|
||||
Reference in New Issue
Block a user