swap chains
parent
4846d2c442
commit
14238117a1
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue