added files

This commit is contained in:
Sven Vogel 2023-04-05 11:57:21 +02:00
commit 8cf63a9348
4 changed files with 1492 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target

1345
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

12
Cargo.toml Normal file
View File

@ -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"

134
src/lib.rs Normal file
View File

@ -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();
}
}