PeriDyno 1.0.0
Loading...
Searching...
No Matches
VkSystem.cpp
Go to the documentation of this file.
1#include "VkSystem.h"
2#include "VulkanTools.h"
3#include "VulkanDebug.h"
4#include "VkContext.h"
5
6#include <iostream>
7
8namespace dyno {
9
11 {
12 static VkSystem gInstance;
13 return &gInstance;
14 }
15
17 {
18 }
19
21 {
22 if (validation && debugUtilsMessenger != nullptr)
23 {
24 auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vkInstance, "vkDestroyDebugUtilsMessengerEXT");
25 if (func != nullptr) {
26 func(vkInstance, debugUtilsMessenger, nullptr);
27 }
28 }
29
30 if (ctx != nullptr) {
31 delete ctx;
32 }
33
34 vkDestroyInstance(vkInstance, nullptr);
35 }
36
37#if defined(VK_USE_PLATFORM_ANDROID_KHR)
38 bool VkSystem::initialize(android_app* state) {
39 androidApp = state;
40 return VkSystem::initialize();
41 }
42#endif
43
44 bool VkSystem::initialize(bool enableValidation)
45 {
46 validation = enableValidation;
47
48#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
49 // To enable Vulkan/OpenGL interop
50 enabledInstanceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
51 enabledInstanceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
52
53 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
54 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
55#ifdef WIN32
56 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
57 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
58#else
59 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
60 enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
61#endif
62#endif
63
64#if defined(VK_USE_PLATFORM_ANDROID_KHR)
65 // Vulkan library is loaded dynamically on Android
66 bool libLoaded = vks::android::loadVulkanLibrary();
67 assert(libLoaded);
68#endif
69
70 VkResult err;
71
72 // Vulkan instance
74 if (err) {
75 vks::tools::exitFatal("Could not create Vulkan instance : \n" + vks::tools::errorString(err), err);
76 return false;
77 }
78
79#if defined(VK_USE_PLATFORM_ANDROID_KHR)
80 vks::android::loadVulkanFunctions(vkInstance);
81#endif
82
83 // If requested, we enable the default validation layers for debugging
84 if (validation)
85 {
86 // The report flags determine what type of messages for the layers will be displayed
87 // For validating (debugging) an application the error and warning bits should suffice
88 //VkDebugReportFlagsEXT debugReportFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
89 // Additional flags include performance info, loader and layer debug messages, etc.
90 //vks::debug::setupDebugging(vkInstance, debugReportFlags, VK_NULL_HANDLE);
91 }
92
93 // Physical device
94 uint32_t gpuCount = 0;
95 // Get number of available physical devices
96 VK_CHECK_RESULT(vkEnumeratePhysicalDevices(vkInstance, &gpuCount, nullptr));
97 assert(gpuCount > 0);
98 // Enumerate devices
99 std::vector<VkPhysicalDevice> physicalDevices(gpuCount);
100 err = vkEnumeratePhysicalDevices(vkInstance, &gpuCount, physicalDevices.data());
101 if (err) {
102 vks::tools::exitFatal("Could not enumerate physical devices : \n" + vks::tools::errorString(err), err);
103 return false;
104 }
105
106 // GPU selection
107
108 // Select physical device to be used for the Vulkan example
109 // Defaults to the first device unless specified by command line
110 uint32_t selectedDevice = 0;
111
112 physicalDevice = physicalDevices[selectedDevice];
113
114 // Store properties (including limits), features and memory properties of the physical device (so that examples can check against them)
115 vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
116 vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
117 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
118
119 // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation
120 //getEnabledFeatures();
121
122 // Vulkan device creation
123 // This is handled by a separate class that gets a logical device representation
124 // and encapsulates functions related to a device
126 VkResult res = ctx->createLogicalDevice(enabledFeatures, enabledDeviceExtensions, deviceCreatepNextChain);
127 if (res != VK_SUCCESS) {
128 vks::tools::exitFatal("Could not create Vulkan device: \n" + vks::tools::errorString(res), res);
129 return false;
130 }
131
132 if (useMemoryPool) {
133 res = ctx->createMemoryPool(vkInstance, apiVersion);
134 if (res != VK_SUCCESS) {
135 vks::tools::exitFatal("Could not create Vulkan memory pool: \n" + vks::tools::errorString(res), res);
136 return false;
137 }
138 }
139
140 return true;
141 }
142
143 VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback(
144 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
145 VkDebugUtilsMessageTypeFlagsEXT messageType,
146 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
147 void* pUserData)
148 {
149 // Select prefix depending on flags passed to the callback
150 const char* prefix = "\033[0;31mUNKNOWN\033[0m";
151
152 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
153 prefix = "\033[0;34mVERBOSE\033[0m";
154 }
155 else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
156 prefix = "\033[0;32mINFO \033[0m";
157 }
158 else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
159 prefix = "\033[0;33mWARNING\033[0m";
160 }
161 else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
162 prefix = "\033[0;31mERROR \033[0m";
163 }
164
165#if defined(__ANDROID__)
166 if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
167 LOGE("%s[%d][%s] : %s\n", prefix.c_str(), pCallbackData->messageIdNumber, pCallbackData->pMessageIdName, pCallbackData->pMessage);
168 }
169 else {
170 LOGD("%s[%d][%s] : %s\n", prefix.c_str(), pCallbackData->messageIdNumber, pCallbackData->pMessageIdName, pCallbackData->pMessage);
171 }
172#else
173 printf("[%s][%d][%s] : %s\n", prefix, pCallbackData->messageIdNumber, pCallbackData->pMessageIdName, pCallbackData->pMessage);
174#endif
175
176
177 // The return value of this callback controls whether the Vulkan call that caused the validation message will be aborted or not
178 // We return VK_FALSE as we DON'T want Vulkan calls that cause a validation message to abort
179 // If you instead want to have calls abort, pass in VK_TRUE and the function will return VK_ERROR_VALIDATION_FAILED_EXT
180 return VK_FALSE;
181 }
182
184 {
185 // Validation can also be forced via a define
186#if defined(_VALIDATION)
187 this->validation = true;
188#endif
189
190 VkApplicationInfo appInfo = {};
191 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
192 appInfo.pApplicationName = name.c_str();
193 appInfo.pEngineName = name.c_str();
194 appInfo.apiVersion = apiVersion;
195
196 std::vector<const char*> instanceExtensions = { VK_KHR_SURFACE_EXTENSION_NAME };
197
198 // Enable surface extensions depending on os
199#if defined(_WIN32)
200 instanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
201#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
202 instanceExtensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
203#elif defined(_DIRECT2DISPLAY)
204 instanceExtensions.push_back(VK_KHR_DISPLAY_EXTENSION_NAME);
205#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
206 instanceExtensions.push_back(VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME);
207#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
208 instanceExtensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
209#elif defined(VK_USE_PLATFORM_XCB_KHR)
210 instanceExtensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
211#elif defined(VK_USE_PLATFORM_IOS_MVK)
212 instanceExtensions.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
213#elif defined(VK_USE_PLATFORM_MACOS_MVK)
214 instanceExtensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
215#endif
216
217 // Get extensions supported by the instance and store for later use
218 uint32_t extCount = 0;
219 std::vector<std::string> supportedInstanceExtensions;
220
221 vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
222 if (extCount > 0)
223 {
224 std::vector<VkExtensionProperties> extensions(extCount);
225 if (vkEnumerateInstanceExtensionProperties(nullptr, &extCount, &extensions.front()) == VK_SUCCESS)
226 {
227 for (VkExtensionProperties extension : extensions)
228 {
229 supportedInstanceExtensions.push_back(extension.extensionName);
230 }
231 }
232 }
233
234 // Enabled requested instance extensions
235 if (enabledInstanceExtensions.size() > 0)
236 {
237 for (const char * enabledExtension : enabledInstanceExtensions)
238 {
239 // Output message if requested extension is not available
240 if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), enabledExtension) == supportedInstanceExtensions.end())
241 {
242 std::cerr << "Enabled instance extension \"" << enabledExtension << "\" is not present at instance level\n";
243 }
244 instanceExtensions.push_back(enabledExtension);
245 }
246 }
247
248 VkInstanceCreateInfo instanceCreateInfo = {};
249 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
250 instanceCreateInfo.pNext = NULL;
251 instanceCreateInfo.pApplicationInfo = &appInfo;
252
253 if (instanceExtensions.size() > 0)
254 {
255 if (validation)
256 {
257 instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
258 }
259 instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size();
260 instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data();
261 }
262
263
264 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
265 debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
266 debugCreateInfo.messageSeverity =
267 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
268 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
269 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
270 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
271 debugCreateInfo.messageType =
272 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
273 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
274 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
275 debugCreateInfo.pfnUserCallback = debugUtilsMessengerCallback;
276
277 // also enable shader debug print
278 VkValidationFeatureEnableEXT enabled[] = { VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT };
279 VkValidationFeaturesEXT validationFeatures{};
280 validationFeatures.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
281 validationFeatures.enabledValidationFeatureCount = 1;
282 validationFeatures.pEnabledValidationFeatures = enabled;
283 validationFeatures.disabledValidationFeatureCount = 0;
284 validationFeatures.pDisabledValidationFeatures = nullptr;
285
286 debugCreateInfo.pNext = &validationFeatures;
287
288 if (validation)
289 {
290 // The VK_LAYER_KHRONOS_validation contains all current validation functionality.
291 // Note that on Android this layer requires at least NDK r20
292 const char* validationLayerName = "VK_LAYER_KHRONOS_validation";
293 // Check if this layer is available at instance level
294 uint32_t instanceLayerCount;
295 vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr);
296 std::vector<VkLayerProperties> instanceLayerProperties(instanceLayerCount);
297 vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProperties.data());
298 bool validationLayerPresent = false;
299 for (VkLayerProperties layer : instanceLayerProperties) {
300 if (strcmp(layer.layerName, validationLayerName) == 0) {
301 validationLayerPresent = true;
302 break;
303 }
304 }
305 if (validationLayerPresent) {
306 instanceCreateInfo.ppEnabledLayerNames = &validationLayerName;
307 instanceCreateInfo.enabledLayerCount = 1;
308 instanceCreateInfo.pNext = &debugCreateInfo;
309 }
310 else {
311 std::cerr << "Validation layer VK_LAYER_KHRONOS_validation not present, validation is disabled";
312 instanceCreateInfo.enabledLayerCount = 0;
313 instanceCreateInfo.pNext = nullptr;
314 }
315 }
316 VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &vkInstance);
317
318 if (result == VK_SUCCESS && validation) {
319 // create debug message callback
320 auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vkInstance, "vkCreateDebugUtilsMessengerEXT");
321
322 if (func != nullptr) {
323 VkResult r = func(vkInstance, &debugCreateInfo, nullptr, &debugUtilsMessenger);
324
325 if (r != VK_SUCCESS) {
326 std::cerr << "Failed to create VkDebugUtilsMessengerEXT" << std::endl;
327 }
328 }
329 }
330 return result;
331 }
332
333}
assert(queueCount >=1)
#define VK_CHECK_RESULT(f)
Definition VulkanTools.h:55
bool useMemoryPool
Definition VkSystem.h:56
VkPhysicalDeviceMemoryProperties deviceMemoryProperties
Definition VkSystem.h:67
bool initialize(bool enableValidation=false)
Definition VkSystem.cpp:44
VkPhysicalDevice physicalDevice
Definition VkSystem.h:64
VkPhysicalDeviceFeatures deviceFeatures
Definition VkSystem.h:66
VkInstance vkInstance
Vulkan instance, stores all per-application states.
Definition VkSystem.h:63
bool validation
Definition VkSystem.h:55
VkPhysicalDeviceFeatures enabledFeatures
Definition VkSystem.h:68
uint32_t apiVersion
Definition VkSystem.h:58
VkDebugUtilsMessengerEXT debugUtilsMessenger
Definition VkSystem.h:71
std::vector< const char * > enabledInstanceExtensions
Definition VkSystem.h:75
VkResult createVulkanInstance()
Creates the application wide Vulkan instance.
Definition VkSystem.cpp:183
static VkSystem * instance()
Definition VkSystem.cpp:10
std::vector< const char * > enabledDeviceExtensions
Definition VkSystem.h:74
void * deviceCreatepNextChain
Definition VkSystem.h:69
std::string name
Definition VkSystem.h:57
VkPhysicalDeviceProperties deviceProperties
Definition VkSystem.h:65
VkContext * ctx
Current Vulkan context.
Definition VkSystem.h:53
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
Definition VkSystem.cpp:143
std::string errorString(VkResult errorCode)
Returns an error code as a string.
void exitFatal(const std::string &message, int32_t exitCode)