Continue refactor

This commit is contained in:
Przemyslaw Gasinski 2024-10-26 12:52:51 +02:00
parent 34135fa83e
commit 525fe1cc25
7 changed files with 96 additions and 109 deletions

View file

@ -5,7 +5,7 @@ const vk = @import("vulkan");
const sdl = @import("sdl"); const sdl = @import("sdl");
const img = @import("zstbi"); const img = @import("zstbi");
const validation = @import("./validation_layers.zig"); const validation = @import("validation_layers.zig");
const Swapchain = @import("Swapchain.zig"); const Swapchain = @import("Swapchain.zig");
const QueueUtils = @import("queue_utils.zig"); const QueueUtils = @import("queue_utils.zig");
@ -46,9 +46,11 @@ instance: Instance,
physical_device: vk.PhysicalDevice, physical_device: vk.PhysicalDevice,
device: Device, device: Device,
command_pool: vk.CommandPool,
graphics_queue: Queue, graphics_queue: Queue,
presentation_queue: Queue, presentation_queue: Queue,
surface: vk.SurfaceKHR, surface: vk.SurfaceKHR,
swapchain: Swapchain,
debug_utils: ?vk.DebugUtilsMessengerEXT, debug_utils: ?vk.DebugUtilsMessengerEXT,
@ -71,6 +73,7 @@ pub fn init(allocator: std.mem.Allocator, window: sdl.Window) !Self {
try self.getPhysicalDevice(); try self.getPhysicalDevice();
try self.createLogicalDevice(); try self.createLogicalDevice();
self.swapchain = try Swapchain.create(allocator, self);
return self; return self;
} }
@ -212,6 +215,20 @@ fn createLogicalDevice(self: *Self) !void {
self.presentation_queue = Queue.init(queues[1], self.device.wrapper); self.presentation_queue = Queue.init(queues[1], self.device.wrapper);
} }
fn createCommandPool(self: *Self) !void {
// Get indices of queue families from device
const queue_family_indices = try QueueUtils.getQueueFamilies(self.*, self.physical_device);
const pool_create_info: vk.CommandPoolCreateInfo = .{
// Queue family type that buffers from this command pool will use
.queue_family_index = queue_family_indices.graphics_family.?,
.flags = .{ .reset_command_buffer_bit = true },
};
// Create a graphics queue family command pool
self.graphics_command_pool = try self.device.createCommandPool(&pool_create_info, null);
}
fn getRequiredExtensions(self: Self) ![][*:0]const u8 { fn getRequiredExtensions(self: Self) ![][*:0]const u8 {
var ext_count = sdl.vulkan.getInstanceExtensionsCount(self.window); var ext_count = sdl.vulkan.getInstanceExtensionsCount(self.window);

View file

@ -2,6 +2,7 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const zm = @import("zmath"); const zm = @import("zmath");
const Context = @import("Context.zig");
const Utilities = @import("utilities.zig"); const Utilities = @import("utilities.zig");
const Vertex = Utilities.Vertex; const Vertex = Utilities.Vertex;
const Device = @import("Context.zig").Device; const Device = @import("Context.zig").Device;
@ -11,7 +12,6 @@ const Model = @import("vulkan_renderer.zig").Model;
const Self = @This(); const Self = @This();
ubo_model: Model, ubo_model: Model,
tex_id: u32,
vertex_count: u32, vertex_count: u32,
vertex_buffer: vk.Buffer, vertex_buffer: vk.Buffer,
@ -21,17 +21,13 @@ index_count: u32,
index_buffer: vk.Buffer, index_buffer: vk.Buffer,
index_buffer_memory: vk.DeviceMemory, index_buffer_memory: vk.DeviceMemory,
instance: Instance, ctx: Context,
physical_device: vk.PhysicalDevice,
device: Device,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
pub fn create( pub fn create(
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
instance: Instance, ctx: Context,
pdev: vk.PhysicalDevice,
device: Device,
transfer_queue: vk.Queue, transfer_queue: vk.Queue,
transfer_command_pool: vk.CommandPool, transfer_command_pool: vk.CommandPool,
vertices: []const Vertex, vertices: []const Vertex,
@ -40,13 +36,12 @@ pub fn create(
) !Self { ) !Self {
var self: Self = undefined; var self: Self = undefined;
self.allocator = allocator;
self.vertex_count = @intCast(vertices.len); self.vertex_count = @intCast(vertices.len);
self.index_count = @intCast(indices.len); self.index_count = @intCast(indices.len);
self.instance = instance; self.ctx = ctx;
self.physical_device = pdev;
self.device = device;
self.allocator = allocator;
try self.createVertexBuffer(transfer_queue, transfer_command_pool, vertices); try self.createVertexBuffer(transfer_queue, transfer_command_pool, vertices);
try self.createIndexBuffer(transfer_queue, transfer_command_pool, indices); try self.createIndexBuffer(transfer_queue, transfer_command_pool, indices);
@ -58,11 +53,11 @@ pub fn create(
} }
pub fn destroy(self: Self) void { pub fn destroy(self: Self) void {
self.device.destroyBuffer(self.vertex_buffer, null); self.ctx.device.destroyBuffer(self.vertex_buffer, null);
self.device.freeMemory(self.vertex_buffer_memory, null); self.ctx.device.freeMemory(self.vertex_buffer_memory, null);
self.device.destroyBuffer(self.index_buffer, null); self.ctx.device.destroyBuffer(self.index_buffer, null);
self.device.freeMemory(self.index_buffer_memory, null); self.ctx.device.freeMemory(self.index_buffer_memory, null);
} }
fn createVertexBuffer( fn createVertexBuffer(
@ -77,14 +72,12 @@ fn createVertexBuffer(
// Temporary buffer to "stage" vertex data before transfering to GPU // Temporary buffer to "stage" vertex data before transfering to GPU
var staging_buffer: vk.Buffer = undefined; var staging_buffer: vk.Buffer = undefined;
var staging_buffer_memory: vk.DeviceMemory = undefined; var staging_buffer_memory: vk.DeviceMemory = undefined;
defer self.device.destroyBuffer(staging_buffer, null); defer self.ctx.device.destroyBuffer(staging_buffer, null);
defer self.device.freeMemory(staging_buffer_memory, null); defer self.ctx.device.freeMemory(staging_buffer_memory, null);
// Create buffer and allocate memory to it // Create buffer and allocate memory to it
try Utilities.createBuffer( try Utilities.createBuffer(
self.physical_device, self.ctx,
self.instance,
self.device,
buffer_size, buffer_size,
.{ .transfer_src_bit = true }, .{ .transfer_src_bit = true },
.{ .host_visible_bit = true, .host_coherent_bit = true }, .{ .host_visible_bit = true, .host_coherent_bit = true },
@ -95,21 +88,19 @@ fn createVertexBuffer(
// Map memory to vertex // Map memory to vertex
// 1. Create pointer to a point in normal memory // 1. Create pointer to a point in normal memory
// 2. Map the vertex buffer memory to that point // 2. Map the vertex buffer memory to that point
const data = try self.device.mapMemory(staging_buffer_memory, 0, buffer_size, .{}); const data = try self.ctx.device.mapMemory(staging_buffer_memory, 0, buffer_size, .{});
// 3. Copy memory from vertices vector to the point in memory // 3. Copy memory from vertices vector to the point in memory
const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(data)); const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(data));
@memcpy(gpu_vertices, vertices[0..]); @memcpy(gpu_vertices, vertices[0..]);
// 4. Unmap the vertex buffer memory // 4. Unmap the vertex buffer memory
self.device.unmapMemory(staging_buffer_memory); self.ctx.device.unmapMemory(staging_buffer_memory);
// --- // ---
// Create buffer with TRANSFER_DST_BIT to mark as recipient of transfer data (also VERTEX_BUFFER) // Create buffer with TRANSFER_DST_BIT to mark as recipient of transfer data (also VERTEX_BUFFER)
// Buffer memory is to be DEVICE_LOCAL_BIT meaning memory is on the GPU and only accessible by it and not CPU (host) // Buffer memory is to be DEVICE_LOCAL_BIT meaning memory is on the GPU and only accessible by it and not CPU (host)
try Utilities.createBuffer( try Utilities.createBuffer(
self.physical_device, self.ctx,
self.instance,
self.device,
buffer_size, buffer_size,
.{ .transfer_dst_bit = true, .vertex_buffer_bit = true }, .{ .transfer_dst_bit = true, .vertex_buffer_bit = true },
.{ .device_local_bit = true }, .{ .device_local_bit = true },
@ -119,7 +110,7 @@ fn createVertexBuffer(
// Copy staging buffer to vertex buffer on GPU // Copy staging buffer to vertex buffer on GPU
try Utilities.copyBuffer( try Utilities.copyBuffer(
self.device, self.ctx,
transfer_queue, transfer_queue,
transfer_command_pool, transfer_command_pool,
staging_buffer, staging_buffer,
@ -140,13 +131,11 @@ fn createIndexBuffer(
// Temporary buffer to "stage" vertex data before transfering to GPU // Temporary buffer to "stage" vertex data before transfering to GPU
var staging_buffer: vk.Buffer = undefined; var staging_buffer: vk.Buffer = undefined;
var staging_buffer_memory: vk.DeviceMemory = undefined; var staging_buffer_memory: vk.DeviceMemory = undefined;
defer self.device.destroyBuffer(staging_buffer, null); defer self.ctx.device.destroyBuffer(staging_buffer, null);
defer self.device.freeMemory(staging_buffer_memory, null); defer self.ctx.device.freeMemory(staging_buffer_memory, null);
try Utilities.createBuffer( try Utilities.createBuffer(
self.physical_device, self.ctx,
self.instance,
self.device,
buffer_size, buffer_size,
.{ .transfer_src_bit = true }, .{ .transfer_src_bit = true },
.{ .host_visible_bit = true, .host_coherent_bit = true }, .{ .host_visible_bit = true, .host_coherent_bit = true },
@ -155,16 +144,14 @@ fn createIndexBuffer(
); );
// Map memory to index buffer // Map memory to index buffer
const data = try self.device.mapMemory(staging_buffer_memory, 0, buffer_size, .{}); const data = try self.ctx.device.mapMemory(staging_buffer_memory, 0, buffer_size, .{});
const gpu_vertices: [*]u32 = @ptrCast(@alignCast(data)); const gpu_vertices: [*]u32 = @ptrCast(@alignCast(data));
@memcpy(gpu_vertices, indices[0..]); @memcpy(gpu_vertices, indices[0..]);
self.device.unmapMemory(staging_buffer_memory); self.ctx.device.unmapMemory(staging_buffer_memory);
// Create buffer for index data on GPU access only // Create buffer for index data on GPU access only
try Utilities.createBuffer( try Utilities.createBuffer(
self.physical_device, self.ctx,
self.instance,
self.device,
buffer_size, buffer_size,
.{ .transfer_dst_bit = true, .index_buffer_bit = true }, .{ .transfer_dst_bit = true, .index_buffer_bit = true },
.{ .device_local_bit = true }, .{ .device_local_bit = true },
@ -174,7 +161,7 @@ fn createIndexBuffer(
// Copy from staging buffer to GPU access buffer // Copy from staging buffer to GPU access buffer
try Utilities.copyBuffer( try Utilities.copyBuffer(
self.device, self.ctx,
transfer_queue, transfer_queue,
transfer_command_pool, transfer_command_pool,
staging_buffer, staging_buffer,

View file

@ -28,6 +28,7 @@ pub fn new(
texture_sampler: vk.Sampler, texture_sampler: vk.Sampler,
model_file: []const u8, model_file: []const u8,
) Self { ) Self {
_ = texture_sampler;
var new_mesh_model: Self = undefined; var new_mesh_model: Self = undefined;
new_mesh_model.allocator = allocator; new_mesh_model.allocator = allocator;

View file

@ -41,6 +41,7 @@ pub fn getMesh(self: *Self, file_name: []const u8) !Mesh {
} }
// TODO Create mesh // TODO Create mesh
// load mesh
return undefined; return undefined;
} }

View file

@ -55,7 +55,9 @@ pub fn create(
return self; return self;
} }
pub fn destroy(self: *Self) void {} pub fn destroy(self: *Self) void {
_ = self;
}
fn createTextureImage( fn createTextureImage(
self: *Self, self: *Self,

View file

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const Context = @import("Context.zig");
const Instance = @import("Context.zig").Instance; const Instance = @import("Context.zig").Instance;
const Device = @import("Context.zig").Device; const Device = @import("Context.zig").Device;
const CommandBuffer = @import("vulkan_renderer.zig").CommandBuffer; const CommandBuffer = @import("vulkan_renderer.zig").CommandBuffer;
@ -15,9 +16,9 @@ pub const Vertex = struct {
tex: Vector2, // Texture coords (u, v) tex: Vector2, // Texture coords (u, v)
}; };
pub fn findMemoryTypeIndex(pdev: vk.PhysicalDevice, instance: Instance, allowed_types: u32, properties: vk.MemoryPropertyFlags) u32 { pub fn findMemoryTypeIndex(ctx: Context, allowed_types: u32, properties: vk.MemoryPropertyFlags) u32 {
// Get properties of physical device memory // Get properties of physical device memory
const memory_properties = instance.getPhysicalDeviceMemoryProperties(pdev); const memory_properties = ctx.instance.getPhysicalDeviceMemoryProperties(ctx.physical_device);
const mem_type_count = memory_properties.memory_type_count; const mem_type_count = memory_properties.memory_type_count;
for (memory_properties.memory_types[0..mem_type_count], 0..mem_type_count) |mem_type, i| { for (memory_properties.memory_types[0..mem_type_count], 0..mem_type_count) |mem_type, i| {
@ -32,9 +33,7 @@ pub fn findMemoryTypeIndex(pdev: vk.PhysicalDevice, instance: Instance, allowed_
} }
pub fn createBuffer( pub fn createBuffer(
pdev: vk.PhysicalDevice, ctx: Context,
instance: Instance,
device: Device,
buffer_size: vk.DeviceSize, buffer_size: vk.DeviceSize,
buffer_usage: vk.BufferUsageFlags, buffer_usage: vk.BufferUsageFlags,
buffer_properties: vk.MemoryPropertyFlags, buffer_properties: vk.MemoryPropertyFlags,
@ -50,17 +49,16 @@ pub fn createBuffer(
.sharing_mode = .exclusive, // Similar to swapchain images, can share vertex buffers .sharing_mode = .exclusive, // Similar to swapchain images, can share vertex buffers
}; };
buffer.* = try device.createBuffer(&buffer_create_info, null); buffer.* = try ctx.device.createBuffer(&buffer_create_info, null);
// Get buffer memory requirements // Get buffer memory requirements
const mem_requirements = device.getBufferMemoryRequirements(buffer.*); const mem_requirements = ctx.device.getBufferMemoryRequirements(buffer.*);
// Allocate memory to buffer // Allocate memory to buffer
const allocate_info: vk.MemoryAllocateInfo = .{ const allocate_info: vk.MemoryAllocateInfo = .{
.allocation_size = mem_requirements.size, .allocation_size = mem_requirements.size,
.memory_type_index = findMemoryTypeIndex( .memory_type_index = findMemoryTypeIndex(
pdev, ctx,
instance,
mem_requirements.memory_type_bits, // Index of memory type of physical device that has required bit flags mem_requirements.memory_type_bits, // Index of memory type of physical device that has required bit flags
// Host visible: CPU can interact with memory // Host visible: CPU can interact with memory
// Host coherent: Allows placement of data straight into buffer after mapping (otherwise would have to specify manually) // Host coherent: Allows placement of data straight into buffer after mapping (otherwise would have to specify manually)
@ -69,10 +67,10 @@ pub fn createBuffer(
}; };
// Allocate memory to vkDeviceMemory // Allocate memory to vkDeviceMemory
buffer_memory.* = try device.allocateMemory(&allocate_info, null); buffer_memory.* = try ctx.device.allocateMemory(&allocate_info, null);
// Allocate memory to given vertex buffer // Allocate memory to given vertex buffer
try device.bindBufferMemory(buffer.*, buffer_memory.*, 0); try ctx.device.bindBufferMemory(buffer.*, buffer_memory.*, 0);
} }
fn beginCommandBuffer(device: Device, command_pool: vk.CommandPool) !CommandBuffer { fn beginCommandBuffer(device: Device, command_pool: vk.CommandPool) !CommandBuffer {

View file

@ -43,7 +43,6 @@ pub const VulkanRenderer = struct {
current_frame: u32 = 0, current_frame: u32 = 0,
ctx: Context, ctx: Context,
swapchain: Swapchain,
// Scene settings // Scene settings
ubo_view_projection: UboViewProjection, ubo_view_projection: UboViewProjection,
@ -93,9 +92,6 @@ pub const VulkanRenderer = struct {
render_pass: vk.RenderPass, render_pass: vk.RenderPass,
// Pools
graphics_command_pool: vk.CommandPool,
// Utilities // Utilities
depth_format: vk.Format, depth_format: vk.Format,
@ -110,7 +106,6 @@ pub const VulkanRenderer = struct {
self.allocator = allocator; self.allocator = allocator;
self.ctx = try Context.init(allocator, window); self.ctx = try Context.init(allocator, window);
self.current_frame = 0; self.current_frame = 0;
self.swapchain = try Swapchain.create(allocator, self.ctx);
try self.createColourBufferImage(); try self.createColourBufferImage();
try self.createDepthBufferImage(); try self.createDepthBufferImage();
@ -121,7 +116,7 @@ pub const VulkanRenderer = struct {
try self.createFramebuffers(); try self.createFramebuffers();
try self.createCommandPool(); try self.createCommandPool();
self.sampler_descriptor_sets = try std.ArrayList(vk.DescriptorSet).initCapacity(self.allocator, self.swapchain.swapchain_images.len); self.sampler_descriptor_sets = try std.ArrayList(vk.DescriptorSet).initCapacity(self.allocator, self.ctx.swapchain.swapchain_images.len);
try self.createCommandBuffers(); try self.createCommandBuffers();
try self.createTextureSampler(); try self.createTextureSampler();
@ -135,7 +130,7 @@ pub const VulkanRenderer = struct {
self.textures = std.ArrayList(Texture).init(self.allocator); self.textures = std.ArrayList(Texture).init(self.allocator);
self.model_list = std.ArrayList(MeshModel).init(allocator); self.model_list = std.ArrayList(MeshModel).init(allocator);
const aspect: f32 = @as(f32, @floatFromInt(self.swapchain.extent.width)) / @as(f32, @floatFromInt(self.swapchain.extent.height)); const aspect: f32 = @as(f32, @floatFromInt(self.ctx.swapchain.extent.width)) / @as(f32, @floatFromInt(self.ctx.swapchain.extent.height));
self.ubo_view_projection.projection = zm.perspectiveFovRh( self.ubo_view_projection.projection = zm.perspectiveFovRh(
std.math.degreesToRadians(45.0), std.math.degreesToRadians(45.0),
aspect, aspect,
@ -180,7 +175,7 @@ pub const VulkanRenderer = struct {
// -- Get next image // -- Get next image
// Get index of next image to be drawn to, and signal semaphore when ready to be drawn to // Get index of next image to be drawn to, and signal semaphore when ready to be drawn to
const image_index_result = try self.ctx.device.acquireNextImageKHR( const image_index_result = try self.ctx.device.acquireNextImageKHR(
self.swapchain.handle, self.ctx.swapchain.handle,
std.math.maxInt(u64), std.math.maxInt(u64),
self.image_available[self.current_frame], self.image_available[self.current_frame],
.null_handle, .null_handle,
@ -211,7 +206,7 @@ pub const VulkanRenderer = struct {
.wait_semaphore_count = 1, // Number of semaphores to wait on .wait_semaphore_count = 1, // Number of semaphores to wait on
.p_wait_semaphores = @ptrCast(&self.render_finished[self.current_frame]), // Semaphores to wait on .p_wait_semaphores = @ptrCast(&self.render_finished[self.current_frame]), // Semaphores to wait on
.swapchain_count = 1, // Number of swapchains to present to .swapchain_count = 1, // Number of swapchains to present to
.p_swapchains = @ptrCast(&self.swapchain.handle), // Swapchains to present images to .p_swapchains = @ptrCast(&self.ctx.swapchain.handle), // Swapchains to present images to
.p_image_indices = @ptrCast(&image_index_result.image_index), // Index of images in swapchains to present .p_image_indices = @ptrCast(&image_index_result.image_index), // Index of images in swapchains to present
}; };
@ -280,7 +275,7 @@ pub const VulkanRenderer = struct {
self.sampler_descriptor_sets.deinit(); self.sampler_descriptor_sets.deinit();
self.allocator.free(self.input_descriptor_sets); self.allocator.free(self.input_descriptor_sets);
for (0..self.swapchain.swapchain_images.len) |i| { for (0..self.ctx.swapchain.swapchain_images.len) |i| {
self.ctx.device.destroyBuffer(self.vp_uniform_buffer[i], null); self.ctx.device.destroyBuffer(self.vp_uniform_buffer[i], null);
self.ctx.device.freeMemory(self.vp_uniform_buffer_memory[i], null); self.ctx.device.freeMemory(self.vp_uniform_buffer_memory[i], null);
} }
@ -303,7 +298,7 @@ pub const VulkanRenderer = struct {
self.ctx.device.destroyPipelineLayout(self.pipeline_layout, null); self.ctx.device.destroyPipelineLayout(self.pipeline_layout, null);
self.ctx.device.destroyRenderPass(self.render_pass, null); self.ctx.device.destroyRenderPass(self.render_pass, null);
self.swapchain.deinit(); self.ctx.swapchain.deinit();
self.ctx.deinit(); self.ctx.deinit();
} }
@ -369,7 +364,7 @@ pub const VulkanRenderer = struct {
// Colour attachment of the render pass // Colour attachment of the render pass
const swapchain_colour_attachment: vk.AttachmentDescription = .{ const swapchain_colour_attachment: vk.AttachmentDescription = .{
.format = self.swapchain.swapchain_image_format, // Format to use for attachment .format = self.ctx.swapchain.swapchain_image_format, // Format to use for attachment
.samples = .{ .@"1_bit" = true }, // Number of samples to write for multisampling .samples = .{ .@"1_bit" = true }, // Number of samples to write for multisampling
.load_op = .clear, // Describes what to do with attachment before rendering .load_op = .clear, // Describes what to do with attachment before rendering
.store_op = .store, // Describes what to do with attachment after rendering .store_op = .store, // Describes what to do with attachment after rendering
@ -540,9 +535,9 @@ pub const VulkanRenderer = struct {
} }
fn createColourBufferImage(self: *Self) !void { fn createColourBufferImage(self: *Self) !void {
self.colour_buffer_image = try self.allocator.alloc(vk.Image, self.swapchain.swapchain_images.len); self.colour_buffer_image = try self.allocator.alloc(vk.Image, self.ctx.swapchain.swapchain_images.len);
self.colour_buffer_image_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain.swapchain_images.len); self.colour_buffer_image_memory = try self.allocator.alloc(vk.DeviceMemory, self.ctx.swapchain.swapchain_images.len);
self.colour_buffer_image_view = try self.allocator.alloc(vk.ImageView, self.swapchain.swapchain_images.len); self.colour_buffer_image_view = try self.allocator.alloc(vk.ImageView, self.ctx.swapchain.swapchain_images.len);
// Get supported format for colour attachment // Get supported format for colour attachment
const colour_format = chooseSupportedFormat( const colour_format = chooseSupportedFormat(
@ -557,8 +552,8 @@ pub const VulkanRenderer = struct {
for (0..self.colour_buffer_image.len) |i| { for (0..self.colour_buffer_image.len) |i| {
self.colour_buffer_image[i] = try Image.createImage( self.colour_buffer_image[i] = try Image.createImage(
self.ctx, self.ctx,
self.swapchain.extent.width, self.ctx.swapchain.extent.width,
self.swapchain.extent.height, self.ctx.swapchain.extent.height,
colour_format, colour_format,
.optimal, .optimal,
.{ .color_attachment_bit = true, .input_attachment_bit = true }, .{ .color_attachment_bit = true, .input_attachment_bit = true },
@ -576,9 +571,9 @@ pub const VulkanRenderer = struct {
} }
fn createDepthBufferImage(self: *Self) !void { fn createDepthBufferImage(self: *Self) !void {
self.depth_buffer_image = try self.allocator.alloc(vk.Image, self.swapchain.swapchain_images.len); self.depth_buffer_image = try self.allocator.alloc(vk.Image, self.ctx.swapchain.swapchain_images.len);
self.depth_buffer_image_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain.swapchain_images.len); self.depth_buffer_image_memory = try self.allocator.alloc(vk.DeviceMemory, self.ctx.swapchain.swapchain_images.len);
self.depth_buffer_image_view = try self.allocator.alloc(vk.ImageView, self.swapchain.swapchain_images.len); self.depth_buffer_image_view = try self.allocator.alloc(vk.ImageView, self.ctx.swapchain.swapchain_images.len);
// Get supported depth buffer format // Get supported depth buffer format
const formats = [_]vk.Format{ .d32_sfloat_s8_uint, .d32_sfloat, .d24_unorm_s8_uint }; const formats = [_]vk.Format{ .d32_sfloat_s8_uint, .d32_sfloat, .d24_unorm_s8_uint };
@ -594,8 +589,8 @@ pub const VulkanRenderer = struct {
// Create depth buffer image // Create depth buffer image
self.depth_buffer_image[i] = try Image.createImage( self.depth_buffer_image[i] = try Image.createImage(
self.ctx, self.ctx,
self.swapchain.extent.width, self.ctx.swapchain.extent.width,
self.swapchain.extent.height, self.ctx.swapchain.extent.height,
self.depth_format, self.depth_format,
.optimal, .optimal,
.{ .depth_stencil_attachment_bit = true, .input_attachment_bit = true }, .{ .depth_stencil_attachment_bit = true, .input_attachment_bit = true },
@ -698,15 +693,15 @@ pub const VulkanRenderer = struct {
self.viewport = .{ self.viewport = .{
.x = 0.0, .x = 0.0,
.y = 0.0, .y = 0.0,
.width = @floatFromInt(self.swapchain.extent.width), .width = @floatFromInt(self.ctx.swapchain.extent.width),
.height = @floatFromInt(self.swapchain.extent.height), .height = @floatFromInt(self.ctx.swapchain.extent.height),
.min_depth = 0.0, .min_depth = 0.0,
.max_depth = 1.0, .max_depth = 1.0,
}; };
self.scissor = .{ self.scissor = .{
.offset = .{ .x = 0, .y = 0 }, .offset = .{ .x = 0, .y = 0 },
.extent = self.swapchain.extent, .extent = self.ctx.swapchain.extent,
}; };
const viewport_state_create_info: vk.PipelineViewportStateCreateInfo = .{ const viewport_state_create_info: vk.PipelineViewportStateCreateInfo = .{
@ -883,10 +878,10 @@ pub const VulkanRenderer = struct {
} }
fn createFramebuffers(self: *Self) !void { fn createFramebuffers(self: *Self) !void {
self.swapchain.swapchain_framebuffers = try self.allocator.alloc(vk.Framebuffer, self.swapchain.swapchain_images.len); self.ctx.swapchain.swapchain_framebuffers = try self.allocator.alloc(vk.Framebuffer, self.ctx.swapchain.swapchain_images.len);
// Create a frammebuffer for each swapchain image // Create a frammebuffer for each swapchain image
for (self.swapchain.swapchain_images, 0..) |swapchain_image, i| { for (self.ctx.swapchain.swapchain_images, 0..) |swapchain_image, i| {
// Order matters // Order matters
const attachments = [_]vk.ImageView{ const attachments = [_]vk.ImageView{
swapchain_image.image_view, swapchain_image.image_view,
@ -898,32 +893,18 @@ pub const VulkanRenderer = struct {
.render_pass = self.render_pass, // Render pass layout the frambuffer will be used with .render_pass = self.render_pass, // Render pass layout the frambuffer will be used with
.attachment_count = @intCast(attachments.len), .attachment_count = @intCast(attachments.len),
.p_attachments = &attachments, // List of attachments (1:1 with render pass) .p_attachments = &attachments, // List of attachments (1:1 with render pass)
.width = self.swapchain.extent.width, // Framebuffer width .width = self.ctx.swapchain.extent.width, // Framebuffer width
.height = self.swapchain.extent.height, // Framebuffer height .height = self.ctx.swapchain.extent.height, // Framebuffer height
.layers = 1, // Framebuffer layers .layers = 1, // Framebuffer layers
}; };
self.swapchain.swapchain_framebuffers[i] = try self.ctx.device.createFramebuffer(&framebuffer_create_info, null); self.ctx.swapchain.swapchain_framebuffers[i] = try self.ctx.device.createFramebuffer(&framebuffer_create_info, null);
} }
} }
fn createCommandPool(self: *Self) !void {
// Get indices of queue families from device
const queue_family_indices = try QueueUtils.getQueueFamilies(self.ctx, self.ctx.physical_device);
const pool_create_info: vk.CommandPoolCreateInfo = .{
// Queue family type that buffers from this command pool will use
.queue_family_index = queue_family_indices.graphics_family.?,
.flags = .{ .reset_command_buffer_bit = true },
};
// Create a graphics queue family command pool
self.graphics_command_pool = try self.ctx.device.createCommandPool(&pool_create_info, null);
}
fn createCommandBuffers(self: *Self) !void { fn createCommandBuffers(self: *Self) !void {
// Allocate one command buffer for each framebuffer // Allocate one command buffer for each framebuffer
const command_buffer_handles = try self.allocator.alloc(vk.CommandBuffer, self.swapchain.swapchain_framebuffers.len); const command_buffer_handles = try self.allocator.alloc(vk.CommandBuffer, self.ctx.swapchain.swapchain_framebuffers.len);
defer self.allocator.free(command_buffer_handles); defer self.allocator.free(command_buffer_handles);
self.command_buffers = try self.allocator.alloc(CommandBuffer, command_buffer_handles.len); self.command_buffers = try self.allocator.alloc(CommandBuffer, command_buffer_handles.len);
@ -980,8 +961,8 @@ pub const VulkanRenderer = struct {
const vp_buffer_size: vk.DeviceSize = @sizeOf(UboViewProjection); const vp_buffer_size: vk.DeviceSize = @sizeOf(UboViewProjection);
// One uniform buffer for each image (and by extension, command buffer) // One uniform buffer for each image (and by extension, command buffer)
self.vp_uniform_buffer = try self.allocator.alloc(vk.Buffer, self.swapchain.swapchain_images.len); self.vp_uniform_buffer = try self.allocator.alloc(vk.Buffer, self.ctx.swapchain.swapchain_images.len);
self.vp_uniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain.swapchain_images.len); self.vp_uniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, self.ctx.swapchain.swapchain_images.len);
// Create the uniform buffers // Create the uniform buffers
for (0..self.vp_uniform_buffer.len) |i| { for (0..self.vp_uniform_buffer.len) |i| {
@ -1013,7 +994,7 @@ pub const VulkanRenderer = struct {
// Data to create descriptor pool // Data to create descriptor pool
const pool_create_info: vk.DescriptorPoolCreateInfo = .{ const pool_create_info: vk.DescriptorPoolCreateInfo = .{
.max_sets = @intCast(self.swapchain.swapchain_images.len), // Maximum number of descriptor sets that can be created from pool .max_sets = @intCast(self.ctx.swapchain.swapchain_images.len), // Maximum number of descriptor sets that can be created from pool
.pool_size_count = @intCast(descriptor_pool_sizes.len), // Amount of pool sizes being passed .pool_size_count = @intCast(descriptor_pool_sizes.len), // Amount of pool sizes being passed
.p_pool_sizes = &descriptor_pool_sizes, // Pool sizes to create pool with .p_pool_sizes = &descriptor_pool_sizes, // Pool sizes to create pool with
}; };
@ -1055,7 +1036,7 @@ pub const VulkanRenderer = struct {
// Create input attachment pool // Create input attachment pool
const input_pool_create_info: vk.DescriptorPoolCreateInfo = .{ const input_pool_create_info: vk.DescriptorPoolCreateInfo = .{
.max_sets = @intCast(self.swapchain.swapchain_images.len), .max_sets = @intCast(self.ctx.swapchain.swapchain_images.len),
.pool_size_count = @intCast(input_pool_sizes.len), .pool_size_count = @intCast(input_pool_sizes.len),
.p_pool_sizes = &input_pool_sizes, .p_pool_sizes = &input_pool_sizes,
}; };
@ -1065,9 +1046,9 @@ pub const VulkanRenderer = struct {
fn createDescriptorSets(self: *Self) !void { fn createDescriptorSets(self: *Self) !void {
// One descriptor set for every buffer // One descriptor set for every buffer
self.descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.swapchain.swapchain_images.len); self.descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.ctx.swapchain.swapchain_images.len);
var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.swapchain.swapchain_images.len); var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.ctx.swapchain.swapchain_images.len);
defer self.allocator.free(set_layouts); defer self.allocator.free(set_layouts);
for (0..set_layouts.len) |i| { for (0..set_layouts.len) |i| {
set_layouts[i] = self.descriptor_set_layout; set_layouts[i] = self.descriptor_set_layout;
@ -1076,7 +1057,7 @@ pub const VulkanRenderer = struct {
// Descriptor set allocation info // Descriptor set allocation info
const set_alloc_info: vk.DescriptorSetAllocateInfo = .{ const set_alloc_info: vk.DescriptorSetAllocateInfo = .{
.descriptor_pool = self.descriptor_pool, // Pool to allocate descriptor set from .descriptor_pool = self.descriptor_pool, // Pool to allocate descriptor set from
.descriptor_set_count = @intCast(self.swapchain.swapchain_images.len), // Number of sets to allocate .descriptor_set_count = @intCast(self.ctx.swapchain.swapchain_images.len), // Number of sets to allocate
.p_set_layouts = set_layouts.ptr, // Layouts to use to allocate sets (1:1 relationship) .p_set_layouts = set_layouts.ptr, // Layouts to use to allocate sets (1:1 relationship)
}; };
@ -1084,7 +1065,7 @@ pub const VulkanRenderer = struct {
try self.ctx.device.allocateDescriptorSets(&set_alloc_info, self.descriptor_sets.ptr); try self.ctx.device.allocateDescriptorSets(&set_alloc_info, self.descriptor_sets.ptr);
// Update all of descriptor set buffer bindings // Update all of descriptor set buffer bindings
for (0..self.swapchain.swapchain_images.len) |i| { for (0..self.ctx.swapchain.swapchain_images.len) |i| {
// -- View projection descriptor // -- View projection descriptor
// Buffer info and data offset info // Buffer info and data offset info
const vp_buffer_info: vk.DescriptorBufferInfo = .{ const vp_buffer_info: vk.DescriptorBufferInfo = .{
@ -1114,10 +1095,10 @@ pub const VulkanRenderer = struct {
} }
fn createInputDescriptorSets(self: *Self) !void { fn createInputDescriptorSets(self: *Self) !void {
self.input_descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.swapchain.swapchain_images.len); self.input_descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.ctx.swapchain.swapchain_images.len);
// Fill array of layouts ready for set creation // Fill array of layouts ready for set creation
var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.swapchain.swapchain_images.len); var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.ctx.swapchain.swapchain_images.len);
defer self.allocator.free(set_layouts); defer self.allocator.free(set_layouts);
for (0..set_layouts.len) |i| { for (0..set_layouts.len) |i| {
set_layouts[i] = self.input_set_layout; set_layouts[i] = self.input_set_layout;
@ -1126,7 +1107,7 @@ pub const VulkanRenderer = struct {
// Input attachment descriptor set allocation info // Input attachment descriptor set allocation info
const set_alloc_info: vk.DescriptorSetAllocateInfo = .{ const set_alloc_info: vk.DescriptorSetAllocateInfo = .{
.descriptor_pool = self.input_descriptor_pool, .descriptor_pool = self.input_descriptor_pool,
.descriptor_set_count = @intCast(self.swapchain.swapchain_images.len), .descriptor_set_count = @intCast(self.ctx.swapchain.swapchain_images.len),
.p_set_layouts = set_layouts.ptr, .p_set_layouts = set_layouts.ptr,
}; };
@ -1134,7 +1115,7 @@ pub const VulkanRenderer = struct {
try self.ctx.device.allocateDescriptorSets(&set_alloc_info, self.input_descriptor_sets.ptr); try self.ctx.device.allocateDescriptorSets(&set_alloc_info, self.input_descriptor_sets.ptr);
// Update each descriptor set with input attachment // Update each descriptor set with input attachment
for (0..self.swapchain.swapchain_images.len) |i| { for (0..self.ctx.swapchain.swapchain_images.len) |i| {
// Colour attachment descriptor // Colour attachment descriptor
const colour_attachment_descriptor: vk.DescriptorImageInfo = .{ const colour_attachment_descriptor: vk.DescriptorImageInfo = .{
.image_layout = .shader_read_only_optimal, .image_layout = .shader_read_only_optimal,
@ -1213,11 +1194,11 @@ pub const VulkanRenderer = struct {
.render_pass = self.render_pass, // Render pass to begin .render_pass = self.render_pass, // Render pass to begin
.render_area = .{ .render_area = .{
.offset = .{ .x = 0, .y = 0 }, // Start point of render pass in pixels .offset = .{ .x = 0, .y = 0 }, // Start point of render pass in pixels
.extent = self.swapchain.extent, // Size of region to run render pass on (starting at offset) .extent = self.ctx.swapchain.extent, // Size of region to run render pass on (starting at offset)
}, },
.p_clear_values = &clear_values, // List of clear values .p_clear_values = &clear_values, // List of clear values
.clear_value_count = @intCast(clear_values.len), .clear_value_count = @intCast(clear_values.len),
.framebuffer = self.swapchain.swapchain_framebuffers[current_image], .framebuffer = self.ctx.swapchain.swapchain_framebuffers[current_image],
}; };
const command_buffer = self.command_buffers[current_image]; const command_buffer = self.command_buffers[current_image];