Fix physical device enumeration and add dummy features

Vulkan loader expects that EnumeratePhysicalDevices will return the same handles on each call. Caching them on startup
This commit is contained in:
msiglreith 2018-03-28 17:39:44 +02:00
parent 8e85630840
commit 8d75459a84
3 changed files with 96 additions and 17 deletions

View file

@ -11,6 +11,10 @@ impl<T> Handle<T> {
Handle(ptr) Handle(ptr)
} }
pub fn null() -> Self {
Handle(VK_NULL_HANDLE as *mut _)
}
pub fn unwrap(self) -> Box<T> { pub fn unwrap(self) -> Box<T> {
unsafe { Box::from_raw(self.0) } unsafe { Box::from_raw(self.0) }
} }
@ -74,6 +78,10 @@ mod dispatch {
DispatchHandle(ptr) DispatchHandle(ptr)
} }
pub fn null() -> Self {
DispatchHandle(VK_NULL_HANDLE as *mut _)
}
pub fn unwrap(self) -> Box<(u64, T)> { pub fn unwrap(self) -> Box<(u64, T)> {
unsafe { Box::from_raw(self.0) } unsafe { Box::from_raw(self.0) }
} }

View file

@ -36,14 +36,21 @@ pub extern "C" fn gfxCreateInstance(
_pAllocator: *const VkAllocationCallbacks, _pAllocator: *const VkAllocationCallbacks,
pInstance: *mut VkInstance, pInstance: *mut VkInstance,
) -> VkResult { ) -> VkResult {
//Note: is this the best place to enable logging? // Note: is this the best place to enable logging?
#[cfg(feature = "env_logger")] #[cfg(feature = "env_logger")]
{ {
use env_logger; use env_logger;
env_logger::init(); env_logger::init();
} }
let instance = back::Instance::create("portability", 1);
unsafe { *pInstance = Handle::new(instance) }; let backend = back::Instance::create("portability", 1);
let adapters = backend
.enumerate_adapters()
.into_iter()
.map(Handle::new)
.collect();
unsafe { *pInstance = Handle::new(RawInstance { backend, adapters }) };
VkResult::VK_SUCCESS VkResult::VK_SUCCESS
} }
@ -62,20 +69,15 @@ pub extern "C" fn gfxEnumeratePhysicalDevices(
pPhysicalDeviceCount: *mut u32, pPhysicalDeviceCount: *mut u32,
pPhysicalDevices: *mut VkPhysicalDevice, pPhysicalDevices: *mut VkPhysicalDevice,
) -> VkResult { ) -> VkResult {
let adapters = instance.enumerate_adapters();
// If NULL, number of devices is returned. // If NULL, number of devices is returned.
if pPhysicalDevices.is_null() { if pPhysicalDevices.is_null() {
unsafe { *pPhysicalDeviceCount = adapters.len() as _ }; unsafe { *pPhysicalDeviceCount = instance.adapters.len() as _ };
return VkResult::VK_SUCCESS; return VkResult::VK_SUCCESS;
} }
let output = unsafe { slice::from_raw_parts_mut(pPhysicalDevices, *pPhysicalDeviceCount as _) }; let output = unsafe { slice::from_raw_parts_mut(pPhysicalDevices, *pPhysicalDeviceCount as _) };
let count = cmp::min(adapters.len(), output.len()); let count = cmp::min(instance.adapters.len(), output.len());
output.copy_from_slice(&instance.adapters[..count]);
for (out, adapter) in output.iter_mut().zip(adapters.into_iter()) {
*out = DispatchHandle::new(adapter);
}
unsafe { *pPhysicalDeviceCount = count as _ }; unsafe { *pPhysicalDeviceCount = count as _ };
VkResult::VK_SUCCESS VkResult::VK_SUCCESS
@ -130,7 +132,65 @@ pub extern "C" fn gfxGetPhysicalDeviceFeatures(
) { ) {
let features = adapter.physical_device.features(); let features = adapter.physical_device.features();
// TODO: fill in information unsafe {
*pFeatures = VkPhysicalDeviceFeatures {
robustBufferAccess: VK_FALSE,
fullDrawIndexUint32: VK_FALSE,
imageCubeArray: VK_FALSE,
independentBlend: VK_FALSE,
geometryShader: VK_FALSE,
tessellationShader: VK_FALSE,
sampleRateShading: VK_FALSE,
dualSrcBlend: VK_FALSE,
logicOp: VK_FALSE,
multiDrawIndirect: VK_FALSE,
drawIndirectFirstInstance: VK_FALSE,
depthClamp: VK_FALSE,
depthBiasClamp: VK_FALSE,
fillModeNonSolid: VK_FALSE,
depthBounds: VK_FALSE,
wideLines: VK_FALSE,
largePoints: VK_FALSE,
alphaToOne: VK_FALSE,
multiViewport: VK_FALSE,
samplerAnisotropy: VK_FALSE,
textureCompressionETC2: VK_FALSE,
textureCompressionASTC_LDR: VK_FALSE,
textureCompressionBC: VK_FALSE,
occlusionQueryPrecise: VK_FALSE,
pipelineStatisticsQuery: VK_FALSE,
vertexPipelineStoresAndAtomics: VK_FALSE,
fragmentStoresAndAtomics: VK_FALSE,
shaderTessellationAndGeometryPointSize: VK_FALSE,
shaderImageGatherExtended: VK_FALSE,
shaderStorageImageExtendedFormats: VK_FALSE,
shaderStorageImageMultisample: VK_FALSE,
shaderStorageImageReadWithoutFormat: VK_FALSE,
shaderStorageImageWriteWithoutFormat: VK_FALSE,
shaderUniformBufferArrayDynamicIndexing: VK_FALSE,
shaderSampledImageArrayDynamicIndexing: VK_FALSE,
shaderStorageBufferArrayDynamicIndexing: VK_FALSE,
shaderStorageImageArrayDynamicIndexing: VK_FALSE,
shaderClipDistance: VK_FALSE,
shaderCullDistance: VK_FALSE,
shaderFloat64: VK_FALSE,
shaderInt64: VK_FALSE,
shaderInt16: VK_FALSE,
shaderResourceResidency: VK_FALSE,
shaderResourceMinLod: VK_FALSE,
sparseBinding: VK_FALSE,
sparseResidencyBuffer: VK_FALSE,
sparseResidencyImage2D: VK_FALSE,
sparseResidencyImage3D: VK_FALSE,
sparseResidency2Samples: VK_FALSE,
sparseResidency4Samples: VK_FALSE,
sparseResidency8Samples: VK_FALSE,
sparseResidency16Samples: VK_FALSE,
sparseResidencyAliased: VK_FALSE,
variableMultisampleRate: VK_FALSE,
inheritedQueries: VK_FALSE,
};
}
} }
#[inline] #[inline]
pub extern "C" fn gfxGetPhysicalDeviceFormatProperties( pub extern "C" fn gfxGetPhysicalDeviceFormatProperties(
@ -232,6 +292,11 @@ pub extern "C" fn gfxGetInstanceProcAddr(
Err(_) => return None, Err(_) => return None,
}; };
let device_addr = gfxGetDeviceProcAddr(DispatchHandle::null(), pName);
if device_addr.is_some() {
return device_addr;
}
proc_addr!{ name, proc_addr!{ name,
vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance, vkCreateInstance, PFN_vkCreateInstance => gfxCreateInstance,
vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance, vkDestroyInstance, PFN_vkDestroyInstance => gfxDestroyInstance,
@ -3182,7 +3247,7 @@ pub extern "C" fn gfxCreateWin32SurfaceKHR(
assert_eq!(info.flags, 0); assert_eq!(info.flags, 0);
assert!(pAllocator.is_null()); assert!(pAllocator.is_null());
*pSurface = Handle::new( *pSurface = Handle::new(
instance.create_surface_from_hwnd(info.hinstance, info.hwnd), instance.backend.create_surface_from_hwnd(info.hinstance, info.hwnd),
); );
VkResult::VK_SUCCESS VkResult::VK_SUCCESS
} }
@ -3192,7 +3257,7 @@ pub extern "C" fn gfxCreateWin32SurfaceKHR(
unsafe { unsafe {
assert_eq!(info.flags, 0); assert_eq!(info.flags, 0);
assert!(pAllocator.is_null()); assert!(pAllocator.is_null());
*pSurface = Handle::new(instance.create_surface_from_hwnd(info.hwnd)); *pSurface = Handle::new(instance.backend.create_surface_from_hwnd(info.hwnd));
VkResult::VK_SUCCESS VkResult::VK_SUCCESS
} }
} }
@ -3212,7 +3277,7 @@ pub extern "C" fn gfxCreateXcbSurfaceKHR(
assert_eq!(info.flags, 0); assert_eq!(info.flags, 0);
assert!(pAllocator.is_null()); assert!(pAllocator.is_null());
*pSurface = Handle::new( *pSurface = Handle::new(
instance.create_surface_from_xcb(info.connection as _, info.window), instance.backend.create_surface_from_xcb(info.connection as _, info.window),
); );
VkResult::VK_SUCCESS VkResult::VK_SUCCESS
} }

View file

@ -30,9 +30,15 @@ use std::collections::HashMap;
pub use impls::*; pub use impls::*;
// Vulkan objects // Vulkan objects
pub type VkInstance = Handle<back::Instance>; pub type VkPhysicalDevice = Handle<hal::Adapter<B>>;
pub type VkPhysicalDevice = DispatchHandle<hal::Adapter<B>>;
pub struct RawInstance {
pub backend: back::Instance,
pub adapters: Vec<VkPhysicalDevice>,
}
pub type VkInstance = Handle<RawInstance>;
pub type VkDevice = DispatchHandle<Gpu<B>>; pub type VkDevice = DispatchHandle<Gpu<B>>;
pub type VkQueue = DispatchHandle<<B as hal::Backend>::CommandQueue>; pub type VkQueue = DispatchHandle<<B as hal::Backend>::CommandQueue>;
pub type VkCommandPool = Handle<<B as hal::Backend>::CommandPool>; pub type VkCommandPool = Handle<<B as hal::Backend>::CommandPool>;