From 282e85db24d438292fa2717ad8604b26290b4487 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Thu, 28 Mar 2024 16:06:50 -0400 Subject: [PATCH] graphics_context incremental teardown --- box.zig | 29 ---------- src/gfx.zig | 75 ++++++++++++++++++++++++ src/gfx/Context.zig | 6 ++ src/graphics_context.zig | 120 +++++---------------------------------- src/main.zig | 75 +++++++++++++++++++----- vecs.zig | 97 ------------------------------- 6 files changed, 155 insertions(+), 247 deletions(-) delete mode 100644 box.zig create mode 100644 src/gfx.zig create mode 100644 src/gfx/Context.zig delete mode 100644 vecs.zig diff --git a/box.zig b/box.zig deleted file mode 100644 index aa17978..0000000 --- a/box.zig +++ /dev/null @@ -1,29 +0,0 @@ -const std = @import("std"); - -pub fn Box(comptime T: type) type { - return struct { - val: T, - }; -} - -pub fn AddBoxType(comptime LHS: type, comptime RHS: type) type { - const x = std.mem.zeroes(std.meta.FieldType(LHS, .val)); - const y = std.mem.zeroes(std.meta.FieldType(RHS, .val)); - return Box(@TypeOf(x + y)); -} - -pub fn addbox(lhs: anytype, rhs: anytype) AddBoxType(@TypeOf(lhs), @TypeOf(rhs)) { - return .{ .val = lhs.val + rhs.val }; -} - -test { - std.testing.refAllDecls(@This()); -} - -test "widen" { - const foo: Box(u8) = .{ .val = 99 }; - const bar: Box(u16) = .{ .val = 599 }; - const actual = addbox(foo, bar); - const expected: Box(u16) = .{ .val = 698 }; - try std.testing.expectEqual(expected, actual); -} diff --git a/src/gfx.zig b/src/gfx.zig new file mode 100644 index 0000000..260368c --- /dev/null +++ b/src/gfx.zig @@ -0,0 +1,75 @@ +const vk = @import("vk"); + +pub const BaseDispatch = vk.BaseWrapper(.{ + .createInstance = true, + .getInstanceProcAddr = true, +}); + +pub const InstanceDispatch = vk.InstanceWrapper(.{ + .destroyInstance = true, + .createDevice = true, + .destroySurfaceKHR = true, + .enumeratePhysicalDevices = true, + .getPhysicalDeviceProperties = true, + .enumerateDeviceExtensionProperties = true, + .getPhysicalDeviceSurfaceFormatsKHR = true, + .getPhysicalDeviceSurfacePresentModesKHR = true, + .getPhysicalDeviceSurfaceCapabilitiesKHR = true, + .getPhysicalDeviceQueueFamilyProperties = true, + .getPhysicalDeviceSurfaceSupportKHR = true, + .getPhysicalDeviceMemoryProperties = true, + .getDeviceProcAddr = true, +}); + +pub const DeviceDispatch = vk.DeviceWrapper(.{ + .destroyDevice = true, + .getDeviceQueue = true, + .createSemaphore = true, + .createFence = true, + .createImageView = true, + .destroyImageView = true, + .destroySemaphore = true, + .destroyFence = true, + .getSwapchainImagesKHR = true, + .createSwapchainKHR = true, + .destroySwapchainKHR = true, + .acquireNextImageKHR = true, + .deviceWaitIdle = true, + .waitForFences = true, + .resetFences = true, + .queueSubmit = true, + .queuePresentKHR = true, + .createCommandPool = true, + .destroyCommandPool = true, + .allocateCommandBuffers = true, + .freeCommandBuffers = true, + .queueWaitIdle = true, + .createShaderModule = true, + .destroyShaderModule = true, + .createPipelineLayout = true, + .destroyPipelineLayout = true, + .createGraphicsPipelines = true, + .destroyPipeline = true, + .beginCommandBuffer = true, + .endCommandBuffer = true, + .allocateMemory = true, + .freeMemory = true, + .createBuffer = true, + .destroyBuffer = true, + .getBufferMemoryRequirements = true, + .mapMemory = true, + .unmapMemory = true, + .bindBufferMemory = true, + .cmdBeginRenderPass = true, + .cmdEndRenderPass = true, + .cmdBindPipeline = true, + .cmdDraw = true, + .cmdDrawIndexed = true, + .cmdSetViewport = true, + .cmdSetScissor = true, + .cmdBindVertexBuffers = true, + .cmdBindIndexBuffer = true, + .cmdCopyBuffer = true, + .cmdBeginRenderingKHR = true, + .cmdEndRenderingKHR = true, +}); diff --git a/src/gfx/Context.zig b/src/gfx/Context.zig new file mode 100644 index 0000000..7c53be3 --- /dev/null +++ b/src/gfx/Context.zig @@ -0,0 +1,6 @@ +const std = @import("std"); +const vk = @import("vk"); + +const d = @import("dispatch.zig"); + +const Self = @This(); diff --git a/src/graphics_context.zig b/src/graphics_context.zig index 45e3b75..959da98 100644 --- a/src/graphics_context.zig +++ b/src/graphics_context.zig @@ -3,91 +3,21 @@ const vk = @import("vk"); const c = @import("c.zig"); const Allocator = std.mem.Allocator; +const gfx = @import("gfx.zig"); + +const BaseDispatch = gfx.BaseDispatch; +const InstanceDispatch = gfx.InstanceDispatch; +const DeviceDispatch = gfx.DeviceDispatch; + const required_device_extensions = [_][*:0]const u8{ vk.extension_info.khr_swapchain.name, vk.extension_info.khr_dynamic_rendering.name, }; -const BaseDispatch = vk.BaseWrapper(.{ - .createInstance = true, - .getInstanceProcAddr = true, -}); - -const InstanceDispatch = vk.InstanceWrapper(.{ - .destroyInstance = true, - .createDevice = true, - .destroySurfaceKHR = true, - .enumeratePhysicalDevices = true, - .getPhysicalDeviceProperties = true, - .enumerateDeviceExtensionProperties = true, - .getPhysicalDeviceSurfaceFormatsKHR = true, - .getPhysicalDeviceSurfacePresentModesKHR = true, - .getPhysicalDeviceSurfaceCapabilitiesKHR = true, - .getPhysicalDeviceQueueFamilyProperties = true, - .getPhysicalDeviceSurfaceSupportKHR = true, - .getPhysicalDeviceMemoryProperties = true, - .getDeviceProcAddr = true, -}); - -const DeviceDispatch = vk.DeviceWrapper(.{ - .destroyDevice = true, - .getDeviceQueue = true, - .createSemaphore = true, - .createFence = true, - .createImageView = true, - .destroyImageView = true, - .destroySemaphore = true, - .destroyFence = true, - .getSwapchainImagesKHR = true, - .createSwapchainKHR = true, - .destroySwapchainKHR = true, - .acquireNextImageKHR = true, - .deviceWaitIdle = true, - .waitForFences = true, - .resetFences = true, - .queueSubmit = true, - .queuePresentKHR = true, - .createCommandPool = true, - .destroyCommandPool = true, - .allocateCommandBuffers = true, - .freeCommandBuffers = true, - .queueWaitIdle = true, - .createShaderModule = true, - .destroyShaderModule = true, - .createPipelineLayout = true, - .destroyPipelineLayout = true, - .createGraphicsPipelines = true, - .destroyPipeline = true, - .beginCommandBuffer = true, - .endCommandBuffer = true, - .allocateMemory = true, - .freeMemory = true, - .createBuffer = true, - .destroyBuffer = true, - .getBufferMemoryRequirements = true, - .mapMemory = true, - .unmapMemory = true, - .bindBufferMemory = true, - .cmdBeginRenderPass = true, - .cmdEndRenderPass = true, - .cmdBindPipeline = true, - .cmdDraw = true, - .cmdDrawIndexed = true, - .cmdSetViewport = true, - .cmdSetScissor = true, - .cmdBindVertexBuffers = true, - .cmdBindIndexBuffer = true, - .cmdCopyBuffer = true, - .cmdBeginRenderingKHR = true, - .cmdEndRenderingKHR = true, -}); - pub const GraphicsContext = struct { - vkb: BaseDispatch, vki: InstanceDispatch, vkd: DeviceDispatch, - instance: vk.Instance, surface: vk.SurfaceKHR, pdev: vk.PhysicalDevice, props: vk.PhysicalDeviceProperties, @@ -97,52 +27,28 @@ pub const GraphicsContext = struct { graphics_queue: Queue, present_queue: Queue, - pub fn init(allocator: Allocator, app_name: [*:0]const u8, window: *c.GLFWwindow) !GraphicsContext { + pub fn init(allocator: Allocator, instance: vk.Instance, surface: vk.SurfaceKHR, vki: InstanceDispatch) !GraphicsContext { var self: GraphicsContext = undefined; - self.vkb = try BaseDispatch.load(c.glfwGetInstanceProcAddress); + self.vki = vki; + self.surface = surface; - var glfw_exts_count: u32 = 0; - const glfw_exts = c.glfwGetRequiredInstanceExtensions(&glfw_exts_count); - - const app_info = vk.ApplicationInfo{ - .p_application_name = app_name, - .application_version = vk.makeApiVersion(0, 0, 0, 0), - .p_engine_name = app_name, - .engine_version = vk.makeApiVersion(0, 0, 0, 0), - .api_version = vk.API_VERSION_1_3, - }; - - self.instance = try self.vkb.createInstance(&.{ - .p_application_info = &app_info, - .enabled_extension_count = glfw_exts_count, - .pp_enabled_extension_names = @as([*]const [*:0]const u8, @ptrCast(glfw_exts)), - }, null); - - self.vki = try InstanceDispatch.load(self.instance, self.vkb.dispatch.vkGetInstanceProcAddr); - errdefer self.vki.destroyInstance(self.instance, null); - - self.surface = try createSurface(self.instance, window); - errdefer self.vki.destroySurfaceKHR(self.instance, self.surface, null); - - const candidate = try pickPhysicalDevice(self.vki, self.instance, allocator, self.surface); + const candidate = try pickPhysicalDevice(vki, instance, allocator, surface); self.pdev = candidate.pdev; self.props = candidate.props; - self.dev = try initializeCandidate(self.vki, candidate); - self.vkd = try DeviceDispatch.load(self.dev, self.vki.dispatch.vkGetDeviceProcAddr); + self.dev = try initializeCandidate(vki, candidate); + self.vkd = try DeviceDispatch.load(self.dev, vki.dispatch.vkGetDeviceProcAddr); errdefer self.vkd.destroyDevice(self.dev, null); self.graphics_queue = Queue.init(self.vkd, self.dev, candidate.queues.graphics_family); self.present_queue = Queue.init(self.vkd, self.dev, candidate.queues.present_family); - self.mem_props = self.vki.getPhysicalDeviceMemoryProperties(self.pdev); + self.mem_props = vki.getPhysicalDeviceMemoryProperties(self.pdev); return self; } pub fn deinit(self: GraphicsContext) void { self.vkd.destroyDevice(self.dev, null); - self.vki.destroySurfaceKHR(self.instance, self.surface, null); - self.vki.destroyInstance(self.instance, null); } pub fn deviceName(self: *const GraphicsContext) []const u8 { diff --git a/src/main.zig b/src/main.zig index cef4a9d..30abb74 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,6 +6,8 @@ const GraphicsContext = @import("graphics_context.zig").GraphicsContext; const Swapchain = @import("swapchain.zig").Swapchain; const Allocator = std.mem.Allocator; +const gfx = @import("gfx.zig"); + const app_name = "vulkan-zig triangle example"; const Vertex = extern struct { @@ -50,7 +52,57 @@ const vertices = [_]Vertex{ const indices = [_]Index{ 4, 5, 6, 6, 5, 7 }; +/// note: destroy with vki.destroyInstance(instance, null) +fn create_instance(vkb: gfx.BaseDispatch) !std.meta.Tuple(&.{ vk.Instance, gfx.InstanceDispatch }) { + var glfw_exts_count: u32 = 0; + const glfw_exts = c.glfwGetRequiredInstanceExtensions(&glfw_exts_count); + + const instance = try vkb.createInstance(&vk.InstanceCreateInfo{ + .p_application_info = &vk.ApplicationInfo{ + .p_application_name = app_name, + .application_version = vk.makeApiVersion(0, 0, 0, 0), + .p_engine_name = app_name, + .engine_version = vk.makeApiVersion(0, 0, 0, 0), + .api_version = vk.API_VERSION_1_3, + }, + .enabled_extension_count = glfw_exts_count, + .pp_enabled_extension_names = @ptrCast(glfw_exts), + }, null); + + const vki = try gfx.InstanceDispatch.load(instance, vkb.dispatch.vkGetInstanceProcAddr); + + return .{ instance, vki }; +} + +/// note: destroy with vki.destroySurfaceKHR(instance, surface, null) +fn create_surface(instance: vk.Instance, window: *c.GLFWwindow) !vk.SurfaceKHR { + var surface: vk.SurfaceKHR = undefined; + if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) { + return error.SurfaceInitFailed; + } + return surface; +} + +/// note: destroy with c.glfwDestroyWindow(window) +fn create_window(extent: vk.Extent2D, title: [*:0]const u8) !*c.GLFWwindow { + 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); + + return c.glfwCreateWindow( + @intCast(extent.width), + @intCast(extent.height), + title, + null, + null, + ) orelse error.WindowInitFailed; +} + pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed; defer c.glfwTerminate(); @@ -61,23 +113,18 @@ pub fn main() !void { var extent = vk.Extent2D{ .width = 800, .height = 600 }; - 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 window = c.glfwCreateWindow( - @intCast(extent.width), - @intCast(extent.height), - app_name, - null, - null, - ) orelse return error.WindowInitFailed; + const window = try create_window(extent, app_name); defer c.glfwDestroyWindow(window); - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); + const vkb = try gfx.BaseDispatch.load(c.glfwGetInstanceProcAddress); - const gc = try GraphicsContext.init(allocator, app_name, window); + const instance, const vki = try create_instance(vkb); + defer vki.destroyInstance(instance, null); + + const surface = try create_surface(instance, window); + defer vki.destroySurfaceKHR(instance, surface, null); + + const gc = try GraphicsContext.init(allocator, instance, surface, vki); defer gc.deinit(); std.log.debug("Using device: {s}", .{gc.deviceName()}); diff --git a/vecs.zig b/vecs.zig deleted file mode 100644 index c1ce0b1..0000000 --- a/vecs.zig +++ /dev/null @@ -1,97 +0,0 @@ -const std = @import("std"); - -const mat4f = mat(4, 4, f32); -const vec4f = mat(4, 1, f32); - -const mat4i = mat(4, 4, i32); -const vec4i = mat(4, 1, i32); - -const mat4u = mat(4, 4, u32); -const vec4u = mat(4, 1, u32); - -pub fn mat(comptime R_: usize, comptime C_: usize, comptime T_: type) type { - return struct { - pub const Rows = R_; - pub const Cols = C_; - pub const T = T_; - - data: [Cols][Rows]T, - - pub fn mul(l: @This(), r: anytype) MatMulReturnType(@This(), @TypeOf(r)) { - return matmul(l, r); - } - }; -} - -fn MatMulReturnType(comptime L: type, comptime R: type) type { - if (L.Cols != R.Rows) @compileError("invalid dimensions"); - - const x: L.T = std.mem.zeroes(L.T); - const y: R.T = std.mem.zeroes(R.T); - const T = @TypeOf(x + y); - - return mat(L.Rows, R.Cols, T); -} - -pub fn matmul(lhs: anytype, rhs: anytype) MatMulReturnType(@TypeOf(lhs), @TypeOf(rhs)) { - @setFloatMode(.optimized); - - const L = @TypeOf(lhs); - const R = @TypeOf(rhs); - const Ret = MatMulReturnType(L, R); - - var res = std.mem.zeroes(Ret); - - if (L.Cols != R.Rows) @compileError("invalid dimensions"); - - inline for (0..R.Cols) |col| { - inline for (0..L.Rows) |row| { - inline for (0..L.Cols) |k| { - res.data[col][row] += lhs.data[k][row] * rhs.data[col][k]; - } - } - } - - return res; -} - -export fn c_matmul_f_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void { - const l: *const mat4f = @alignCast(@ptrCast(lhs)); - const r: *const vec4f = @alignCast(@ptrCast(rhs)); - const o: *vec4f = @alignCast(@ptrCast(out)); - - o.* = matmul(l.*, r.*); -} - -export fn c_matmul_i_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void { - const l: *const mat4i = @alignCast(@ptrCast(lhs)); - const r: *const vec4i = @alignCast(@ptrCast(rhs)); - const o: *vec4i = @alignCast(@ptrCast(out)); - - o.* = matmul(l.*, r.*); -} - -export fn c_matmul_u_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void { - const l: *const mat4u = @alignCast(@ptrCast(lhs)); - const r: *const vec4u = @alignCast(@ptrCast(rhs)); - const o: *vec4u = @alignCast(@ptrCast(out)); - - o.* = matmul(l.*, r.*); -} - -test "matmul" { - // note, column major; it's transposed. - const m: mat4u = .{ .data = .{ - .{ 85, 84, 87, 37 }, - .{ 33, 54, 49, 83 }, - .{ 96, 97, 3, 13 }, - .{ 69, 12, 45, 77 }, - } }; - const u: vec4u = .{ .data = .{.{ 37, 69, 94, 87 }} }; - - const actual: vec4u = matmul(m, u); - - const expect: vec4u = .{ .data = .{.{ 20449, 16996, 10797, 15017 }} }; - - try std.testing.expectEqualDeep(expect, actual); -}