refucktor
parent
14238117a1
commit
77c88aa27a
|
@ -26,7 +26,7 @@ impl Renderer {
|
|||
pub fn initialize() -> Self {
|
||||
let mut instance = vulkan::Instance::new("threepy".to_string());
|
||||
let (events_loop, surface) = Self::init_window(instance.get_vulkan());
|
||||
instance.bind_surface(&surface);
|
||||
instance.use_surface(&surface);
|
||||
Self {
|
||||
instance,
|
||||
events_loop,
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use log;
|
||||
|
||||
use vulkano::instance as vi;
|
||||
use vulkano::device as vd;
|
||||
use vulkano::swapchain as vs;
|
||||
use vulkano::image as vm;
|
||||
use vulkano::format as vf;
|
||||
use vulkano::sync as vy;
|
||||
|
||||
struct QueueFamilyIndices {
|
||||
graphics_family: i32,
|
||||
present_family: i32,
|
||||
}
|
||||
|
||||
impl QueueFamilyIndices {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
graphics_family: -1,
|
||||
present_family: -1,
|
||||
}
|
||||
}
|
||||
fn is_complete(&self) -> bool {
|
||||
self.graphics_family >= 0 && self.present_family >= 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const VERSION: vi::Version = vi::Version { major: 1, minor: 0, patch: 0};
|
||||
|
||||
pub struct Instance<WT> {
|
||||
debug_callback: vi::debug::DebugCallback,
|
||||
vulkan: Arc<vi::Instance>,
|
||||
|
||||
physical_device_ix: Option<usize>,
|
||||
device: Option<Arc<vd::Device>>,
|
||||
surface: Option<Arc<vs::Surface<WT>>>,
|
||||
graphics_queue: Option<Arc<vd::Queue>>,
|
||||
present_queue: Option<Arc<vd::Queue>>,
|
||||
|
||||
swap_chain: Option<Arc<vs::Swapchain<WT>>>,
|
||||
swap_chain_images: Option<Vec<Arc<vm::SwapchainImage<WT>>>>,
|
||||
}
|
||||
|
||||
impl<WT> Instance<WT> {
|
||||
pub fn new(name: String) -> Self {
|
||||
let ai = vi::ApplicationInfo {
|
||||
application_name: Some(name.clone().into()),
|
||||
application_version: Some(VERSION),
|
||||
engine_name: Some(name.clone().into()),
|
||||
engine_version: Some(VERSION),
|
||||
};
|
||||
|
||||
let exts = Self::required_instance_extensions();
|
||||
let layers = ["VK_LAYER_LUNARG_standard_validation"];
|
||||
let vulkan = vi::Instance::new(Some(&ai), &exts, layers.iter().cloned()).expect("could not create vulkan instance");
|
||||
let debug_callback = Self::init_debug_callback(&vulkan);
|
||||
|
||||
|
||||
Self {
|
||||
debug_callback,
|
||||
vulkan,
|
||||
|
||||
physical_device_ix: None,
|
||||
device: None,
|
||||
surface: None,
|
||||
graphics_queue: None,
|
||||
present_queue: None,
|
||||
|
||||
swap_chain: None,
|
||||
swap_chain_images: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_surface(&mut self, surface: &Arc<vs::Surface<WT>>) {
|
||||
let physical_device_ix = Self::pick_physical_device(&self.vulkan, &surface);
|
||||
let physical_device = vi::PhysicalDevice::from_index(&self.vulkan, physical_device_ix).unwrap();
|
||||
let indices = Self::find_queue_families(&surface, &physical_device).unwrap();
|
||||
|
||||
let families = [indices.graphics_family, indices.present_family];
|
||||
use std::iter::FromIterator;
|
||||
let unique_queue_families: HashSet<&i32> = HashSet::from_iter(families.iter());
|
||||
|
||||
let queue_priority = 1.0;
|
||||
let qf = unique_queue_families.iter().map(|i| {
|
||||
(physical_device.queue_families().nth(**i as usize).unwrap(), queue_priority)
|
||||
});
|
||||
|
||||
let (device, mut queues) = vd::Device::new(
|
||||
physical_device,
|
||||
&vd::Features::none(),
|
||||
&Self::required_device_extensions(),
|
||||
qf
|
||||
).expect("could not create logical device and queues");
|
||||
|
||||
let graphics_queue = queues.next().unwrap();
|
||||
let present_queue = queues.next().unwrap_or_else(|| graphics_queue.clone());
|
||||
|
||||
self.physical_device_ix = Some(physical_device_ix);
|
||||
self.device = Some(device.clone());
|
||||
self.surface = Some(surface.clone());
|
||||
self.graphics_queue = Some(graphics_queue.clone());
|
||||
self.present_queue = Some(present_queue.clone());
|
||||
|
||||
let capabilities = surface.capabilities(physical_device).expect("could not get capabilities");
|
||||
let surface_format = Self::choose_swap_surface_format(&capabilities.supported_formats);
|
||||
let present_mode = Self::choose_swap_present_mode(capabilities.present_modes);
|
||||
let extent = Self::choose_swap_extent(&capabilities);
|
||||
|
||||
let mut image_count = capabilities.min_image_count + 1;
|
||||
if let Some(max_image_count) = capabilities.max_image_count {
|
||||
if image_count > max_image_count {
|
||||
image_count = max_image_count;
|
||||
}
|
||||
}
|
||||
|
||||
let image_usage = vm::ImageUsage {
|
||||
color_attachment: true,
|
||||
.. vm::ImageUsage::none()
|
||||
};
|
||||
|
||||
let sharing: vy::SharingMode = if indices.graphics_family != indices.present_family {
|
||||
vec![&graphics_queue, &present_queue].as_slice().into()
|
||||
} else {
|
||||
(&graphics_queue).into()
|
||||
};
|
||||
|
||||
let (swap_chain, images) = vs::Swapchain::new(
|
||||
device.clone(),
|
||||
surface.clone(),
|
||||
image_count,
|
||||
surface_format.0,
|
||||
extent,
|
||||
1,
|
||||
image_usage,
|
||||
sharing,
|
||||
capabilities.current_transform,
|
||||
vs::CompositeAlpha::Opaque,
|
||||
present_mode,
|
||||
true,
|
||||
None,
|
||||
).expect("could not create swap chain");
|
||||
|
||||
self.swap_chain = Some(swap_chain);
|
||||
self.swap_chain_images = Some(images);
|
||||
}
|
||||
|
||||
pub fn get_vulkan(&self) -> Arc<vi::Instance> {
|
||||
self.vulkan.clone()
|
||||
}
|
||||
|
||||
fn find_queue_families(surface: &Arc<vs::Surface<WT>>, device: &vi::PhysicalDevice) -> Option<QueueFamilyIndices> {
|
||||
let mut indices = QueueFamilyIndices::new();
|
||||
for (i, queue_family) in device.queue_families().enumerate() {
|
||||
if queue_family.supports_graphics() {
|
||||
indices.graphics_family = i as i32
|
||||
}
|
||||
if surface.is_supported(queue_family).unwrap() {
|
||||
indices.present_family = i as i32
|
||||
}
|
||||
if indices.is_complete() {
|
||||
return Some(indices);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn pick_physical_device(instance: &Arc<vi::Instance>, surface: &Arc<vs::Surface<WT>>) -> usize {
|
||||
vi::PhysicalDevice::enumerate(&instance)
|
||||
.position(|dev| Self::is_device_suitable(surface, &dev))
|
||||
.expect("could not find suitable GPU")
|
||||
}
|
||||
|
||||
fn is_device_suitable(surface: &Arc<vs::Surface<WT>>, device: &vi::PhysicalDevice) -> bool {
|
||||
if !Self::find_queue_families(surface, &device).is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let available_extensions = vd::DeviceExtensions::supported_by_device(*device);
|
||||
let want_extensions = Self::required_device_extensions();
|
||||
if available_extensions.intersection(&want_extensions) != want_extensions {
|
||||
return false;
|
||||
}
|
||||
|
||||
let capabilities = surface.capabilities(*device).expect("could not get device capabilities");
|
||||
if capabilities.supported_formats.is_empty() {
|
||||
return false;
|
||||
}
|
||||
if !capabilities.present_modes.iter().next().is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn required_device_extensions() -> vd::DeviceExtensions {
|
||||
vd::DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
.. vd::DeviceExtensions::none()
|
||||
}
|
||||
}
|
||||
|
||||
fn required_instance_extensions() -> vi::InstanceExtensions {
|
||||
let mut exts = vulkano_win::required_extensions();
|
||||
exts.ext_debug_report = true;
|
||||
exts
|
||||
}
|
||||
|
||||
|
||||
fn init_debug_callback(instance: &Arc<vi::Instance>) -> vi::debug::DebugCallback {
|
||||
let mt = vi::debug::MessageTypes {
|
||||
error: true,
|
||||
warning: true,
|
||||
performance_warning: true,
|
||||
information: true,
|
||||
debug: true,
|
||||
};
|
||||
vi::debug::DebugCallback::new(&instance, mt, |msg| {
|
||||
log::info!("validation layer: {:?}", msg.description);
|
||||
}).expect("could not create debug callback")
|
||||
}
|
||||
|
||||
fn choose_swap_surface_format(available_formats: &[(vf::Format, vs::ColorSpace)]) -> (vf::Format, vs::ColorSpace) {
|
||||
*available_formats.iter()
|
||||
.find(|(format, color_space)|
|
||||
*format == vf::Format::B8G8R8A8Unorm && *color_space == vs::ColorSpace::SrgbNonLinear
|
||||
)
|
||||
.unwrap_or_else(|| &available_formats[0])
|
||||
}
|
||||
|
||||
fn choose_swap_present_mode(available_present_modes: vs::SupportedPresentModes) -> vs::PresentMode {
|
||||
if available_present_modes.mailbox {
|
||||
vs::PresentMode::Mailbox
|
||||
} else if available_present_modes.immediate {
|
||||
vs::PresentMode::Immediate
|
||||
} else {
|
||||
vs::PresentMode::Fifo
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
|
||||
capabilities.current_extent.expect("could not get current extent")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use vulkano::instance as vi;
|
||||
use vulkano::device as vd;
|
||||
use vulkano::swapchain as vs;
|
||||
|
||||
// A Binding to a surface, resulting in concrete device information.
|
||||
pub struct Binding<WT> {
|
||||
instance: Arc<vi::Instance>,
|
||||
physical_device_ix: usize,
|
||||
pub device: Arc<vd::Device>,
|
||||
pub surface: Arc<vs::Surface<WT>>,
|
||||
pub graphics_queue: Arc<vd::Queue>,
|
||||
pub present_queue: Arc<vd::Queue>,
|
||||
}
|
||||
|
||||
impl <WT> Binding<WT> {
|
||||
pub fn physical_device(&self) -> vi::PhysicalDevice {
|
||||
vi::PhysicalDevice::from_index(&self.instance, self.physical_device_ix).unwrap()
|
||||
}
|
||||
|
||||
pub fn new(instance: &Arc<vi::Instance>, surface: &Arc<vs::Surface<WT>>) -> Self {
|
||||
let physical_device_ix = Self::pick_physical_device(instance, &surface);
|
||||
let physical_device = vi::PhysicalDevice::from_index(instance, physical_device_ix).unwrap();
|
||||
let indices = super::qfi::QueueFamilyIndices::find(&surface, &physical_device).unwrap();
|
||||
|
||||
let families = [indices.graphics_family, indices.present_family];
|
||||
use std::iter::FromIterator;
|
||||
let unique_queue_families: HashSet<&i32> = HashSet::from_iter(families.iter());
|
||||
|
||||
let queue_priority = 1.0;
|
||||
let qf = unique_queue_families.iter().map(|i| {
|
||||
(physical_device.queue_families().nth(**i as usize).unwrap(), queue_priority)
|
||||
});
|
||||
|
||||
let (device, mut queues) = vd::Device::new(
|
||||
physical_device,
|
||||
&vd::Features::none(),
|
||||
&required_device_extensions(),
|
||||
qf
|
||||
).expect("could not create logical device and queues");
|
||||
|
||||
let graphics_queue = queues.next().unwrap();
|
||||
let present_queue = queues.next().unwrap_or_else(|| graphics_queue.clone());
|
||||
|
||||
Self {
|
||||
instance: instance.clone(),
|
||||
physical_device_ix,
|
||||
device: device.clone(),
|
||||
surface: surface.clone(),
|
||||
graphics_queue: graphics_queue.clone(),
|
||||
present_queue: present_queue.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_physical_device(instance: &Arc<vi::Instance>, surface: &Arc<vs::Surface<WT>>) -> usize {
|
||||
vi::PhysicalDevice::enumerate(&instance)
|
||||
.position(|dev| Self::is_device_suitable(surface, &dev))
|
||||
.expect("could not find suitable GPU")
|
||||
}
|
||||
|
||||
fn is_device_suitable(surface: &Arc<vs::Surface<WT>>, device: &vi::PhysicalDevice) -> bool {
|
||||
if !super::qfi::QueueFamilyIndices::find(surface, &device).is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let available_extensions = vd::DeviceExtensions::supported_by_device(*device);
|
||||
let want_extensions = required_device_extensions();
|
||||
if available_extensions.intersection(&want_extensions) != want_extensions {
|
||||
return false;
|
||||
}
|
||||
|
||||
let capabilities = surface.capabilities(*device).expect("could not get device capabilities");
|
||||
if capabilities.supported_formats.is_empty() {
|
||||
return false;
|
||||
}
|
||||
if !capabilities.present_modes.iter().next().is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn required_device_extensions() -> vd::DeviceExtensions {
|
||||
vd::DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
.. vd::DeviceExtensions::none()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
use std::sync::Arc;
|
||||
use log;
|
||||
|
||||
use vulkano::instance as vi;
|
||||
use vulkano::swapchain as vs;
|
||||
|
||||
mod binding;
|
||||
mod swapchains;
|
||||
mod qfi;
|
||||
|
||||
const VERSION: vi::Version = vi::Version { major: 1, minor: 0, patch: 0};
|
||||
|
||||
pub struct Instance<WT> {
|
||||
debug_callback: vi::debug::DebugCallback,
|
||||
vulkan: Arc<vi::Instance>,
|
||||
|
||||
binding: Option<binding::Binding<WT>>,
|
||||
swapchains: Option<swapchains::Swapchains<WT>>,
|
||||
}
|
||||
|
||||
impl<WT> Instance<WT> {
|
||||
pub fn new(name: String) -> Self {
|
||||
let ai = vi::ApplicationInfo {
|
||||
application_name: Some(name.clone().into()),
|
||||
application_version: Some(VERSION),
|
||||
engine_name: Some(name.clone().into()),
|
||||
engine_version: Some(VERSION),
|
||||
};
|
||||
|
||||
let exts = Self::required_instance_extensions();
|
||||
let layers = ["VK_LAYER_LUNARG_standard_validation"];
|
||||
let vulkan = vi::Instance::new(Some(&ai), &exts, layers.iter().cloned()).expect("could not create vulkan instance");
|
||||
let debug_callback = Self::init_debug_callback(&vulkan);
|
||||
|
||||
|
||||
Self {
|
||||
debug_callback,
|
||||
vulkan,
|
||||
|
||||
binding: None,
|
||||
swapchains: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vulkan(&self) -> Arc<vi::Instance> {
|
||||
self.vulkan.clone()
|
||||
}
|
||||
|
||||
pub fn use_surface(&mut self, surface: &Arc<vs::Surface<WT>>) {
|
||||
self.binding = Some(binding::Binding::new(&self.vulkan, &surface));
|
||||
self.swapchains = Some(swapchains::Swapchains::new(self.binding.as_ref().unwrap()));
|
||||
|
||||
log::info!("Bound to Vulkan Device: {}", self.binding.as_ref().unwrap().physical_device().name());
|
||||
}
|
||||
|
||||
fn required_instance_extensions() -> vi::InstanceExtensions {
|
||||
let mut exts = vulkano_win::required_extensions();
|
||||
exts.ext_debug_report = true;
|
||||
exts
|
||||
}
|
||||
|
||||
|
||||
fn init_debug_callback(instance: &Arc<vi::Instance>) -> vi::debug::DebugCallback {
|
||||
let mt = vi::debug::MessageTypes {
|
||||
error: true,
|
||||
warning: true,
|
||||
performance_warning: true,
|
||||
information: true,
|
||||
debug: true,
|
||||
};
|
||||
vi::debug::DebugCallback::new(&instance, mt, |msg| {
|
||||
log::debug!("validation layer: {:?}", msg.description);
|
||||
}).expect("could not create debug callback")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use vulkano::instance as vi;
|
||||
use vulkano::swapchain as vs;
|
||||
|
||||
pub struct QueueFamilyIndices {
|
||||
pub graphics_family: i32,
|
||||
pub present_family: i32,
|
||||
}
|
||||
|
||||
impl QueueFamilyIndices {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
graphics_family: -1,
|
||||
present_family: -1,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_complete(&self) -> bool {
|
||||
self.graphics_family >= 0 && self.present_family >= 0
|
||||
}
|
||||
|
||||
|
||||
pub fn find<WT>(surface: &Arc<vs::Surface<WT>>, device: &vi::PhysicalDevice) -> Option<Self> {
|
||||
let mut indices = QueueFamilyIndices::new();
|
||||
for (i, queue_family) in device.queue_families().enumerate() {
|
||||
if queue_family.supports_graphics() {
|
||||
indices.graphics_family = i as i32
|
||||
}
|
||||
if surface.is_supported(queue_family).unwrap() {
|
||||
indices.present_family = i as i32
|
||||
}
|
||||
if indices.is_complete() {
|
||||
return Some(indices);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use vulkano::swapchain as vs;
|
||||
use vulkano::image as vm;
|
||||
use vulkano::format as vf;
|
||||
use vulkano::sync as vy;
|
||||
|
||||
pub struct Swapchains<WT> {
|
||||
chain: Arc<vs::Swapchain<WT>>,
|
||||
images: Vec<Arc<vm::SwapchainImage<WT>>>,
|
||||
}
|
||||
|
||||
impl<WT> Swapchains<WT> {
|
||||
pub fn new(binding: &super::binding::Binding<WT>) -> Self {
|
||||
let physical_device = binding.physical_device();
|
||||
let capabilities = binding.surface.capabilities(physical_device).expect("could not get capabilities");
|
||||
|
||||
let surface_format = Self::choose_swap_surface_format(&capabilities.supported_formats);
|
||||
let present_mode = Self::choose_swap_present_mode(capabilities.present_modes);
|
||||
let extent = Self::choose_swap_extent(&capabilities);
|
||||
|
||||
let mut image_count = capabilities.min_image_count + 1;
|
||||
if let Some(max_image_count) = capabilities.max_image_count {
|
||||
if image_count > max_image_count {
|
||||
image_count = max_image_count;
|
||||
}
|
||||
}
|
||||
|
||||
let image_usage = vm::ImageUsage {
|
||||
color_attachment: true,
|
||||
.. vm::ImageUsage::none()
|
||||
};
|
||||
|
||||
let indices = super::qfi::QueueFamilyIndices::find(&binding.surface, &physical_device).unwrap();
|
||||
let sharing: vy::SharingMode = if indices.graphics_family != indices.present_family {
|
||||
vec![&binding.graphics_queue, &binding.present_queue].as_slice().into()
|
||||
} else {
|
||||
(&binding.graphics_queue).into()
|
||||
};
|
||||
|
||||
let (chain, images) = vs::Swapchain::new(
|
||||
binding.device.clone(),
|
||||
binding.surface.clone(),
|
||||
image_count,
|
||||
surface_format.0,
|
||||
extent,
|
||||
1,
|
||||
image_usage,
|
||||
sharing,
|
||||
capabilities.current_transform,
|
||||
vs::CompositeAlpha::Opaque,
|
||||
present_mode,
|
||||
true,
|
||||
None,
|
||||
).expect("could not create swap chain");
|
||||
|
||||
Self {
|
||||
chain, images
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_swap_surface_format(available_formats: &[(vf::Format, vs::ColorSpace)]) -> (vf::Format, vs::ColorSpace) {
|
||||
*available_formats.iter()
|
||||
.find(|(format, color_space)|
|
||||
*format == vf::Format::B8G8R8A8Unorm && *color_space == vs::ColorSpace::SrgbNonLinear
|
||||
)
|
||||
.unwrap_or_else(|| &available_formats[0])
|
||||
}
|
||||
|
||||
fn choose_swap_present_mode(available_present_modes: vs::SupportedPresentModes) -> vs::PresentMode {
|
||||
if available_present_modes.mailbox {
|
||||
vs::PresentMode::Mailbox
|
||||
} else if available_present_modes.immediate {
|
||||
vs::PresentMode::Immediate
|
||||
} else {
|
||||
vs::PresentMode::Fifo
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
|
||||
capabilities.current_extent.expect("could not get current extent")
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue