Actually display a triangle on screen!
This commit is contained in:
parent
b0159a299c
commit
61bd125414
67
src/app.rs
67
src/app.rs
@ -2,7 +2,7 @@ mod functions;
|
|||||||
use functions::{
|
use functions::{
|
||||||
create_command_buffers, create_command_pool, create_framebuffers, create_instance,
|
create_command_buffers, create_command_pool, create_framebuffers, create_instance,
|
||||||
create_logical_device, create_pipeline, create_render_pass, create_swapchain,
|
create_logical_device, create_pipeline, create_render_pass, create_swapchain,
|
||||||
create_swapchain_image_views, pick_physical_device,
|
create_swapchain_image_views, create_sync_objects, pick_physical_device,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::VALIDATION_ENABLED;
|
use crate::VALIDATION_ENABLED;
|
||||||
@ -13,11 +13,21 @@ use ::vulkanalia::loader::{LibloadingLoader, LIBRARY};
|
|||||||
use ::vulkanalia::prelude::v1_0::*;
|
use ::vulkanalia::prelude::v1_0::*;
|
||||||
use ::vulkanalia::vk::{ExtDebugUtilsExtension, KhrSurfaceExtension, KhrSwapchainExtension};
|
use ::vulkanalia::vk::{ExtDebugUtilsExtension, KhrSurfaceExtension, KhrSwapchainExtension};
|
||||||
use ::vulkanalia::window as vk_window;
|
use ::vulkanalia::window as vk_window;
|
||||||
|
use ::vulkanalia::Version;
|
||||||
use ::winit::window::Window;
|
use ::winit::window::Window;
|
||||||
|
|
||||||
pub(crate) const VALIDATION_LAYER: vk::ExtensionName =
|
/// The name of the validation layers.
|
||||||
|
pub const VALIDATION_LAYER: vk::ExtensionName =
|
||||||
vk::ExtensionName::from_bytes(b"VK_LAYER_KHRONOS_validation");
|
vk::ExtensionName::from_bytes(b"VK_LAYER_KHRONOS_validation");
|
||||||
pub(crate) const DEVICE_EXTENSIONS: &[vk::ExtensionName] = &[vk::KHR_SWAPCHAIN_EXTENSION.name];
|
|
||||||
|
/// The Vulkan SDK version that started requiring the portability subset extension for macOS.
|
||||||
|
pub const PORTABILITY_MACOS_VERSION: Version = Version::new(1, 3, 216);
|
||||||
|
|
||||||
|
/// The required device extensions
|
||||||
|
pub const DEVICE_EXTENSIONS: &[vk::ExtensionName] = &[vk::KHR_SWAPCHAIN_EXTENSION.name];
|
||||||
|
|
||||||
|
/// The maximum number of frames that can be processed concurrently.
|
||||||
|
pub const MAX_FRAMES_IN_FLIGHT: usize = 2;
|
||||||
|
|
||||||
/// Our Vulkan app.
|
/// Our Vulkan app.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -25,7 +35,8 @@ pub struct App {
|
|||||||
entry: Entry,
|
entry: Entry,
|
||||||
instance: Instance,
|
instance: Instance,
|
||||||
data: AppData,
|
data: AppData,
|
||||||
device: Device,
|
pub device: Device,
|
||||||
|
frame: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
@ -51,12 +62,14 @@ impl App {
|
|||||||
create_framebuffers(&device, &mut data)?;
|
create_framebuffers(&device, &mut data)?;
|
||||||
create_command_pool(&instance, &device, &mut data)?;
|
create_command_pool(&instance, &device, &mut data)?;
|
||||||
create_command_buffers(&device, &mut data)?;
|
create_command_buffers(&device, &mut data)?;
|
||||||
|
create_sync_objects(&device, &mut data)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
entry,
|
entry,
|
||||||
instance,
|
instance,
|
||||||
data,
|
data,
|
||||||
device,
|
device,
|
||||||
|
frame: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +78,41 @@ impl App {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// Here be Dragons
|
/// Here be Dragons
|
||||||
pub unsafe fn render(&mut self, _window: &Window) -> Result<()> {
|
pub unsafe fn render(&mut self, _window: &Window) -> Result<()> {
|
||||||
|
let image_index = self
|
||||||
|
.device
|
||||||
|
.acquire_next_image_khr(
|
||||||
|
self.data.swapchain,
|
||||||
|
u64::max_value(),
|
||||||
|
self.data.image_available_semaphores[self.frame],
|
||||||
|
vk::Fence::null(),
|
||||||
|
)?
|
||||||
|
.0 as usize;
|
||||||
|
|
||||||
|
let wait_semaphores = &[self.data.image_available_semaphores[self.frame]];
|
||||||
|
let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
||||||
|
let command_buffers = &[self.data.command_buffers[image_index as usize]];
|
||||||
|
let signal_semaphores = &[self.data.render_finished_semaphores[self.frame]];
|
||||||
|
let submit_info = vk::SubmitInfo::builder()
|
||||||
|
.wait_semaphores(wait_semaphores)
|
||||||
|
.wait_dst_stage_mask(wait_stages)
|
||||||
|
.command_buffers(command_buffers)
|
||||||
|
.signal_semaphores(signal_semaphores);
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.queue_submit(self.data.graphics_queue, &[submit_info], vk::Fence::null())?;
|
||||||
|
|
||||||
|
let swapchains = &[self.data.swapchain];
|
||||||
|
let image_indices = &[image_index as u32];
|
||||||
|
let present_info = vk::PresentInfoKHR::builder()
|
||||||
|
.wait_semaphores(signal_semaphores)
|
||||||
|
.swapchains(swapchains)
|
||||||
|
.image_indices(image_indices);
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.queue_present_khr(self.data.present_queue, &present_info)?;
|
||||||
|
|
||||||
|
self.frame = (self.frame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +121,14 @@ impl App {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// Here be Dragons
|
/// Here be Dragons
|
||||||
pub unsafe fn destroy(&mut self) {
|
pub unsafe fn destroy(&mut self) {
|
||||||
|
self.data
|
||||||
|
.render_finished_semaphores
|
||||||
|
.iter()
|
||||||
|
.for_each(|s| self.device.destroy_semaphore(*s, None));
|
||||||
|
self.data
|
||||||
|
.image_available_semaphores
|
||||||
|
.iter()
|
||||||
|
.for_each(|s| self.device.destroy_semaphore(*s, None));
|
||||||
self.device
|
self.device
|
||||||
.destroy_command_pool(self.data.command_pool, None);
|
.destroy_command_pool(self.data.command_pool, None);
|
||||||
self.data
|
self.data
|
||||||
@ -127,6 +183,9 @@ pub struct AppData {
|
|||||||
command_pool: vk::CommandPool,
|
command_pool: vk::CommandPool,
|
||||||
// Command Buffers
|
// Command Buffers
|
||||||
command_buffers: Vec<vk::CommandBuffer>,
|
command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
// Sync Objects
|
||||||
|
image_available_semaphores: Vec<vk::Semaphore>,
|
||||||
|
render_finished_semaphores: Vec<vk::Semaphore>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppData {}
|
impl AppData {}
|
||||||
|
@ -76,11 +76,13 @@ pub(super) unsafe fn create_instance(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compatibility extension for macOS
|
// Compatibility extension for macOS
|
||||||
let flags = if entry
|
let flags = if (cfg!(target_os = "macos") && entry.version()? >= PORTABILITY_MACOS_VERSION)
|
||||||
|
|| entry
|
||||||
.enumerate_instance_extension_properties(None)?
|
.enumerate_instance_extension_properties(None)?
|
||||||
.iter()
|
.iter()
|
||||||
.any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name)
|
.any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name)
|
||||||
{
|
{
|
||||||
|
info!("Enabling extensions for macOS compatibility.");
|
||||||
extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr());
|
extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr());
|
||||||
extensions.push(
|
extensions.push(
|
||||||
vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION
|
vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION
|
||||||
@ -397,12 +399,21 @@ pub(super) unsafe fn create_render_pass(
|
|||||||
let subpass = vk::SubpassDescription::builder()
|
let subpass = vk::SubpassDescription::builder()
|
||||||
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
||||||
.color_attachments(color_attachments);
|
.color_attachments(color_attachments);
|
||||||
|
let dependency = vk::SubpassDependency::builder()
|
||||||
|
.src_subpass(vk::SUBPASS_EXTERNAL)
|
||||||
|
.dst_subpass(0)
|
||||||
|
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
||||||
|
.src_access_mask(vk::AccessFlags::empty())
|
||||||
|
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
||||||
|
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
|
||||||
|
|
||||||
let attachments = &[color_attachment];
|
let attachments = &[color_attachment];
|
||||||
let subpasses = &[subpass];
|
let subpasses = &[subpass];
|
||||||
|
let dependencies = &[dependency];
|
||||||
let info = vk::RenderPassCreateInfo::builder()
|
let info = vk::RenderPassCreateInfo::builder()
|
||||||
.attachments(attachments)
|
.attachments(attachments)
|
||||||
.subpasses(subpasses);
|
.subpasses(subpasses)
|
||||||
|
.dependencies(dependencies);
|
||||||
|
|
||||||
data.render_pass = device.create_render_pass(&info, None)?;
|
data.render_pass = device.create_render_pass(&info, None)?;
|
||||||
|
|
||||||
@ -615,3 +626,16 @@ pub(super) unsafe fn create_command_buffers(device: &Device, data: &mut AppData)
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) unsafe fn create_sync_objects(device: &Device, data: &mut AppData) -> Result<()> {
|
||||||
|
let semaphore_info = vk::SemaphoreCreateInfo::builder();
|
||||||
|
|
||||||
|
for _ in 0..MAX_FRAMES_IN_FLIGHT {
|
||||||
|
data.image_available_semaphores
|
||||||
|
.push(device.create_semaphore(&semaphore_info, None)?);
|
||||||
|
data.render_finished_semaphores
|
||||||
|
.push(device.create_semaphore(&semaphore_info, None)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ mod app;
|
|||||||
pub use app::App;
|
pub use app::App;
|
||||||
|
|
||||||
use ::anyhow::Result;
|
use ::anyhow::Result;
|
||||||
|
use ::vulkanalia::vk::DeviceV1_0;
|
||||||
use ::winit::dpi::LogicalSize;
|
use ::winit::dpi::LogicalSize;
|
||||||
use ::winit::event::{Event, WindowEvent};
|
use ::winit::event::{Event, WindowEvent};
|
||||||
use ::winit::event_loop::{ControlFlow, EventLoop};
|
use ::winit::event_loop::{ControlFlow, EventLoop};
|
||||||
@ -33,6 +34,7 @@ pub fn run() -> Result<()> {
|
|||||||
destroying = true;
|
destroying = true;
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
app.device.device_wait_idle().unwrap();
|
||||||
app.destroy();
|
app.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user