Create command buffers

This commit is contained in:
Przemyslaw Gasinski 2024-07-03 23:33:16 +02:00
parent f008f67921
commit 6a85e4ce51

View file

@ -29,6 +29,7 @@ const DeviceDispatch = vk.DeviceWrapper(apis);
const Instance = vk.InstanceProxy(apis); const Instance = vk.InstanceProxy(apis);
const Device = vk.DeviceProxy(apis); const Device = vk.DeviceProxy(apis);
const Queue = vk.QueueProxy(apis); const Queue = vk.QueueProxy(apis);
const CommandBuffer = vk.CommandBufferProxy(apis);
pub const VulkanRenderer = struct { pub const VulkanRenderer = struct {
const Self = @This(); const Self = @This();
@ -47,13 +48,19 @@ pub const VulkanRenderer = struct {
presentation_queue: Queue, presentation_queue: Queue,
surface: vk.SurfaceKHR, surface: vk.SurfaceKHR,
swapchain: vk.SwapchainKHR, swapchain: vk.SwapchainKHR,
swapchain_images: []SwapchainImage, swapchain_images: []SwapchainImage,
swapchain_framebuffers: []vk.Framebuffer,
command_buffers: []CommandBuffer,
// Pipeline // Pipeline
graphics_pipeline: vk.Pipeline, graphics_pipeline: vk.Pipeline,
pipeline_layout: vk.PipelineLayout, pipeline_layout: vk.PipelineLayout,
render_pass: vk.RenderPass, render_pass: vk.RenderPass,
// Pools
graphics_command_pool: vk.CommandPool,
// Utilities // Utilities
swapchain_image_format: vk.Format, swapchain_image_format: vk.Format,
extent: vk.Extent2D, extent: vk.Extent2D,
@ -79,6 +86,9 @@ pub const VulkanRenderer = struct {
try self.createSwapchain(); try self.createSwapchain();
try self.createRenderPass(); try self.createRenderPass();
try self.createGraphicsPipeline(); try self.createGraphicsPipeline();
try self.createFramebuffers();
try self.createCommandPool();
try self.createCommandBuffers();
return self; return self;
} }
@ -487,6 +497,105 @@ pub const VulkanRenderer = struct {
); );
} }
fn createFramebuffers(self: *Self) !void {
self.swapchain_framebuffers = try self.allocator.alloc(vk.Framebuffer, self.swapchain_images.len);
// Create a frammebuffer for each swapchain image
for (self.swapchain_images, 0..) |swapchain_image, i| {
const attachments = [_]vk.ImageView{swapchain_image.image_view};
const framebuffer_create_info: vk.FramebufferCreateInfo = .{
.render_pass = self.render_pass, // Render pass layout the frambuffer will be used with
.attachment_count = @intCast(attachments.len),
.p_attachments = &attachments, // List of attachments (1:1 with render pass)
.width = self.extent.width, // Framebuffer width
.height = self.extent.height, // Framebuffer height
.layers = 1, // Framebuffer layers
};
self.swapchain_framebuffers[i] = try self.device.createFramebuffer(&framebuffer_create_info, null);
}
}
fn createCommandPool(self: *Self) !void {
// Get indices of queue families from device
const queue_family_indices = try self.getQueueFamilies(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.?,
};
// Create a graphics queue family command pool
self.graphics_command_pool = try self.device.createCommandPool(&pool_create_info, null);
}
fn createCommandBuffers(self: *Self) !void {
// Allocate one command buffer for each framebuffer
const command_buffer_handles = try self.allocator.alloc(vk.CommandBuffer, self.swapchain_framebuffers.len);
defer self.allocator.free(command_buffer_handles);
self.command_buffers = try self.allocator.alloc(CommandBuffer, command_buffer_handles.len);
const command_buffer_allocate_info: vk.CommandBufferAllocateInfo = .{
.command_pool = self.graphics_command_pool,
.level = .primary, // primary: buffer you submit directly to queue. Can't be called by other buffers
.command_buffer_count = @intCast(command_buffer_handles.len),
};
// Allocate command buffers and place handles in array of buffers
try self.device.allocateCommandBuffers(&command_buffer_allocate_info, command_buffer_handles.ptr);
for (command_buffer_handles, 0..) |command_buffer_handle, i| {
self.command_buffers[i] = CommandBuffer.init(command_buffer_handle, self.device.wrapper);
}
}
fn recordCommands(self: *Self) !void {
// Information about how to begin each command
const buffer_begin_info: vk.CommandBufferBeginInfo = .{
// Buffer can be resubmitted when it has already been submitted and is awaiting execution
.flags = .{ .simultaneous_use_bit = true },
};
const clear_values = [_]vk.ClearValue{
.{ .color = .{ .float_32 = [4]f32{ 0.6, 0.65, 0.4, 1.0 } } },
};
// Information about how to begin a render pass (only needed for graphical application)
var render_pass_begin_info: vk.RenderPassBeginInfo = .{
.render_pass = self.render_pass, // Render pass to begin
.render_area = .{
.offset = .{ .x = 0, .y = 0 }, // Start point of render pass in pixels
.extent = self.extent, // Size of region to run render pass on (starting at offset)
},
.p_clear_values = &clear_values, // List of clear values (TODO: Depth attachment clear value)
.clear_value_count = 1,
};
for (self.command_buffers, 0..) |command_buffer, i| {
render_pass_begin_info.framebuffer = self.swapchain_framebuffers[i];
// Start recording commands to command buffer
try command_buffer.beginCommandBuffer(&buffer_begin_info);
{
// Begin render pass
command_buffer.beginRenderPass(&render_pass_begin_info, vk.SubpassContents.@"inline");
// Bind pipeline to be used in render pass
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
// Execute a pipeline
command_buffer.draw(3, 1, 0, 0);
// End render pass
command_buffer.endRenderPass();
}
// Stop recording to command buffer
try command_buffer.endCommandBuffer();
}
}
fn getPhysicalDevice(self: *Self) !void { fn getPhysicalDevice(self: *Self) !void {
var pdev_count: u32 = 0; var pdev_count: u32 = 0;
_ = try self.instance.enumeratePhysicalDevices(&pdev_count, null); _ = try self.instance.enumeratePhysicalDevices(&pdev_count, null);
@ -703,6 +812,15 @@ pub const VulkanRenderer = struct {
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null); self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
} }
self.allocator.free(self.command_buffers);
self.device.destroyCommandPool(self.graphics_command_pool, null);
for (self.swapchain_framebuffers) |framebuffer| {
self.device.destroyFramebuffer(framebuffer, null);
}
self.allocator.free(self.swapchain_framebuffers);
self.device.destroyPipeline(self.graphics_pipeline, null); self.device.destroyPipeline(self.graphics_pipeline, null);
self.device.destroyPipelineLayout(self.pipeline_layout, null); self.device.destroyPipelineLayout(self.pipeline_layout, null);
self.device.destroyRenderPass(self.render_pass, null); self.device.destroyRenderPass(self.render_pass, null);