added files
This commit is contained in:
commit
8cf63a9348
|
@ -0,0 +1 @@
|
||||||
|
target
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "eruption"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["Sven Vogel"]
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
vulkano = "0.33.0"
|
||||||
|
vulkano-win = "0.33.0"
|
||||||
|
winit = "0.28.3"
|
|
@ -0,0 +1,134 @@
|
||||||
|
use vulkano::device::{DeviceExtensions, Properties, QueueFlags};
|
||||||
|
use vulkano::device::physical::PhysicalDeviceType;
|
||||||
|
use vulkano::instance::{Instance, InstanceCreateInfo};
|
||||||
|
use vulkano::VulkanLibrary;
|
||||||
|
use vulkano_win::VkSurfaceBuild;
|
||||||
|
use winit::event_loop::EventLoop;
|
||||||
|
use winit::window::WindowBuilder;
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
let lib = VulkanLibrary::new().unwrap();
|
||||||
|
|
||||||
|
let ext = vulkano_win::required_extensions(&lib);
|
||||||
|
|
||||||
|
// Now creating the instance.
|
||||||
|
let instance = Instance::new(
|
||||||
|
lib,
|
||||||
|
InstanceCreateInfo {
|
||||||
|
enabled_extensions: ext,
|
||||||
|
// Enable enumerating devices that use non-conformant Vulkan implementations. (e.g.
|
||||||
|
// MoltenVK)
|
||||||
|
enumerate_portability: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
// The objective of this example is to draw a triangle on a window. To do so, we first need to
|
||||||
|
// create the window.
|
||||||
|
//
|
||||||
|
// This is done by creating a `WindowBuilder` from the `winit` crate, then calling the
|
||||||
|
// `build_vk_surface` method provided by the `VkSurfaceBuild` trait from `vulkano_win`. If you
|
||||||
|
// ever get an error about `build_vk_surface` being undefined in one of your projects, this
|
||||||
|
// probably means that you forgot to import this trait.
|
||||||
|
//
|
||||||
|
// This returns a `vulkano::swapchain::Surface` object that contains both a cross-platform
|
||||||
|
// winit window and a cross-platform Vulkan surface that represents the surface of the window.
|
||||||
|
let event_loop = EventLoop::new();
|
||||||
|
let surface = WindowBuilder::new()
|
||||||
|
.build_vk_surface(&event_loop, instance.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Choose device extensions that we're going to use. In order to present images to a surface,
|
||||||
|
// we need a `Swapchain`, which is provided by the `khr_swapchain` extension.
|
||||||
|
let device_extensions = DeviceExtensions {
|
||||||
|
khr_swapchain: true,
|
||||||
|
..DeviceExtensions::empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
// We then choose which physical device to use. First, we enumerate all the available physical
|
||||||
|
// devices, then apply filters to narrow them down to those that can support our needs.
|
||||||
|
let (physical_device, queue_family_index) = instance
|
||||||
|
.enumerate_physical_devices()
|
||||||
|
.unwrap()
|
||||||
|
.filter(|p| {
|
||||||
|
// Some devices may not support the extensions or features that your application, or
|
||||||
|
// report properties and limits that are not sufficient for your application. These
|
||||||
|
// should be filtered out here.
|
||||||
|
p.supported_extensions().contains(&device_extensions)
|
||||||
|
})
|
||||||
|
.filter_map(|p| {
|
||||||
|
// For each physical device, we try to find a suitable queue family that will execute
|
||||||
|
// our draw commands.
|
||||||
|
//
|
||||||
|
// Devices can provide multiple queues to run commands in parallel (for example a draw
|
||||||
|
// queue and a compute queue), similar to CPU threads. This is something you have to
|
||||||
|
// have to manage manually in Vulkan. Queues of the same type belong to the same queue
|
||||||
|
// family.
|
||||||
|
//
|
||||||
|
// Here, we look for a single queue family that is suitable for our purposes. In a
|
||||||
|
// real-world application, you may want to use a separate dedicated transfer queue to
|
||||||
|
// handle data transfers in parallel with graphics operations. You may also need a
|
||||||
|
// separate queue for compute operations, if your application uses those.
|
||||||
|
p.queue_family_properties()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.position(|(i, q)| {
|
||||||
|
// We select a queue family that supports graphics operations. When drawing to
|
||||||
|
// a window surface, as we do in this example, we also need to check that
|
||||||
|
// queues in this queue family are capable of presenting images to the surface.
|
||||||
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
|
})
|
||||||
|
// The code here searches for the first queue family that is suitable. If none is
|
||||||
|
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||||
|
// device.
|
||||||
|
.map(|i| (p, i as u32))
|
||||||
|
})
|
||||||
|
// All the physical devices that pass the filters above are suitable for the application.
|
||||||
|
// However, not every device is equal, some are preferred over others. Now, we assign each
|
||||||
|
// physical device a score, and pick the device with the lowest ("best") score.
|
||||||
|
//
|
||||||
|
// In this example, we simply select the best-scoring device to use in the application.
|
||||||
|
// In a real-world setting, you may want to use the best-scoring device only as a "default"
|
||||||
|
// or "recommended" device, and let the user choose the device themself.
|
||||||
|
.min_by_key(|(p, _)| {
|
||||||
|
// We assign a lower score to device types that are likely to be faster/better.
|
||||||
|
match p.properties().device_type {
|
||||||
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
|
PhysicalDeviceType::IntegratedGpu => 1,
|
||||||
|
PhysicalDeviceType::VirtualGpu => 2,
|
||||||
|
PhysicalDeviceType::Cpu => 3,
|
||||||
|
PhysicalDeviceType::Other => 4,
|
||||||
|
_ => 5,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect("no suitable physical device found");
|
||||||
|
|
||||||
|
print_physical_device_info(physical_device.properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_physical_device_info(device_properties: &Properties) {
|
||||||
|
println!("name: {}", device_properties.device_name);
|
||||||
|
|
||||||
|
print_device_driver_info(device_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_device_driver_info(device_properties: &Properties) {
|
||||||
|
let default_name = String::from("<none>");
|
||||||
|
let name = device_properties.driver_name.as_ref().unwrap_or(&default_name);
|
||||||
|
|
||||||
|
let default_info = String::from("<none>");
|
||||||
|
let info = device_properties.driver_info.as_ref().unwrap_or(&default_info);
|
||||||
|
|
||||||
|
format!("driver:\n\tname: {}\n\tversion: {}\n\t info: {}\n", name, device_properties.driver_version, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue