Update [broken]
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s
This commit is contained in:
parent
8f1172e888
commit
1dc9da0d61
8 changed files with 222 additions and 31 deletions
|
@ -32,6 +32,11 @@ impl ApplicationHandler for App {
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
|
match self.render_context.as_ref() {
|
||||||
|
Some(render_context) => render_context.exit(),
|
||||||
|
None => log::warn!("Window closed but no render context found"),
|
||||||
|
};
|
||||||
|
|
||||||
log::debug!("The close button was pressed; stopping");
|
log::debug!("The close button was pressed; stopping");
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(unused_imports)]
|
|
||||||
|
|
||||||
pub(self) mod vk_render_context;
|
pub(self) mod vk_render_context;
|
||||||
pub use vk_render_context::VkRenderContext;
|
pub use vk_render_context::VkRenderContext;
|
||||||
|
|
||||||
|
@ -25,5 +23,13 @@ pub(self) mod vk_graphics_pipeline;
|
||||||
pub use vk_graphics_pipeline::VkGraphicsPipeline;
|
pub use vk_graphics_pipeline::VkGraphicsPipeline;
|
||||||
|
|
||||||
mod vk_render_pass;
|
mod vk_render_pass;
|
||||||
|
pub(self) use vk_render_pass::VkRenderPass;
|
||||||
|
|
||||||
|
mod vk_semaphore;
|
||||||
|
pub(self) use vk_semaphore::VkSemaphore;
|
||||||
|
|
||||||
|
mod vk_command_pool;
|
||||||
|
|
||||||
|
mod vk_framebuffer;
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
31
src/vulkan/vk_command_pool.rs
Normal file
31
src/vulkan/vk_command_pool.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use crate::vulkan::VkDevice;
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use ash::vk;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct VkCommandPool {
|
||||||
|
device: Arc<VkDevice>,
|
||||||
|
|
||||||
|
pub(super) handle: vk::CommandPool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VkCommandPool {
|
||||||
|
pub fn new(device: Arc<VkDevice>) -> VkResult<Self> {
|
||||||
|
let command_pool_info = vk::CommandPoolCreateInfo::default()
|
||||||
|
.queue_family_index(device.queue_family_index);
|
||||||
|
let command_pool = unsafe { device.handle.create_command_pool(&command_pool_info, None)? };
|
||||||
|
log::debug!("Command pool created ({command_pool:?})");
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
device,
|
||||||
|
handle: command_pool,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VkCommandPool {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.device.handle.destroy_command_pool(self.handle, None) };
|
||||||
|
log::debug!("Command pool destroyed ({:?})", self.handle);
|
||||||
|
}
|
||||||
|
}
|
52
src/vulkan/vk_framebuffer.rs
Normal file
52
src/vulkan/vk_framebuffer.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::vulkan::vk_render_pass::VkRenderPass;
|
||||||
|
use crate::vulkan::{VkDevice, VkSwapchain};
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use ash::vk;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct VkSwapchainFramebuffer {
|
||||||
|
device: Arc<VkDevice>,
|
||||||
|
swapchain: Arc<VkSwapchain>,
|
||||||
|
render_pass: Arc<VkRenderPass>,
|
||||||
|
image_view_index: usize,
|
||||||
|
|
||||||
|
pub(super) handle: vk::Framebuffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VkSwapchainFramebuffer {
|
||||||
|
pub fn new(
|
||||||
|
device: Arc<VkDevice>,
|
||||||
|
swapchain: Arc<VkSwapchain>,
|
||||||
|
render_pass: Arc<VkRenderPass>,
|
||||||
|
image_view_index: usize,
|
||||||
|
) -> VkResult<Self> {
|
||||||
|
let present_image_view = swapchain
|
||||||
|
.present_image_views
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()[image_view_index];
|
||||||
|
let attachments = [present_image_view];
|
||||||
|
let framebuffer_info = vk::FramebufferCreateInfo::default()
|
||||||
|
.render_pass(render_pass.handle)
|
||||||
|
.width(swapchain.surface_resolution.width)
|
||||||
|
.height(swapchain.surface_resolution.height)
|
||||||
|
.attachments(&attachments)
|
||||||
|
.layers(1);
|
||||||
|
|
||||||
|
let framebuffer = unsafe { device.handle.create_framebuffer(&framebuffer_info, None)? };
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
device,
|
||||||
|
swapchain,
|
||||||
|
render_pass,
|
||||||
|
image_view_index,
|
||||||
|
|
||||||
|
handle: framebuffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VkSwapchainFramebuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.device.handle.destroy_framebuffer(self.handle, None) };
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,8 @@ pub struct VkGraphicsPipeline {
|
||||||
swapchain: Arc<VkSwapchain>,
|
swapchain: Arc<VkSwapchain>,
|
||||||
render_pass: Arc<VkRenderPass>,
|
render_pass: Arc<VkRenderPass>,
|
||||||
|
|
||||||
pipeline_layout: vk::PipelineLayout,
|
pub(super) pipeline_layout: vk::PipelineLayout,
|
||||||
pipeline: vk::Pipeline,
|
pub(super) pipeline: vk::Pipeline,
|
||||||
vertex_shader: VkShaderModule,
|
vertex_shader: VkShaderModule,
|
||||||
fragment_shader: VkShaderModule,
|
fragment_shader: VkShaderModule,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::vulkan::vk_render_pass::VkRenderPass;
|
use crate::vulkan::vk_command_pool::VkCommandPool;
|
||||||
use crate::vulkan::{VkDevice, VkGraphicsPipeline, VkInstance, VkPhysicalDevice, VkSurface, VkSwapchain};
|
use crate::vulkan::{VkDevice, VkGraphicsPipeline, VkInstance, VkPhysicalDevice, VkRenderPass, VkSemaphore, VkSurface, VkSwapchain};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use std::mem::swap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct VkRenderContext {
|
pub struct VkRenderContext {
|
||||||
|
@ -9,6 +10,12 @@ pub struct VkRenderContext {
|
||||||
device: Arc<VkDevice>,
|
device: Arc<VkDevice>,
|
||||||
|
|
||||||
swapchain: Arc<VkSwapchain>,
|
swapchain: Arc<VkSwapchain>,
|
||||||
|
render_pass: Arc<VkRenderPass>,
|
||||||
|
pipeline: Arc<VkGraphicsPipeline>,
|
||||||
|
command_pool: VkCommandPool,
|
||||||
|
command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
image_available_semaphore: VkSemaphore,
|
||||||
|
render_finished_semaphore: VkSemaphore,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VkRenderContext {
|
impl VkRenderContext {
|
||||||
|
@ -51,57 +58,88 @@ impl VkRenderContext {
|
||||||
swapchain.clone(),
|
swapchain.clone(),
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
|
let framebuffers = swapchain.create_framebuffers(render_pass.clone())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Failed to get framebuffers"))?;
|
||||||
|
|
||||||
let pipeline = Arc::new(VkGraphicsPipeline::new(
|
let pipeline = Arc::new(VkGraphicsPipeline::new(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
swapchain.clone(),
|
swapchain.clone(),
|
||||||
render_pass.clone(),
|
render_pass.clone(),
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
let framebuffers = swapchain.present_image_views
|
let command_pool = VkCommandPool::new(device.clone())?;
|
||||||
.as_ref()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("No present image views found"))?
|
|
||||||
.iter()
|
|
||||||
.map(|present_image_view| {
|
|
||||||
let attachments = [*present_image_view];
|
|
||||||
let framebuffer_info = vk::FramebufferCreateInfo::default()
|
|
||||||
.render_pass(render_pass.handle)
|
|
||||||
.width(swapchain.surface_resolution.width)
|
|
||||||
.height(swapchain.surface_resolution.height)
|
|
||||||
.attachments(&attachments)
|
|
||||||
.layers(1);
|
|
||||||
|
|
||||||
unsafe { device.handle.create_framebuffer(&framebuffer_info, None).unwrap() }
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let command_pool_info = vk::CommandPoolCreateInfo::default()
|
|
||||||
.queue_family_index(device.queue_family_index);
|
|
||||||
let command_pool = unsafe { device.handle.create_command_pool(&command_pool_info, None)? };
|
|
||||||
|
|
||||||
let command_buffer_info = vk::CommandBufferAllocateInfo::default()
|
let command_buffer_info = vk::CommandBufferAllocateInfo::default()
|
||||||
.command_pool(command_pool)
|
.command_pool(command_pool.handle)
|
||||||
.level(vk::CommandBufferLevel::PRIMARY)
|
.level(vk::CommandBufferLevel::PRIMARY)
|
||||||
.command_buffer_count(framebuffers.len() as u32);
|
.command_buffer_count(framebuffers.as_ref().unwrap().len() as u32);
|
||||||
|
|
||||||
// Destroyed with command pool
|
// Destroyed with command pool
|
||||||
let command_buffers = unsafe { device.handle.allocate_command_buffers(&command_buffer_info)? };
|
let command_buffers = unsafe { device.handle.allocate_command_buffers(&command_buffer_info)? };
|
||||||
|
|
||||||
|
// Same in VkGraphicsPipeline (TODO: Refactor this)
|
||||||
|
let render_area = vk::Rect2D::default().extent(swapchain.surface_resolution);
|
||||||
|
let clear_value = vk::ClearValue::default();
|
||||||
|
for (index, command_buffer) in command_buffers.iter().enumerate() {
|
||||||
|
let command_buffer_begin_info = vk::CommandBufferBeginInfo::default();
|
||||||
|
unsafe { device.handle.begin_command_buffer(*command_buffer, &command_buffer_begin_info)? };
|
||||||
|
|
||||||
unsafe { device.handle.destroy_command_pool(command_pool, None) };
|
let clear_values = [clear_value];
|
||||||
for framebuffer in framebuffers {
|
let render_pass_begin_info = vk::RenderPassBeginInfo::default()
|
||||||
unsafe { device.handle.destroy_framebuffer(framebuffer, None) };
|
.render_pass(render_pass.handle)
|
||||||
|
.framebuffer(framebuffers[index])
|
||||||
|
.render_area(render_area)
|
||||||
|
.clear_values(&clear_values);
|
||||||
|
|
||||||
|
unsafe { device.handle.cmd_begin_render_pass(*command_buffer, &render_pass_begin_info, vk::SubpassContents::INLINE); };
|
||||||
|
|
||||||
|
unsafe { device.handle.cmd_bind_pipeline(*command_buffer, vk::PipelineBindPoint::GRAPHICS, pipeline.pipeline) };
|
||||||
|
|
||||||
|
unsafe { device.handle.cmd_draw(*command_buffer, 3, 1, 0, 0) };
|
||||||
|
|
||||||
|
unsafe { device.handle.cmd_end_render_pass(*command_buffer) };
|
||||||
|
|
||||||
|
unsafe { device.handle.end_command_buffer(*command_buffer)? };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let image_available_semaphore = VkSemaphore::new(device.clone())?;
|
||||||
|
let render_finished_semaphore = VkSemaphore::new(device.clone())?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
instance,
|
instance,
|
||||||
surface,
|
surface,
|
||||||
device,
|
device,
|
||||||
|
|
||||||
swapchain,
|
swapchain,
|
||||||
|
render_pass,
|
||||||
|
pipeline,
|
||||||
|
|
||||||
|
command_pool,
|
||||||
|
command_buffers,
|
||||||
|
|
||||||
|
image_available_semaphore,
|
||||||
|
render_finished_semaphore,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self) -> anyhow::Result<()> {
|
pub fn render(&mut self) -> anyhow::Result<()> {
|
||||||
|
let queue = self.device.get_device_queue(0)
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Failed to get a queue"))?;
|
||||||
|
|
||||||
|
let (index, _) = self.swapchain.acquire_next_image(&self.image_available_semaphore)?;
|
||||||
|
|
||||||
|
let wait_semaphores = [self.image_available_semaphore.handle];
|
||||||
|
let signal_semaphores = [self.render_finished_semaphore.handle];
|
||||||
|
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
||||||
|
let command_buffers_to_submit = [self.command_buffers[index as usize]];
|
||||||
|
let submit_info = vk::SubmitInfo::default()
|
||||||
|
.wait_semaphores(&wait_semaphores)
|
||||||
|
.wait_dst_stage_mask(&wait_stages)
|
||||||
|
.command_buffers(&command_buffers_to_submit)
|
||||||
|
.signal_semaphores(&signal_semaphores);
|
||||||
|
|
||||||
|
unsafe { self.device.handle.queue_submit(*queue, &[submit_info], vk::Fence::null())? };
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,4 +150,8 @@ impl VkRenderContext {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit(&self) {
|
||||||
|
unsafe { self.device.handle.device_wait_idle().unwrap() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/vulkan/vk_semaphore.rs
Normal file
29
src/vulkan/vk_semaphore.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use crate::vulkan::VkDevice;
|
||||||
|
use ash::vk;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct VkSemaphore {
|
||||||
|
device: Arc<VkDevice>,
|
||||||
|
|
||||||
|
pub(super) handle: vk::Semaphore,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VkSemaphore {
|
||||||
|
pub fn new(device: Arc<VkDevice>) -> anyhow::Result<Self> {
|
||||||
|
let semaphore_info = vk::SemaphoreCreateInfo::default();
|
||||||
|
let semaphore = unsafe { device.handle.create_semaphore(&semaphore_info, None)? };
|
||||||
|
log::debug!("Semaphore created ({semaphore:?})");
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
device,
|
||||||
|
handle: semaphore,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VkSemaphore {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.device.handle.destroy_semaphore(self.handle, None) };
|
||||||
|
log::debug!("Semaphore destroyed ({:?})", self.handle);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::display::Window;
|
use crate::display::Window;
|
||||||
|
use crate::vulkan::vk_framebuffer::VkSwapchainFramebuffer;
|
||||||
|
use crate::vulkan::vk_render_pass::VkRenderPass;
|
||||||
|
use crate::vulkan::vk_semaphore::VkSemaphore;
|
||||||
use crate::vulkan::vk_surface::SwapchainSupportDetails;
|
use crate::vulkan::vk_surface::SwapchainSupportDetails;
|
||||||
use crate::vulkan::{VkDevice, VkPhysicalDevice, VkSurface};
|
use crate::vulkan::{VkDevice, VkPhysicalDevice, VkSurface};
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
|
@ -8,6 +11,7 @@ use std::sync::Arc;
|
||||||
pub struct VkSwapchain {
|
pub struct VkSwapchain {
|
||||||
surface: Arc<VkSurface>,
|
surface: Arc<VkSurface>,
|
||||||
device: Arc<VkDevice>,
|
device: Arc<VkDevice>,
|
||||||
|
|
||||||
swapchain: Option<vk::SwapchainKHR>,
|
swapchain: Option<vk::SwapchainKHR>,
|
||||||
swapchain_support_details: SwapchainSupportDetails,
|
swapchain_support_details: SwapchainSupportDetails,
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ impl VkSwapchain {
|
||||||
let mut swapchain = Self {
|
let mut swapchain = Self {
|
||||||
surface,
|
surface,
|
||||||
device,
|
device,
|
||||||
|
|
||||||
swapchain: None,
|
swapchain: None,
|
||||||
swapchain_support_details,
|
swapchain_support_details,
|
||||||
desired_image_count,
|
desired_image_count,
|
||||||
|
@ -116,6 +121,16 @@ impl VkSwapchain {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn create_framebuffers(&self, render_pass: Arc<VkRenderPass>) -> Option<Vec<VkSwapchainFramebuffer>> {
|
||||||
|
let present_image_views = self.present_image_views.as_ref()?;
|
||||||
|
|
||||||
|
present_image_views.iter().enumerate()
|
||||||
|
.map(|present_image_view| {
|
||||||
|
VkSwapchainFramebuffer::new()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
|
pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
|
||||||
log::debug!("New resolution requested ({width}x{height})");
|
log::debug!("New resolution requested ({width}x{height})");
|
||||||
|
|
||||||
|
@ -141,6 +156,17 @@ impl VkSwapchain {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn acquire_next_image(&self, semaphore: &VkSemaphore) -> VkResult<(u32, bool)> {
|
||||||
|
unsafe {
|
||||||
|
self.device.swapchain_loader.acquire_next_image(
|
||||||
|
self.swapchain.unwrap(),
|
||||||
|
u64::MAX,
|
||||||
|
semaphore.handle,
|
||||||
|
vk::Fence::null(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_swapchain_info(&self, surface: &VkSurface) -> vk::SwapchainCreateInfoKHR {
|
fn create_swapchain_info(&self, surface: &VkSurface) -> vk::SwapchainCreateInfoKHR {
|
||||||
vk::SwapchainCreateInfoKHR::default()
|
vk::SwapchainCreateInfoKHR::default()
|
||||||
.surface(surface.surface)
|
.surface(surface.surface)
|
||||||
|
|
Loading…
Reference in a new issue