@@ -38,13 +38,20 @@ class HelloTriangleApplication {
3838 GLFWwindow* window = nullptr ;
3939
4040 vk::raii::Context context;
41- std::unique_ptr< vk::raii::Instance> instance;
42- std::unique_ptr< vk::raii::DebugUtilsMessengerEXT> debugMessenger;
41+ vk::raii::Instance instance = nullptr ;
42+ vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr ;
4343
44- std::unique_ptr< vk::raii::PhysicalDevice> physicalDevice;
45- std::unique_ptr< vk::raii::Device> device;
44+ vk::raii::PhysicalDevice physicalDevice = nullptr ;
45+ vk::raii::Device device = nullptr ;
4646
47- std::unique_ptr<vk::raii::Queue> graphicsQueue;
47+ vk::raii::Queue graphicsQueue = nullptr ;
48+
49+ std::vector<const char *> deviceExtensions = {
50+ vk::KHRSwapchainExtensionName,
51+ vk::KHRSpirv14ExtensionName,
52+ vk::KHRSynchronization2ExtensionName,
53+ vk::KHRCreateRenderpass2ExtensionName
54+ };
4855
4956 void initWindow () {
5057 glfwInit ();
@@ -79,48 +86,95 @@ class HelloTriangleApplication {
7986 throw std::runtime_error (" validation layers requested, but not available!" );
8087 }
8188
82- constexpr auto appInfo = vk::ApplicationInfo (" Hello Triangle" , 1 , " No Engine" , 1 , vk::ApiVersion14);
89+ constexpr vk::ApplicationInfo appInfo{ .pApplicationName = " Hello Triangle" ,
90+ .applicationVersion = VK_MAKE_VERSION ( 1 , 0 , 0 ),
91+ .pEngineName = " No Engine" ,
92+ .engineVersion = VK_MAKE_VERSION ( 1 , 0 , 0 ),
93+ .apiVersion = vk::ApiVersion14 };
8394 auto extensions = getRequiredExtensions ();
8495 std::vector<char const *> enabledLayers;
8596 if (enableValidationLayers) {
8697 enabledLayers.assign (validationLayers.begin (), validationLayers.end ());
8798 }
88- vk::InstanceCreateInfo createInfo ({}, &appInfo, enabledLayers.size (), enabledLayers.data (), extensions.size (), extensions.data ());
89- instance = std::make_unique<vk::raii::Instance>(context, createInfo);
99+ vk::InstanceCreateInfo createInfo{
100+ .pApplicationInfo = &appInfo,
101+ .enabledLayerCount = static_cast <uint32_t >(enabledLayers.size ()),
102+ .ppEnabledLayerNames = enabledLayers.data (),
103+ .enabledExtensionCount = static_cast <uint32_t >(extensions.size ()),
104+ .ppEnabledExtensionNames = extensions.data () };
105+ instance = vk::raii::Instance (context, createInfo);
90106 }
91107
92108 void setupDebugMessenger () {
93109 if (!enableValidationLayers) return ;
94110
95111 vk::DebugUtilsMessageSeverityFlagsEXT severityFlags ( vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
96112 vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags ( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
97- vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT ({}, severityFlags, messageTypeFlags, &debugCallback);
98- debugMessenger = std::make_unique<vk::raii::DebugUtilsMessengerEXT>( *instance, debugUtilsMessengerCreateInfoEXT );
113+ vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{
114+ .messageSeverity = severityFlags,
115+ .messageType = messageTypeFlags,
116+ .pfnUserCallback = &debugCallback
117+ };
118+ debugMessenger = instance.createDebugUtilsMessengerEXT (debugUtilsMessengerCreateInfoEXT);
99119 }
100120
101121 void pickPhysicalDevice () {
102- physicalDevice = std::make_unique<vk::raii::PhysicalDevice>(vk::raii::PhysicalDevices ( *instance ).front ());
122+ std::vector<vk::raii::PhysicalDevice> devices = instance.enumeratePhysicalDevices ();
123+ const auto devIter = std::ranges::find_if (devices,
124+ [&](auto const & device) {
125+ auto queueFamilies = device.getQueueFamilyProperties ();
126+ bool isSuitable = device.getProperties ().apiVersion >= VK_API_VERSION_1_3;
127+ const auto qfpIter = std::ranges::find_if (queueFamilies,
128+ []( vk::QueueFamilyProperties const & qfp )
129+ {
130+ return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast <vk::QueueFlags>(0 );
131+ } );
132+ isSuitable = isSuitable && ( qfpIter != queueFamilies.end () );
133+ auto extensions = device.enumerateDeviceExtensionProperties ( );
134+ bool found = true ;
135+ for (auto const & extension : deviceExtensions) {
136+ auto extensionIter = std::ranges::find_if (extensions, [extension](auto const & ext) {return strcmp (ext.extensionName , extension) == 0 ;});
137+ found = found && extensionIter != extensions.end ();
138+ }
139+ isSuitable = isSuitable && found;
140+ printf (" \n " );
141+ if (isSuitable) {
142+ physicalDevice = device;
143+ }
144+ return isSuitable;
145+ });
146+ if (devIter == devices.end ()) {
147+ throw std::runtime_error (" failed to find a suitable GPU!" );
148+ }
103149 }
104150
105151 void createLogicalDevice () {
106152 // find the index of the first queue family that supports graphics
107- std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice-> getQueueFamilyProperties ();
153+ std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice. getQueueFamilyProperties ();
108154
109- // get the first index into queueFamiliyProperties which supports graphics
110- auto graphicsQueueFamilyProperty =
111- std::find_if ( queueFamilyProperties.begin (),
112- queueFamilyProperties.end (),
113- []( vk::QueueFamilyProperties const & qfp ) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; } );
155+ // get the first index into queueFamilyProperties which supports graphics
156+ auto graphicsQueueFamilyProperty = std::ranges::find_if ( queueFamilyProperties, []( auto const & qfp )
157+ { return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast <vk::QueueFlags>(0 ); } );
114158
115159 auto graphicsIndex = static_cast <uint32_t >( std::distance ( queueFamilyProperties.begin (), graphicsQueueFamilyProperty ) );
116160
161+ // query for Vulkan 1.3 features
162+ auto features = physicalDevice.getFeatures2 ();
163+ vk::PhysicalDeviceVulkan13Features vulkan13Features;
164+ vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures;
165+ vulkan13Features.dynamicRendering = vk::True;
166+ extendedDynamicStateFeatures.extendedDynamicState = vk::True;
167+ vulkan13Features.pNext = &extendedDynamicStateFeatures;
168+ features.pNext = &vulkan13Features;
117169 // create a Device
118170 float queuePriority = 0 .0f ;
119- vk::DeviceQueueCreateInfo deviceQueueCreateInfo ( {}, graphicsIndex, 1 , &queuePriority );
120- vk::DeviceCreateInfo deviceCreateInfo ( {}, deviceQueueCreateInfo );
171+ vk::DeviceQueueCreateInfo deviceQueueCreateInfo { .queueFamilyIndex = graphicsIndex, .queueCount = 1 , .pQueuePriorities = &queuePriority };
172+ vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &features, .queueCreateInfoCount = 1 , .pQueueCreateInfos = &deviceQueueCreateInfo };
173+ deviceCreateInfo.enabledExtensionCount = deviceExtensions.size ();
174+ deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data ();
121175
122- device = std::make_unique< vk::raii::Device>( * physicalDevice, deviceCreateInfo );
123- graphicsQueue = std::make_unique< vk::raii::Queue>( * device, graphicsIndex, 0 );
176+ device = vk::raii::Device ( physicalDevice, deviceCreateInfo );
177+ graphicsQueue = vk::raii::Queue ( device, graphicsIndex, 0 );
124178 }
125179
126180 std::vector<const char *> getRequiredExtensions () {
0 commit comments