mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 20:51:29 +11:00
Make graphics support non-optional for Vulkan
This also removes the new present flag, deletes some commented code and explains the lack of surface validation in device selection.
This commit is contained in:
parent
fb952de1f3
commit
d6ffe970f9
|
@ -49,8 +49,6 @@ bitflags! {
|
||||||
pub struct InstanceFlags: u32 {
|
pub struct InstanceFlags: u32 {
|
||||||
/// Prefer DX12 over Vulkan.
|
/// Prefer DX12 over Vulkan.
|
||||||
const DX12 = 0x1;
|
const DX12 = 0x1;
|
||||||
/// Support presentation to a surface.
|
|
||||||
const PRESENT = 0x2;
|
|
||||||
// TODO: discrete vs integrated selection
|
// TODO: discrete vs integrated selection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ impl Instance {
|
||||||
mux_cfg! {
|
mux_cfg! {
|
||||||
#[cfg(vk)]
|
#[cfg(vk)]
|
||||||
{
|
{
|
||||||
if let Ok(instance) = vulkan::VkInstance::new(flags.contains(InstanceFlags::PRESENT)) {
|
if let Ok(instance) = vulkan::VkInstance::new() {
|
||||||
return Ok(Instance::Vk(instance));
|
return Ok(Instance::Vk(instance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ impl Instance {
|
||||||
/// a "session" which is similar but provides many conveniences.
|
/// a "session" which is similar but provides many conveniences.
|
||||||
pub unsafe fn device(&self) -> Result<Device, Error> {
|
pub unsafe fn device(&self) -> Result<Device, Error> {
|
||||||
mux_match! { self;
|
mux_match! { self;
|
||||||
Instance::Vk(i) => i.device(true).map(Device::Vk),
|
Instance::Vk(i) => i.device().map(Device::Vk),
|
||||||
Instance::Dx12(i) => i.device().map(Device::Dx12),
|
Instance::Dx12(i) => i.device().map(Device::Dx12),
|
||||||
Instance::Mtl(i) => i.device().map(Device::Mtl),
|
Instance::Mtl(i) => i.device().map(Device::Mtl),
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,10 +154,7 @@ impl VkInstance {
|
||||||
///
|
///
|
||||||
/// There's more to be done to make this suitable for integration with other
|
/// There's more to be done to make this suitable for integration with other
|
||||||
/// systems, but for now the goal is to make things simple.
|
/// systems, but for now the goal is to make things simple.
|
||||||
///
|
pub fn new() -> Result<VkInstance, Error> {
|
||||||
/// The caller is responsible for making sure that window which owns the raw window handle
|
|
||||||
/// outlives the surface.
|
|
||||||
pub fn new(support_present: bool) -> Result<VkInstance, Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let app_name = CString::new("VkToy").unwrap();
|
let app_name = CString::new("VkToy").unwrap();
|
||||||
let entry = Entry::new()?;
|
let entry = Entry::new()?;
|
||||||
|
@ -174,34 +171,31 @@ impl VkInstance {
|
||||||
has_debug_ext = exts.try_add(DebugUtils::name());
|
has_debug_ext = exts.try_add(DebugUtils::name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable platform specific surface extensions if presentation
|
// Enable platform specific surface extensions.
|
||||||
// support is requested.
|
exts.try_add(khr::Surface::name());
|
||||||
if support_present {
|
|
||||||
exts.try_add(khr::Surface::name());
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
exts.try_add(khr::Win32Surface::name());
|
exts.try_add(khr::Win32Surface::name());
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
))]
|
))]
|
||||||
{
|
{
|
||||||
exts.try_add(khr::XlibSurface::name());
|
exts.try_add(khr::XlibSurface::name());
|
||||||
exts.try_add(khr::XcbSurface::name());
|
exts.try_add(khr::XcbSurface::name());
|
||||||
exts.try_add(khr::WaylandSurface::name());
|
exts.try_add(khr::WaylandSurface::name());
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "android"))]
|
|
||||||
exts.try_add(khr::AndroidSurface::name());
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
||||||
exts.try_add(kkr::MetalSurface::name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "android"))]
|
||||||
|
exts.try_add(khr::AndroidSurface::name());
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
exts.try_add(kkr::MetalSurface::name());
|
||||||
|
|
||||||
let supported_version = entry
|
let supported_version = entry
|
||||||
.try_enumerate_instance_version()?
|
.try_enumerate_instance_version()?
|
||||||
.unwrap_or(vk::make_api_version(0, 1, 0, 0));
|
.unwrap_or(vk::make_api_version(0, 1, 0, 0));
|
||||||
|
@ -270,18 +264,17 @@ impl VkInstance {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a device from the instance, suitable for compute, with an optional presentation
|
/// Create a device from the instance, suitable for compute and graphics.
|
||||||
/// support.
|
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller is responsible for making sure that the instance outlives the device
|
/// The caller is responsible for making sure that the instance outlives the device.
|
||||||
/// and surface. We could enforce that, for example having an `Arc` of the raw instance,
|
/// We could enforce that, for example having an `Arc` of the raw instance,
|
||||||
/// but for now keep things simple.
|
/// but for now keep things simple.
|
||||||
pub unsafe fn device(&self, support_present: bool) -> Result<VkDevice, Error> {
|
pub unsafe fn device(&self) -> Result<VkDevice, Error> {
|
||||||
let devices = self.instance.enumerate_physical_devices()?;
|
let devices = self.instance.enumerate_physical_devices()?;
|
||||||
let (pdevice, qfi) =
|
let (pdevice, qfi) =
|
||||||
choose_device(&self.instance, &devices, support_present).ok_or("no suitable device")?;
|
choose_device(&self.instance, &devices).ok_or("no suitable device")?;
|
||||||
|
|
||||||
let mut has_descriptor_indexing = false;
|
let mut has_descriptor_indexing = false;
|
||||||
let vk1_1 = self.vk_version >= vk::make_api_version(0, 1, 1, 0);
|
let vk1_1 = self.vk_version >= vk::make_api_version(0, 1, 1, 0);
|
||||||
|
@ -317,9 +310,7 @@ impl VkInstance {
|
||||||
self.instance
|
self.instance
|
||||||
.enumerate_device_extension_properties(pdevice)?,
|
.enumerate_device_extension_properties(pdevice)?,
|
||||||
);
|
);
|
||||||
if support_present {
|
extensions.try_add(khr::Swapchain::name());
|
||||||
extensions.try_add(khr::Swapchain::name());
|
|
||||||
}
|
|
||||||
if has_descriptor_indexing {
|
if has_descriptor_indexing {
|
||||||
extensions.try_add(vk::KhrMaintenance3Fn::name());
|
extensions.try_add(vk::KhrMaintenance3Fn::name());
|
||||||
extensions.try_add(vk::ExtDescriptorIndexingFn::name());
|
extensions.try_add(vk::ExtDescriptorIndexingFn::name());
|
||||||
|
@ -1453,32 +1444,17 @@ impl Layers {
|
||||||
unsafe fn choose_device(
|
unsafe fn choose_device(
|
||||||
instance: &Instance,
|
instance: &Instance,
|
||||||
devices: &[vk::PhysicalDevice],
|
devices: &[vk::PhysicalDevice],
|
||||||
support_graphics: bool,
|
|
||||||
) -> Option<(vk::PhysicalDevice, u32)> {
|
) -> Option<(vk::PhysicalDevice, u32)> {
|
||||||
let mut desired_flags = vk::QueueFlags::COMPUTE;
|
|
||||||
if support_graphics {
|
|
||||||
desired_flags |= vk::QueueFlags::GRAPHICS;
|
|
||||||
}
|
|
||||||
for pdevice in devices {
|
for pdevice in devices {
|
||||||
let props = instance.get_physical_device_queue_family_properties(*pdevice);
|
let props = instance.get_physical_device_queue_family_properties(*pdevice);
|
||||||
for (ix, info) in props.iter().enumerate() {
|
for (ix, info) in props.iter().enumerate() {
|
||||||
// TODO: is this strictly necessary? We'll need a queue supporting graphics
|
// Select a device that supports both compute and graphics workloads.
|
||||||
// for image rendering regardless, and I'm leaning on the assumption that
|
// This function used to check for surface compatibility but that was removed
|
||||||
// all physical device + queue family combinations that support graphics also
|
// to allow device creation without an instantiated surface. This follows from
|
||||||
// support presentation particularly when the appropriate extensions are enabled
|
// both Metal and DX12 which do not require such validation. It might be worth
|
||||||
// at instance creation. This may be faulty.
|
// exposing this to the user in a future device enumeration API, which would
|
||||||
|
// also allow selection between discrete and integrated devices.
|
||||||
// Check for surface presentation support
|
if info.queue_flags.contains(vk::QueueFlags::COMPUTE | vk::QueueFlags::GRAPHICS) {
|
||||||
// if let Some(surface) = surface {
|
|
||||||
// if !surface
|
|
||||||
// .surface_fn
|
|
||||||
// .get_physical_device_surface_support(*pdevice, ix as u32, surface.surface)
|
|
||||||
// .unwrap()
|
|
||||||
// {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if info.queue_flags.contains(desired_flags) {
|
|
||||||
return Some((*pdevice, ix as u32));
|
return Some((*pdevice, ix as u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn my_main() -> Result<(), Error> {
|
||||||
let width = window.width() as usize;
|
let width = window.width() as usize;
|
||||||
let height = window.height() as usize;
|
let height = window.height() as usize;
|
||||||
let handle = get_handle(window);
|
let handle = get_handle(window);
|
||||||
let instance = Instance::new(InstanceFlags::PRESENT)?;
|
let instance = Instance::new(InstanceFlags::default())?;
|
||||||
let surface = unsafe { instance.surface(&handle)? };
|
let surface = unsafe { instance.surface(&handle)? };
|
||||||
gfx_state = Some(GfxState::new(&instance, Some(&surface), width, height)?);
|
gfx_state = Some(GfxState::new(&instance, Some(&surface), width, height)?);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -57,7 +57,7 @@ fn main() -> Result<(), Error> {
|
||||||
.with_resizable(false) // currently not supported
|
.with_resizable(false) // currently not supported
|
||||||
.build(&event_loop)?;
|
.build(&event_loop)?;
|
||||||
|
|
||||||
let instance = Instance::new(InstanceFlags::PRESENT)?;
|
let instance = Instance::new(InstanceFlags::default())?;
|
||||||
let mut info_string = "info".to_string();
|
let mut info_string = "info".to_string();
|
||||||
unsafe {
|
unsafe {
|
||||||
let surface = instance.surface(&window)?;
|
let surface = instance.surface(&window)?;
|
||||||
|
|
Loading…
Reference in a new issue