Implement drawing
This commit is contained in:
parent
6a85e4ce51
commit
656406f121
2 changed files with 95 additions and 36 deletions
|
@ -28,6 +28,8 @@ pub fn main() !void {
|
|||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
try vulkan_renderer.draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ pub const VulkanRenderer = struct {
|
|||
presentation_queue: Queue,
|
||||
surface: vk.SurfaceKHR,
|
||||
swapchain: vk.SwapchainKHR,
|
||||
viewport: vk.Viewport,
|
||||
scissor: vk.Rect2D,
|
||||
|
||||
swapchain_images: []SwapchainImage,
|
||||
swapchain_framebuffers: []vk.Framebuffer,
|
||||
|
@ -65,6 +67,10 @@ pub const VulkanRenderer = struct {
|
|||
swapchain_image_format: vk.Format,
|
||||
extent: vk.Extent2D,
|
||||
|
||||
// Synchronisation
|
||||
image_available: vk.Semaphore,
|
||||
render_finished: vk.Semaphore,
|
||||
|
||||
debug_utils: ?vk.DebugUtilsMessengerEXT,
|
||||
|
||||
pub fn init(window: sdl.Window, allocator: std.mem.Allocator) !Self {
|
||||
|
@ -89,10 +95,82 @@ pub const VulkanRenderer = struct {
|
|||
try self.createFramebuffers();
|
||||
try self.createCommandPool();
|
||||
try self.createCommandBuffers();
|
||||
try self.recordCommands();
|
||||
try self.createSynchronisation();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self) !void {
|
||||
// -- Get next image
|
||||
// Get index of next image to be drawn to, and signal semaphore when ready to be drawn to
|
||||
const image_index_result = try self.device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), self.image_available, .null_handle);
|
||||
|
||||
// -- Submit command buffer to render
|
||||
// Queue submission information
|
||||
const wait_stages = [_]vk.PipelineStageFlags{.{ .color_attachment_output_bit = true }};
|
||||
|
||||
const submit_info: vk.SubmitInfo = .{
|
||||
.wait_semaphore_count = 1, // Number of semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.image_available), // List of semaphores to wait on
|
||||
.p_wait_dst_stage_mask = &wait_stages, // Stages to check semaphores at
|
||||
.command_buffer_count = 1, // Number of command buffers to submit
|
||||
.p_command_buffers = @ptrCast(&self.command_buffers[image_index_result.image_index]), // Command buffer to submit
|
||||
.signal_semaphore_count = 1, // Number of semaphores to signal
|
||||
.p_signal_semaphores = @ptrCast(&self.render_finished), // List of semaphores to signal when command buffer finishes
|
||||
};
|
||||
|
||||
// Submit command buffer to queue
|
||||
try self.device.queueSubmit(self.graphics_queue.handle, 1, @ptrCast(&submit_info), .null_handle);
|
||||
|
||||
// -- Present rendered image to screen
|
||||
const present_info: vk.PresentInfoKHR = .{
|
||||
.wait_semaphore_count = 1, // Number of semaphores to wait on
|
||||
.p_wait_semaphores = @ptrCast(&self.render_finished), // Semaphores to wait on
|
||||
.swapchain_count = 1, // Number of swapchains to present to
|
||||
.p_swapchains = @ptrCast(&self.swapchain), // Swapchains to present images to
|
||||
.p_image_indices = @ptrCast(&image_index_result.image_index), // Index of images in swapchains to present
|
||||
};
|
||||
|
||||
// Present image
|
||||
_ = try self.device.queuePresentKHR(self.presentation_queue.handle, &present_info);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
if (enable_validation_layers) {
|
||||
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
|
||||
}
|
||||
|
||||
self.device.destroySemaphore(self.render_finished, null);
|
||||
self.device.destroySemaphore(self.image_available, 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.destroyPipelineLayout(self.pipeline_layout, null);
|
||||
self.device.destroyRenderPass(self.render_pass, 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);
|
||||
self.instance.destroyInstance(null);
|
||||
|
||||
self.allocator.destroy(self.device.wrapper);
|
||||
self.allocator.destroy(self.instance.wrapper);
|
||||
}
|
||||
|
||||
fn createInstance(self: *Self) !void {
|
||||
if (enable_validation_layers and !self.checkValidationLayersSupport()) {
|
||||
// TODO Better error
|
||||
|
@ -380,7 +458,7 @@ pub const VulkanRenderer = struct {
|
|||
};
|
||||
|
||||
// -- Viewport & scissor --
|
||||
const viewport: vk.Viewport = .{
|
||||
self.viewport = .{
|
||||
.x = 0.0,
|
||||
.y = 0.0,
|
||||
.width = @floatFromInt(self.extent.width),
|
||||
|
@ -389,16 +467,16 @@ pub const VulkanRenderer = struct {
|
|||
.max_depth = 1.0,
|
||||
};
|
||||
|
||||
const scissor: vk.Rect2D = .{
|
||||
self.scissor = .{
|
||||
.offset = .{ .x = 0, .y = 0 },
|
||||
.extent = self.extent,
|
||||
};
|
||||
|
||||
const viewport_state_create_info: vk.PipelineViewportStateCreateInfo = .{
|
||||
.viewport_count = 1,
|
||||
.p_viewports = @ptrCast(&viewport),
|
||||
.p_viewports = @ptrCast(&self.viewport),
|
||||
.scissor_count = 1,
|
||||
.p_scissors = @ptrCast(&scissor),
|
||||
.p_scissors = @ptrCast(&self.scissor),
|
||||
};
|
||||
|
||||
// -- Dynamic states --
|
||||
|
@ -549,6 +627,12 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn createSynchronisation(self: *Self) !void {
|
||||
// Semaphore creation information
|
||||
self.image_available = try self.device.createSemaphore(&.{}, null);
|
||||
self.render_finished = try self.device.createSemaphore(&.{}, null);
|
||||
}
|
||||
|
||||
fn recordCommands(self: *Self) !void {
|
||||
// Information about how to begin each command
|
||||
const buffer_begin_info: vk.CommandBufferBeginInfo = .{
|
||||
|
@ -569,6 +653,7 @@ pub const VulkanRenderer = struct {
|
|||
},
|
||||
.p_clear_values = &clear_values, // List of clear values (TODO: Depth attachment clear value)
|
||||
.clear_value_count = 1,
|
||||
.framebuffer = undefined,
|
||||
};
|
||||
|
||||
for (self.command_buffers, 0..) |command_buffer, i| {
|
||||
|
@ -584,6 +669,10 @@ pub const VulkanRenderer = struct {
|
|||
// Bind pipeline to be used in render pass
|
||||
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
||||
|
||||
// Needed when using dynamic state
|
||||
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
||||
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
||||
|
||||
// Execute a pipeline
|
||||
command_buffer.draw(3, 1, 0, 0);
|
||||
|
||||
|
@ -806,38 +895,6 @@ pub const VulkanRenderer = struct {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
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.destroyPipelineLayout(self.pipeline_layout, null);
|
||||
self.device.destroyRenderPass(self.render_pass, 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);
|
||||
self.instance.destroyInstance(null);
|
||||
|
||||
self.allocator.destroy(self.device.wrapper);
|
||||
self.allocator.destroy(self.instance.wrapper);
|
||||
}
|
||||
};
|
||||
|
||||
// Format: VK_FORMAT_R8G8B8A8_UNORM (VK_FORMAT_B8G8R8A8_UNORM as backup)
|
||||
|
|
Loading…
Reference in a new issue