Rework semaphores & fences
This commit is contained in:
parent
059fa90096
commit
c4193db891
2 changed files with 48 additions and 19 deletions
11
README.md
Normal file
11
README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Vulkan renderer in Zig & SDL2
|
||||
|
||||
This is just a project to learn Vulkan using the Zig programming language.
|
||||
|
||||
## Dependencies
|
||||
|
||||
TODO
|
||||
|
||||
## Build
|
||||
|
||||
TODO
|
|
@ -12,6 +12,8 @@ const SwapchainImage = Utilities.SwapchainImage;
|
|||
const enable_validation_layers = builtin.mode == .Debug;
|
||||
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||
|
||||
const MAX_FRAME_DRAWS: u32 = 2;
|
||||
|
||||
const apis: []const vk.ApiInfo = &.{
|
||||
vk.features.version_1_0,
|
||||
vk.features.version_1_1,
|
||||
|
@ -40,6 +42,8 @@ pub const VulkanRenderer = struct {
|
|||
|
||||
window: sdl.Window,
|
||||
|
||||
current_frame: u32 = 0,
|
||||
|
||||
// Main
|
||||
instance: Instance,
|
||||
physical_device: vk.PhysicalDevice,
|
||||
|
@ -68,9 +72,9 @@ pub const VulkanRenderer = struct {
|
|||
extent: vk.Extent2D,
|
||||
|
||||
// Synchronisation
|
||||
image_available: vk.Semaphore,
|
||||
render_finished: vk.Semaphore,
|
||||
frame_fence: vk.Fence,
|
||||
image_available: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||
render_finished: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||
draw_fences: [MAX_FRAME_DRAWS]vk.Fence,
|
||||
|
||||
debug_utils: ?vk.DebugUtilsMessengerEXT,
|
||||
|
||||
|
@ -78,6 +82,7 @@ pub const VulkanRenderer = struct {
|
|||
var self: Self = undefined;
|
||||
|
||||
self.window = window;
|
||||
self.current_frame = 0;
|
||||
self.allocator = allocator;
|
||||
self.vkb = try BaseDispatch.load(try sdl.vulkan.getVkGetInstanceProcAddr());
|
||||
|
||||
|
@ -103,14 +108,17 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
|
||||
pub fn draw(self: *Self) !void {
|
||||
_ = try self.device.waitForFences(1, @ptrCast(&self.frame_fence), vk.TRUE, std.math.maxInt(u64));
|
||||
_ = try self.device.resetFences(1, @ptrCast(&self.frame_fence));
|
||||
// Wait for given fence to signal (open) from last draw before continuing
|
||||
_ = try self.device.waitForFences(1, @ptrCast(&self.draw_fences[self.current_frame]), vk.TRUE, std.math.maxInt(u64));
|
||||
// Manually reset (close) fences
|
||||
try self.device.resetFences(1, @ptrCast(&self.draw_fences[self.current_frame]));
|
||||
|
||||
// -- Get next image
|
||||
// Get index of next image to be drawn to, and signal semaphore when ready to be drawn to
|
||||
const image_index_result = try self.device.acquireNextImageKHR(
|
||||
self.swapchain,
|
||||
std.math.maxInt(u64),
|
||||
self.image_available,
|
||||
self.image_available[self.current_frame],
|
||||
.null_handle,
|
||||
);
|
||||
|
||||
|
@ -120,21 +128,22 @@ pub const VulkanRenderer = struct {
|
|||
|
||||
const submit_info: vk.SubmitInfo = .{
|
||||
.wait_semaphore_count = 1, // Number of semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.image_available), // List of semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.image_available[self.current_frame]), // List of semaphores to wait on
|
||||
.p_wait_dst_stage_mask = &wait_stages, // Stages to check semaphores at
|
||||
.command_buffer_count = 1, // Number of command buffers to submit
|
||||
.p_command_buffers = @ptrCast(&self.command_buffers[image_index_result.image_index]), // Command buffer to submit
|
||||
.signal_semaphore_count = 1, // Number of semaphores to signal
|
||||
.p_signal_semaphores = @ptrCast(&self.render_finished), // List of semaphores to signal when command buffer finishes
|
||||
.p_signal_semaphores = @ptrCast(&self.render_finished[self.current_frame]), // List of semaphores to signal when command buffer finishes
|
||||
};
|
||||
|
||||
// Submit command buffer to queue
|
||||
try self.device.queueSubmit(self.graphics_queue.handle, 1, @ptrCast(&submit_info), self.frame_fence);
|
||||
try self.device.queueSubmit(self.graphics_queue.handle, 1, @ptrCast(&submit_info), self.draw_fences[self.current_frame]);
|
||||
// try self.device.queueSubmit(self.graphics_queue.handle, 1, @ptrCast(&submit_info), self.frame_fence);
|
||||
|
||||
// -- Present rendered image to screen
|
||||
const present_info: vk.PresentInfoKHR = .{
|
||||
.wait_semaphore_count = 1, // Number of semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.render_finished), // Semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.render_finished[self.current_frame]), // Semaphores to wait on
|
||||
.swapchain_count = 1, // Number of swapchains to present to
|
||||
.p_swapchains = @ptrCast(&self.swapchain), // Swapchains to present images to
|
||||
.p_image_indices = @ptrCast(&image_index_result.image_index), // Index of images in swapchains to present
|
||||
|
@ -142,6 +151,9 @@ pub const VulkanRenderer = struct {
|
|||
|
||||
// Present image
|
||||
_ = try self.device.queuePresentKHR(self.presentation_queue.handle, &present_info);
|
||||
|
||||
// Get next frame (use % to keep the current frame below MAX_FRAME_DRAWS)
|
||||
self.current_frame = (self.current_frame + 1) % MAX_FRAME_DRAWS;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
|
@ -149,10 +161,13 @@ pub const VulkanRenderer = struct {
|
|||
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
|
||||
}
|
||||
|
||||
_ = self.device.waitForFences(1, @ptrCast(&self.frame_fence), vk.TRUE, std.math.maxInt(u64)) catch undefined;
|
||||
self.device.destroyFence(self.frame_fence, null);
|
||||
self.device.destroySemaphore(self.render_finished, null);
|
||||
self.device.destroySemaphore(self.image_available, null);
|
||||
self.device.deviceWaitIdle() catch undefined;
|
||||
|
||||
for (0..MAX_FRAME_DRAWS) |i| {
|
||||
self.device.destroySemaphore(self.render_finished[i], null);
|
||||
self.device.destroySemaphore(self.image_available[i], null);
|
||||
self.device.destroyFence(self.draw_fences[i], null);
|
||||
}
|
||||
|
||||
self.allocator.free(self.command_buffers);
|
||||
self.device.destroyCommandPool(self.graphics_command_pool, null);
|
||||
|
@ -638,12 +653,15 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
|
||||
fn createSynchronisation(self: *Self) !void {
|
||||
// Semaphore creation information
|
||||
self.image_available = try self.device.createSemaphore(&.{}, null);
|
||||
self.render_finished = try self.device.createSemaphore(&.{}, null);
|
||||
|
||||
// Fence create information
|
||||
const fence_create_info: vk.FenceCreateInfo = .{ .flags = .{ .signaled_bit = true } };
|
||||
self.frame_fence = try self.device.createFence(&fence_create_info, null);
|
||||
|
||||
// Semaphore creation information
|
||||
for (0..MAX_FRAME_DRAWS) |i| {
|
||||
self.image_available[i] = try self.device.createSemaphore(&.{}, null);
|
||||
self.render_finished[i] = try self.device.createSemaphore(&.{}, null);
|
||||
self.draw_fences[i] = try self.device.createFence(&fence_create_info, null);
|
||||
}
|
||||
}
|
||||
|
||||
fn recordCommands(self: *Self) !void {
|
||||
|
|
Loading…
Reference in a new issue