Add logical device struct and surface handling for Vulkan
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
Introduce the VkLogicalDevice struct and add surface creation logic in VkInstance. Also, import necessary extensions and refine Vulkan physical device and window handling. Included a dependency on 'anyhow' for error management.
This commit is contained in:
parent
4048937a6c
commit
da0be47b14
14 changed files with 258 additions and 153 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -116,6 +116,12 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -1066,6 +1072,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
name = "rust_ash_test"
|
name = "rust_ash_test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"ash",
|
"ash",
|
||||||
"ash-window",
|
"ash-window",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|
|
@ -6,6 +6,7 @@ authors = ["Florian RICHER <florian.richer@protonmail.com>"]
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
winit = { version = "0.30", features = [ "rwh_06" ] }
|
winit = { version = "0.30", features = [ "rwh_06" ] }
|
||||||
ash = { version = "0.38", default-features = false, features = ["linked", "debug", "std"] }
|
ash = { version = "0.38", default-features = false, features = ["linked", "debug", "std"] }
|
||||||
ash-window = "0.13"
|
ash-window = "0.13"
|
||||||
|
|
|
@ -1,52 +1,70 @@
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use winit::{
|
use ash::vk::QueueFlags;
|
||||||
application::ApplicationHandler, event::WindowEvent, event_loop::ActiveEventLoop, raw_window_handle::{HasDisplayHandle, DisplayHandle, HandleError}, window::{Window, WindowId}
|
use winit::application::ApplicationHandler;
|
||||||
};
|
use winit::event::WindowEvent;
|
||||||
use winit::window::WindowAttributes;
|
use winit::event_loop::ActiveEventLoop;
|
||||||
use crate::vulkan::VkInstance;
|
use winit::window::{WindowId};
|
||||||
|
use crate::display::window::Window;
|
||||||
|
use crate::vulkan::{VkInstance, VkPhysicalDevice};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
window_attributes: WindowAttributes,
|
window: Window,
|
||||||
window: Option<Window>,
|
instance: Option<VkInstance>
|
||||||
instance: Option<VkInstance>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(window_attributes: WindowAttributes) -> Self {
|
pub fn new(window: Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
window_attributes,
|
window,
|
||||||
window: None,
|
instance: None
|
||||||
instance: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl HasDisplayHandle for App {
|
fn init_vulkan(&mut self) {
|
||||||
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
|
let required_extensions = self.window
|
||||||
self.window.as_ref()
|
.required_extensions()
|
||||||
.ok_or_else(|| HandleError::Unavailable)?
|
.expect("Unable to get required required extensions");
|
||||||
.display_handle()
|
|
||||||
|
log::info!("Initializing Vulkan instance");
|
||||||
|
let instance = VkInstance::new(&required_extensions);
|
||||||
|
log::info!("Vulkan instance created");
|
||||||
|
log::info!("\t{}", instance);
|
||||||
|
|
||||||
|
let surface = instance.create_surface(&self.window)
|
||||||
|
.expect("Unable to create surface");
|
||||||
|
|
||||||
|
let mut physical_devices = instance.get_physical_devices();
|
||||||
|
physical_devices.sort_by(|a, b| b.priority().cmp(&a.priority()));
|
||||||
|
|
||||||
|
let (physical_device, queue_family_index) = physical_devices
|
||||||
|
.iter()
|
||||||
|
.find_map(|physical_device| {
|
||||||
|
physical_device.queue_family_properties
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(index, queue_family_property)| {
|
||||||
|
if surface.physical_device_queue_supported(physical_device, index as u32).unwrap_or(false) {
|
||||||
|
Some((physical_device, index as u32))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.expect("Unable to find suitable device");
|
||||||
|
|
||||||
|
|
||||||
|
self.instance = Some(instance);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplicationHandler for App {
|
impl ApplicationHandler for App {
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
self.window = event_loop
|
self.window.create_window(event_loop)
|
||||||
.create_window(self.window_attributes.clone())
|
.map_err(|err| format!("Failed to create window: {}", err))
|
||||||
.ok();
|
.unwrap();
|
||||||
|
|
||||||
self.instance = self.window
|
self.init_vulkan();
|
||||||
.as_ref()
|
|
||||||
.and_then(|w| Some(VkInstance::new(w)));
|
|
||||||
|
|
||||||
if let Some(instance) = self.instance.as_ref() {
|
|
||||||
let physical_devices = instance.get_physical_devices();
|
|
||||||
|
|
||||||
log::info!("Physical Devices:");
|
|
||||||
for physical_device in physical_devices {
|
|
||||||
log::info!("{}", physical_device)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
|
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
|
||||||
|
@ -55,10 +73,7 @@ impl ApplicationHandler for App {
|
||||||
log::info!("The close button was pressed; stopping");
|
log::info!("The close button was pressed; stopping");
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
WindowEvent::RedrawRequested => {
|
_ => self.window.window_event(event_loop, id, event),
|
||||||
self.window.as_ref().unwrap().request_redraw();
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
mod app;
|
mod app;
|
||||||
pub use app::App;
|
mod window;
|
||||||
|
|
||||||
|
pub use app::App;
|
||||||
|
pub use window::Window;
|
63
src/display/window.rs
Normal file
63
src/display/window.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use std::ffi::c_char;
|
||||||
|
use winit::event::WindowEvent;
|
||||||
|
use winit::event_loop::ActiveEventLoop;
|
||||||
|
use winit::raw_window_handle::HasDisplayHandle;
|
||||||
|
use winit::window::WindowId;
|
||||||
|
|
||||||
|
pub struct Window {
|
||||||
|
handle: Option<winit::window::Window>,
|
||||||
|
window_attributes: winit::window::WindowAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn new(window_attributes: winit::window::WindowAttributes) -> Self {
|
||||||
|
Self {
|
||||||
|
handle: None,
|
||||||
|
window_attributes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_window(&mut self, event_loop: &ActiveEventLoop) -> anyhow::Result<()> {
|
||||||
|
let window = event_loop.create_window(self.window_attributes.clone())?;
|
||||||
|
|
||||||
|
self.handle = Some(window);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn required_extensions(&self) -> anyhow::Result<Vec<*const c_char>> {
|
||||||
|
let display_handle = self.handle
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_else(||anyhow::anyhow!("Window not found"))?
|
||||||
|
.display_handle()?;
|
||||||
|
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut extension_names = ash_window::enumerate_required_extensions(display_handle.as_raw())?
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
{
|
||||||
|
extension_names.push(ash::khr::portability_enumeration::NAME.as_ptr());
|
||||||
|
// Enabling this extension is a requirement when using `VK_KHR_portability_subset`
|
||||||
|
extension_names.push(ash::khr::get_physical_device_properties2::NAME.as_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(extension_names)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle(&self) -> Option<&winit::window::Window> {
|
||||||
|
self.handle.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_event(&mut self, _event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||||
|
match event {
|
||||||
|
WindowEvent::RedrawRequested => {
|
||||||
|
match self.handle.as_ref() {
|
||||||
|
Some(window) => window.request_redraw(),
|
||||||
|
None => log::warn!("Redraw requested but no window found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use winit::event_loop::EventLoop;
|
use winit::event_loop::EventLoop;
|
||||||
use winit::window::Window;
|
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
mod vulkan;
|
mod vulkan;
|
||||||
|
@ -9,7 +8,7 @@ fn main() {
|
||||||
|
|
||||||
let event_loop = EventLoop::new().unwrap();
|
let event_loop = EventLoop::new().unwrap();
|
||||||
|
|
||||||
let window_attributes = Window::default_attributes()
|
let window_attributes = winit::window::Window::default_attributes()
|
||||||
.with_title("Rust ASH Test")
|
.with_title("Rust ASH Test")
|
||||||
.with_visible(true)
|
.with_visible(true)
|
||||||
.with_inner_size(winit::dpi::LogicalSize::new(
|
.with_inner_size(winit::dpi::LogicalSize::new(
|
||||||
|
@ -17,7 +16,8 @@ fn main() {
|
||||||
f64::from(600),
|
f64::from(600),
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut app = display::App::new(window_attributes);
|
let window = display::Window::new(window_attributes);
|
||||||
|
let mut app = display::App::new(window);
|
||||||
|
|
||||||
let _ = event_loop.run_app(&mut app);
|
let _ = event_loop.run_app(&mut app);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
pub(self) mod vk_instance;
|
pub(self) mod vk_instance;
|
||||||
pub(self) mod vk_physical_device;
|
pub(self) mod vk_physical_device;
|
||||||
|
pub(self) mod vk_logical_device;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod vk_surface;
|
||||||
|
|
||||||
pub use vk_instance::VkInstance;
|
pub use vk_instance::VkInstance;
|
||||||
pub use vk_physical_device::VkPhysicalDevice;
|
pub use vk_physical_device::VkPhysicalDevice;
|
|
@ -1,74 +0,0 @@
|
||||||
use std::ffi::CString;
|
|
||||||
|
|
||||||
pub fn use_layers(
|
|
||||||
entry: &ash::Entry,
|
|
||||||
layers_to_select: Vec<&str>,
|
|
||||||
) -> Vec<CString> {
|
|
||||||
let layers_available = get_layers_available(entry);
|
|
||||||
|
|
||||||
log_layers_available(&layers_available);
|
|
||||||
|
|
||||||
let selected_layers = select_layers(&layers_available, &layers_to_select);
|
|
||||||
|
|
||||||
log_layers_wanted(&layers_to_select, &selected_layers);
|
|
||||||
|
|
||||||
selected_layers
|
|
||||||
.iter()
|
|
||||||
.map(|sl| CString::new(sl.clone().as_bytes()).unwrap())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_layers_available(entry: &ash::Entry) -> Vec<ash::vk::LayerProperties> {
|
|
||||||
unsafe { entry.enumerate_instance_layer_properties().unwrap_or_default() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log_layers_available(layers_available: &[ash::vk::LayerProperties]) {
|
|
||||||
log::info!("Available layers ({}):", layers_available.len());
|
|
||||||
for l in layers_available {
|
|
||||||
log::info!(
|
|
||||||
"\t{:?}\tImplementation version: {}\tVulkan Version: {}\tDescription: {:?}",
|
|
||||||
l.layer_name_as_c_str().unwrap_or_default(),
|
|
||||||
l.implementation_version,
|
|
||||||
print_version(l.spec_version),
|
|
||||||
l.description_as_c_str().unwrap_or_default()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
log::info!(""); // Add blank line
|
|
||||||
}
|
|
||||||
|
|
||||||
fn select_layers(
|
|
||||||
layers_available: &[ash::vk::LayerProperties],
|
|
||||||
layers_to_select: &[&str],
|
|
||||||
) -> Vec<String> {
|
|
||||||
layers_available
|
|
||||||
.iter()
|
|
||||||
.filter_map(|l| {
|
|
||||||
let layer_name = l
|
|
||||||
.layer_name_as_c_str()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.to_string_lossy();
|
|
||||||
layers_to_select
|
|
||||||
.iter()
|
|
||||||
.find(|&&ln| ln == layer_name)
|
|
||||||
.map(|_| layer_name.into_owned())
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log_layers_wanted(layers_to_select: &[&str], selected_layers: &[String]) {
|
|
||||||
log::info!("Layers wanted ({}):", layers_to_select.len());
|
|
||||||
for ol in layers_to_select {
|
|
||||||
let selected = selected_layers.iter().any(|sl| sl == ol);
|
|
||||||
log::info!("\t{:?}\tSelected: {}", ol, selected);
|
|
||||||
}
|
|
||||||
log::info!(""); // Add blank line
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_version(version: u32) -> String {
|
|
||||||
format!(
|
|
||||||
"{}.{}.{}",
|
|
||||||
ash::vk::api_version_major(version),
|
|
||||||
ash::vk::api_version_minor(version),
|
|
||||||
ash::vk::api_version_patch(version)
|
|
||||||
)
|
|
||||||
}
|
|
38
src/vulkan/utils/layers.rs
Normal file
38
src/vulkan/utils/layers.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use std::ffi::CString;
|
||||||
|
|
||||||
|
pub fn use_layers(
|
||||||
|
entry: &ash::Entry,
|
||||||
|
layers_to_select: Vec<&str>,
|
||||||
|
) -> Vec<CString> {
|
||||||
|
let layers_available = get_layers_available(entry);
|
||||||
|
|
||||||
|
let selected_layers = select_layers(&layers_available, &layers_to_select);
|
||||||
|
|
||||||
|
selected_layers
|
||||||
|
.iter()
|
||||||
|
.map(|sl| CString::new(sl.clone().as_bytes()).unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_layers_available(entry: &ash::Entry) -> Vec<ash::vk::LayerProperties> {
|
||||||
|
unsafe { entry.enumerate_instance_layer_properties().unwrap_or_default() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_layers(
|
||||||
|
layers_available: &[ash::vk::LayerProperties],
|
||||||
|
layers_to_select: &[&str],
|
||||||
|
) -> Vec<String> {
|
||||||
|
layers_available
|
||||||
|
.iter()
|
||||||
|
.filter_map(|l| {
|
||||||
|
let layer_name = l
|
||||||
|
.layer_name_as_c_str()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_string_lossy();
|
||||||
|
layers_to_select
|
||||||
|
.iter()
|
||||||
|
.find(|&&ln| ln == layer_name)
|
||||||
|
.map(|_| layer_name.into_owned())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
11
src/vulkan/utils/mod.rs
Normal file
11
src/vulkan/utils/mod.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
mod layers;
|
||||||
|
pub use layers::use_layers;
|
||||||
|
|
||||||
|
pub fn print_version(version: u32) -> String {
|
||||||
|
format!(
|
||||||
|
"{}.{}.{}",
|
||||||
|
ash::vk::api_version_major(version),
|
||||||
|
ash::vk::api_version_minor(version),
|
||||||
|
ash::vk::api_version_patch(version)
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
use std::ffi::CString;
|
use std::ffi::{c_char, CString};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use ash::{Instance, vk, Entry};
|
use ash::{Instance, vk, Entry};
|
||||||
use winit::raw_window_handle::{HasDisplayHandle};
|
use ash::khr::surface;
|
||||||
|
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
use crate::vulkan::utils::use_layers;
|
use crate::vulkan::utils::use_layers;
|
||||||
|
use crate::vulkan::vk_surface::VkSurface;
|
||||||
use crate::vulkan::VkPhysicalDevice;
|
use crate::vulkan::VkPhysicalDevice;
|
||||||
|
|
||||||
pub struct VkInstance {
|
pub struct VkInstance {
|
||||||
|
@ -10,7 +13,9 @@ pub struct VkInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VkInstance {
|
impl VkInstance {
|
||||||
pub fn new(window: &impl HasDisplayHandle) -> Self {
|
pub fn new(
|
||||||
|
required_extensions: &Vec<*const c_char>,
|
||||||
|
) -> Self {
|
||||||
let entry = Entry::linked();
|
let entry = Entry::linked();
|
||||||
|
|
||||||
// Layers
|
// Layers
|
||||||
|
@ -21,19 +26,6 @@ impl VkInstance {
|
||||||
]);
|
]);
|
||||||
let layers_raw = layers.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
|
let layers_raw = layers.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
|
||||||
|
|
||||||
// Extensions
|
|
||||||
let mut extension_names =
|
|
||||||
ash_window::enumerate_required_extensions(window.display_handle().expect("No display handle").as_raw())
|
|
||||||
.unwrap()
|
|
||||||
.to_vec();
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
||||||
{
|
|
||||||
extension_names.push(ash::khr::portability_enumeration::NAME.as_ptr());
|
|
||||||
// Enabling this extension is a requirement when using `VK_KHR_portability_subset`
|
|
||||||
extension_names.push(ash::khr::get_physical_device_properties2::NAME.as_ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
// App Info
|
// App Info
|
||||||
let app_name = CString::new("VulkanTriangle").unwrap();
|
let app_name = CString::new("VulkanTriangle").unwrap();
|
||||||
let appinfo = vk::ApplicationInfo::default()
|
let appinfo = vk::ApplicationInfo::default()
|
||||||
|
@ -53,7 +45,7 @@ impl VkInstance {
|
||||||
let create_info = vk::InstanceCreateInfo::default()
|
let create_info = vk::InstanceCreateInfo::default()
|
||||||
.application_info(&appinfo)
|
.application_info(&appinfo)
|
||||||
.enabled_layer_names(&layers_raw)
|
.enabled_layer_names(&layers_raw)
|
||||||
.enabled_extension_names(&extension_names)
|
.enabled_extension_names(&required_extensions)
|
||||||
.flags(create_flags);
|
.flags(create_flags);
|
||||||
|
|
||||||
let instance: Instance = unsafe {
|
let instance: Instance = unsafe {
|
||||||
|
@ -75,6 +67,31 @@ impl VkInstance {
|
||||||
.iter().map(|physical_device| VkPhysicalDevice::new(&self.handle, *physical_device))
|
.iter().map(|physical_device| VkPhysicalDevice::new(&self.handle, *physical_device))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_surface(
|
||||||
|
&self,
|
||||||
|
window: &crate::display::Window
|
||||||
|
) -> anyhow::Result<VkSurface> {
|
||||||
|
let window_handle = window.handle()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Window handle is not available."))?;
|
||||||
|
|
||||||
|
let surface_loader = surface::Instance::new(&self.entry, &self.handle);
|
||||||
|
|
||||||
|
let surface = unsafe {
|
||||||
|
ash_window::create_surface(
|
||||||
|
&self.entry,
|
||||||
|
&self.handle,
|
||||||
|
window_handle.display_handle()?.as_raw(),
|
||||||
|
window_handle.window_handle()?.as_raw(),
|
||||||
|
None,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(VkSurface::new(
|
||||||
|
surface_loader,
|
||||||
|
surface,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VkInstance {
|
impl Drop for VkInstance {
|
||||||
|
@ -83,4 +100,10 @@ impl Drop for VkInstance {
|
||||||
self.handle.destroy_instance(None);
|
self.handle.destroy_instance(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for VkInstance {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Vulkan Version:")
|
||||||
|
}
|
||||||
}
|
}
|
3
src/vulkan/vk_logical_device.rs
Normal file
3
src/vulkan/vk_logical_device.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub struct VkLogicalDevice {
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use crate::display::App;
|
use crate::vulkan::vk_surface::VkSurface;
|
||||||
|
|
||||||
pub struct VkPhysicalDevice {
|
pub struct VkPhysicalDevice {
|
||||||
// Vulkan properties
|
// Vulkan properties
|
||||||
handle: vk::PhysicalDevice,
|
pub(super) handle: vk::PhysicalDevice,
|
||||||
pub properties: vk::PhysicalDeviceProperties,
|
pub properties: vk::PhysicalDeviceProperties,
|
||||||
pub features: vk::PhysicalDeviceFeatures,
|
pub features: vk::PhysicalDeviceFeatures,
|
||||||
pub queue_family_properties: Vec<vk::QueueFamilyProperties>,
|
pub queue_family_properties: Vec<vk::QueueFamilyProperties>,
|
||||||
|
@ -26,33 +27,16 @@ impl VkPhysicalDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn priority(&self) -> usize {
|
pub fn priority(&self) -> usize {
|
||||||
let mut priority = 0;
|
match self.properties.device_type {
|
||||||
|
|
||||||
let has_graphics_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::GRAPHICS));
|
|
||||||
let has_compute_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::COMPUTE));
|
|
||||||
let has_transfer_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::TRANSFER));
|
|
||||||
let has_sparse_binding_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::SPARSE_BINDING));
|
|
||||||
let physical_device_type = self.properties.device_type;
|
|
||||||
|
|
||||||
priority |= has_graphics_support as usize;
|
|
||||||
priority |= (has_sparse_binding_support as usize) << 1;
|
|
||||||
priority |= (has_transfer_support as usize) << 2;
|
|
||||||
priority |= (has_compute_support as usize) << 3;
|
|
||||||
|
|
||||||
let weight : usize = match physical_device_type {
|
|
||||||
vk::PhysicalDeviceType::CPU => 1,
|
vk::PhysicalDeviceType::CPU => 1,
|
||||||
vk::PhysicalDeviceType::VIRTUAL_GPU => 2,
|
vk::PhysicalDeviceType::VIRTUAL_GPU => 2,
|
||||||
vk::PhysicalDeviceType::INTEGRATED_GPU => 3,
|
vk::PhysicalDeviceType::INTEGRATED_GPU => 3,
|
||||||
vk::PhysicalDeviceType::DISCRETE_GPU => 4,
|
vk::PhysicalDeviceType::DISCRETE_GPU => 4,
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
}
|
||||||
priority |= weight << 4;
|
|
||||||
|
|
||||||
priority
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Display for VkPhysicalDevice {
|
impl Display for VkPhysicalDevice {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "\tNom: {:?}, Priorité: {}", self.properties.device_name_as_c_str().unwrap_or_default(), self.priority())
|
write!(f, "\tNom: {:?}, Priorité: {}", self.properties.device_name_as_c_str().unwrap_or_default(), self.priority())
|
||||||
|
|
29
src/vulkan/vk_surface.rs
Normal file
29
src/vulkan/vk_surface.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use crate::vulkan::VkPhysicalDevice;
|
||||||
|
|
||||||
|
pub struct VkSurface {
|
||||||
|
surface_loader: ash::khr::surface::Instance,
|
||||||
|
surface: ash::vk::SurfaceKHR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VkSurface {
|
||||||
|
pub fn new(
|
||||||
|
surface_loader: ash::khr::surface::Instance,
|
||||||
|
surface: ash::vk::SurfaceKHR,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
surface_loader,
|
||||||
|
surface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_device_queue_supported(&self, physical_device: &VkPhysicalDevice, queue_index: u32) -> VkResult<bool> {
|
||||||
|
unsafe {
|
||||||
|
self.surface_loader.get_physical_device_surface_support(
|
||||||
|
physical_device.handle,
|
||||||
|
queue_index,
|
||||||
|
self.surface
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue