Export triangle to external scene
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 1s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 1s
This commit is contained in:
parent
4b08b7359d
commit
7b5cae8322
18 changed files with 121 additions and 65 deletions
|
@ -1,13 +1,15 @@
|
|||
use crate::display::window::Window;
|
||||
use crate::renderer::vulkan::VkRenderContext;
|
||||
use crate::renderer::{vulkan::VkRenderContext, Renderable};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
use winit::window::WindowId;
|
||||
use crate::scene::TriangleScene;
|
||||
|
||||
pub struct App {
|
||||
window: Window,
|
||||
render_context: Option<VkRenderContext>,
|
||||
scene: Option<Box<dyn Renderable>>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
@ -15,6 +17,18 @@ impl App {
|
|||
Self {
|
||||
window,
|
||||
render_context: None,
|
||||
scene: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_scene(&mut self, mut scene: Box<dyn Renderable>) {
|
||||
let result = self.render_context.as_mut()
|
||||
.ok_or_else(|| anyhow::anyhow!("No render context"))
|
||||
.and_then(|render_context| render_context.init_scene(&mut scene));
|
||||
|
||||
match result {
|
||||
Ok(_) => self.scene = Some(scene),
|
||||
Err(err) => log::warn!("{err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +41,9 @@ impl ApplicationHandler for App {
|
|||
.unwrap();
|
||||
|
||||
self.render_context = VkRenderContext::init(&self.window).ok();
|
||||
|
||||
let scene = TriangleScene::new();
|
||||
self.set_scene(Box::new(scene));
|
||||
}
|
||||
|
||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||
|
@ -59,7 +76,7 @@ impl ApplicationHandler for App {
|
|||
if !event_loop.exiting() {
|
||||
match self.render_context.as_mut() {
|
||||
Some(render_context) => {
|
||||
if let Err(error) = render_context.render() {
|
||||
if let Err(error) = render_context.render(self.scene.as_ref()) {
|
||||
log::error!("Failed to render with render context : {}", error);
|
||||
event_loop.exit();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use winit::event_loop::{ControlFlow, EventLoop};
|
|||
|
||||
mod display;
|
||||
mod renderer;
|
||||
mod scene;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::sync::Arc;
|
||||
use ash::vk;
|
||||
|
||||
pub mod vulkan;
|
||||
|
||||
pub trait Renderable {
|
||||
fn render(device: &vulkan::VkDevice, command_buffer: vk::CommandBuffer);
|
||||
fn init(&mut self, device: &Arc<vulkan::VkDevice>, render_pass: &Arc<vulkan::VkRenderPass>) -> anyhow::Result<()>;
|
||||
fn render(&self, device: &vulkan::VkDevice, swapchain: &vulkan::VkSwapchain, command_buffer: &vk::CommandBuffer) -> anyhow::Result<()>;
|
||||
}
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
pub struct VkCommandPool {
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: vk::CommandPool,
|
||||
pub handle: vk::CommandPool,
|
||||
}
|
||||
|
||||
impl VkCommandPool {
|
||||
|
|
|
@ -5,9 +5,9 @@ use std::sync::Arc;
|
|||
|
||||
pub struct VkDevice {
|
||||
instance: Arc<VkInstance>,
|
||||
pub(super) handle: ash::Device,
|
||||
pub(super) swapchain_loader: ash::khr::swapchain::Device,
|
||||
pub(super) queue_family_index: u32,
|
||||
pub handle: ash::Device,
|
||||
pub swapchain_loader: ash::khr::swapchain::Device,
|
||||
pub queue_family_index: u32,
|
||||
|
||||
// Arc not used because vk::Queue is destroyed with Device automatically
|
||||
// so any references of vk::Queue must be destroyed with VkDevice
|
||||
|
@ -15,7 +15,7 @@ pub struct VkDevice {
|
|||
}
|
||||
|
||||
impl VkDevice {
|
||||
pub(super) fn new_graphics_device(
|
||||
pub fn new_graphics_device(
|
||||
instance: &Arc<VkInstance>,
|
||||
physical_device: &VkPhysicalDevice,
|
||||
queue_family_index: u32,
|
||||
|
@ -64,11 +64,11 @@ impl VkDevice {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn get_device_queue(&self, queue_index: u32) -> Option<&vk::Queue> {
|
||||
pub fn get_device_queue(&self, queue_index: u32) -> Option<&vk::Queue> {
|
||||
self.queues.get(queue_index as usize)
|
||||
}
|
||||
|
||||
pub(super) fn create_command_pool(
|
||||
pub fn create_command_pool(
|
||||
&self,
|
||||
info: &vk::CommandPoolCreateInfo,
|
||||
) -> VkResult<vk::CommandPool> {
|
||||
|
@ -77,18 +77,18 @@ impl VkDevice {
|
|||
unsafe { self.handle.create_command_pool(&info, None) }
|
||||
}
|
||||
|
||||
pub(super) fn allocate_command_buffers(
|
||||
pub fn allocate_command_buffers(
|
||||
&self,
|
||||
info: &vk::CommandBufferAllocateInfo,
|
||||
) -> VkResult<Vec<vk::CommandBuffer>> {
|
||||
unsafe { self.handle.allocate_command_buffers(&info) }
|
||||
}
|
||||
|
||||
pub(super) fn create_fence(&self, info: &vk::FenceCreateInfo) -> VkResult<vk::Fence> {
|
||||
pub fn create_fence(&self, info: &vk::FenceCreateInfo) -> VkResult<vk::Fence> {
|
||||
unsafe { self.handle.create_fence(&info, None) }
|
||||
}
|
||||
|
||||
pub(super) fn create_semaphore(
|
||||
pub fn create_semaphore(
|
||||
&self,
|
||||
info: &vk::SemaphoreCreateInfo,
|
||||
) -> VkResult<vk::Semaphore> {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
|||
pub struct VkFence {
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: vk::Fence,
|
||||
pub handle: vk::Fence,
|
||||
}
|
||||
|
||||
impl VkFence {
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct VkFramebuffer {
|
|||
image_view: Arc<vk::ImageView>,
|
||||
render_pass: Arc<VkRenderPass>,
|
||||
|
||||
pub(super) handle: vk::Framebuffer,
|
||||
pub handle: vk::Framebuffer,
|
||||
}
|
||||
|
||||
impl VkFramebuffer {
|
||||
|
|
|
@ -7,8 +7,8 @@ pub struct VkGraphicsPipeline {
|
|||
device: Arc<VkDevice>,
|
||||
render_pass: Arc<VkRenderPass>,
|
||||
|
||||
pub(super) pipeline_layout: vk::PipelineLayout,
|
||||
pub(super) pipeline: vk::Pipeline,
|
||||
pub pipeline_layout: vk::PipelineLayout,
|
||||
pub pipeline: vk::Pipeline,
|
||||
vertex_shader: VkShaderModule,
|
||||
fragment_shader: VkShaderModule,
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use ash::{vk, Entry, Instance};
|
|||
use std::ffi::{c_char, CStr, CString};
|
||||
|
||||
pub struct VkInstance {
|
||||
pub(super) entry: Entry,
|
||||
pub(super) handle: Instance,
|
||||
pub(super) surface_loader: surface::Instance,
|
||||
pub entry: Entry,
|
||||
pub handle: Instance,
|
||||
pub surface_loader: surface::Instance,
|
||||
}
|
||||
|
||||
impl VkInstance {
|
||||
|
|
|
@ -3,7 +3,7 @@ use ash::vk;
|
|||
|
||||
pub struct VkPhysicalDevice {
|
||||
// Vulkan properties
|
||||
pub(super) handle: vk::PhysicalDevice,
|
||||
pub handle: vk::PhysicalDevice,
|
||||
pub properties: vk::PhysicalDeviceProperties,
|
||||
pub features: vk::PhysicalDeviceFeatures,
|
||||
pub queue_family_properties: Vec<vk::QueueFamilyProperties>,
|
||||
|
|
|
@ -4,6 +4,7 @@ use super::{
|
|||
};
|
||||
use ash::vk;
|
||||
use std::sync::Arc;
|
||||
use crate::renderer::Renderable;
|
||||
|
||||
pub struct VkRenderContext {
|
||||
instance: Arc<VkInstance>,
|
||||
|
@ -13,7 +14,7 @@ pub struct VkRenderContext {
|
|||
swapchain: Arc<VkSwapchain>,
|
||||
render_pass: Arc<VkRenderPass>,
|
||||
framebuffers: Vec<Arc<VkFramebuffer>>,
|
||||
pipeline: Arc<VkGraphicsPipeline>,
|
||||
|
||||
command_pool: VkCommandPool,
|
||||
command_buffers: Vec<vk::CommandBuffer>,
|
||||
image_available_semaphore: VkSemaphore,
|
||||
|
@ -62,8 +63,6 @@ impl VkRenderContext {
|
|||
.create_framebuffers(&render_pass)
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to get framebuffers"))?;
|
||||
|
||||
let pipeline = Arc::new(VkGraphicsPipeline::new(&device, &render_pass)?);
|
||||
|
||||
let command_pool = VkCommandPool::new(&device)?;
|
||||
|
||||
// Destroyed with command pool
|
||||
|
@ -82,7 +81,6 @@ impl VkRenderContext {
|
|||
swapchain,
|
||||
render_pass,
|
||||
framebuffers,
|
||||
pipeline,
|
||||
|
||||
command_pool,
|
||||
command_buffers,
|
||||
|
@ -93,7 +91,7 @@ impl VkRenderContext {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> anyhow::Result<()> {
|
||||
pub fn render(&mut self, scene: Option<&Box<dyn Renderable>>) -> anyhow::Result<()> {
|
||||
unsafe { self.device.handle.wait_for_fences(&[self.in_flight_fence.handle], true, u64::MAX)? };
|
||||
unsafe { self.device.handle.reset_fences(&[self.in_flight_fence.handle])? };
|
||||
|
||||
|
@ -133,26 +131,9 @@ impl VkRenderContext {
|
|||
);
|
||||
};
|
||||
|
||||
unsafe {
|
||||
self.device.handle.cmd_bind_pipeline(
|
||||
command_buffer,
|
||||
vk::PipelineBindPoint::GRAPHICS,
|
||||
self.pipeline.pipeline,
|
||||
)
|
||||
};
|
||||
|
||||
let viewport = vk::Viewport::default()
|
||||
.width(self.swapchain.surface_resolution.width as f32)
|
||||
.height(self.swapchain.surface_resolution.height as f32)
|
||||
.max_depth(1.0);
|
||||
|
||||
unsafe { self.device.handle.cmd_set_viewport(command_buffer, 0, &[viewport]) }
|
||||
|
||||
let scissor = self.swapchain.surface_resolution.into();
|
||||
|
||||
unsafe { self.device.handle.cmd_set_scissor(command_buffer, 0, &[scissor]) }
|
||||
|
||||
unsafe { self.device.handle.cmd_draw(command_buffer, 3, 1, 0, 0) };
|
||||
if let Some(scene) = scene {
|
||||
scene.render(&self.device, &self.swapchain, &command_buffer)?;
|
||||
}
|
||||
|
||||
unsafe { self.device.handle.cmd_end_render_pass(command_buffer) };
|
||||
|
||||
|
@ -204,6 +185,10 @@ impl VkRenderContext {
|
|||
unsafe { self.device.handle.device_wait_idle().unwrap() }
|
||||
}
|
||||
|
||||
pub fn init_scene(&self, scene: &mut Box<dyn Renderable>) -> anyhow::Result<()> {
|
||||
scene.init(&self.device, &self.render_pass)
|
||||
}
|
||||
|
||||
fn update_swapchain(&mut self) -> anyhow::Result<()> {
|
||||
match Arc::get_mut(&mut self.swapchain) {
|
||||
Some(swapchain) => {
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
pub struct VkRenderPass {
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: vk::RenderPass,
|
||||
pub handle: vk::RenderPass,
|
||||
}
|
||||
|
||||
impl VkRenderPass {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
|||
pub struct VkSemaphore {
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: vk::Semaphore,
|
||||
pub handle: vk::Semaphore,
|
||||
}
|
||||
|
||||
impl VkSemaphore {
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
pub struct VkShaderModule {
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: vk::ShaderModule,
|
||||
pub handle: vk::ShaderModule,
|
||||
}
|
||||
|
||||
impl VkShaderModule {
|
||||
|
|
|
@ -13,7 +13,7 @@ pub struct SwapchainSupportDetails(
|
|||
pub struct VkSurface {
|
||||
instance: Arc<VkInstance>,
|
||||
|
||||
pub(super) handle: vk::SurfaceKHR,
|
||||
pub handle: vk::SurfaceKHR,
|
||||
}
|
||||
|
||||
impl VkSurface {
|
||||
|
|
|
@ -8,22 +8,22 @@ pub struct VkSwapchain {
|
|||
surface: Arc<VkSurface>,
|
||||
device: Arc<VkDevice>,
|
||||
|
||||
pub(super) handle: Option<vk::SwapchainKHR>,
|
||||
pub handle: Option<vk::SwapchainKHR>,
|
||||
swapchain_support_details: SwapchainSupportDetails,
|
||||
|
||||
pub(super) desired_image_count: u32,
|
||||
pub(super) surface_format: vk::SurfaceFormatKHR,
|
||||
pub(super) surface_resolution: vk::Extent2D,
|
||||
pub(super) new_requested_surface_resolution: Option<vk::Extent2D>,
|
||||
pub(super) present_mode: vk::PresentModeKHR,
|
||||
pub(super) pre_transform: vk::SurfaceTransformFlagsKHR,
|
||||
pub desired_image_count: u32,
|
||||
pub surface_format: vk::SurfaceFormatKHR,
|
||||
pub surface_resolution: vk::Extent2D,
|
||||
pub new_requested_surface_resolution: Option<vk::Extent2D>,
|
||||
pub present_mode: vk::PresentModeKHR,
|
||||
pub pre_transform: vk::SurfaceTransformFlagsKHR,
|
||||
|
||||
pub(super) present_images: Option<Vec<vk::Image>>,
|
||||
pub(super) present_image_views: Option<Vec<Arc<vk::ImageView>>>,
|
||||
pub present_images: Option<Vec<vk::Image>>,
|
||||
pub present_image_views: Option<Vec<Arc<vk::ImageView>>>,
|
||||
}
|
||||
|
||||
impl VkSwapchain {
|
||||
pub(super) fn new(
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
surface: &Arc<VkSurface>,
|
||||
device: &Arc<VkDevice>,
|
||||
|
@ -78,7 +78,7 @@ impl VkSwapchain {
|
|||
Ok(swapchain)
|
||||
}
|
||||
|
||||
pub(super) fn create_swapchain(&mut self) -> VkResult<()> {
|
||||
pub fn create_swapchain(&mut self) -> VkResult<()> {
|
||||
if let Some(new_requested_surface_resolution) = self.new_requested_surface_resolution {
|
||||
self.surface_resolution = new_requested_surface_resolution;
|
||||
self.new_requested_surface_resolution = None;
|
||||
|
@ -125,7 +125,7 @@ impl VkSwapchain {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn create_framebuffers(
|
||||
pub fn create_framebuffers(
|
||||
&self,
|
||||
render_pass: &Arc<VkRenderPass>,
|
||||
) -> Option<Vec<Arc<VkFramebuffer>>> {
|
||||
|
@ -148,7 +148,7 @@ impl VkSwapchain {
|
|||
)
|
||||
}
|
||||
|
||||
pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
|
||||
pub fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
|
||||
log::debug!("New resolution requested ({width}x{height})");
|
||||
|
||||
let chosen_extent = Self::choose_swapchain_extent(
|
||||
|
@ -171,7 +171,7 @@ impl VkSwapchain {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn acquire_next_image(&self, semaphore: &VkSemaphore) -> VkResult<(u32, bool)> {
|
||||
pub fn acquire_next_image(&self, semaphore: &VkSemaphore) -> VkResult<(u32, bool)> {
|
||||
unsafe {
|
||||
self.device.swapchain_loader.acquire_next_image(
|
||||
self.handle.unwrap(),
|
||||
|
@ -182,7 +182,7 @@ impl VkSwapchain {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_dirty(&self) -> bool {
|
||||
pub fn is_dirty(&self) -> bool {
|
||||
self.new_requested_surface_resolution.is_some()
|
||||
}
|
||||
|
||||
|
|
2
src/scene/mod.rs
Normal file
2
src/scene/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
mod triangle;
|
||||
pub use triangle::Triangle as TriangleScene;
|
49
src/scene/triangle.rs
Normal file
49
src/scene/triangle.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use std::sync::Arc;
|
||||
use ash::vk;
|
||||
use crate::renderer::vulkan::{VkDevice, VkGraphicsPipeline, VkRenderPass, VkSwapchain};
|
||||
use crate::renderer::Renderable;
|
||||
use ash::vk::CommandBuffer;
|
||||
|
||||
pub struct Triangle {
|
||||
pipeline: Option<VkGraphicsPipeline>,
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
pub fn new() -> Self {
|
||||
Self { pipeline: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for Triangle {
|
||||
fn init(&mut self, device: &Arc<VkDevice>, render_pass: &Arc<VkRenderPass>) -> anyhow::Result<()> {
|
||||
let pipeline = VkGraphicsPipeline::new(&device, &render_pass)?;
|
||||
self.pipeline = Some(pipeline);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render(&self, device: &VkDevice, swapchain: &VkSwapchain, command_buffer: &CommandBuffer) -> anyhow::Result<()> {
|
||||
unsafe {
|
||||
device.handle.cmd_bind_pipeline(
|
||||
*command_buffer,
|
||||
vk::PipelineBindPoint::GRAPHICS,
|
||||
self.pipeline.as_ref().unwrap().pipeline,
|
||||
)
|
||||
};
|
||||
|
||||
let viewport = vk::Viewport::default()
|
||||
.width(swapchain.surface_resolution.width as f32)
|
||||
.height(swapchain.surface_resolution.height as f32)
|
||||
.max_depth(1.0);
|
||||
|
||||
unsafe { device.handle.cmd_set_viewport(*command_buffer, 0, &[viewport]) }
|
||||
|
||||
let scissor = swapchain.surface_resolution.into();
|
||||
|
||||
unsafe { device.handle.cmd_set_scissor(*command_buffer, 0, &[scissor]) }
|
||||
|
||||
unsafe { device.handle.cmd_draw(*command_buffer, 3, 1, 0, 0) };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue