From defc4c53d3d3935b1a4e544300d8182c4b43625c Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Mon, 29 Apr 2024 21:15:02 +0200 Subject: [PATCH] update example with new proxying wrappers --- examples/graphics_context.zig | 117 ++++++++++++++++++-------------- examples/swapchain.zig | 71 ++++++++++---------- examples/triangle.zig | 121 +++++++++++++++++----------------- 3 files changed, 163 insertions(+), 146 deletions(-) diff --git a/examples/graphics_context.zig b/examples/graphics_context.zig index 2ca6894..e6f3727 100644 --- a/examples/graphics_context.zig +++ b/examples/graphics_context.zig @@ -27,23 +27,30 @@ const BaseDispatch = vk.BaseWrapper(apis); const InstanceDispatch = vk.InstanceWrapper(apis); const DeviceDispatch = vk.DeviceWrapper(apis); -pub const GraphicsContext = struct { - vkb: BaseDispatch, - vki: InstanceDispatch, - vkd: DeviceDispatch, +// Also create some proxying wrappers, which also have the respective handles +const Instance = vk.InstanceProxy(apis); +const Device = vk.DeviceProxy(apis); - instance: vk.Instance, +pub const GraphicsContext = struct { + pub const CommandBuffer = vk.CommandBufferProxy(apis); + + allocator: Allocator, + + vkb: BaseDispatch, + + instance: Instance, surface: vk.SurfaceKHR, pdev: vk.PhysicalDevice, props: vk.PhysicalDeviceProperties, mem_props: vk.PhysicalDeviceMemoryProperties, - dev: vk.Device, + dev: Device, graphics_queue: Queue, present_queue: Queue, pub fn init(allocator: Allocator, app_name: [*:0]const u8, window: *c.GLFWwindow) !GraphicsContext { var self: GraphicsContext = undefined; + self.allocator = allocator; self.vkb = try BaseDispatch.load(c.glfwGetInstanceProcAddress); var glfw_exts_count: u32 = 0; @@ -57,37 +64,49 @@ pub const GraphicsContext = struct { .api_version = vk.API_VERSION_1_2, }; - self.instance = try self.vkb.createInstance(&.{ + const 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)), + .pp_enabled_extension_names = @ptrCast(glfw_exts), }, null); - self.vki = try InstanceDispatch.load(self.instance, self.vkb.dispatch.vkGetInstanceProcAddr); - errdefer self.vki.destroyInstance(self.instance, null); + const vki = try allocator.create(InstanceDispatch); + errdefer allocator.destroy(vki); + vki.* = try InstanceDispatch.load(instance, self.vkb.dispatch.vkGetInstanceProcAddr); + self.instance = Instance.init(instance, vki); + errdefer self.instance.destroyInstance(null); self.surface = try createSurface(self.instance, window); - errdefer self.vki.destroySurfaceKHR(self.instance, self.surface, null); + errdefer self.instance.destroySurfaceKHR(self.surface, null); - const candidate = try pickPhysicalDevice(self.vki, self.instance, allocator, self.surface); + const candidate = try pickPhysicalDevice(self.instance, allocator, self.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); - 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); + const dev = try initializeCandidate(self.instance, candidate); - self.mem_props = self.vki.getPhysicalDeviceMemoryProperties(self.pdev); + const vkd = try allocator.create(DeviceDispatch); + errdefer allocator.destroy(vkd); + vkd.* = try DeviceDispatch.load(dev, self.instance.wrapper.dispatch.vkGetDeviceProcAddr); + self.dev = Device.init(dev, vkd); + errdefer self.dev.destroyDevice(null); + + self.graphics_queue = Queue.init(self.dev, candidate.queues.graphics_family); + self.present_queue = Queue.init(self.dev, candidate.queues.present_family); + + self.mem_props = self.instance.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); + self.dev.destroyDevice(null); + self.instance.destroySurfaceKHR(self.surface, null); + self.instance.destroyInstance(null); + + // Don't forget to free the tables to prevent a memory leak. + self.allocator.destroy(self.dev.wrapper); + self.allocator.destroy(self.instance.wrapper); } pub fn deviceName(self: *const GraphicsContext) []const u8 { @@ -105,7 +124,7 @@ pub const GraphicsContext = struct { } pub fn allocate(self: GraphicsContext, requirements: vk.MemoryRequirements, flags: vk.MemoryPropertyFlags) !vk.DeviceMemory { - return try self.vkd.allocateMemory(self.dev, &.{ + return try self.dev.allocateMemory(&.{ .allocation_size = requirements.size, .memory_type_index = try self.findMemoryTypeIndex(requirements.memory_type_bits, flags), }, null); @@ -116,24 +135,24 @@ pub const Queue = struct { handle: vk.Queue, family: u32, - fn init(vkd: DeviceDispatch, dev: vk.Device, family: u32) Queue { + fn init(device: Device, family: u32) Queue { return .{ - .handle = vkd.getDeviceQueue(dev, family, 0), + .handle = device.getDeviceQueue(family, 0), .family = family, }; } }; -fn createSurface(instance: vk.Instance, window: *c.GLFWwindow) !vk.SurfaceKHR { +fn createSurface(instance: Instance, window: *c.GLFWwindow) !vk.SurfaceKHR { var surface: vk.SurfaceKHR = undefined; - if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) { + if (c.glfwCreateWindowSurface(instance.handle, window, null, &surface) != .success) { return error.SurfaceInitFailed; } return surface; } -fn initializeCandidate(vki: InstanceDispatch, candidate: DeviceCandidate) !vk.Device { +fn initializeCandidate(instance: Instance, candidate: DeviceCandidate) !vk.Device { const priority = [_]f32{1}; const qci = [_]vk.DeviceQueueCreateInfo{ .{ @@ -153,11 +172,11 @@ fn initializeCandidate(vki: InstanceDispatch, candidate: DeviceCandidate) !vk.De else 2; - return try vki.createDevice(candidate.pdev, &.{ + return try instance.createDevice(candidate.pdev, &.{ .queue_create_info_count = queue_count, .p_queue_create_infos = &qci, .enabled_extension_count = required_device_extensions.len, - .pp_enabled_extension_names = @as([*]const [*:0]const u8, @ptrCast(&required_device_extensions)), + .pp_enabled_extension_names = @ptrCast(&required_device_extensions), }, null); } @@ -173,21 +192,20 @@ const QueueAllocation = struct { }; fn pickPhysicalDevice( - vki: InstanceDispatch, - instance: vk.Instance, + instance: Instance, allocator: Allocator, surface: vk.SurfaceKHR, ) !DeviceCandidate { var device_count: u32 = undefined; - _ = try vki.enumeratePhysicalDevices(instance, &device_count, null); + _ = try instance.enumeratePhysicalDevices(&device_count, null); const pdevs = try allocator.alloc(vk.PhysicalDevice, device_count); defer allocator.free(pdevs); - _ = try vki.enumeratePhysicalDevices(instance, &device_count, pdevs.ptr); + _ = try instance.enumeratePhysicalDevices(&device_count, pdevs.ptr); for (pdevs) |pdev| { - if (try checkSuitable(vki, pdev, allocator, surface)) |candidate| { + if (try checkSuitable(instance, pdev, allocator, surface)) |candidate| { return candidate; } } @@ -196,22 +214,21 @@ fn pickPhysicalDevice( } fn checkSuitable( - vki: InstanceDispatch, + instance: Instance, pdev: vk.PhysicalDevice, allocator: Allocator, surface: vk.SurfaceKHR, ) !?DeviceCandidate { - const props = vki.getPhysicalDeviceProperties(pdev); - - if (!try checkExtensionSupport(vki, pdev, allocator)) { + if (!try checkExtensionSupport(instance, pdev, allocator)) { return null; } - if (!try checkSurfaceSupport(vki, pdev, surface)) { + if (!try checkSurfaceSupport(instance, pdev, surface)) { return null; } - if (try allocateQueues(vki, pdev, allocator, surface)) |allocation| { + if (try allocateQueues(instance, pdev, allocator, surface)) |allocation| { + const props = instance.getPhysicalDeviceProperties(pdev); return DeviceCandidate{ .pdev = pdev, .props = props, @@ -222,13 +239,13 @@ fn checkSuitable( return null; } -fn allocateQueues(vki: InstanceDispatch, pdev: vk.PhysicalDevice, allocator: Allocator, surface: vk.SurfaceKHR) !?QueueAllocation { +fn allocateQueues(instance: Instance, pdev: vk.PhysicalDevice, allocator: Allocator, surface: vk.SurfaceKHR) !?QueueAllocation { var family_count: u32 = undefined; - vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null); + instance.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null); const families = try allocator.alloc(vk.QueueFamilyProperties, family_count); defer allocator.free(families); - vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, families.ptr); + instance.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, families.ptr); var graphics_family: ?u32 = null; var present_family: ?u32 = null; @@ -240,7 +257,7 @@ fn allocateQueues(vki: InstanceDispatch, pdev: vk.PhysicalDevice, allocator: All graphics_family = family; } - if (present_family == null and (try vki.getPhysicalDeviceSurfaceSupportKHR(pdev, family, surface)) == vk.TRUE) { + if (present_family == null and (try instance.getPhysicalDeviceSurfaceSupportKHR(pdev, family, surface)) == vk.TRUE) { present_family = family; } } @@ -255,28 +272,28 @@ fn allocateQueues(vki: InstanceDispatch, pdev: vk.PhysicalDevice, allocator: All return null; } -fn checkSurfaceSupport(vki: InstanceDispatch, pdev: vk.PhysicalDevice, surface: vk.SurfaceKHR) !bool { +fn checkSurfaceSupport(instance: Instance, pdev: vk.PhysicalDevice, surface: vk.SurfaceKHR) !bool { var format_count: u32 = undefined; - _ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &format_count, null); + _ = try instance.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &format_count, null); var present_mode_count: u32 = undefined; - _ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &present_mode_count, null); + _ = try instance.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &present_mode_count, null); return format_count > 0 and present_mode_count > 0; } fn checkExtensionSupport( - vki: InstanceDispatch, + instance: Instance, pdev: vk.PhysicalDevice, allocator: Allocator, ) !bool { var count: u32 = undefined; - _ = try vki.enumerateDeviceExtensionProperties(pdev, null, &count, null); + _ = try instance.enumerateDeviceExtensionProperties(pdev, null, &count, null); const propsv = try allocator.alloc(vk.ExtensionProperties, count); defer allocator.free(propsv); - _ = try vki.enumerateDeviceExtensionProperties(pdev, null, &count, propsv.ptr); + _ = try instance.enumerateDeviceExtensionProperties(pdev, null, &count, propsv.ptr); for (required_device_extensions) |ext| { for (propsv) |props| { diff --git a/examples/swapchain.zig b/examples/swapchain.zig index fc2972c..1439692 100644 --- a/examples/swapchain.zig +++ b/examples/swapchain.zig @@ -26,7 +26,7 @@ pub const Swapchain = struct { } pub fn initRecycle(gc: *const GraphicsContext, allocator: Allocator, extent: vk.Extent2D, old_handle: vk.SwapchainKHR) !Swapchain { - const caps = try gc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(gc.pdev, gc.surface); + const caps = try gc.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(gc.pdev, gc.surface); const actual_extent = findActualExtent(caps, extent); if (actual_extent.width == 0 or actual_extent.height == 0) { return error.InvalidSurfaceDimensions; @@ -46,7 +46,7 @@ pub const Swapchain = struct { else .exclusive; - const handle = try gc.vkd.createSwapchainKHR(gc.dev, &.{ + const handle = try gc.dev.createSwapchainKHR(&.{ .surface = gc.surface, .min_image_count = image_count, .image_format = surface_format.format, @@ -63,11 +63,11 @@ pub const Swapchain = struct { .clipped = vk.TRUE, .old_swapchain = old_handle, }, null); - errdefer gc.vkd.destroySwapchainKHR(gc.dev, handle, null); + errdefer gc.dev.destroySwapchainKHR(handle, null); if (old_handle != .null_handle) { // Apparently, the old swapchain handle still needs to be destroyed after recreating. - gc.vkd.destroySwapchainKHR(gc.dev, old_handle, null); + gc.dev.destroySwapchainKHR(old_handle, null); } const swap_images = try initSwapchainImages(gc, handle, surface_format.format, allocator); @@ -76,10 +76,10 @@ pub const Swapchain = struct { allocator.free(swap_images); } - var next_image_acquired = try gc.vkd.createSemaphore(gc.dev, &.{}, null); - errdefer gc.vkd.destroySemaphore(gc.dev, next_image_acquired, null); + var next_image_acquired = try gc.dev.createSemaphore(&.{}, null); + errdefer gc.dev.destroySemaphore(next_image_acquired, null); - const result = try gc.vkd.acquireNextImageKHR(gc.dev, handle, std.math.maxInt(u64), next_image_acquired, .null_handle); + const result = try gc.dev.acquireNextImageKHR(handle, std.math.maxInt(u64), next_image_acquired, .null_handle); if (result.result != .success) { return error.ImageAcquireFailed; } @@ -101,7 +101,7 @@ pub const Swapchain = struct { fn deinitExceptSwapchain(self: Swapchain) void { for (self.swap_images) |si| si.deinit(self.gc); self.allocator.free(self.swap_images); - self.gc.vkd.destroySemaphore(self.gc.dev, self.next_image_acquired, null); + self.gc.dev.destroySemaphore(self.next_image_acquired, null); } pub fn waitForAllFences(self: Swapchain) !void { @@ -110,7 +110,7 @@ pub const Swapchain = struct { pub fn deinit(self: Swapchain) void { self.deinitExceptSwapchain(); - self.gc.vkd.destroySwapchainKHR(self.gc.dev, self.handle, null); + self.gc.dev.destroySwapchainKHR(self.handle, null); } pub fn recreate(self: *Swapchain, new_extent: vk.Extent2D) !void { @@ -150,11 +150,11 @@ pub const Swapchain = struct { // Step 1: Make sure the current frame has finished rendering const current = self.currentSwapImage(); try current.waitForFence(self.gc); - try self.gc.vkd.resetFences(self.gc.dev, 1, @ptrCast(¤t.frame_fence)); + try self.gc.dev.resetFences(1, @ptrCast(¤t.frame_fence)); // Step 2: Submit the command buffer const wait_stage = [_]vk.PipelineStageFlags{.{ .top_of_pipe_bit = true }}; - try self.gc.vkd.queueSubmit(self.gc.graphics_queue.handle, 1, &[_]vk.SubmitInfo{.{ + try self.gc.dev.queueSubmit(self.gc.graphics_queue.handle, 1, &[_]vk.SubmitInfo{.{ .wait_semaphore_count = 1, .p_wait_semaphores = @ptrCast(¤t.image_acquired), .p_wait_dst_stage_mask = &wait_stage, @@ -165,17 +165,16 @@ pub const Swapchain = struct { }}, current.frame_fence); // Step 3: Present the current frame - _ = try self.gc.vkd.queuePresentKHR(self.gc.present_queue.handle, &.{ + _ = try self.gc.dev.queuePresentKHR(self.gc.present_queue.handle, &.{ .wait_semaphore_count = 1, - .p_wait_semaphores = @as([*]const vk.Semaphore, @ptrCast(¤t.render_finished)), + .p_wait_semaphores = @ptrCast(¤t.render_finished), .swapchain_count = 1, - .p_swapchains = @as([*]const vk.SwapchainKHR, @ptrCast(&self.handle)), - .p_image_indices = @as([*]const u32, @ptrCast(&self.image_index)), + .p_swapchains = @ptrCast(&self.handle), + .p_image_indices = @ptrCast(&self.image_index), }); // Step 4: Acquire next frame - const result = try self.gc.vkd.acquireNextImageKHR( - self.gc.dev, + const result = try self.gc.dev.acquireNextImageKHR( self.handle, std.math.maxInt(u64), self.next_image_acquired, @@ -201,7 +200,7 @@ const SwapImage = struct { frame_fence: vk.Fence, fn init(gc: *const GraphicsContext, image: vk.Image, format: vk.Format) !SwapImage { - const view = try gc.vkd.createImageView(gc.dev, &.{ + const view = try gc.dev.createImageView(&.{ .image = image, .view_type = .@"2d", .format = format, @@ -214,16 +213,16 @@ const SwapImage = struct { .layer_count = 1, }, }, null); - errdefer gc.vkd.destroyImageView(gc.dev, view, null); + errdefer gc.dev.destroyImageView(view, null); - const image_acquired = try gc.vkd.createSemaphore(gc.dev, &.{}, null); - errdefer gc.vkd.destroySemaphore(gc.dev, image_acquired, null); + const image_acquired = try gc.dev.createSemaphore(&.{}, null); + errdefer gc.dev.destroySemaphore(image_acquired, null); - const render_finished = try gc.vkd.createSemaphore(gc.dev, &.{}, null); - errdefer gc.vkd.destroySemaphore(gc.dev, render_finished, null); + const render_finished = try gc.dev.createSemaphore(&.{}, null); + errdefer gc.dev.destroySemaphore(render_finished, null); - const frame_fence = try gc.vkd.createFence(gc.dev, &.{ .flags = .{ .signaled_bit = true } }, null); - errdefer gc.vkd.destroyFence(gc.dev, frame_fence, null); + const frame_fence = try gc.dev.createFence(&.{ .flags = .{ .signaled_bit = true } }, null); + errdefer gc.dev.destroyFence(frame_fence, null); return SwapImage{ .image = image, @@ -236,23 +235,23 @@ const SwapImage = struct { fn deinit(self: SwapImage, gc: *const GraphicsContext) void { self.waitForFence(gc) catch return; - gc.vkd.destroyImageView(gc.dev, self.view, null); - gc.vkd.destroySemaphore(gc.dev, self.image_acquired, null); - gc.vkd.destroySemaphore(gc.dev, self.render_finished, null); - gc.vkd.destroyFence(gc.dev, self.frame_fence, null); + gc.dev.destroyImageView(self.view, null); + gc.dev.destroySemaphore(self.image_acquired, null); + gc.dev.destroySemaphore(self.render_finished, null); + gc.dev.destroyFence(self.frame_fence, null); } fn waitForFence(self: SwapImage, gc: *const GraphicsContext) !void { - _ = try gc.vkd.waitForFences(gc.dev, 1, @ptrCast(&self.frame_fence), vk.TRUE, std.math.maxInt(u64)); + _ = try gc.dev.waitForFences(1, @ptrCast(&self.frame_fence), vk.TRUE, std.math.maxInt(u64)); } }; fn initSwapchainImages(gc: *const GraphicsContext, swapchain: vk.SwapchainKHR, format: vk.Format, allocator: Allocator) ![]SwapImage { var count: u32 = undefined; - _ = try gc.vkd.getSwapchainImagesKHR(gc.dev, swapchain, &count, null); + _ = try gc.dev.getSwapchainImagesKHR(swapchain, &count, null); const images = try allocator.alloc(vk.Image, count); defer allocator.free(images); - _ = try gc.vkd.getSwapchainImagesKHR(gc.dev, swapchain, &count, images.ptr); + _ = try gc.dev.getSwapchainImagesKHR(swapchain, &count, images.ptr); const swap_images = try allocator.alloc(SwapImage, count); errdefer allocator.free(swap_images); @@ -275,10 +274,10 @@ fn findSurfaceFormat(gc: *const GraphicsContext, allocator: Allocator) !vk.Surfa }; var count: u32 = undefined; - _ = try gc.vki.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, null); + _ = try gc.instance.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, null); const surface_formats = try allocator.alloc(vk.SurfaceFormatKHR, count); defer allocator.free(surface_formats); - _ = try gc.vki.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, surface_formats.ptr); + _ = try gc.instance.getPhysicalDeviceSurfaceFormatsKHR(gc.pdev, gc.surface, &count, surface_formats.ptr); for (surface_formats) |sfmt| { if (std.meta.eql(sfmt, preferred)) { @@ -291,10 +290,10 @@ fn findSurfaceFormat(gc: *const GraphicsContext, allocator: Allocator) !vk.Surfa fn findPresentMode(gc: *const GraphicsContext, allocator: Allocator) !vk.PresentModeKHR { var count: u32 = undefined; - _ = try gc.vki.getPhysicalDeviceSurfacePresentModesKHR(gc.pdev, gc.surface, &count, null); + _ = try gc.instance.getPhysicalDeviceSurfacePresentModesKHR(gc.pdev, gc.surface, &count, null); const present_modes = try allocator.alloc(vk.PresentModeKHR, count); defer allocator.free(present_modes); - _ = try gc.vki.getPhysicalDeviceSurfacePresentModesKHR(gc.pdev, gc.surface, &count, present_modes.ptr); + _ = try gc.instance.getPhysicalDeviceSurfacePresentModesKHR(gc.pdev, gc.surface, &count, present_modes.ptr); const preferred = [_]vk.PresentModeKHR{ .mailbox_khr, diff --git a/examples/triangle.zig b/examples/triangle.zig index 11aff8d..60702b0 100644 --- a/examples/triangle.zig +++ b/examples/triangle.zig @@ -73,39 +73,39 @@ pub fn main() !void { var swapchain = try Swapchain.init(&gc, allocator, extent); defer swapchain.deinit(); - const pipeline_layout = try gc.vkd.createPipelineLayout(gc.dev, &.{ + const pipeline_layout = try gc.dev.createPipelineLayout(&.{ .flags = .{}, .set_layout_count = 0, .p_set_layouts = undefined, .push_constant_range_count = 0, .p_push_constant_ranges = undefined, }, null); - defer gc.vkd.destroyPipelineLayout(gc.dev, pipeline_layout, null); + defer gc.dev.destroyPipelineLayout(pipeline_layout, null); const render_pass = try createRenderPass(&gc, swapchain); - defer gc.vkd.destroyRenderPass(gc.dev, render_pass, null); + defer gc.dev.destroyRenderPass(render_pass, null); const pipeline = try createPipeline(&gc, pipeline_layout, render_pass); - defer gc.vkd.destroyPipeline(gc.dev, pipeline, null); + defer gc.dev.destroyPipeline(pipeline, null); var framebuffers = try createFramebuffers(&gc, allocator, render_pass, swapchain); defer destroyFramebuffers(&gc, allocator, framebuffers); - const pool = try gc.vkd.createCommandPool(gc.dev, &.{ + const pool = try gc.dev.createCommandPool(&.{ .queue_family_index = gc.graphics_queue.family, }, null); - defer gc.vkd.destroyCommandPool(gc.dev, pool, null); + defer gc.dev.destroyCommandPool(pool, null); - const buffer = try gc.vkd.createBuffer(gc.dev, &.{ + const buffer = try gc.dev.createBuffer(&.{ .size = @sizeOf(@TypeOf(vertices)), .usage = .{ .transfer_dst_bit = true, .vertex_buffer_bit = true }, .sharing_mode = .exclusive, }, null); - defer gc.vkd.destroyBuffer(gc.dev, buffer, null); - const mem_reqs = gc.vkd.getBufferMemoryRequirements(gc.dev, buffer); + defer gc.dev.destroyBuffer(buffer, null); + const mem_reqs = gc.dev.getBufferMemoryRequirements(buffer); const memory = try gc.allocate(mem_reqs, .{ .device_local_bit = true }); - defer gc.vkd.freeMemory(gc.dev, memory, null); - try gc.vkd.bindBufferMemory(gc.dev, buffer, memory, 0); + defer gc.dev.freeMemory(memory, null); + try gc.dev.bindBufferMemory(buffer, memory, 0); try uploadVertices(&gc, pool, buffer); @@ -164,24 +164,24 @@ pub fn main() !void { } try swapchain.waitForAllFences(); - try gc.vkd.deviceWaitIdle(gc.dev); + try gc.dev.deviceWaitIdle(); } fn uploadVertices(gc: *const GraphicsContext, pool: vk.CommandPool, buffer: vk.Buffer) !void { - const staging_buffer = try gc.vkd.createBuffer(gc.dev, &.{ + const staging_buffer = try gc.dev.createBuffer(&.{ .size = @sizeOf(@TypeOf(vertices)), .usage = .{ .transfer_src_bit = true }, .sharing_mode = .exclusive, }, null); - defer gc.vkd.destroyBuffer(gc.dev, staging_buffer, null); - const mem_reqs = gc.vkd.getBufferMemoryRequirements(gc.dev, staging_buffer); + defer gc.dev.destroyBuffer(staging_buffer, null); + const mem_reqs = gc.dev.getBufferMemoryRequirements(staging_buffer); const staging_memory = try gc.allocate(mem_reqs, .{ .host_visible_bit = true, .host_coherent_bit = true }); - defer gc.vkd.freeMemory(gc.dev, staging_memory, null); - try gc.vkd.bindBufferMemory(gc.dev, staging_buffer, staging_memory, 0); + defer gc.dev.freeMemory(staging_memory, null); + try gc.dev.bindBufferMemory(staging_buffer, staging_memory, 0); { - const data = try gc.vkd.mapMemory(gc.dev, staging_memory, 0, vk.WHOLE_SIZE, .{}); - defer gc.vkd.unmapMemory(gc.dev, staging_memory); + const data = try gc.dev.mapMemory(staging_memory, 0, vk.WHOLE_SIZE, .{}); + defer gc.dev.unmapMemory(staging_memory); const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(data)); @memcpy(gpu_vertices, vertices[0..]); @@ -191,15 +191,17 @@ fn uploadVertices(gc: *const GraphicsContext, pool: vk.CommandPool, buffer: vk.B } fn copyBuffer(gc: *const GraphicsContext, pool: vk.CommandPool, dst: vk.Buffer, src: vk.Buffer, size: vk.DeviceSize) !void { - var cmdbuf: vk.CommandBuffer = undefined; - try gc.vkd.allocateCommandBuffers(gc.dev, &.{ + var cmdbuf_handle: vk.CommandBuffer = undefined; + try gc.dev.allocateCommandBuffers(&.{ .command_pool = pool, .level = .primary, .command_buffer_count = 1, - }, @ptrCast(&cmdbuf)); - defer gc.vkd.freeCommandBuffers(gc.dev, pool, 1, @ptrCast(&cmdbuf)); + }, @ptrCast(&cmdbuf_handle)); + defer gc.dev.freeCommandBuffers(pool, 1, @ptrCast(&cmdbuf_handle)); - try gc.vkd.beginCommandBuffer(cmdbuf, &.{ + const cmdbuf = GraphicsContext.CommandBuffer.init(cmdbuf_handle, gc.dev.wrapper); + + try cmdbuf.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true }, }); @@ -208,17 +210,17 @@ fn copyBuffer(gc: *const GraphicsContext, pool: vk.CommandPool, dst: vk.Buffer, .dst_offset = 0, .size = size, }; - gc.vkd.cmdCopyBuffer(cmdbuf, src, dst, 1, @ptrCast(®ion)); + cmdbuf.copyBuffer(src, dst, 1, @ptrCast(®ion)); - try gc.vkd.endCommandBuffer(cmdbuf); + try cmdbuf.endCommandBuffer(); const si = vk.SubmitInfo{ .command_buffer_count = 1, - .p_command_buffers = @ptrCast(&cmdbuf), + .p_command_buffers = (&cmdbuf.handle)[0..1], .p_wait_dst_stage_mask = undefined, }; - try gc.vkd.queueSubmit(gc.graphics_queue.handle, 1, @ptrCast(&si), .null_handle); - try gc.vkd.queueWaitIdle(gc.graphics_queue.handle); + try gc.dev.queueSubmit(gc.graphics_queue.handle, 1, @ptrCast(&si), .null_handle); + try gc.dev.queueWaitIdle(gc.graphics_queue.handle); } fn createCommandBuffers( @@ -234,12 +236,12 @@ fn createCommandBuffers( const cmdbufs = try allocator.alloc(vk.CommandBuffer, framebuffers.len); errdefer allocator.free(cmdbufs); - try gc.vkd.allocateCommandBuffers(gc.dev, &.{ + try gc.dev.allocateCommandBuffers(&.{ .command_pool = pool, .level = .primary, - .command_buffer_count = @as(u32, @truncate(cmdbufs.len)), + .command_buffer_count = @intCast(cmdbufs.len), }, cmdbufs.ptr); - errdefer gc.vkd.freeCommandBuffers(gc.dev, pool, @truncate(cmdbufs.len), cmdbufs.ptr); + errdefer gc.dev.freeCommandBuffers(pool, @intCast(cmdbufs.len), cmdbufs.ptr); const clear = vk.ClearValue{ .color = .{ .float_32 = .{ 0, 0, 0, 1 } }, @@ -248,8 +250,8 @@ fn createCommandBuffers( const viewport = vk.Viewport{ .x = 0, .y = 0, - .width = @as(f32, @floatFromInt(extent.width)), - .height = @as(f32, @floatFromInt(extent.height)), + .width = @floatFromInt(extent.width), + .height = @floatFromInt(extent.height), .min_depth = 0, .max_depth = 1, }; @@ -260,10 +262,10 @@ fn createCommandBuffers( }; for (cmdbufs, framebuffers) |cmdbuf, framebuffer| { - try gc.vkd.beginCommandBuffer(cmdbuf, &.{}); + try gc.dev.beginCommandBuffer(cmdbuf, &.{}); - gc.vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport)); - gc.vkd.cmdSetScissor(cmdbuf, 0, 1, @ptrCast(&scissor)); + gc.dev.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport)); + gc.dev.cmdSetScissor(cmdbuf, 0, 1, @ptrCast(&scissor)); // This needs to be a separate definition - see https://github.com/ziglang/zig/issues/7627. const render_area = vk.Rect2D{ @@ -271,28 +273,28 @@ fn createCommandBuffers( .extent = extent, }; - gc.vkd.cmdBeginRenderPass(cmdbuf, &.{ + gc.dev.cmdBeginRenderPass(cmdbuf, &.{ .render_pass = render_pass, .framebuffer = framebuffer, .render_area = render_area, .clear_value_count = 1, - .p_clear_values = @as([*]const vk.ClearValue, @ptrCast(&clear)), + .p_clear_values = @ptrCast(&clear), }, .@"inline"); - gc.vkd.cmdBindPipeline(cmdbuf, .graphics, pipeline); + gc.dev.cmdBindPipeline(cmdbuf, .graphics, pipeline); const offset = [_]vk.DeviceSize{0}; - gc.vkd.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&buffer), &offset); - gc.vkd.cmdDraw(cmdbuf, vertices.len, 1, 0, 0); + gc.dev.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&buffer), &offset); + gc.dev.cmdDraw(cmdbuf, vertices.len, 1, 0, 0); - gc.vkd.cmdEndRenderPass(cmdbuf); - try gc.vkd.endCommandBuffer(cmdbuf); + gc.dev.cmdEndRenderPass(cmdbuf); + try gc.dev.endCommandBuffer(cmdbuf); } return cmdbufs; } fn destroyCommandBuffers(gc: *const GraphicsContext, pool: vk.CommandPool, allocator: Allocator, cmdbufs: []vk.CommandBuffer) void { - gc.vkd.freeCommandBuffers(gc.dev, pool, @truncate(cmdbufs.len), cmdbufs.ptr); + gc.dev.freeCommandBuffers(pool, @truncate(cmdbufs.len), cmdbufs.ptr); allocator.free(cmdbufs); } @@ -301,13 +303,13 @@ fn createFramebuffers(gc: *const GraphicsContext, allocator: Allocator, render_p errdefer allocator.free(framebuffers); var i: usize = 0; - errdefer for (framebuffers[0..i]) |fb| gc.vkd.destroyFramebuffer(gc.dev, fb, null); + errdefer for (framebuffers[0..i]) |fb| gc.dev.destroyFramebuffer(fb, null); for (framebuffers) |*fb| { - fb.* = try gc.vkd.createFramebuffer(gc.dev, &.{ + fb.* = try gc.dev.createFramebuffer(&.{ .render_pass = render_pass, .attachment_count = 1, - .p_attachments = @as([*]const vk.ImageView, @ptrCast(&swapchain.swap_images[i].view)), + .p_attachments = @ptrCast(&swapchain.swap_images[i].view), .width = swapchain.extent.width, .height = swapchain.extent.height, .layers = 1, @@ -319,7 +321,7 @@ fn createFramebuffers(gc: *const GraphicsContext, allocator: Allocator, render_p } fn destroyFramebuffers(gc: *const GraphicsContext, allocator: Allocator, framebuffers: []const vk.Framebuffer) void { - for (framebuffers) |fb| gc.vkd.destroyFramebuffer(gc.dev, fb, null); + for (framebuffers) |fb| gc.dev.destroyFramebuffer(fb, null); allocator.free(framebuffers); } @@ -346,11 +348,11 @@ fn createRenderPass(gc: *const GraphicsContext, swapchain: Swapchain) !vk.Render .p_color_attachments = @ptrCast(&color_attachment_ref), }; - return try gc.vkd.createRenderPass(gc.dev, &.{ + return try gc.dev.createRenderPass(&.{ .attachment_count = 1, - .p_attachments = @as([*]const vk.AttachmentDescription, @ptrCast(&color_attachment)), + .p_attachments = @ptrCast(&color_attachment), .subpass_count = 1, - .p_subpasses = @as([*]const vk.SubpassDescription, @ptrCast(&subpass)), + .p_subpasses = @ptrCast(&subpass), }, null); } @@ -359,17 +361,17 @@ fn createPipeline( layout: vk.PipelineLayout, render_pass: vk.RenderPass, ) !vk.Pipeline { - const vert = try gc.vkd.createShaderModule(gc.dev, &.{ + const vert = try gc.dev.createShaderModule(&.{ .code_size = shaders.triangle_vert.len, - .p_code = @as([*]const u32, @ptrCast(&shaders.triangle_vert)), + .p_code = @ptrCast(&shaders.triangle_vert), }, null); - defer gc.vkd.destroyShaderModule(gc.dev, vert, null); + defer gc.dev.destroyShaderModule(vert, null); - const frag = try gc.vkd.createShaderModule(gc.dev, &.{ + const frag = try gc.dev.createShaderModule(&.{ .code_size = shaders.triangle_frag.len, - .p_code = @as([*]const u32, @ptrCast(&shaders.triangle_frag)), + .p_code = @ptrCast(&shaders.triangle_frag), }, null); - defer gc.vkd.destroyShaderModule(gc.dev, frag, null); + defer gc.dev.destroyShaderModule(frag, null); const pssci = [_]vk.PipelineShaderStageCreateInfo{ .{ @@ -471,8 +473,7 @@ fn createPipeline( }; var pipeline: vk.Pipeline = undefined; - _ = try gc.vkd.createGraphicsPipelines( - gc.dev, + _ = try gc.dev.createGraphicsPipelines( .null_handle, 1, @ptrCast(&gpci),