Skip to content

Commit 07d4d97

Browse files
authored
Merge pull request #78 from asuessenbach/01_instance_creation
Add layer and extension checks on instance creation
2 parents 17528f7 + a609649 commit 07d4d97

29 files changed

+1025
-617
lines changed

attachments/01_instance_creation.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <algorithm>
12
#include <iostream>
23
#include <stdexcept>
34
#include <cstdlib>
@@ -58,11 +59,27 @@ class HelloTriangleApplication {
5859
.pEngineName = "No Engine",
5960
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
6061
.apiVersion = vk::ApiVersion14 };
62+
63+
// Get the required instance extensions from GLFW.
6164
uint32_t glfwExtensionCount = 0;
6265
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
66+
67+
// Check if the required GLFW extensions are supported by the Vulkan implementation.
68+
auto extensionProperties = context.enumerateInstanceExtensionProperties();
69+
for (uint32_t i = 0; i < glfwExtensionCount; ++i)
70+
{
71+
if (std::ranges::none_of(extensionProperties,
72+
[glfwExtension = glfwExtensions[i]](auto const& extensionProperty)
73+
{ return strcmp(extensionProperty.extensionName, glfwExtension) == 0; }))
74+
{
75+
throw std::runtime_error("Required GLFW extension not supported: " + std::string(glfwExtensions[i]));
76+
}
77+
}
78+
6379
vk::InstanceCreateInfo createInfo{
6480
.pApplicationInfo = &appInfo,
65-
.ppEnabledLayerNames = glfwExtensions};
81+
.enabledExtensionCount = glfwExtensionCount,
82+
.ppEnabledExtensionNames = glfwExtensions};
6683
instance = vk::raii::Instance(context, createInfo);
6784
}
6885
};

attachments/02_validation_layers.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -68,26 +68,51 @@ class HelloTriangleApplication {
6868
}
6969

7070
void createInstance() {
71-
if (enableValidationLayers && !checkValidationLayerSupport()) {
72-
throw std::runtime_error("validation layers requested, but not available!");
73-
}
74-
7571
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
7672
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
7773
.pEngineName = "No Engine",
7874
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
7975
.apiVersion = vk::ApiVersion14 };
80-
auto extensions = getRequiredExtensions();
81-
std::vector<char const *> enabledLayers;
76+
77+
// Get the required layers
78+
std::vector<char const*> requiredLayers;
8279
if (enableValidationLayers) {
83-
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
80+
requiredLayers.assign(validationLayers.begin(), validationLayers.end());
81+
}
82+
83+
// Check if the required layers are supported by the Vulkan implementation.
84+
auto layerProperties = context.enumerateInstanceLayerProperties();
85+
for (auto const& requiredLayer : requiredLayers)
86+
{
87+
if (std::ranges::none_of(layerProperties,
88+
[requiredLayer](auto const& layerProperty)
89+
{ return strcmp(layerProperty.layerName, requiredLayer) == 0; }))
90+
{
91+
throw std::runtime_error("Required layer not supported: " + std::string(requiredLayer));
92+
}
8493
}
94+
95+
// Get the required extensions.
96+
auto requiredExtensions = getRequiredExtensions();
97+
98+
// Check if the required extensions are supported by the Vulkan implementation.
99+
auto extensionProperties = context.enumerateInstanceExtensionProperties();
100+
for (auto const & requiredExtension : requiredExtensions)
101+
{
102+
if (std::ranges::none_of(extensionProperties,
103+
[requiredExtension](auto const& extensionProperty)
104+
{ return strcmp(extensionProperty.extensionName, requiredExtension) == 0; }))
105+
{
106+
throw std::runtime_error("Required extension not supported: " + std::string(requiredExtension));
107+
}
108+
}
109+
85110
vk::InstanceCreateInfo createInfo{
86111
.pApplicationInfo = &appInfo,
87-
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
88-
.ppEnabledLayerNames = enabledLayers.data(),
89-
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
90-
.ppEnabledExtensionNames = extensions.data() };
112+
.enabledLayerCount = static_cast<uint32_t>(requiredLayers.size()),
113+
.ppEnabledLayerNames = requiredLayers.data(),
114+
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
115+
.ppEnabledExtensionNames = requiredExtensions.data() };
91116
instance = vk::raii::Instance(context, createInfo);
92117
}
93118

