108: fix overly conservative function pointer retrieval r=kvark a=msiglreith

Addresses some parts of https://github.com/gfx-rs/portability/pull/98
Current implementation rejects too agressively which is not required, in most cases the spec defines the returned pointers as undefined. InstanceProcAddr also doesn't correctly retrieve some device proc addresses.

CTS looks fine 
(9 green, 3 unsupported, `dEQP-VK.api.device_init.create_instance_device_intentional_alloc_fail` crashes but seems unrelated)

cc @grovesNL 

Co-authored-by: msiglreith <m.siglreith@gmail.com>
This commit is contained in:
bors[bot] 2018-06-25 17:29:39 +00:00
commit 468147d823

View file

@ -4,15 +4,15 @@ use hal::{
Surface, Swapchain as HalSwapchain, FrameSync, Surface, Swapchain as HalSwapchain, FrameSync,
}; };
use hal::buffer::IndexBufferView; use hal::buffer::IndexBufferView;
use hal::command::RawCommandBuffer;
use hal::device::WaitFor; use hal::device::WaitFor;
use hal::pool::RawCommandPool; use hal::pool::RawCommandPool;
use hal::command::RawCommandBuffer;
use hal::queue::RawCommandQueue; use hal::queue::RawCommandQueue;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::{mem, ptr};
#[cfg(feature = "renderdoc")] #[cfg(feature = "renderdoc")]
use std::os::raw::c_void; use std::os::raw::c_void;
use std::{mem, ptr};
use super::*; use super::*;
@ -61,7 +61,9 @@ pub extern "C" fn gfxCreateInstance(
// Compare major and minor parts of version only - patch is ignored // Compare major and minor parts of version only - patch is ignored
let (supported_major, supported_minor, _) = VERSION; let (supported_major, supported_minor, _) = VERSION;
let requested_major_minor = ai.apiVersion >> 12; let requested_major_minor = ai.apiVersion >> 12;
let version_supported = requested_major_minor & (supported_major << 10 | supported_minor) == requested_major_minor; let version_supported = requested_major_minor
& (supported_major << 10 | supported_minor)
== requested_major_minor;
if !version_supported { if !version_supported {
return VkResult::VK_ERROR_INCOMPATIBLE_DRIVER; return VkResult::VK_ERROR_INCOMPATIBLE_DRIVER;
} }
@ -70,13 +72,16 @@ pub extern "C" fn gfxCreateInstance(
let enabled_extensions = if create_info.enabledExtensionCount == 0 { let enabled_extensions = if create_info.enabledExtensionCount == 0 {
Vec::new() Vec::new()
} else { } else {
let extensions = slice::from_raw_parts(create_info.ppEnabledExtensionNames, create_info.enabledExtensionCount as _) let extensions = slice::from_raw_parts(
.iter() create_info.ppEnabledExtensionNames,
.map(|raw| CStr::from_ptr(*raw) create_info.enabledExtensionCount as _,
).iter()
.map(|raw| {
CStr::from_ptr(*raw)
.to_str() .to_str()
.expect("Invalid extension name") .expect("Invalid extension name")
.to_owned() .to_owned()
) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for extension in &extensions { for extension in &extensions {
if !INSTANCE_EXTENSION_NAMES.contains(&extension.as_str()) { if !INSTANCE_EXTENSION_NAMES.contains(&extension.as_str()) {
@ -366,43 +371,6 @@ pub extern "C" fn gfxGetInstanceProcAddr(
return device_addr; 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;
}
}
}
// Required extensions
match name {
"vkGetPhysicalDeviceSurfaceSupportKHR" |
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR" |
"vkGetPhysicalDeviceSurfaceFormatsKHR" |
"vkGetPhysicalDeviceSurfacePresentModesKHR" |
"vkDestroySurfaceKHR"
=> {
let surface_extension_enabled = instance
.as_ref()
.unwrap()
.enabled_extensions
.iter()
.any(|e| e == INSTANCE_EXTENSION_NAME_VK_KHR_SURFACE);
if !surface_extension_enabled {
return None;
}
}
_ => {}
}
proc_addr!{ name, proc_addr!{ name,
vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance, vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance,
vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance, vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance,
@ -446,22 +414,16 @@ pub extern "C" fn gfxGetDeviceProcAddr(
Err(_) => return None, Err(_) => return None,
}; };
// Required device // Requesting the function pointer to an extensions which is available but not
if device.as_ref().is_none() { // enabled with an valid device requires returning NULL.
return None; if let Some(device) = device.as_ref() {
}
// Required extensions
match name { match name {
"vkCreateSwapchainKHR" | "vkCreateSwapchainKHR"
"vkDestroySwapchainKHR" | | "vkDestroySwapchainKHR"
"vkGetSwapchainImagesKHR" | | "vkGetSwapchainImagesKHR"
"vkAcquireNextImageKHR" | | "vkAcquireNextImageKHR"
"vkQueuePresentKHR" | "vkQueuePresentKHR" => {
=> {
let swapchain_extension_enabled = device let swapchain_extension_enabled = device
.as_ref()
.unwrap()
.enabled_extensions .enabled_extensions
.iter() .iter()
.any(|e| e == DEVICE_EXTENSION_NAME_VK_KHR_SWAPCHAIN); .any(|e| e == DEVICE_EXTENSION_NAME_VK_KHR_SWAPCHAIN);
@ -471,6 +433,7 @@ pub extern "C" fn gfxGetDeviceProcAddr(
} }
_ => {} _ => {}
} }
}
proc_addr!{ name, proc_addr!{ name,
vkGetDeviceProcAddr, PFN_vkGetDeviceProcAddr => gfxGetDeviceProcAddr, vkGetDeviceProcAddr, PFN_vkGetDeviceProcAddr => gfxGetDeviceProcAddr,