@@ -98,36 +98,38 @@ class HelloTriangleApplication
9898 }
9999
100100 // Check if the required layers are supported by the Vulkan implementation.
101- auto layerProperties = context.enumerateInstanceLayerProperties ();
102- for (auto const &requiredLayer : requiredLayers)
101+ auto layerProperties = context.enumerateInstanceLayerProperties ();
102+ auto unsupportedLayerIt = std::ranges::find_if (requiredLayers,
103+ [&layerProperties](auto const &requiredLayer) {
104+ return std::ranges::none_of (layerProperties,
105+ [requiredLayer](auto const &layerProperty) { return strcmp (layerProperty.layerName , requiredLayer) == 0 ; });
106+ });
107+ if (unsupportedLayerIt != requiredLayers.end ())
103108 {
104- if (std::ranges::none_of (layerProperties,
105- [requiredLayer](auto const &layerProperty) { return strcmp (layerProperty.layerName , requiredLayer) == 0 ; }))
106- {
107- throw std::runtime_error (" Required layer not supported: " + std::string (requiredLayer));
108- }
109+ throw std::runtime_error (" Required layer not supported: " + std::string (*unsupportedLayerIt));
109110 }
110111
111112 // Get the required extensions.
112- auto requiredExtensions = getRequiredExtensions ();
113+ auto requiredExtensions = getRequiredInstanceExtensions ();
113114
114115 // Check if the required extensions are supported by the Vulkan implementation.
115116 auto extensionProperties = context.enumerateInstanceExtensionProperties ();
116- for (auto const &requiredExtension : requiredExtensions)
117+ auto unsupportedPropertyIt =
118+ std::ranges::find_if (requiredExtensions,
119+ [&extensionProperties](auto const &requiredExtension) {
120+ return std::ranges::none_of (extensionProperties,
121+ [requiredExtension](auto const &extensionProperty) { return strcmp (extensionProperty.extensionName , requiredExtension) == 0 ; });
122+ });
123+ if (unsupportedPropertyIt != requiredExtensions.end ())
117124 {
118- if (std::ranges::none_of (extensionProperties,
119- [requiredExtension](auto const &extensionProperty) { return strcmp (extensionProperty.extensionName , requiredExtension) == 0 ; }))
120- {
121- throw std::runtime_error (" Required extension not supported: " + std::string (requiredExtension));
122- }
125+ throw std::runtime_error (" Required extension not supported: " + std::string (*unsupportedPropertyIt));
123126 }
124127
125- vk::InstanceCreateInfo createInfo{
126- .pApplicationInfo = &appInfo,
127- .enabledLayerCount = static_cast <uint32_t >(requiredLayers.size ()),
128- .ppEnabledLayerNames = requiredLayers.data (),
129- .enabledExtensionCount = static_cast <uint32_t >(requiredExtensions.size ()),
130- .ppEnabledExtensionNames = requiredExtensions.data ()};
128+ vk::InstanceCreateInfo createInfo{.pApplicationInfo = &appInfo,
129+ .enabledLayerCount = static_cast <uint32_t >(requiredLayers.size ()),
130+ .ppEnabledLayerNames = requiredLayers.data (),
131+ .enabledExtensionCount = static_cast <uint32_t >(requiredExtensions.size ()),
132+ .ppEnabledExtensionNames = requiredExtensions.data ()};
131133 instance = vk::raii::Instance (context, createInfo);
132134 }
133135
@@ -136,55 +138,59 @@ class HelloTriangleApplication
136138 if (!enableValidationLayers)
137139 return ;
138140
139- vk::DebugUtilsMessageSeverityFlagsEXT severityFlags (vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError);
140- vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags (vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation);
141- vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{
142- .messageSeverity = severityFlags,
143- .messageType = messageTypeFlags,
144- .pfnUserCallback = &debugCallback};
141+ vk::DebugUtilsMessageSeverityFlagsEXT severityFlags (vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
142+ vk::DebugUtilsMessageSeverityFlagBitsEXT::eError);
143+ vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags (
144+ vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation);
145+ vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{.messageSeverity = severityFlags,
146+ .messageType = messageTypeFlags,
147+ .pfnUserCallback = &debugCallback};
145148 debugMessenger = instance.createDebugUtilsMessengerEXT (debugUtilsMessengerCreateInfoEXT);
146149 }
147150
151+ bool isDeviceSuitable (vk::raii::PhysicalDevice const &physicalDevice)
152+ {
153+ // Check if the physicalDevice supports the Vulkan 1.3 API version
154+ bool supportsVulkan1_3 = physicalDevice.getProperties ().apiVersion >= vk::ApiVersion13;
155+
156+ // Check if any of the queue families support graphics operations
157+ auto queueFamilies = physicalDevice.getQueueFamilyProperties ();
158+ bool supportsGraphics = std::ranges::any_of (queueFamilies, [](auto const &qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); });
159+
160+ // Check if all required physicalDevice extensions are available
161+ auto availableDeviceExtensions = physicalDevice.enumerateDeviceExtensionProperties ();
162+ bool supportsAllRequiredExtensions =
163+ std::ranges::all_of (requiredDeviceExtension,
164+ [&availableDeviceExtensions](auto const &requiredDeviceExtension) {
165+ return std::ranges::any_of (availableDeviceExtensions,
166+ [requiredDeviceExtension](auto const &availableDeviceExtension) { return strcmp (availableDeviceExtension.extensionName , requiredDeviceExtension) == 0 ; });
167+ });
168+
169+ // Check if the physicalDevice supports the required features
170+ auto features = physicalDevice.template getFeatures2 <vk::PhysicalDeviceFeatures2,
171+ vk::PhysicalDeviceVulkan11Features,
172+ vk::PhysicalDeviceVulkan13Features,
173+ vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
174+ bool supportsRequiredFeatures = features.template get <vk::PhysicalDeviceVulkan11Features>().shaderDrawParameters &&
175+ features.template get <vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
176+ features.template get <vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState ;
177+
178+ // Return true if the physicalDevice meets all the criteria
179+ return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
180+ }
181+
148182 void pickPhysicalDevice ()
149183 {
150- std::vector<vk::raii::PhysicalDevice> devices = instance.enumeratePhysicalDevices ();
151- const auto devIter = std::ranges::find_if (
152- devices,
153- [&](auto const &device) {
154- // Check if the device supports the Vulkan 1.3 API version
155- bool supportsVulkan1_3 = device.getProperties ().apiVersion >= VK_API_VERSION_1_3 ;
156-
157- // Check if any of the queue families support graphics operations
158- auto queueFamilies = device.getQueueFamilyProperties ();
159- bool supportsGraphics =
160- std::ranges::any_of (queueFamilies, [](auto const &qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); });
161-
162- // Check if all required device extensions are available
163- auto availableDeviceExtensions = device.enumerateDeviceExtensionProperties ();
164- bool supportsAllRequiredExtensions =
165- std::ranges::all_of (requiredDeviceExtension,
166- [&availableDeviceExtensions](auto const &requiredDeviceExtension) {
167- return std::ranges::any_of (availableDeviceExtensions,
168- [requiredDeviceExtension](auto const &availableDeviceExtension) { return strcmp (availableDeviceExtension.extensionName , requiredDeviceExtension) == 0 ; });
169- });
170-
171- auto features = device.template getFeatures2 <vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
172- bool supportsRequiredFeatures = features.template get <vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
173- features.template get <vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState ;
174-
175- return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
176- });
177- if (devIter != devices.end ())
178- {
179- physicalDevice = *devIter;
180- }
181- else
184+ std::vector<vk::raii::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices ();
185+ auto const devIter = std::ranges::find_if (physicalDevices, [&](auto const &physicalDevice) { return isDeviceSuitable (physicalDevice); });
186+ if (devIter == physicalDevices.end ())
182187 {
183188 throw std::runtime_error (" failed to find a suitable GPU!" );
184189 }
190+ physicalDevice = *devIter;
185191 }
186192
187- std::vector<const char *> getRequiredExtensions ()
193+ std::vector<const char *> getRequiredInstanceExtensions ()
188194 {
189195 uint32_t glfwExtensionCount = 0 ;
190196 auto glfwExtensions = glfwGetRequiredInstanceExtensions (&glfwExtensionCount);
0 commit comments