Create command buffers
This commit is contained in:
parent
f008f67921
commit
6a85e4ce51
1 changed files with 118 additions and 0 deletions
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue