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::{
|
||||
create_command_buffers, create_command_pool, create_framebuffers, create_instance,
|
||||
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;
|
||||
@ -13,11 +13,21 @@ use ::vulkanalia::loader::{LibloadingLoader, LIBRARY};
|
||||
use ::vulkanalia::prelude::v1_0::*;
|
||||
use ::vulkanalia::vk::{ExtDebugUtilsExtension, KhrSurfaceExtension, KhrSwapchainExtension};
|
||||
use ::vulkanalia::window as vk_window;
|
||||
use ::vulkanalia::Version;
|
||||
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");
|
||||
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.
|
||||
#[derive(Clone, Debug)]
|
||||
@ -25,7 +35,8 @@ pub struct App {
|
||||
entry: Entry,
|
||||
instance: Instance,
|
||||
data: AppData,
|
||||
device: Device,
|
||||
pub device: Device,
|
||||
frame: usize,
|
||||
}
|
||||
|
||||
impl App {
|
||||
@ -51,12 +62,14 @@ impl App {
|
||||
create_framebuffers(&device, &mut data)?;
|
||||
create_command_pool(&instance, &device, &mut data)?;
|
||||
create_command_buffers(&device, &mut data)?;
|
||||
create_sync_objects(&device, &mut data)?;
|
||||
|
||||
Ok(Self {
|
||||
entry,
|
||||
instance,
|
||||
data,
|
||||
device,
|
||||
frame: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@ -65,6 +78,41 @@ impl App {
|
||||
/// # Safety
|
||||
/// Here be Dragons
|
||||
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(())
|
||||
}
|
||||
|
||||
@ -73,6 +121,14 @@ impl App {
|
||||
/// # Safety
|
||||
/// Here be Dragons
|
||||
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
|
||||
.destroy_command_pool(self.data.command_pool, None);
|
||||
self.data
|
||||
@ -127,6 +183,9 @@ pub struct AppData {
|
||||
command_pool: vk::CommandPool,
|
||||
// Command Buffers
|
||||
command_buffers: Vec<vk::CommandBuffer>,
|
||||
// Sync Objects
|
||||
image_available_semaphores: Vec<vk::Semaphore>,
|
||||
render_finished_semaphores: Vec<vk::Semaphore>,
|
||||
}
|
||||
|
||||
impl AppData {}
|
||||
|
@ -76,11 +76,13 @@ pub(super) unsafe fn create_instance(
|
||||
}
|
||||
|
||||
// Compatibility extension for macOS
|
||||
let flags = if entry
|
||||
.enumerate_instance_extension_properties(None)?
|
||||
.iter()
|
||||
.any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name)
|
||||
let flags = if (cfg!(target_os = "macos") && entry.version()? >= PORTABILITY_MACOS_VERSION)
|
||||
|| entry
|
||||
.enumerate_instance_extension_properties(None)?
|
||||
.iter()
|
||||
.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_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION
|
||||
@ -397,12 +399,21 @@ pub(super) unsafe fn create_render_pass(
|
||||
let subpass = vk::SubpassDescription::builder()
|
||||
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
||||
.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 subpasses = &[subpass];
|
||||
let dependencies = &[dependency];
|
||||
let info = vk::RenderPassCreateInfo::builder()
|
||||
.attachments(attachments)
|
||||
.subpasses(subpasses);
|
||||
.subpasses(subpasses)
|
||||
.dependencies(dependencies);
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
use ::anyhow::Result;
|
||||
use ::vulkanalia::vk::DeviceV1_0;
|
||||
use ::winit::dpi::LogicalSize;
|
||||
use ::winit::event::{Event, WindowEvent};
|
||||
use ::winit::event_loop::{ControlFlow, EventLoop};
|
||||
@ -33,6 +34,7 @@ pub fn run() -> Result<()> {
|
||||
destroying = true;
|
||||
*control_flow = ControlFlow::Exit;
|
||||
unsafe {
|
||||
app.device.device_wait_idle().unwrap();
|
||||
app.destroy();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user