diff --git a/src/gfx/Base.zig b/src/gfx/Base.zig deleted file mode 100644 index e0f3fd7..0000000 --- a/src/gfx/Base.zig +++ /dev/null @@ -1,30 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -const vk = @import("vk"); -const c = @import("../c.zig"); -const gfx = @import("../gfx.zig"); - -const Self = @This(); - -vkb: Wrapper, - -pub fn init() !Self { - if (c.glfwInit() != c.GLFW_TRUE) - return error.GLFWInitFailed; - errdefer c.glfwTerminate(); - - if (c.glfwVulkanSupported() != c.GLFW_TRUE) { - return error.GLFWNoVulkan; - } - - return .{ - .vkb = try Wrapper.load(c.glfwGetInstanceProcAddress), - }; -} - -pub fn deinit(_: Self) void { - c.glfwTerminate(); -} - -pub const Wrapper = vk.BaseWrapper(gfx.apis); diff --git a/src/gfx/Context.zig b/src/gfx/Context.zig deleted file mode 100644 index 646d492..0000000 --- a/src/gfx/Context.zig +++ /dev/null @@ -1,5 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const vk = @import("vk"); -const c = @import("../c.zig"); -const gfx = @import("../c.zig"); diff --git a/src/gfx/Device.zig b/src/gfx/Device.zig deleted file mode 100644 index d27f63c..0000000 --- a/src/gfx/Device.zig +++ /dev/null @@ -1,182 +0,0 @@ -//! The point here is to select _a_ physical device and create a logical device around it. - -const std = @import("std"); -const builtin = @import("builtin"); - -const vk = @import("vk"); -const c = @import("../c.zig"); -const gfx = @import("../gfx.zig"); - -const Instance = @import("Instance.zig"); -const Window = @import("Window.zig"); - -const Self = @This(); - -const required_extensions: []const [*:0]const u8 = &.{ - vk.extensions.khr_swapchain.name, - vk.extensions.khr_dynamic_rendering.name, -}; - -const preferred_surface_format: vk.SurfaceFormatKHR = .{ - .color_space = .srgb_nonlinear_khr, - .format = .r8g8b8a8_sint, -}; - -const preferred_present_mode: vk.PresentModeKHR = .mailbox_khr; - -dev: vk.Device, -pdev: vk.PhysicalDevice, -vkd: Wrapper, - -inst: *const Instance, -win: *const Window, - -format: vk.SurfaceFormatKHR, -mode: vk.PresentModeKHR, -family: u32, -queue: vk.Queue, - -pool: vk.CommandPool, - -pub fn init( - ally: std.mem.Allocator, - inst: *const Instance, - win: *const Window, -) !Self { - var pdev_count: u32 = undefined; - _ = try inst.vki.enumeratePhysicalDevices(inst.ref, &pdev_count, null); - const pdevs = try ally.alloc(vk.PhysicalDevice, pdev_count); - defer ally.free(pdevs); - _ = try inst.vki.enumeratePhysicalDevices(inst.ref, &pdev_count, pdevs.ptr); - - for (pdevs) |pdev| { - return wrap(ally, inst, win, pdev) catch continue; - } - - return error.NoSuitableDevice; -} - -pub fn wrap( - ally: std.mem.Allocator, - inst: *const Instance, - win: *const Window, - pdev: vk.PhysicalDevice, -) !Self { - // TODO: Need to rank devices and select the best one - // the new laptop doesn't have a discrete gpu. - // const props = inst.vki.getPhysicalDeviceProperties(pdev); - // if (props.device_type != .discrete_gpu) return error.NotDiscrete; - - var format_count: u32 = undefined; - _ = try inst.vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, win.surface, &format_count, null); - if (format_count == 0) return error.NoSurfaceFormat; - const formats = try ally.alloc(vk.SurfaceFormatKHR, format_count); - defer ally.free(formats); - _ = try inst.vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, win.surface, &format_count, formats.ptr); - - const format = for (formats) |f| { - if (std.meta.eql(f, preferred_surface_format)) - break f; - } else formats[0]; - - var mode_count: u32 = undefined; - _ = try inst.vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, win.surface, &mode_count, null); - if (mode_count == 0) return error.NoSurfaceMode; - const modes = try ally.alloc(vk.PresentModeKHR, mode_count); - defer ally.free(modes); - _ = try inst.vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, win.surface, &mode_count, modes.ptr); - - const mode = for (modes) |m| { - if (std.meta.eql(m, preferred_present_mode)) - break m; - } else modes[0]; - - var ext_count: u32 = undefined; - _ = try inst.vki.enumerateDeviceExtensionProperties(pdev, null, &ext_count, null); - const exts = try ally.alloc(vk.ExtensionProperties, ext_count); - defer ally.free(exts); - _ = try inst.vki.enumerateDeviceExtensionProperties(pdev, null, &ext_count, exts.ptr); - - for (required_extensions) |name| { - for (exts) |ext| { - if (std.mem.eql( - u8, - std.mem.span(name), - std.mem.sliceTo(&ext.extension_name, 0), - )) { - break; - } - } else { - return error.MissingRequiredExtension; - } - } - - var family_count: u32 = undefined; - inst.vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null); - const families = try ally.alloc(vk.QueueFamilyProperties, family_count); - defer ally.free(families); - inst.vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, families.ptr); - - // just find one family that does graphics and present, so we can use exclusive sharing - // on the swapchain. apparently most hardware supports this. logic for queue allocation - // and swapchain creation is so much simpler this way. swapchain creation needs to know - // the list of queue family indices which will have access to the images, and there's a - // performance penalty to allow concurrent access to multiple queue families. - // - // multiple _queues_ may have exclusive access, but only if they're in the smae family. - - const family: u32 = for (families, 0..) |family, idx| { - const graphics = family.queue_flags.graphics_bit; - const present = try inst.vki.getPhysicalDeviceSurfaceSupportKHR(pdev, @intCast(idx), win.surface) == vk.TRUE; - if (graphics and present) break @intCast(idx); - } else { - return error.NoSuitableQueueFamily; - }; - - const qci: []const vk.DeviceQueueCreateInfo = &.{ - vk.DeviceQueueCreateInfo{ - .queue_family_index = family, - .queue_count = 1, - .p_queue_priorities = &[_]f32{1.0}, - }, - }; - - const dev = try inst.vki.createDevice(pdev, &.{ - .queue_create_info_count = @intCast(qci.len), - .p_queue_create_infos = qci.ptr, - .enabled_extension_count = @intCast(required_extensions.len), - .pp_enabled_extension_names = required_extensions.ptr, - .p_next = &vk.PhysicalDeviceDynamicRenderingFeaturesKHR{ - .dynamic_rendering = vk.TRUE, - }, - }, null); - const vkd = try Wrapper.load(dev, inst.vki.dispatch.vkGetDeviceProcAddr); - errdefer vkd.destroyDevice(dev, null); - - const pool = try vkd.createCommandPool(dev, &.{ - .queue_family_index = family, - }, null); - errdefer vkd.destroyCommandPool(dev, pool, null); - - const queue = vkd.getDeviceQueue(dev, family, 0); - - return .{ - .dev = dev, - .pdev = pdev, - .vkd = vkd, - .inst = inst, - .win = win, - .format = format, - .mode = mode, - .pool = pool, - .family = family, - .queue = queue, - }; -} - -pub fn deinit(self: Self) void { - self.vkd.destroyCommandPool(self.dev, self.pool, null); - self.vkd.destroyDevice(self.dev, null); -} - -pub const Wrapper = vk.DeviceWrapper(gfx.apis); diff --git a/src/gfx/Instance.zig b/src/gfx/Instance.zig deleted file mode 100644 index c5c04d3..0000000 --- a/src/gfx/Instance.zig +++ /dev/null @@ -1,143 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -const vk = @import("vk"); -const c = @import("../c.zig"); -const gfx = @import("../gfx.zig"); - -const Self = @This(); - -const app_info: vk.ApplicationInfo = .{ - .p_application_name = "zig-glfw-vulkan", - .application_version = vk.makeApiVersion(0, 0, 0, 0), - .p_engine_name = "zig-glfw-vulkan", - .engine_version = vk.makeApiVersion(0, 0, 0, 0), - .api_version = vk.API_VERSION_1_3, -}; - -ref: vk.Instance, -vki: Wrapper, -base: *const gfx.Base, - -messenger: if (gfx.use_debug_messenger) vk.DebugUtilsMessengerEXT else void, - -pub fn init( - base: *const gfx.Base, -) !Self { - var exts: std.BoundedArray([*:0]const u8, 32) = .{}; - var layers: std.BoundedArray([*:0]const u8, 32) = .{}; - - if (gfx.use_debug_messenger) { - try exts.appendSlice(&.{ - vk.extensions.ext_debug_utils.name, - }); - - try layers.appendSlice(&.{ - "VK_LAYER_KHRONOS_validation", - }); - } - - var glfw_exts_count: u32 = 0; - const glfw_exts: [*]const [*:0]const u8 = - @ptrCast(c.glfwGetRequiredInstanceExtensions(&glfw_exts_count)); - try exts.appendSlice(glfw_exts[0..glfw_exts_count]); - - const mci: vk.DebugUtilsMessengerCreateInfoEXT = .{ - .message_severity = .{ - .error_bit_ext = true, - .info_bit_ext = true, - .verbose_bit_ext = true, - .warning_bit_ext = true, - }, - .message_type = .{ - .device_address_binding_bit_ext = true, - .general_bit_ext = false, - .performance_bit_ext = true, - .validation_bit_ext = true, - }, - .pfn_user_callback = &debug_callback, - .p_user_data = null, - }; - - const ref = try base.vkb.createInstance(&.{ - .p_application_info = &app_info, - .enabled_extension_count = @intCast(exts.len), - .pp_enabled_extension_names = &exts.buffer, - .enabled_layer_count = @intCast(layers.len), - .pp_enabled_layer_names = &layers.buffer, - .p_next = if (gfx.use_debug_messenger) &mci else null, - }, null); - - const vki = try Wrapper.load(ref, base.vkb.dispatch.vkGetInstanceProcAddr); - errdefer vki.destroyInstance(ref, null); - - const messenger = if (gfx.use_debug_messenger) - try vki.createDebugUtilsMessengerEXT(ref, &mci, null) - else - void{}; - - errdefer if (gfx.use_debug_messenger) - vki.destroyDebugUtilsMessengerEXT(ref, messenger, null); - - return .{ - .ref = ref, - .vki = vki, - .base = base, - .messenger = messenger, - }; -} - -pub fn deinit(self: Self) void { - if (gfx.use_debug_messenger) - self.vki.destroyDebugUtilsMessengerEXT(self.ref, self.messenger, null); - self.vki.destroyInstance(self.ref, null); -} - -pub const Wrapper = vk.InstanceWrapper(gfx.apis); - -pub fn debug_callback( - msg_severity: vk.DebugUtilsMessageSeverityFlagsEXT, - msg_type: vk.DebugUtilsMessageTypeFlagsEXT, - p_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT, - _: ?*anyopaque, -) callconv(vk.vulkan_call_conv) vk.Bool32 { - // ripped from std.log.defaultLog - - const data = p_data orelse return vk.FALSE; - const message = data.p_message orelse return vk.FALSE; - - const severity_prefix = if (msg_severity.verbose_bit_ext) - "verbose:" - else if (msg_severity.info_bit_ext) - "info:" - else if (msg_severity.warning_bit_ext) - "warning:" - else if (msg_severity.error_bit_ext) - "error:" - else - "?:"; - - const type_prefix = if (msg_type.general_bit_ext) - "" - else if (msg_type.validation_bit_ext) - "validation:" - else if (msg_type.performance_bit_ext) - "performance:" - else if (msg_type.device_address_binding_bit_ext) - "device_address_binding:" - else - "?:"; - - const stderr = std.io.getStdErr().writer(); - var bw = std.io.bufferedWriter(stderr); - const writer = bw.writer(); - - std.debug.lockStdErr(); - defer std.debug.unlockStdErr(); - nosuspend { - writer.print("vk-{s}{s} {s}\n", .{ severity_prefix, type_prefix, message }) catch return vk.FALSE; - bw.flush() catch return vk.FALSE; - } - - return vk.FALSE; -} diff --git a/src/gfx/Window.zig b/src/gfx/Window.zig deleted file mode 100644 index d2c2c2b..0000000 --- a/src/gfx/Window.zig +++ /dev/null @@ -1,41 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -const vk = @import("vk"); -const c = @import("../c.zig"); - -const Base = @import("Base.zig"); -const Instance = @import("Instance.zig"); - -const Self = @This(); - -ref: *c.GLFWwindow, -surface: vk.SurfaceKHR, - -inst: *const Instance, - -pub fn init(inst: *const Instance, title: [*:0]const u8, extent: vk.Extent2D) !Self { - c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, "floating_window"); - c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, "floating_window"); - c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API); - - const ref = c.glfwCreateWindow(@intCast(extent.width), @intCast(extent.height), title, null, null) orelse - return error.GLFWWindowCreateFailed; - errdefer c.glfwDestroyWindow(ref); - - var surface: vk.SurfaceKHR = undefined; - if (c.glfwCreateWindowSurface(inst.ref, ref, null, &surface) != .success) - return error.GLFWWindowSurfaceFailed; - errdefer inst.vki.destroySurfaceKHR(inst.ref, surface, null); - - return .{ - .ref = ref, - .surface = surface, - .inst = inst, - }; -} - -pub fn deinit(self: Self) void { - self.inst.vki.destroySurfaceKHR(self.inst.ref, self.surface, null); - c.glfwDestroyWindow(self.ref); -}