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