@@ -108,12 +133,6 @@ class HelloTriangleApplication {
108133
uint32_t glfwExtensionCount = 0;
109134
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
110135

111-
std::vector<vk::ExtensionProperties> props = context.enumerateInstanceExtensionProperties();
112-
if (const auto propsIterator = std::ranges::find_if(props, []( vk::ExtensionProperties const & ep ) { return strcmp( ep.extensionName, vk::EXTDebugUtilsExtensionName ) == 0; } ); propsIterator == props.end() )
113-
{
114-
std::cout << "Something went very wrong, cannot find VK_EXT_debug_utils extension" << std::endl;
115-
exit( 1 );
116-
}
117136
std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
118137
if (enableValidationLayers) {
119138
extensions.push_back(vk::EXTDebugUtilsExtensionName );
@@ -122,11 +141,6 @@ class HelloTriangleApplication {
122141
return extensions;
123142
}
124143

125-
bool checkValidationLayerSupport() {
126-
return (std::ranges::any_of(context.enumerateInstanceLayerProperties(),
127-
[]( vk::LayerProperties const & lp ) { return ( strcmp( "VK_LAYER_KHRONOS_validation", lp.layerName ) == 0 ); } ) );
128-
}
129-
130144
static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type, const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) {
131145
if (severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eError || severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning) {
132146
std::cerr << "validation layer: type " << to_string(type) << " msg: " << pCallbackData->pMessage << std::endl;

attachments/03_physical_device_selection.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,51 @@ class HelloTriangleApplication {
7878
}
7979

8080
void createInstance() {
81-
if (enableValidationLayers && !checkValidationLayerSupport()) {
82-
throw std::runtime_error("validation layers requested, but not available!");
83-
}
84-
8581
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
8682
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
8783
.pEngineName = "No Engine",
8884
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
8985
.apiVersion = vk::ApiVersion14 };
90-
auto extensions = getRequiredExtensions();
91-
std::vector<char const *> enabledLayers;
86+
87+
// Get the required layers
88+
std::vector<char const*> requiredLayers;
9289
if (enableValidationLayers) {
93-
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
90+
requiredLayers.assign(validationLayers.begin(), validationLayers.end());
91+
}
92+
93+
// Check if the required layers are supported by the Vulkan implementation.
94+
auto layerProperties = context.enumerateInstanceLayerProperties();
95+
for (auto const& requiredLayer : requiredLayers)
96+
{
97+
if (std::ranges::none_of(layerProperties,
98+
[requiredLayer](auto const& layerProperty)
99+
{ return strcmp(layerProperty.layerName, requiredLayer) == 0; }))
100+
{
101+
throw std::runtime_error("Required layer not supported: " + std::string(requiredLayer));
102+
}
94103
}
104+
105+
// Get the required extensions.
106+
auto requiredExtensions = getRequiredExtensions();
107+
108+
// Check if the required extensions are supported by the Vulkan implementation.
109+
auto extensionProperties = context.enumerateInstanceExtensionProperties();
110+
for (auto const& requiredExtension : requiredExtensions)
111+
{
112+
if (std::ranges::none_of(extensionProperties,
113+
[requiredExtension](auto const& extensionProperty)
114+
{ return strcmp(extensionProperty.extensionName, requiredExtension) == 0; }))
115+
{
116+
throw std::runtime_error("Required extension not supported: " + std::string(requiredExtension));
117+
}
118+
}
119+
95120
vk::InstanceCreateInfo createInfo{
96121
.pApplicationInfo = &appInfo,
97-
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
98-
.ppEnabledLayerNames = enabledLayers.data(),
99-
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
100-
.ppEnabledExtensionNames = extensions.data() };
122+
.enabledLayerCount = static_cast<uint32_t>(requiredLayers.size()),
123+
.ppEnabledLayerNames = requiredLayers.data(),
124+
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
125+
.ppEnabledExtensionNames = requiredExtensions.data() };
101126
instance = vk::raii::Instance(context, createInfo);
102127
}
103128

@@ -159,12 +184,6 @@ class HelloTriangleApplication {
159184
uint32_t glfwExtensionCount = 0;
160185
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
161186

162-
std::vector<vk::ExtensionProperties> props = context.enumerateInstanceExtensionProperties();
163-
if (const auto propsIterator = std::ranges::find_if(props, []( vk::ExtensionProperties const & ep ) { return strcmp( ep.extensionName, vk::EXTDebugUtilsExtensionName ) == 0; } ); propsIterator == props.end() )
164-
{
165-
std::cout << "Something went very wrong, cannot find VK_EXT_debug_utils extension" << std::endl;
166-
exit( 1 );
167-
}
168187
std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
169188
if (enableValidationLayers) {
170189
extensions.push_back(vk::EXTDebugUtilsExtensionName );
@@ -173,11 +192,6 @@ class HelloTriangleApplication {
173192
return extensions;
174193
}
175194

176-
bool checkValidationLayerSupport() {
177-
return (std::ranges::any_of(context.enumerateInstanceLayerProperties(),
178-
[]( vk::LayerProperties const & lp ) { return ( strcmp( "VK_LAYER_KHRONOS_validation", lp.layerName ) == 0 ); } ) );
179-
}
180-
181195
static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type, const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) {
182196
if (severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eError || severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning) {
183197
std::cerr << "validation layer: type " << to_string(type) << " msg: " << pCallbackData->pMessage << std::endl;

attachments/04_logical_device.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,26 +82,51 @@ class HelloTriangleApplication {
8282
}
8383

8484
void createInstance() {
85-
if (enableValidationLayers && !checkValidationLayerSupport()) {
86-
throw std::runtime_error("validation layers requested, but not available!");
87-
}
88-
8985
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
9086
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
9187
.pEngineName = "No Engine",
9288
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
9389
.apiVersion = vk::ApiVersion14 };
94-
auto extensions = getRequiredExtensions();
95-
std::vector<char const *> enabledLayers;
90+
91+
// Get the required layers
92+
std::vector<char const*> requiredLayers;
9693
if (enableValidationLayers) {
97-
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
94+
requiredLayers.assign(validationLayers.begin(), validationLayers.end());
95+
}
96+
97+
// Check if the required layers are supported by the Vulkan implementation.
98+
auto layerProperties = context.enumerateInstanceLayerProperties();
99+
for (auto const& requiredLayer : requiredLayers)
100+
{
101+
if (std::ranges::none_of(layerProperties,
102+
[requiredLayer](auto const& layerProperty)
103+
{ return strcmp(layerProperty.layerName, requiredLayer) == 0; }))
104+
{
105+
throw std::runtime_error("Required layer not supported: " + std::string(requiredLayer));
106+
}
98107
}
108+
109+
// Get the required extensions.
110+
auto requiredExtensions = getRequiredExtensions();
111+
112+
// Check if the required extensions are supported by the Vulkan implementation.
113+
auto extensionProperties = context.enumerateInstanceExtensionProperties();
114+
for (auto const& requiredExtension : requiredExtensions)
115+
{
116+
if (std::ranges::none_of(extensionProperties,
117+
[requiredExtension](auto const& extensionProperty)
118+
{ return strcmp(extensionProperty.extensionName, requiredExtension) == 0; }))
119+
{
120+
throw std::runtime_error("Required extension not supported: " + std::string(requiredExtension));
121+
}
122+
}
123+
99124
vk::InstanceCreateInfo createInfo{
100125
.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() };
126+
.enabledLayerCount = static_cast<uint32_t>(requiredLayers.size()),
127+
.ppEnabledLayerNames = requiredLayers.data(),
128+
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
129+
.ppEnabledExtensionNames = requiredExtensions.data() };
105130
instance = vk::raii::Instance(context, createInfo);
106131
}
107132

@@ -192,12 +217,6 @@ class HelloTriangleApplication {
192217
uint32_t glfwExtensionCount = 0;
193218
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
194219

195-
std::vector<vk::ExtensionProperties> props = context.enumerateInstanceExtensionProperties();
196-
if (const auto propsIterator = std::ranges::find_if(props, []( vk::ExtensionProperties const & ep ) { return strcmp( ep.extensionName, vk::EXTDebugUtilsExtensionName ) == 0; } ); propsIterator == props.end() )
197-
{
198-
std::cout << "Something went very wrong, cannot find VK_EXT_debug_utils extension" << std::endl;
199-
exit( 1 );
200-
}
201220
std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
202221
if (enableValidationLayers) {
203222
extensions.push_back(vk::EXTDebugUtilsExtensionName );
@@ -206,11 +225,6 @@ class HelloTriangleApplication {
206225
return extensions;
207226
}
208227

209-
bool checkValidationLayerSupport() {
210-
return (std::ranges::any_of(context.enumerateInstanceLayerProperties(),
211-
[]( vk::LayerProperties const & lp ) { return ( strcmp( "VK_LAYER_KHRONOS_validation", lp.layerName ) == 0 ); } ) );
212-
}
213-
214228
static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type, const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) {
215229
if (severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eError || severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning) {
216230
std::cerr << "validation layer: type " << to_string(type) << " msg: " << pCallbackData->pMessage << std::endl;

0 commit comments

Comments
 (0)