From 3e716b08ad0832565a375d2a037193864d679dec Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Fri, 15 Jun 2018 18:45:05 -0600 Subject: [PATCH 1/7] Map present modes --- Cargo.lock | 31 +++++++++++++++++++++---------- libportability-gfx/src/conv.rs | 6 ++++++ libportability-gfx/src/impls.rs | 8 +++++++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7f9bce..19d1345 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,14 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.54" @@ -252,13 +260,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "gfx-backend-dx12" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#63826ab79f8339436f1e1b26b0e99f72d4274b67" +source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "derivative 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-hal 0.1.0 (git+https://github.com/gfx-rs/gfx)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "spirv_cross 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -268,7 +276,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#63826ab79f8339436f1e1b26b0e99f72d4274b67" +source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -277,12 +285,13 @@ dependencies = [ "core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "derivative 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-hal 0.1.0 (git+https://github.com/gfx-rs/gfx)", "io-surface 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "metal-rs 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "spirv_cross 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -290,7 +299,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#63826ab79f8339436f1e1b26b0e99f72d4274b67" +source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" dependencies = [ "ash 0.24.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -298,7 +307,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.18.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -308,11 +317,12 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#63826ab79f8339436f1e1b26b0e99f72d4274b67" +source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -653,7 +663,7 @@ dependencies = [ [[package]] name = "smallvec" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -966,6 +976,7 @@ dependencies = [ "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gfx-backend-dx12 0.1.0 (git+https://github.com/gfx-rs/gfx)" = "" "checksum gfx-backend-metal 0.1.0 (git+https://github.com/gfx-rs/gfx)" = "" @@ -1008,7 +1019,7 @@ dependencies = [ "checksum renderdoc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3aee9badfb4078c375d2d0479ed29c9c057b51ade78f94792ba2dcb11f343e7e" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1" -"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" +"checksum smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "312a7df010092e73d6bbaf141957e868d4f30efd2bfd9bb1028ad91abec58514" "checksum spirv_cross 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "387a12e5de5d5cd284d07fe7edbcac83163c0b9b4304bd3a0efb1274bcda83cf" "checksum spirv_cross 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c30addbd9ad947994bcd75019e06d09cccbe30d481f8ce6a16e1b406235b69" "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" diff --git a/libportability-gfx/src/conv.rs b/libportability-gfx/src/conv.rs index ce3eff7..fca8d15 100644 --- a/libportability-gfx/src/conv.rs +++ b/libportability-gfx/src/conv.rs @@ -568,6 +568,12 @@ pub fn map_primitive_topology(topology: VkPrimitiveTopology, patch_size: PatchSi }) } +#[inline] +pub fn map_present_mode(present_mode: VkPresentModeKHR) -> window::PresentMode { + // Vulkan and HAL values are equal + unsafe { mem::transmute(present_mode) } +} + #[inline] pub fn map_compare_op(op: VkCompareOp) -> pso::Comparison { // Vulkan and HAL values are equal diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 2e6939d..e23e97c 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -3602,7 +3602,12 @@ pub extern "C" fn gfxGetPhysicalDeviceSurfacePresentModesKHR( pPresentModeCount: *mut u32, pPresentModes: *mut VkPresentModeKHR, ) -> VkResult { - let modes = vec![VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR]; //TODO + let modes = vec![ + VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR, + VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR, + VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR, + VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR + ]; //TODO let output = unsafe { slice::from_raw_parts_mut(pPresentModes, *pPresentModeCount as usize) }; if output.len() > modes.len() { @@ -3631,6 +3636,7 @@ pub extern "C" fn gfxCreateSwapchainKHR( ); // TODO let config = hal::SwapchainConfig { + present_mode: conv::map_present_mode(info.presentMode), color_format: conv::map_format(info.imageFormat).unwrap(), depth_stencil_format: None, image_count: info.minImageCount, From 967cd9b445a8466b75924eb7396eecf687ceb05c Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 12:41:59 -0600 Subject: [PATCH 2/7] Add present mode querying --- Cargo.lock | 8 +++--- libportability-gfx/src/conv.rs | 6 +++++ libportability-gfx/src/impls.rs | 45 ++++++++++++++++++++------------- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19d1345..189fb18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,7 +260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "gfx-backend-dx12" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" +source = "git+https://github.com/gfx-rs/gfx#39aff0d7cf5e756fafdc310731d426c7883f9414" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "derivative 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -276,7 +276,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" +source = "git+https://github.com/gfx-rs/gfx#39aff0d7cf5e756fafdc310731d426c7883f9414" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -299,7 +299,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" +source = "git+https://github.com/gfx-rs/gfx#39aff0d7cf5e756fafdc310731d426c7883f9414" dependencies = [ "ash 0.24.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -317,7 +317,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#61588a5a82a24552d45931c906ebd4150ee589b3" +source = "git+https://github.com/gfx-rs/gfx#39aff0d7cf5e756fafdc310731d426c7883f9414" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/libportability-gfx/src/conv.rs b/libportability-gfx/src/conv.rs index fca8d15..7770cab 100644 --- a/libportability-gfx/src/conv.rs +++ b/libportability-gfx/src/conv.rs @@ -574,6 +574,12 @@ pub fn map_present_mode(present_mode: VkPresentModeKHR) -> window::PresentMode { unsafe { mem::transmute(present_mode) } } +#[inline] +pub fn map_present_mode_from_hal(present_mode: window::PresentMode) -> VkPresentModeKHR { + // Vulkan and HAL values are equal + unsafe { mem::transmute(present_mode) } +} + #[inline] pub fn map_compare_op(op: VkCompareOp) -> pso::Comparison { // Vulkan and HAL values are equal diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index e23e97c..8bbc7d2 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -3535,7 +3535,7 @@ pub extern "C" fn gfxGetPhysicalDeviceSurfaceCapabilitiesKHR( surface: VkSurfaceKHR, pSurfaceCapabilities: *mut VkSurfaceCapabilitiesKHR, ) -> VkResult { - let (caps, _) = surface.capabilities_and_formats(&adapter.physical_device); + let (caps, _, _) = surface.compatibility(&adapter.physical_device); let output = VkSurfaceCapabilitiesKHR { minImageCount: caps.image_count.start, @@ -3570,7 +3570,7 @@ pub extern "C" fn gfxGetPhysicalDeviceSurfaceFormatsKHR( pSurfaceFormats: *mut VkSurfaceFormatKHR, ) -> VkResult { let formats = surface - .capabilities_and_formats(&adapter.physical_device) + .compatibility(&adapter.physical_device) .1 .map(|formats| formats.into_iter().map(conv::format_from_hal).collect()) .unwrap_or(vec![VkFormat::VK_FORMAT_UNDEFINED]); @@ -3597,27 +3597,38 @@ pub extern "C" fn gfxGetPhysicalDeviceSurfaceFormatsKHR( #[inline] pub extern "C" fn gfxGetPhysicalDeviceSurfacePresentModesKHR( - _adapter: VkPhysicalDevice, - _surface: VkSurfaceKHR, + adapter: VkPhysicalDevice, + surface: VkSurfaceKHR, pPresentModeCount: *mut u32, pPresentModes: *mut VkPresentModeKHR, ) -> VkResult { - let modes = vec![ - VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR, - VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR, - VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR, - VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR - ]; //TODO - let output = unsafe { slice::from_raw_parts_mut(pPresentModes, *pPresentModeCount as usize) }; + let present_modes = surface + .compatibility(&adapter.physical_device) + .2; - if output.len() > modes.len() { - unsafe { *pPresentModeCount = modes.len() as u32 }; - } - for (out, mode) in output.iter_mut().zip(modes) { - *out = mode; + let num_present_modes = present_modes.len(); + + // If NULL, number of present modes is returned. + if pPresentModes.is_null() { + unsafe { *pPresentModeCount = num_present_modes as _ }; + return VkResult::VK_SUCCESS; } - VkResult::VK_SUCCESS + let output = unsafe { slice::from_raw_parts_mut(pPresentModes, *pPresentModeCount as _) }; + let num_output = output.len(); + let (code, count) = if num_output < num_present_modes { + (VkResult::VK_INCOMPLETE, num_output) + } else { + (VkResult::VK_SUCCESS, num_present_modes) + }; + + for (out, present_mode) in output.iter_mut().zip(present_modes) { + *out = conv::map_present_mode_from_hal(present_mode); + } + + unsafe { *pPresentModeCount = count as _ }; + + code } #[inline] From 321cc54f81227f711d0ae7d8aff93a957233bc1d Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 16:17:06 -0600 Subject: [PATCH 3/7] Check for `None` in `gfxGet{Instance|Device}ProcAddr` --- libportability-gfx/src/impls.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 8bbc7d2..602e97d 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -312,7 +312,7 @@ pub extern "C" fn gfxGetPhysicalDeviceMemoryProperties( } #[inline] pub extern "C" fn gfxGetInstanceProcAddr( - _instance: VkInstance, + instance: VkInstance, pName: *const ::std::os::raw::c_char, ) -> PFN_vkVoidFunction { let name = unsafe { CStr::from_ptr(pName) }; @@ -326,6 +326,22 @@ pub extern "C" fn gfxGetInstanceProcAddr( return device_addr; } + match name { + + "vkEnumerateInstanceVersion" | + "vkEnumerateInstanceExtensionProperties" | + "vkEnumerateInstanceLayerProperties" | + "vkCreateInstance" => { + // Instance is not required for these special cases + // See https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html + }, + _ => { + if instance.as_ref().is_none() { + return None; + } + } + } + proc_addr!{ name, vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance, vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance, @@ -360,7 +376,7 @@ pub extern "C" fn gfxGetInstanceProcAddr( #[inline] pub extern "C" fn gfxGetDeviceProcAddr( - _device: VkDevice, + device: VkDevice, pName: *const ::std::os::raw::c_char, ) -> PFN_vkVoidFunction { let name = unsafe { CStr::from_ptr(pName) }; @@ -369,6 +385,10 @@ pub extern "C" fn gfxGetDeviceProcAddr( Err(_) => return None, }; + if device.as_ref().is_none() { + return None; + } + proc_addr!{ name, vkGetDeviceProcAddr, PFN_vkGetDeviceProcAddr => gfxGetDeviceProcAddr, vkDestroyDevice, PFN_vkDestroyDevice => gfxDestroyDevice, From 52bfd5d3ca829cf0a049db48d0e4f722ee3296e3 Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 20:29:45 -0600 Subject: [PATCH 4/7] Check enabled extensions --- libportability-gfx/src/impls.rs | 91 +++++++++++++++++++++++++++++++-- libportability-gfx/src/lib.rs | 2 + 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 602e97d..05c3d63 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -35,7 +35,7 @@ macro_rules! proc_addr { #[inline] pub extern "C" fn gfxCreateInstance( - _pCreateInfo: *const VkInstanceCreateInfo, + pCreateInfo: *const VkInstanceCreateInfo, _pAllocator: *const VkAllocationCallbacks, pInstance: *mut VkInstance, ) -> VkResult { @@ -52,7 +52,29 @@ pub extern "C" fn gfxCreateInstance( .map(Handle::new) .collect(); - unsafe { *pInstance = Handle::new(RawInstance { backend, adapters }) }; + unsafe { + let create_info = &*pCreateInfo; + + let enabled_extensions = if create_info.enabledExtensionCount == 0 { + Vec::new() + } else { + slice::from_raw_parts(create_info.ppEnabledExtensionNames, create_info.enabledExtensionCount as _) + .iter() + .map(|raw| CStr::from_ptr(*raw) + .to_str() + .expect("Invalid extension name") + .to_owned() + ) + .collect() + }; + + *pInstance = Handle::new(RawInstance { + backend, + adapters, + enabled_extensions, + }); + } + VkResult::VK_SUCCESS } @@ -326,15 +348,15 @@ pub extern "C" fn gfxGetInstanceProcAddr( return device_addr; } + // Required instance match name { - "vkEnumerateInstanceVersion" | "vkEnumerateInstanceExtensionProperties" | "vkEnumerateInstanceLayerProperties" | "vkCreateInstance" => { // Instance is not required for these special cases // See https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html - }, + } _ => { if instance.as_ref().is_none() { return None; @@ -342,6 +364,28 @@ pub extern "C" fn gfxGetInstanceProcAddr( } } + // Required extensions + match name { + "vkGetPhysicalDeviceSurfaceSupportKHR" | + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR" | + "vkGetPhysicalDeviceSurfaceFormatsKHR" | + "vkGetPhysicalDeviceSurfacePresentModesKHR" | + "vkDestroySurfaceKHR" + => { + let surface_ext = unsafe { *VK_KHR_SURFACE_EXTENSION_NAME.as_ptr() }; + let surface_extension_enabled = instance + .as_ref() + .unwrap() + .enabled_extensions + .iter() + .any(|e| unsafe { *e.as_ptr() } == surface_ext); + if !surface_extension_enabled { + return None; + } + } + _ => {} + } + proc_addr!{ name, vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance, vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance, @@ -385,10 +429,33 @@ pub extern "C" fn gfxGetDeviceProcAddr( Err(_) => return None, }; + // Required device if device.as_ref().is_none() { return None; } + // Required extensions + match name { + "vkCreateSwapchainKHR" | + "vkDestroySwapchainKHR" | + "vkGetSwapchainImagesKHR" | + "vkAcquireNextImageKHR" | + "vkQueuePresentKHR" + => { + let swapchain_ext = unsafe { *VK_KHR_SWAPCHAIN_EXTENSION_NAME.as_ptr() }; + let swapchain_extension_enabled = device + .as_ref() + .unwrap() + .enabled_extensions + .iter() + .any(|e| unsafe { *e.as_ptr() } == swapchain_ext); + if !swapchain_extension_enabled { + return None; + } + } + _ => {} + } + proc_addr!{ name, vkGetDeviceProcAddr, PFN_vkGetDeviceProcAddr => gfxGetDeviceProcAddr, vkDestroyDevice, PFN_vkDestroyDevice => gfxDestroyDevice, @@ -595,9 +662,25 @@ pub extern "C" fn gfxCreateDevice( rd_device }; + let enabled_extensions = if dev_info.enabledExtensionCount == 0 { + Vec::new() + } else { + unsafe { + slice::from_raw_parts(dev_info.ppEnabledExtensionNames, dev_info.enabledExtensionCount as _) + .iter() + .map(|raw| CStr::from_ptr(*raw) + .to_str() + .expect("Invalid extension name") + .to_owned() + ) + .collect() + } + }; + let gpu = Gpu { device: gpu.device, queues, + enabled_extensions, #[cfg(feature = "renderdoc")] renderdoc, #[cfg(feature = "renderdoc")] diff --git a/libportability-gfx/src/lib.rs b/libportability-gfx/src/lib.rs index 0a799fb..3ef0941 100644 --- a/libportability-gfx/src/lib.rs +++ b/libportability-gfx/src/lib.rs @@ -63,11 +63,13 @@ pub type QueueFamilyIndex = u32; pub struct RawInstance { pub backend: back::Instance, pub adapters: Vec, + pub enabled_extensions: Vec, } pub struct Gpu { device: B::Device, queues: HashMap>, + enabled_extensions: Vec, #[cfg(feature = "renderdoc")] renderdoc: renderdoc::RenderDoc, #[cfg(feature = "renderdoc")] From 4c2b2f13e5e726a2f6a3977ec36271cf10d34df1 Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 21:06:08 -0600 Subject: [PATCH 5/7] Check API version --- libportability-gfx/src/impls.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 05c3d63..bba2153 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -55,6 +55,18 @@ pub extern "C" fn gfxCreateInstance( unsafe { let create_info = &*pCreateInfo; + let application_info = create_info.pApplicationInfo.as_ref(); + + if let Some(ai) = application_info { + // Compare major and minor parts of version only - patch is ignored + let (supported_major, supported_minor, _) = VERSION; + let requested_major_minor = ai.apiVersion >> 12; + let version_supported = requested_major_minor & (supported_major << 10 | supported_minor) == requested_major_minor; + if !version_supported { + return VkResult::VK_ERROR_INCOMPATIBLE_DRIVER; + } + } + let enabled_extensions = if create_info.enabledExtensionCount == 0 { Vec::new() } else { From 6f76d2c7c66931f5f590646ed657a23ced9bed28 Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 22:08:53 -0600 Subject: [PATCH 6/7] Ensure instance and device extensions exist --- libportability-gfx/src/impls.rs | 64 +++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index bba2153..62c7e4b 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -70,14 +70,20 @@ pub extern "C" fn gfxCreateInstance( let enabled_extensions = if create_info.enabledExtensionCount == 0 { Vec::new() } else { - slice::from_raw_parts(create_info.ppEnabledExtensionNames, create_info.enabledExtensionCount as _) + let extensions = slice::from_raw_parts(create_info.ppEnabledExtensionNames, create_info.enabledExtensionCount as _) .iter() .map(|raw| CStr::from_ptr(*raw) .to_str() .expect("Invalid extension name") .to_owned() ) - .collect() + .collect::>(); + for extension in &extensions { + if !INSTANCE_EXTENSION_NAMES.contains(&extension.as_str()) { + return VkResult::VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + extensions }; *pInstance = Handle::new(RawInstance { @@ -384,13 +390,12 @@ pub extern "C" fn gfxGetInstanceProcAddr( "vkGetPhysicalDeviceSurfacePresentModesKHR" | "vkDestroySurfaceKHR" => { - let surface_ext = unsafe { *VK_KHR_SURFACE_EXTENSION_NAME.as_ptr() }; let surface_extension_enabled = instance .as_ref() .unwrap() .enabled_extensions .iter() - .any(|e| unsafe { *e.as_ptr() } == surface_ext); + .any(|e| e == INSTANCE_EXTENSION_NAME_VK_KHR_SURFACE); if !surface_extension_enabled { return None; } @@ -454,13 +459,12 @@ pub extern "C" fn gfxGetDeviceProcAddr( "vkAcquireNextImageKHR" | "vkQueuePresentKHR" => { - let swapchain_ext = unsafe { *VK_KHR_SWAPCHAIN_EXTENSION_NAME.as_ptr() }; let swapchain_extension_enabled = device .as_ref() .unwrap() .enabled_extensions .iter() - .any(|e| unsafe { *e.as_ptr() } == swapchain_ext); + .any(|e| e == DEVICE_EXTENSION_NAME_VK_KHR_SWAPCHAIN); if !swapchain_extension_enabled { return None; } @@ -677,16 +681,22 @@ pub extern "C" fn gfxCreateDevice( let enabled_extensions = if dev_info.enabledExtensionCount == 0 { Vec::new() } else { - unsafe { - slice::from_raw_parts(dev_info.ppEnabledExtensionNames, dev_info.enabledExtensionCount as _) - .iter() - .map(|raw| CStr::from_ptr(*raw) - .to_str() - .expect("Invalid extension name") - .to_owned() - ) - .collect() + let extensions = unsafe { + slice::from_raw_parts(dev_info.ppEnabledExtensionNames, dev_info.enabledExtensionCount as _) + .iter() + .map(|raw| CStr::from_ptr(*raw) + .to_str() + .expect("Invalid extension name") + .to_owned() + ) + .collect::>() + }; + for extension in &extensions { + if !DEVICE_EXTENSION_NAMES.contains(&extension.as_ref()) { + return VkResult::VK_ERROR_EXTENSION_NOT_PRESENT; + } } + extensions }; let gpu = Gpu { @@ -728,8 +738,26 @@ pub extern "C" fn gfxDestroyDevice(gpu: VkDevice, _pAllocator: *const VkAllocati } } +// TODO: Avoid redefining these somehow +static INSTANCE_EXTENSION_NAME_VK_KHR_SURFACE: &str = "VK_KHR_surface"; +#[cfg(target_os="windows")] +static INSTANCE_EXTENSION_NAME_VK_KHR_WIN32_SURFACE: &str = "VK_KHR_win32_surface"; +#[cfg(target_os="macos")] +static INSTANCE_EXTENSION_NAME_VK_MACOS_SURFACE: &str = "VK_MVK_macos_surface"; +static DEVICE_EXTENSION_NAME_VK_KHR_SWAPCHAIN: &str = "VK_KHR_swapchain"; + lazy_static! { // TODO: Request from backend + static ref INSTANCE_EXTENSION_NAMES: Vec<&'static str> = { + vec![ + INSTANCE_EXTENSION_NAME_VK_KHR_SURFACE, + #[cfg(target_os="windows")] + INSTANCE_EXTENSION_NAME_VK_KHR_WIN32_SURFACE, + #[cfg(target_os="macos")] + INSTANCE_EXTENSION_NAME_VK_MACOS_SURFACE, + ] + }; + static ref INSTANCE_EXTENSIONS: Vec = { let mut extensions = [ VkExtensionProperties { @@ -769,6 +797,12 @@ lazy_static! { extensions.to_vec() }; + static ref DEVICE_EXTENSION_NAMES: Vec<&'static str> = { + vec![ + DEVICE_EXTENSION_NAME_VK_KHR_SWAPCHAIN, + ] + }; + static ref DEVICE_EXTENSIONS: Vec = { let mut extensions = [ VkExtensionProperties { From 07657f783bb75706827c33f077aa675a940896f8 Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 17 Jun 2018 22:43:50 -0600 Subject: [PATCH 7/7] Ensure requested features are supported --- libportability-gfx/src/impls.rs | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 62c7e4b..43d0e13 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -645,6 +645,67 @@ pub extern "C" fn gfxCreateDevice( }) .collect::>(); + if let Some(ef) = unsafe { dev_info.pEnabledFeatures.as_ref() } { + let supported = adapter.physical_device.features(); + if (ef.robustBufferAccess != 0 && !supported.contains(Features::ROBUST_BUFFER_ACCESS)) || + (ef.fullDrawIndexUint32 != 0 && !supported.contains(Features::FULL_DRAW_INDEX_U32)) || + (ef.imageCubeArray != 0 && !supported.contains(Features::IMAGE_CUBE_ARRAY)) || + (ef.independentBlend != 0 && !supported.contains(Features::INDEPENDENT_BLENDING)) || + (ef.geometryShader != 0 && !supported.contains(Features::GEOMETRY_SHADER)) || + (ef.tessellationShader != 0 && !supported.contains(Features::TESSELLATION_SHADER)) || + (ef.sampleRateShading != 0 && !supported.contains(Features::SAMPLE_RATE_SHADING)) || + (ef.dualSrcBlend != 0 && !supported.contains(Features::DUAL_SRC_BLENDING)) || + (ef.logicOp != 0 && !supported.contains(Features::LOGIC_OP)) || + (ef.multiDrawIndirect != 0 && !supported.contains(Features::MULTI_DRAW_INDIRECT)) || + (ef.drawIndirectFirstInstance != 0 && !supported.contains(Features::DRAW_INDIRECT_FIRST_INSTANCE)) || + (ef.depthClamp != 0 && !supported.contains(Features::DEPTH_CLAMP)) || + (ef.depthBiasClamp != 0 && !supported.contains(Features::DEPTH_BIAS_CLAMP)) || + (ef.fillModeNonSolid != 0 && !supported.contains(Features::NON_FILL_POLYGON_MODE)) || + (ef.depthBounds != 0 && !supported.contains(Features::DEPTH_BOUNDS)) || + (ef.wideLines != 0 && !supported.contains(Features::LINE_WIDTH)) || + (ef.largePoints != 0 && !supported.contains(Features::POINT_SIZE)) || + (ef.alphaToOne != 0 && !supported.contains(Features::ALPHA_TO_ONE)) || + (ef.multiViewport != 0 && !supported.contains(Features::MULTI_VIEWPORTS)) || + (ef.samplerAnisotropy != 0 && !supported.contains(Features::SAMPLER_ANISOTROPY)) || + (ef.textureCompressionETC2 != 0 && !supported.contains(Features::FORMAT_ETC2)) || + (ef.textureCompressionASTC_LDR != 0 && !supported.contains(Features::FORMAT_ASTC_LDR)) || + (ef.textureCompressionBC != 0 && !supported.contains(Features::FORMAT_BC)) || + (ef.occlusionQueryPrecise != 0 && !supported.contains(Features::PRECISE_OCCLUSION_QUERY)) || + (ef.pipelineStatisticsQuery != 0 && !supported.contains(Features::PIPELINE_STATISTICS_QUERY)) || + (ef.vertexPipelineStoresAndAtomics != 0 && !supported.contains(Features::VERTEX_STORES_AND_ATOMICS)) || + (ef.fragmentStoresAndAtomics != 0 && !supported.contains(Features::FRAGMENT_STORES_AND_ATOMICS)) || + (ef.shaderTessellationAndGeometryPointSize != 0 && !supported.contains(Features::SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE)) || + (ef.shaderImageGatherExtended != 0 && !supported.contains(Features::SHADER_IMAGE_GATHER_EXTENDED)) || + (ef.shaderStorageImageExtendedFormats != 0 && !supported.contains(Features::SHADER_STORAGE_IMAGE_EXTENDED_FORMATS)) || + (ef.shaderStorageImageMultisample != 0 && !supported.contains(Features::SHADER_STORAGE_IMAGE_MULTISAMPLE)) || + (ef.shaderStorageImageReadWithoutFormat != 0 && !supported.contains(Features::SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT)) || + (ef.shaderStorageImageWriteWithoutFormat != 0 && !supported.contains(Features::SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT)) || + (ef.shaderUniformBufferArrayDynamicIndexing != 0 && !supported.contains(Features::SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING)) || + (ef.shaderSampledImageArrayDynamicIndexing != 0 && !supported.contains(Features::SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING)) || + (ef.shaderStorageBufferArrayDynamicIndexing != 0 && !supported.contains(Features::SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING)) || + (ef.shaderStorageImageArrayDynamicIndexing != 0 && !supported.contains(Features::SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING)) || + (ef.shaderClipDistance != 0 && !supported.contains(Features::SHADER_CLIP_DISTANCE)) || + (ef.shaderCullDistance != 0 && !supported.contains(Features::SHADER_CULL_DISTANCE)) || + (ef.shaderFloat64 != 0 && !supported.contains(Features::SHADER_FLOAT64)) || + (ef.shaderInt64 != 0 && !supported.contains(Features::SHADER_INT64)) || + (ef.shaderInt16 != 0 && !supported.contains(Features::SHADER_INT16)) || + (ef.shaderResourceResidency != 0 && !supported.contains(Features::SHADER_RESOURCE_RESIDENCY)) || + (ef.shaderResourceMinLod != 0 && !supported.contains(Features::SHADER_RESOURCE_MIN_LOD)) || + (ef.sparseBinding != 0 && !supported.contains(Features::SPARSE_BINDING)) || + (ef.sparseResidencyBuffer != 0 && !supported.contains(Features::SPARSE_RESIDENCY_BUFFER)) || + (ef.sparseResidencyImage2D != 0 && !supported.contains(Features::SHADER_RESIDENCY_IMAGE_2D)) || + (ef.sparseResidencyImage3D != 0 && !supported.contains(Features::SHADER_RESIDENSY_IMAGE_3D)) || + (ef.sparseResidency2Samples != 0 && !supported.contains(Features::SPARSE_RESIDENCY_2_SAMPLES)) || + (ef.sparseResidency4Samples != 0 && !supported.contains(Features::SPARSE_RESIDENCY_4_SAMPLES)) || + (ef.sparseResidency8Samples != 0 && !supported.contains(Features::SPARSE_RESIDENCY_8_SAMPLES)) || + (ef.sparseResidency16Samples != 0 && !supported.contains(Features::SPARSE_RESIDENCY_16_SAMPLES)) || + (ef.sparseResidencyAliased != 0 && !supported.contains(Features::SPARSE_RESIDENCY_ALIASED)) || + (ef.variableMultisampleRate != 0 && !supported.contains(Features::VARIABLE_MULTISAMPLE_RATE)) || + (ef.inheritedQueries != 0 && !supported.contains(Features::INHERITED_QUERIES)) { + return VkResult::VK_ERROR_FEATURE_NOT_PRESENT; + } + } + #[cfg(feature = "renderdoc")] let mut renderdoc = { use renderdoc::RenderDoc;