From 02380af6abc21d251dc8be8eef24223b3e929d52 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Thu, 21 Mar 2024 15:12:49 -0400 Subject: [PATCH] vulkan-tutorial 06 --- src/Context.zig | 105 ++++++++++++++++++++++++++++++++++++++++-------- src/Window.zig | 42 ------------------- src/main.zig | 25 +++++++----- 3 files changed, 102 insertions(+), 70 deletions(-) delete mode 100644 src/Window.zig diff --git a/src/Context.zig b/src/Context.zig index 6f08bca..6ac0810 100644 --- a/src/Context.zig +++ b/src/Context.zig @@ -21,11 +21,14 @@ device: vk.Device, queues: struct { graphics: vk.Queue, + present: vk.Queue, }, +surface: vk.SurfaceKHR, + messenger: if (USE_DEBUG_LAYERS) vk.DebugUtilsMessengerEXT else void, -pub fn init(allocator: std.mem.Allocator) !Self { +pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { var self: Self = undefined; self.allocator = allocator; @@ -107,7 +110,7 @@ pub fn init(allocator: std.mem.Allocator) !Self { .api_version = vk.API_VERSION_1_3, }; - const create_info = vk.InstanceCreateInfo{ + const instance_create_info = vk.InstanceCreateInfo{ .p_application_info = &app_info, .enabled_extension_count = @intCast(exts.items.len), .pp_enabled_extension_names = exts.items.ptr, @@ -116,7 +119,7 @@ pub fn init(allocator: std.mem.Allocator) !Self { .p_next = if (USE_DEBUG_LAYERS) &debug_create_info else null, }; - self.instance = try vkb.createInstance(&create_info, null); + self.instance = try vkb.createInstance(&instance_create_info, null); self.vki = try InstanceDispatch.load(self.instance, vkb.dispatch.vkGetInstanceProcAddr); const vki = self.vki; errdefer vki.destroyInstance(self.instance, null); @@ -132,6 +135,20 @@ pub fn init(allocator: std.mem.Allocator) !Self { null, ); + switch (c.glfwCreateWindowSurface( + self.instance, + window, + null, + &self.surface, + )) { + .success => {}, + else => |e| { + std.log.err("{}", .{e}); + return error.Unknown; + }, + } + errdefer vki.destroySurfaceKHR(self.instance, self.surface, null); + var device_count: u32 = 0; _ = try vki.enumeratePhysicalDevices(self.instance, &device_count, null); const devices = try allocator.alloc(vk.PhysicalDevice, device_count); @@ -170,35 +187,76 @@ pub fn init(allocator: std.mem.Allocator) !Self { // todo this should be incorporated with physical device selection/ranking. const Indices = struct { graphics: u32, + present: u32, }; const indices: Indices = find_index: { var graphics: ?u32 = null; + var present: ?u32 = null; for (queue_family_properties, 0..) |prop, idx| { if (graphics == null and prop.queue_flags.graphics_bit) { graphics = @intCast(idx); + // continue; // forces distinct queue families } - if (graphics != null) { - break :find_index .{ .graphics = graphics.? }; + if (present == null) { + const present_support = try vki.getPhysicalDeviceSurfaceSupportKHR( + selected.device, + @intCast(idx), + self.surface, + ) == vk.TRUE; + if (present_support) { + present = @intCast(idx); + } + } + + if (graphics != null and present != null) { + break :find_index .{ + .graphics = graphics.?, + .present = present.?, + }; } } return error.IncompatibleDeviceQueues; }; - const priorities = [_]f32{1.0}; - const queue_create_infos = [_]vk.DeviceQueueCreateInfo{ - .{ + const gp_priorities = [_]f32{ 1.0, 1.0 }; + + var queue_create_infos = std.ArrayList(vk.DeviceQueueCreateInfo).init(allocator); + defer queue_create_infos.deinit(); + + // queue info family indices must be unique. so if the graphics and present queues are the same, create two queues + // in the same family. otherwise create queues in separate families. there should probably be some general way to + // group and unpack the queues, but I'm not bothering with that for now until I restructure this monolithic function + // in general. + if (indices.graphics == indices.present) { + std.log.info("using one queue family", .{}); + const gp_slice = gp_priorities[0..2]; + try queue_create_infos.append(.{ .queue_family_index = indices.graphics, - .queue_count = priorities.len, - .p_queue_priorities = &priorities, - }, - }; + .queue_count = @intCast(gp_slice.len), + .p_queue_priorities = gp_slice.ptr, + }); + } else { + std.log.info("using two queue families", .{}); + const g_slice = gp_priorities[0..1]; + const p_slice = gp_priorities[1..2]; + try queue_create_infos.append(.{ + .queue_family_index = indices.graphics, + .queue_count = @intCast(g_slice.len), + .p_queue_priorities = g_slice.ptr, + }); + try queue_create_infos.append(.{ + .queue_family_index = indices.present, + .queue_count = @intCast(p_slice.len), + .p_queue_priorities = p_slice.ptr, + }); + } const device_create_info = vk.DeviceCreateInfo{ - .queue_create_info_count = queue_create_infos.len, - .p_queue_create_infos = &queue_create_infos, + .queue_create_info_count = @intCast(queue_create_infos.items.len), + .p_queue_create_infos = queue_create_infos.items.ptr, .p_enabled_features = &selected.feats, // .enabled_extension_count = @intCast(exts.items.len), // .pp_enabled_extension_names = exts.items.ptr, @@ -215,14 +273,25 @@ pub fn init(allocator: std.mem.Allocator) !Self { const vkd = self.vkd; errdefer vkd.destroyDevice(self.device, null); - self.queues = .{ - .graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0), - }; + if (indices.graphics == indices.present) { + // two queues in the same family + self.queues = .{ + .graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0), + .present = vkd.getDeviceQueue(self.device, indices.present, 1), + }; + } else { + // queues from different families + self.queues = .{ + .graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0), + .present = vkd.getDeviceQueue(self.device, indices.present, 0), + }; + } return self; } pub fn deinit(self: Self) void { + self.vki.destroySurfaceKHR(self.instance, self.surface, null); self.vkd.destroyDevice(self.device, null); if (USE_DEBUG_LAYERS) self.vki.destroyDebugUtilsMessengerEXT( self.instance, @@ -305,6 +374,8 @@ const InstanceDispatch = vk.InstanceWrapper(.{ .getPhysicalDeviceQueueFamilyProperties = true, .createDevice = true, .getDeviceProcAddr = true, + .destroySurfaceKHR = true, + .getPhysicalDeviceSurfaceSupportKHR = true, }); const DeviceDispatch = vk.DeviceWrapper(.{ diff --git a/src/Window.zig b/src/Window.zig deleted file mode 100644 index d792468..0000000 --- a/src/Window.zig +++ /dev/null @@ -1,42 +0,0 @@ -const Self = @This(); - -const std = @import("std"); -const c = @import("c.zig"); -const vk = @import("vk"); -const builtin = @import("builtin"); - -allocator: std.mem.Allocator, - -window: *c.GLFWwindow, - -pub fn mainLoop(self: Self) void { - while (c.glfwWindowShouldClose(self.window) == 0) : (c.glfwPollEvents()) { - c.glfwSwapBuffers(self.window); - } -} - -pub fn init( - allocator: std.mem.Allocator, - width: u32, - height: u32, - title: []const u8, -) !Self { - var self: Self = undefined; - self.allocator = allocator; - - c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API); - self.window = c.glfwCreateWindow( - @intCast(width), - @intCast(height), - title.ptr, - null, - null, - ) orelse return error.glfwCreateWindowFailed; - errdefer c.glfwDestroyWindow(self.window); - - return self; -} - -pub fn deinit(self: Self) void { - c.glfwDestroyWindow(self.window); -} diff --git a/src/main.zig b/src/main.zig index fdf0ba4..3841f81 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,7 +2,6 @@ const std = @import("std"); const c = @import("c.zig"); const vk = @import("vk"); -const Window = @import("Window.zig"); const Context = @import("Context.zig"); pub fn main() !void { @@ -15,16 +14,20 @@ pub fn main() !void { } defer c.glfwTerminate(); - const ctx = try Context.init(allocator); + c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API); + const window = c.glfwCreateWindow( + 720, + 1280, + "Hello World!", + null, + null, + ) orelse return error.glfwCreateWindowFailed; + defer c.glfwDestroyWindow(window); + + const ctx = try Context.init(allocator, window); defer ctx.deinit(); - const window = try Window.init( - allocator, - 1280, - 720, - "Hello World", - ); - defer window.deinit(); - - window.mainLoop(); + while (c.glfwWindowShouldClose(window) == 0) : (c.glfwPollEvents()) { + c.glfwSwapBuffers(window); + } }