@@ -273,13 +273,29 @@ static inline void clearVector(T& v, S func, bool downsize = true)
273273
274274// ---------------------------- VULKAN DEVICE MANAGEMENT ----------------------------
275275
276- double GPUDisplayBackendVulkan::checkDevice (vk::PhysicalDevice device, const std::vector<const char *>& reqDeviceExtensions, bool silent)
276+ static bool hasFeatures (const vk::PhysicalDeviceFeatures& available, const vk::PhysicalDeviceFeatures& required) // The struct consists only of VkBool32 members
277+ {
278+ static_assert (sizeof (vk::PhysicalDeviceFeatures) % sizeof (vk::Bool32) == 0 );
279+ const vk::Bool32* a = reinterpret_cast <const vk::Bool32*>(&available);
280+ const vk::Bool32* r = reinterpret_cast <const vk::Bool32*>(&required);
281+ for (size_t i = 0 ; i < sizeof (vk::PhysicalDeviceFeatures) / sizeof (vk::Bool32); i++) {
282+ if (r[i] && !a[i]) {
283+ return false ;
284+ }
285+ }
286+ return true ;
287+ }
288+
289+ double GPUDisplayBackendVulkan::checkDevice (vk::PhysicalDevice device, const std::vector<const char *>& reqDeviceExtensions, const vk::PhysicalDeviceFeatures& reqDeviceFeatures, bool silent)
277290{
278291 double score = -1 .;
279292 vk::PhysicalDeviceProperties deviceProperties = device.getProperties ();
280293 vk::PhysicalDeviceFeatures deviceFeatures = device.getFeatures ();
281294 vk::PhysicalDeviceMemoryProperties memoryProperties = device.getMemoryProperties ();
282- if (!deviceFeatures.geometryShader || !deviceFeatures.wideLines || !deviceFeatures.largePoints ) {
295+ if (!hasFeatures (deviceFeatures, reqDeviceFeatures)) {
296+ if (!silent) {
297+ GPUInfo (" %s ignored due to missing features" , &deviceProperties.deviceName [0 ]);
298+ }
283299 return (-1 );
284300 }
285301
@@ -431,8 +447,9 @@ void GPUDisplayBackendVulkan::createDevice()
431447 throw std::runtime_error (" Frontend does not provide Vulkan surface" );
432448 }
433449
434- const std::vector<const char *> reqDeviceExtensions = {
435- VK_KHR_SWAPCHAIN_EXTENSION_NAME };
450+ const std::vector<const char *> reqDeviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME };
451+ vk::PhysicalDeviceFeatures reqDeviceFeatures{};
452+ reqDeviceFeatures.geometryShader = reqDeviceFeatures.wideLines = reqDeviceFeatures.largePoints = VK_TRUE ;
436453
437454 mPhysicalDevice = VkPhysicalDevice (VK_NULL_HANDLE );
438455 std::vector<vk::PhysicalDevice> devices = mInstance .enumeratePhysicalDevices ();
@@ -441,7 +458,7 @@ void GPUDisplayBackendVulkan::createDevice()
441458 }
442459 double bestScore = -1 .;
443460 for (uint32_t i = 0 ; i < devices.size (); i++) {
444- double score = checkDevice (devices[i], reqDeviceExtensions);
461+ double score = checkDevice (devices[i], reqDeviceExtensions, reqDeviceFeatures );
445462 if (mDisplay ->GetProcessingSettings ().debugLevel >= 2 ) {
446463 vk::PhysicalDeviceProperties deviceProperties = devices[i].getProperties ();
447464 GPUInfo (" Available Vulkan device %d: %s - Score %f" , i, &deviceProperties.deviceName [0 ], score);
@@ -460,13 +477,12 @@ void GPUDisplayBackendVulkan::createDevice()
460477 if (!mPhysicalDevice ) {
461478 throw std::runtime_error (" All available Vulkan devices unsuited" );
462479 }
463- if (checkDevice (mPhysicalDevice , reqDeviceExtensions, true ) <= 0 ) {
480+ if (checkDevice (mPhysicalDevice , reqDeviceExtensions, reqDeviceFeatures, true ) <= 0 ) {
464481 throw std::runtime_error (" Selected vulkan device is incompatible" );
465482 }
466483
467484 updateSwapChainDetails (mPhysicalDevice );
468485 vk::PhysicalDeviceProperties deviceProperties = mPhysicalDevice .getProperties ();
469- vk::PhysicalDeviceFeatures deviceFeatures = mPhysicalDevice .getFeatures ();
470486 vk::FormatProperties depth32FormatProperties = mPhysicalDevice .getFormatProperties (vk::Format::eD32Sfloat);
471487 vk::FormatProperties depth64FormatProperties = mPhysicalDevice .getFormatProperties (vk::Format::eD32SfloatS8Uint);
472488 GPUInfo (" Using physical Vulkan device %s" , &deviceProperties.deviceName [0 ]);
@@ -486,7 +502,7 @@ void GPUDisplayBackendVulkan::createDevice()
486502 vk::DeviceCreateInfo deviceCreateInfo{};
487503 deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
488504 deviceCreateInfo.queueCreateInfoCount = 1 ;
489- deviceCreateInfo.pEnabledFeatures = &deviceFeatures ;
505+ deviceCreateInfo.pEnabledFeatures = &reqDeviceFeatures ;
490506 deviceCreateInfo.enabledExtensionCount = static_cast <uint32_t >(reqDeviceExtensions.size ());
491507 deviceCreateInfo.ppEnabledExtensionNames = reqDeviceExtensions.data ();
492508 mDevice = mPhysicalDevice .createDevice (deviceCreateInfo, nullptr );
0 commit comments