Hubris Engine Dev
A Project to learn and get into Game Engine developement.
 
Loading...
Searching...
No Matches
vkBackend.h
Go to the documentation of this file.
1#pragma once
2#include <Logger.h>
3#include "volk.h"
4#include <GLFW/glfw3.h>
5#include "Engine.h"
6#include "vkRenderer.h"
7
9
10 #ifdef NDEBUG
11 const bool enableValidationLayers = false;
12 #else
13 const bool enableValidationLayers = true;
14 #endif
19 struct Device{
20 uint32_t DeviceID = 0;
21 uint32_t VendorID = 0;
22 uint32_t APIVersion = 0;
23 uint32_t DriverVersion = 0;
24
25 unsigned int Score = 0;
26 bool ExtSupported = false;
27 bool RayTracingCapable = false;
28 bool GeometryShader = false;
29 bool TessellationShader = false;
30 bool ShaderInt64 = false;
31 bool DiscreteGPU = false;
32 bool SparceBinding = false;
33 };
34
38 struct QueueFamily {
39 std::optional<uint32_t> Index;
40 uint32_t Count = 0;
42 };
43
46 class vkBackend final {
47 private:
53 struct RuntimeDeviceData{
54 Device device;
55 VkDevice vkDevice;
56 VkPhysicalDevice vkPhysicalDevice;
59 QueueFamily Present;
60 std::vector<QueueFamily> Transfer;
61 };
62
63 static inline RuntimeDeviceData SelectedDevice;
64 static inline VkDebugUtilsMessengerEXT debugMessenger;
65
66 static inline VkInstance instance = nullptr;
67 static inline VkPhysicalDevice physicalDevice = nullptr;
68 static inline VkDevice device = nullptr;
69 static inline const std::vector<const char*> requiredExt = {
70 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
71 VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
72 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
73 VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,
74 VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
75 VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,
76 VK_KHR_SPIRV_1_4_EXTENSION_NAME
77 };
78
79 static inline const std::vector<const char*> validationLayers = {
80 "VK_LAYER_KHRONOS_validation"
81 };
82
83 static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
84 auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
85 if (func != nullptr) {
86 return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
87 } else {
88 return VK_ERROR_EXTENSION_NOT_PRESENT;
89 }
90 }
91
92 static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {
93 auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
94 if (func != nullptr) {
95 func(instance, debugMessenger, pAllocator);
96 }
97 }
98
99 static Device ScoreGPU(const VkPhysicalDeviceProperties& prop, const VkPhysicalDeviceFeatures& features, const std::vector<VkExtensionProperties>& ext) noexcept {
100 Device device;
101 device.GeometryShader = features.geometryShader;
102 device.TessellationShader = features.tessellationShader;
103 device.DiscreteGPU = prop.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
104 device.ShaderInt64 = features.shaderInt64;
105 device.SparceBinding = features.sparseBinding;
106 device.APIVersion = prop.apiVersion;
107 //This is redundent but is used to detect raytracing specific extension, Remove if possible.
108 static const std::vector<const char*> requiredRTExtensions = {
109 // Required ray tracing extensions
110 VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
111 VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,
112 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
113 VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
114 VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,
115 VK_KHR_SPIRV_1_4_EXTENSION_NAME
116 };
117
118 if(!device.GeometryShader){
119 Logger::Log("Device does not support Geometry Shader");
120 return device;
121 }
122
123 if (prop.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
124 device.Score += 1000;
125 }
126
127 std::set<std::string> requiredExtensions(requiredExt.begin(), requiredExt.end());
128 std::set<std::string> rtxExt(requiredRTExtensions.begin(), requiredRTExtensions.end());
129 int found = 0;
130 for(const auto& supportedExt : ext){
131 requiredExtensions.erase(supportedExt.extensionName);
132 rtxExt.erase(supportedExt.extensionName);
133 }
134
135 if(rtxExt.empty()){
136 device.RayTracingCapable = true;
137 device.Score += 1000;
138 }
139 if(requiredExtensions.empty()){
140 device.Score +=1000;
141 device.ExtSupported = true;
142 }
143 return device;
144 }
145
146 static void InitLayers() noexcept {
147 uint32_t layerCount;
148 vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
149
150 Logger::Log("(vk)Found {} Layers", layerCount);
151
152 std::vector<VkLayerProperties> availableLayers(layerCount);
153 vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
154
155 for (const char* layerName : validationLayers) {
156 bool layerFound = false;
157
158 for (const auto& layerProperties : availableLayers) {
159 if (strcmp(layerName, layerProperties.layerName) == 0) {
160 layerFound = true;
161 break;
162 }
163 }
164
165 if (!layerFound) {
166 Logger::Log("(vk)Validation Layers not found");
167 }
168 }
169 Logger::Log("(vk)Validation Layers Found");
170
171 }
172 public:
173 vkBackend() = delete;
174 ~vkBackend() = delete;
175
176 static void CreateInstance() noexcept {
177 if(instance){
178 Logger::Log("A Vulkan Instance already exists. Attempt to create another instance ignored.");
179 return;
180 }
181 if (volkInitialize() != VK_SUCCESS) {
182 Logger::Fatal("Unable to initialize volk");
183 return;
184 }
185
186 uint32_t extensionCount = 0;
187 vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
188
189 std::cout << extensionCount << " extensions supported\n";
190 auto& ProjectName = Engine::GetProjectName();
191 VkApplicationInfo appInfo{};
192 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
193 appInfo.pApplicationName = ProjectName.data();
194 const Version& pVersion = Engine::GetProjectVersion();
195 appInfo.applicationVersion = VK_MAKE_API_VERSION(pVersion.Variant, pVersion.Major, pVersion.Minor, pVersion.Patch);
196 appInfo.pEngineName = "Hubris Engine";
197 appInfo.engineVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
198 appInfo.apiVersion = VK_API_VERSION_1_3;
199
200 VkInstanceCreateInfo createInfo{};
201 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
202 createInfo.pApplicationInfo = &appInfo;
203 createInfo.enabledExtensionCount = extensionCount;
204
205 uint32_t glfwExtensionCount = 0;
206 const char** glfwExtensions;
207
208 glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
209
210 if(!glfwExtensions){
211 const char* desc;
212 glfwGetError(&desc);
213 Logger::Fatal("GLFW: {}", desc);
214 return;
215 }
216 std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
218 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
219 }
220 //According to vulkan specs, size will never overflow. Thus, this has no risk and the warning can be ignored here.
221#pragma warning( push )
222#pragma warning( disable : 4267)
223 createInfo.enabledExtensionCount = extensions.size();
224#pragma warning( pop )
225 createInfo.ppEnabledExtensionNames = extensions.data();
226
227 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
229 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
230 createInfo.ppEnabledLayerNames = validationLayers.data();
231
232 populateDebugMessengerCreateInfo(debugCreateInfo);
233 createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
234 } else {
235 createInfo.enabledLayerCount = 0;
236
237 createInfo.pNext = nullptr;
238 }
239
240 if(vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS){
241 Logger::Log("Failed to create vulkan instance");
242 return;
243 }
244 Logger::Log("Vulkan Instance Created");
245
246 volkLoadInstance(instance);
247
249 }
250
251 static VkInstance GetInstance() noexcept { return instance;};
252 static VkDevice GetDevice() noexcept { return device; };
253 static VkPhysicalDevice GetPhysicalDevice() noexcept {return physicalDevice;};
260 static ErrorCode Init(VkSurfaceKHR surface)noexcept {
261 auto Devices = QueryDevices(surface);
262 if(!Devices.size())return ErrorCode::INTERNAL_ERROR;
263 auto bestDev = (*Devices.begin()).second;
264 SelectedDevice = bestDev;
265
266 physicalDevice = bestDev.vkPhysicalDevice;
267
268 std::set<uint32_t> UniqueQueueFamilies = { bestDev.Graphics.Index.value(), bestDev.Present.Index.value()};
269 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
270
271 float queuePriority = 1.0f;
272
273 for (uint32_t queueFamily : UniqueQueueFamilies) {
274 VkDeviceQueueCreateInfo queueCreateInfo{};
275 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
276 queueCreateInfo.queueFamilyIndex = queueFamily;
277 queueCreateInfo.queueCount = 1;
278 queueCreateInfo.pQueuePriorities = &queuePriority;
279 queueCreateInfos.push_back(queueCreateInfo);
280 }
281
282 VkPhysicalDeviceFeatures deviceFeatures{};
283 deviceFeatures.geometryShader = true;
284
285 VkDeviceCreateInfo deviceCreateInfo{};
286 deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
287
288 //TODO: Add other queues (Compute, Transfer).
289 deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
290 // The number of queue create infos is guaranteed to fit within uint32_t by Vulkan API constraints.
291 deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
292
293 deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
294
295 deviceCreateInfo.ppEnabledExtensionNames = requiredExt.data();
296 deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(requiredExt.size());
297
298#ifdef NDEBUG
299 deviceCreateInfo.enabledLayerCount = 0;
300#else
301 deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
302 deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
303#endif
304 if(vkCreateDevice(bestDev.vkPhysicalDevice, &deviceCreateInfo, nullptr, &device) != VK_SUCCESS){
305 Logger::Log("(vk) Unable to create device.");
306 return ErrorCode::FAILED;
307 }
308
309
310 vkGetDeviceQueue(device, bestDev.Graphics.Index.value(), 0, &vkRenderer::GraphicsQueue.queue);
311 vkRenderer::GraphicsQueue.index = bestDev.Graphics.Index.value();
312 if(bestDev.Graphics.Index == bestDev.Present.Index){
313 vkRenderer::PresentQueue = vkRenderer::GraphicsQueue;
314 vkRenderer::PresentQueue.index = bestDev.Graphics.Index.value();
315 }else{
316 vkGetDeviceQueue(device, bestDev.Present.Index.value(), 0, &vkRenderer::PresentQueue.queue);
317 vkRenderer::PresentQueue.index = bestDev.Present.Index.value();
318 }
319
320
321
322 return ErrorCode::OK;
323 }
324
328 static std::multimap<int, RuntimeDeviceData> QueryDevices(VkSurfaceKHR surface) noexcept{
329 uint32_t deviceCount = 0;
330 vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
331
332 if(deviceCount == 0){
333 Logger::Log("Failed to find GPUs with Vulkan support. Verify that your driver supports Vulkan");
334 return std::multimap<int, RuntimeDeviceData>();
335 }
336
337 std::vector<VkPhysicalDevice> devices(deviceCount);
338 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
339 std::multimap<int, RuntimeDeviceData> deviceMap;
340
341 std::fstream file;
342
343 if(std::filesystem::exists("GPUDevice.cache")){
344 Logger::Log("GPU Device info cache found.");
345 //TODO: read the file.
346 file = std::fstream("GPUDevice.cache", std::ios::out | std::ios::binary);
347 if(file.is_open()){
348 file.write((char*)&deviceCount, sizeof(size_t));
349 }
350 }else{
351 Logger::Log("GPU Device info cache not found.");
352 file = std::fstream("GPUDevice.cache", std::ios::out | std::ios::binary);
353 if(file.is_open()){
354 file.write((char*)&deviceCount, sizeof(size_t));
355 }
356 }
357
358 for(const auto& device : devices){
359 VkPhysicalDeviceProperties deviceProperties;
360 vkGetPhysicalDeviceProperties(device, &deviceProperties);
361
362 Logger::Log("(vk)Found Device : " + std::string(deviceProperties.deviceName));
363
364 VkPhysicalDeviceFeatures deviceFeatures;
365 vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
366
367 uint32_t extensionCount;
368 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
369 std::vector<VkExtensionProperties> extensions(extensionCount);
370 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data());
371
372 Device d = ScoreGPU(deviceProperties, deviceFeatures, extensions);
373
374 if(!d.ExtSupported){ continue; } //Ignore Devices that don't support needed extension (e.g: Swapchain)
375 //Queue Family Scoring.
376 uint32_t queueFamilyCount = 0;
377 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
378
379 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
380 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
381
382 QueueFamily GraphicQueueFamily;
383 //Dedicated Compute Queue family
384 QueueFamily ComputeQueueFamily;
385 //Having every dedicated Transfer queue family is never a problem i think.
386 std::vector<QueueFamily> TransferQueueFamily;
387 //Used in case the Graphics Queue Family Doesn't support Surface Present.
388 //This will hold the first Queue Family that supports Surface Presenting.
389 QueueFamily PresentQueueFamily;
390
391
392 unsigned int queueIndex = 0;
393 uint32_t SurfaceSupport = false;
394 for(const auto& queueFamily : queueFamilies){
395 SurfaceSupport = false;
396 vkGetPhysicalDeviceSurfaceSupportKHR(device, queueIndex, surface, &SurfaceSupport);
397
398 if(!PresentQueueFamily.Index.has_value()){
399 d.Score += 1000;//Very Important.
400 PresentQueueFamily.Index = queueIndex;
401 PresentQueueFamily.Count = queueFamily.queueCount;
402 PresentQueueFamily.PresentSupport = true;
403 }
404
405 Logger::Log("Device Queue Families {} Flags: {}{}{}{} Surface Support: {}", queueIndex,
406 queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT ? "Graphics " : "",
407 queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT ? "Compute " : "",
408 queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT ? "Transfer " : "",
409 queueFamily.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT ? "Sparce " : "",
410 SurfaceSupport ? "True" : "False");
411 Logger::Log("Queue Count: {}", queueFamily.queueCount);
412 if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT){
413 d.Score += 100;//Graphics is a general purpose feature.
414 if(!GraphicQueueFamily.Index.has_value()){
415 GraphicQueueFamily.Count = queueFamily.queueCount;
416 GraphicQueueFamily.Index = queueIndex;
417 GraphicQueueFamily.PresentSupport = SurfaceSupport;
418 }else if(GraphicQueueFamily.Count < queueFamily.queueCount){
419 GraphicQueueFamily.Count = queueFamily.queueCount;
420 GraphicQueueFamily.Index = queueIndex;
421 GraphicQueueFamily.PresentSupport = SurfaceSupport;
422 }else if(!(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) && !(queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT)){
423 //Favor dedicated graphics queue if found.
424 GraphicQueueFamily.Count = queueFamily.queueCount;
425 GraphicQueueFamily.Index = queueIndex;
426 GraphicQueueFamily.PresentSupport = SurfaceSupport;
427 continue;
428 }
429 //Check for Surface support.
430 }
431 if((queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) && !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)){
432 d.Score += 150;//dedicated Compute queue is a beneficial feature.
433 if(!ComputeQueueFamily.Index.has_value()){
434 ComputeQueueFamily.Index = queueIndex;
435 ComputeQueueFamily.Count = queueFamily.queueCount;
436 ComputeQueueFamily.PresentSupport = SurfaceSupport;
437 }
438 continue;
439 }
440 if(queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT){
441 if(!(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
442 && !(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)){
443 d.Score += 150;//Dedicated transfer queue.
444 QueueFamily qf{ queueIndex, queueFamily.queueCount, SurfaceSupport};
445 TransferQueueFamily.push_back(qf);
446 }
447 continue;
448 }
449
450 ++queueIndex;
451 }//Queue Family Scoring
452
453 RuntimeDeviceData rt_dev = RuntimeDeviceData();
454 rt_dev.device = d;
455 rt_dev.Graphics = GraphicQueueFamily;
456 rt_dev.Compute = ComputeQueueFamily;
457 rt_dev.Transfer = TransferQueueFamily;
458 rt_dev.Present = PresentQueueFamily;
459 rt_dev.vkPhysicalDevice = device;
460
461 deviceMap.insert(std::make_pair(d.Score, rt_dev));
462 Logger::Log("Device Score: {}", d.Score);
463 //Cache the scored devices.
464 if(file.is_open()){
465 file.write((char*)&d, sizeof(Device));
466 uint32_t index;
467 bool hasvalue;
468 hasvalue = GraphicQueueFamily.Index.has_value();
469 file.write(reinterpret_cast<char*>(&hasvalue), sizeof(bool));
470 if(hasvalue){
471 index = reinterpret_cast<uint32_t&&>(GraphicQueueFamily.Index.value());
472 file.write((char*)&index, sizeof(uint32_t));
473 file.write((char*)&GraphicQueueFamily.Count, sizeof(uint32_t));
474 }
475 hasvalue = ComputeQueueFamily.Index.has_value();
476 file.write((char*)&hasvalue, sizeof(bool));
477 if(hasvalue){
478 index = reinterpret_cast<uint32_t&&>(ComputeQueueFamily.Index.value());
479 file.write((char*)&index, sizeof(uint32_t));
480 file.write((char*)&ComputeQueueFamily.Count, sizeof(uint32_t));
481 }
482 size_t count = TransferQueueFamily.size();
483 file.write((char*)&count, sizeof(size_t));
484 for(size_t i = 0; i < count; i++){
485 hasvalue = TransferQueueFamily[i].Index.has_value();
486 file.write((char*)&hasvalue, sizeof(bool));
487 if(hasvalue){
488 index = reinterpret_cast<uint32_t&&>(TransferQueueFamily[i].Index.value());
489 file.write((char*)&index, sizeof(uint32_t));
490 file.write((char*)&TransferQueueFamily[i].Count, sizeof(uint32_t));
491 }
492 }
493 hasvalue = PresentQueueFamily.Index.has_value();
494 file.write((char*)&hasvalue, sizeof(bool));
495 if(hasvalue){
496 index = reinterpret_cast<uint32_t&&>(PresentQueueFamily.Index.value());
497 file.write((char*)&index, sizeof(uint32_t));
498 file.write((char*)&PresentQueueFamily.Count, sizeof(uint32_t));
499 }
500 }
501 }//Device Scoring
502 file.close();
503 return deviceMap;
504 }
505
506 static void Cleanup(){
507 vkDestroyDevice(device, nullptr);
508 vkDestroyInstance(instance, nullptr);
509
511 DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
512 }
513 }
514
515 static const VkAllocationCallbacks* GetAllocator() noexcept {
516 return nullptr;
517 }
518
519 static void SetAllocator(VkAllocationCallbacks cb) /*noexcept*/ {
520 throw std::exception("Not Implemented");
521 }
522
523 static void setupDebugMessenger() {
524 if (!enableValidationLayers) return;
525
526 VkDebugUtilsMessengerCreateInfoEXT createInfo;
528
529 if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
530 throw std::runtime_error("failed to set up debug messenger!");
531 }
532 }
533
534 static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
535 createInfo = {};
536 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
537 createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
538 createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
539 createInfo.pfnUserCallback = debugCallback;
540 }
541
542 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
543 std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
544
545 return VK_FALSE;
546 }
547 };
548
549}
static const std::string & GetProjectName() noexcept
Definition Engine.h:167
static const Version & GetProjectVersion() noexcept
Definition Engine.h:168
static VkInstance GetInstance() noexcept
Definition vkBackend.h:251
static std::multimap< int, RuntimeDeviceData > QueryDevices(VkSurfaceKHR surface) noexcept
Queries the available devices and scores them based on their features, then caches the Query....
Definition vkBackend.h:328
static const VkAllocationCallbacks * GetAllocator() noexcept
Definition vkBackend.h:515
static VkPhysicalDevice GetPhysicalDevice() noexcept
Definition vkBackend.h:253
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
Definition vkBackend.h:542
static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
Definition vkBackend.h:534
static ErrorCode Init(VkSurfaceKHR surface) noexcept
Initializes the Vulkan backend. This is the first step to use any vulkan api.
Definition vkBackend.h:260
static VkDevice GetDevice() noexcept
Definition vkBackend.h:252
static void CreateInstance() noexcept
Definition vkBackend.h:176
static void SetAllocator(VkAllocationCallbacks cb)
Definition vkBackend.h:519
static void Log(const char *message)
Definition Logger.h:104
static void Fatal(fmt::format_string< Args... > message, Args &&... args)
Definition Logger.h:147
const bool enableValidationLayers
Definition vkBackend.h:13
ErrorCode
Definition Error.h:6
A struct to hold the device information and Important features availability. It's mainly used to cach...
Definition vkBackend.h:19
uint32_t DriverVersion
The Driver version, used for cache validation.
Definition vkBackend.h:23
uint32_t DeviceID
The Device ID, used for caching.
Definition vkBackend.h:20
unsigned int Score
The Computed score of the device.
Definition vkBackend.h:25
bool ExtSupported
Indicates if the Device can be used.
Definition vkBackend.h:26
bool GeometryShader
Can Geometry Shaders be used ? This is a required feature.
Definition vkBackend.h:28
bool SparceBinding
Is the Device capable of Sparce Binding.
Definition vkBackend.h:32
uint32_t APIVersion
Vulkan API version, used for cache validation.
Definition vkBackend.h:22
bool RayTracingCapable
Is the Device Capable of Raytracing.
Definition vkBackend.h:27
uint32_t VendorID
The Vendor ID, used for caching.
Definition vkBackend.h:21
bool DiscreteGPU
Is the Device a Discrete (Dedicated) GPU.
Definition vkBackend.h:31
bool TessellationShader
Can Tesselation Shaders be used ?
Definition vkBackend.h:29
Basic info about a QueueFamily.
Definition vkBackend.h:38
std::optional< uint32_t > Index
Definition vkBackend.h:39