swap chains

ecs
q3k 2019-05-07 02:25:52 +02:00
parent 4846d2c442
commit 14238117a1
1 changed files with 121 additions and 20 deletions

View File

@ -5,6 +5,9 @@ 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,
@ -35,6 +38,9 @@ pub struct Instance<WT> {
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> {
@ -46,7 +52,7 @@ impl<WT> Instance<WT> {
engine_version: Some(VERSION),
};
let exts = Self::required_extensions();
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);
@ -61,6 +67,9 @@ impl<WT> Instance<WT> {
surface: None,
graphics_queue: None,
present_queue: None,
swap_chain: None,
swap_chain_images: None,
}
}
@ -78,34 +87,69 @@ impl<WT> Instance<WT> {
(physical_device.queue_families().nth(**i as usize).unwrap(), queue_priority)
});
let (device, mut queues) = vd::Device::new(physical_device, &vd::Features::none(), &vd::DeviceExtensions::none(), qf).expect("could not create logical device and queues");
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);
self.device = Some(device.clone());
self.surface = Some(surface.clone());
self.graphics_queue = Some(graphics_queue);
self.present_queue = Some(present_queue);
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 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 required_extensions() -> vi::InstanceExtensions {
let mut exts = vulkano_win::required_extensions();
exts.ext_debug_report = true;
exts
}
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() {
@ -122,13 +166,48 @@ impl<WT> Instance<WT> {
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 {
match Self::find_queue_families(surface, &device) {
Some(_) => true,
None => false
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,
@ -141,6 +220,28 @@ impl<WT> Instance<WT> {
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")
}
}