diff --git a/src/utilities.zig b/src/utilities.zig index a8c9969..ae96b47 100644 --- a/src/utilities.zig +++ b/src/utilities.zig @@ -17,3 +17,8 @@ pub const SwapchainDetails = struct { formats: []vk.SurfaceFormatKHR, presentation_modes: []vk.PresentModeKHR, }; + +pub const SwapchainImage = struct { + image: vk.Image, + image_view: vk.ImageView, +}; diff --git a/src/vulkan_renderer.zig b/src/vulkan_renderer.zig index 6789026..72fff8a 100644 --- a/src/vulkan_renderer.zig +++ b/src/vulkan_renderer.zig @@ -2,9 +2,11 @@ const std = @import("std"); const sdl = @import("sdl2"); const vk = @import("vulkan"); const builtin = @import("builtin"); + const Utilities = @import("utilities.zig"); const QueueFamilyIndices = Utilities.QueueFamilyIndices; const SwapchainDetails = Utilities.SwapchainDetails; +const SwapchainImage = Utilities.SwapchainImage; const enable_validation_layers = builtin.mode == .Debug; const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"}; @@ -36,16 +38,19 @@ pub const VulkanRenderer = struct { window: sdl.Window, + // Main instance: Instance, physical_device: vk.PhysicalDevice, device: Device, - graphics_queue: Queue, presentation_queue: Queue, - surface: vk.SurfaceKHR, - swapchain: vk.SwapchainKHR, + swapchain_images: []SwapchainImage, + + // Utilities + swapchain_image_format: vk.Format, + extent: vk.Extent2D, debug_utils: ?vk.DebugUtilsMessengerEXT, @@ -65,7 +70,7 @@ pub const VulkanRenderer = struct { try self.getPhysicalDevice(); try self.createLogicalDevice(); - try self.createSwapChain(); + try self.createSwapchain(); return self; } @@ -166,7 +171,7 @@ pub const VulkanRenderer = struct { self.presentation_queue = Queue.init(queues[1], self.device.wrapper); } - fn createSwapChain(self: *Self) !void { + fn createSwapchain(self: *Self) !void { const swapchain_details = try self.getSwapchainDetails(self.physical_device); defer self.allocator.free(swapchain_details.formats); defer self.allocator.free(swapchain_details.presentation_modes); @@ -221,6 +226,26 @@ pub const VulkanRenderer = struct { } self.swapchain = try self.device.createSwapchainKHR(&swapchain_create_info, null); + self.swapchain_image_format = surface_format.format; + self.extent = extent; + + // Swapchain images + var swapchain_image_count: u32 = 0; + _ = try self.device.getSwapchainImagesKHR(self.swapchain, &swapchain_image_count, null); + + const images = try self.allocator.alloc(vk.Image, swapchain_image_count); + defer self.allocator.free(images); + + _ = try self.device.getSwapchainImagesKHR(self.swapchain, &swapchain_image_count, images.ptr); + + self.swapchain_images = try self.allocator.alloc(SwapchainImage, swapchain_image_count); + + for (images, 0..) |image, i| { + self.swapchain_images[i] = .{ + .image = image, + .image_view = try self.createImageView(image, self.swapchain_image_format, .{ .color_bit = true }), + }; + } } fn getPhysicalDevice(self: *Self) !void { @@ -235,12 +260,12 @@ pub const VulkanRenderer = struct { for (pdevs) |pdev| { if (self.checkDeviceSuitable(pdev)) { self.physical_device = pdev; - return; + break; } + } else { + // TODO Obviously needs to be something else + unreachable; } - - // TODO Obviously needs to be something else - unreachable; } fn getRequiredExtensions(self: Self) ![][*:0]const u8 { @@ -410,10 +435,40 @@ pub const VulkanRenderer = struct { }; } + fn createImageView(self: Self, image: vk.Image, format: vk.Format, aspect_flags: vk.ImageAspectFlags) !vk.ImageView { + const image_view_create_info: vk.ImageViewCreateInfo = .{ + .image = image, + .format = format, + .view_type = .@"2d", + .components = .{ + // Used for remapping rgba values to other rgba values + .r = .identity, + .g = .identity, + .b = .identity, + .a = .identity, + }, + .subresource_range = .{ + .aspect_mask = aspect_flags, // Which aspect of image to view (e.g.: colour, depth, stencil, etc...) + .base_mip_level = 0, // Start mipmap level to view from + .level_count = 1, // Number of mipmap levels to view + .base_array_layer = 0, // Start array level to view from + .layer_count = 1, // Number of array levels to view + }, + }; + + return try self.device.createImageView(&image_view_create_info, null); + } + pub fn deinit(self: *Self) void { if (enable_validation_layers) { self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null); } + + for (self.swapchain_images) |swapchain_image| { + self.device.destroyImageView(swapchain_image.image_view, null); + } + + self.allocator.free(self.swapchain_images); self.device.destroySwapchainKHR(self.swapchain, null); self.device.destroyDevice(null); self.instance.destroySurfaceKHR(self.surface, null);