diff --git a/src/Context.zig b/src/Context.zig index 6ac0810..6a138fd 100644 --- a/src/Context.zig +++ b/src/Context.zig @@ -35,23 +35,29 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { self.vkb = try BaseDispatch.load(&c.glfwGetInstanceProcAddress); const vkb = self.vkb; - var exts = std.ArrayList([*:0]const u8).init(allocator); - defer exts.deinit(); + var req_exts = std.ArrayList([*:0]const u8).init(allocator); + defer req_exts.deinit(); - var layers = std.ArrayList([*:0]const u8).init(allocator); - defer layers.deinit(); + var req_layers = std.ArrayList([*:0]const u8).init(allocator); + defer req_layers.deinit(); + + var req_device_exts = std.ArrayList([*:0]const u8).init(allocator); + defer req_device_exts.deinit(); if (USE_DEBUG_LAYERS) { - try layers.append("VK_LAYER_KHRONOS_validation"); - try exts.append("VK_EXT_debug_utils"); + try req_layers.append("VK_LAYER_KHRONOS_validation"); + try req_exts.append("VK_EXT_debug_utils"); } + try req_device_exts.append("VK_KHR_swapchain"); + var glfw_ext_count: u32 = 0; const glfw_exts: [*][*:0]const u8 = @ptrCast(c.glfwGetRequiredInstanceExtensions(&glfw_ext_count)); - try exts.appendSlice(glfw_exts[0..glfw_ext_count]); + try req_exts.appendSlice(glfw_exts[0..glfw_ext_count]); - std.log.debug("requesting extensions: {s}", .{exts.items}); - std.log.debug("requesting layers: {s}", .{layers.items}); + std.log.debug("requesting extensions: {s}", .{req_exts.items}); + std.log.debug("requesting layers: {s}", .{req_layers.items}); + std.log.debug("requesting device extensions: {s}", .{req_device_exts.items}); var available_ext_count: u32 = 0; _ = try vkb.enumerateInstanceExtensionProperties(null, &available_ext_count, null); @@ -65,7 +71,7 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { defer allocator.free(available_layers); _ = try vkb.enumerateInstanceLayerProperties(&available_layer_count, available_layers.ptr); - for (exts.items) |name| { + for (req_exts.items) |name| { const required_name = std.mem.sliceTo(name, 0); for (available_exts) |prop| { const available_name = std.mem.sliceTo(&prop.extension_name, 0); @@ -75,7 +81,7 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { } } - for (layers.items) |name| { + for (req_layers.items) |name| { const required_name = std.mem.sliceTo(name, 0); for (available_layers) |prop| { const available_name = std.mem.sliceTo(&prop.layer_name, 0); @@ -112,10 +118,10 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { 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, - .enabled_layer_count = @intCast(layers.items.len), - .pp_enabled_layer_names = layers.items.ptr, + .enabled_extension_count = @intCast(req_exts.items.len), + .pp_enabled_extension_names = req_exts.items.ptr, + .enabled_layer_count = @intCast(req_layers.items.len), + .pp_enabled_layer_names = req_layers.items.ptr, .p_next = if (USE_DEBUG_LAYERS) &debug_create_info else null, }; @@ -155,13 +161,17 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { defer allocator.free(devices); _ = try vki.enumeratePhysicalDevices(self.instance, &device_count, devices.ptr); + var available_device_exts_count: u32 = 0; + var available_device_exts = std.ArrayList(vk.ExtensionProperties).init(allocator); + defer available_device_exts.deinit(); + // todo some ranking strategy to find the most-suitable device const Selection = struct { device: vk.PhysicalDevice, props: vk.PhysicalDeviceProperties, feats: vk.PhysicalDeviceFeatures, }; - const selected: Selection = for (devices) |device| { + const selected: Selection = find_device: for (devices) |device| { const props = vki.getPhysicalDeviceProperties(device); const feats = vki.getPhysicalDeviceFeatures(device); @@ -169,6 +179,31 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { // if (feats.geometry_shader == vk.FALSE) continue; + _ = try vki.enumerateDeviceExtensionProperties( + device, + null, + &available_device_exts_count, + null, + ); + try available_device_exts.resize(available_device_exts_count); + _ = try vki.enumerateDeviceExtensionProperties( + device, + null, + &available_device_exts_count, + available_device_exts.items.ptr, + ); + + for (req_device_exts.items) |name| { + const required_name = std.mem.sliceTo(name, 0); + for (available_device_exts.items) |prop| { + const available_name = std.mem.sliceTo(&prop.extension_name, 0); + if (std.mem.eql(u8, required_name, available_name)) break; + } else { + std.log.warn("cannot find {s}\n", .{required_name}); + continue :find_device; + } + } + break .{ .device = device, .props = props, @@ -231,7 +266,6 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { // 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, @@ -239,7 +273,6 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { .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(.{ @@ -258,10 +291,10 @@ pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self { .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, - .enabled_layer_count = @intCast(layers.items.len), - .pp_enabled_layer_names = layers.items.ptr, + .enabled_extension_count = @intCast(req_device_exts.items.len), + .pp_enabled_extension_names = req_device_exts.items.ptr, + .enabled_layer_count = @intCast(req_layers.items.len), + .pp_enabled_layer_names = req_layers.items.ptr, }; self.device = try vki.createDevice( @@ -376,6 +409,7 @@ const InstanceDispatch = vk.InstanceWrapper(.{ .getDeviceProcAddr = true, .destroySurfaceKHR = true, .getPhysicalDeviceSurfaceSupportKHR = true, + .enumerateDeviceExtensionProperties = true, }); const DeviceDispatch = vk.DeviceWrapper(.{