178 Logger::Log(
"A Vulkan Instance already exists. Attempt to create another instance ignored.");
181 if (volkInitialize() != VK_SUCCESS) {
186 uint32_t extensionCount = 0;
187 vkEnumerateInstanceExtensionProperties(
nullptr, &extensionCount,
nullptr);
189 std::cout << extensionCount <<
" extensions supported\n";
191 VkApplicationInfo appInfo{};
192 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
193 appInfo.pApplicationName = ProjectName.data();
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;
200 VkInstanceCreateInfo createInfo{};
201 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
202 createInfo.pApplicationInfo = &appInfo;
203 createInfo.enabledExtensionCount = extensionCount;
205 uint32_t glfwExtensionCount = 0;
206 const char** glfwExtensions;
208 glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
216 std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
218 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
221#pragma warning( push )
222#pragma warning( disable : 4267)
223 createInfo.enabledExtensionCount = extensions.size();
224#pragma warning( pop )
225 createInfo.ppEnabledExtensionNames = extensions.data();
227 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
229 createInfo.enabledLayerCount =
static_cast<uint32_t
>(validationLayers.size());
230 createInfo.ppEnabledLayerNames = validationLayers.data();
233 createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
235 createInfo.enabledLayerCount = 0;
237 createInfo.pNext =
nullptr;
240 if(vkCreateInstance(&createInfo,
nullptr, &instance) != VK_SUCCESS){
246 volkLoadInstance(instance);
263 auto bestDev = (*Devices.begin()).second;
264 SelectedDevice = bestDev;
266 physicalDevice = bestDev.vkPhysicalDevice;
268 std::set<uint32_t> UniqueQueueFamilies = { bestDev.Graphics.Index.value(), bestDev.Present.Index.value()};
269 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
271 float queuePriority = 1.0f;
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);
282 VkPhysicalDeviceFeatures deviceFeatures{};
283 deviceFeatures.geometryShader =
true;
285 VkDeviceCreateInfo deviceCreateInfo{};
286 deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
289 deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
291 deviceCreateInfo.queueCreateInfoCount =
static_cast<uint32_t
>(queueCreateInfos.size());
293 deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
295 deviceCreateInfo.ppEnabledExtensionNames = requiredExt.data();
296 deviceCreateInfo.enabledExtensionCount =
static_cast<uint32_t
>(requiredExt.size());
299 deviceCreateInfo.enabledLayerCount = 0;
301 deviceCreateInfo.enabledLayerCount =
static_cast<uint32_t
>(validationLayers.size());
302 deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
304 if(vkCreateDevice(bestDev.vkPhysicalDevice, &deviceCreateInfo,
nullptr, &device) != VK_SUCCESS){
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();
316 vkGetDeviceQueue(device, bestDev.Present.Index.value(), 0, &vkRenderer::PresentQueue.queue);
317 vkRenderer::PresentQueue.index = bestDev.Present.Index.value();
328 static std::multimap<int, RuntimeDeviceData>
QueryDevices(VkSurfaceKHR surface)
noexcept{
329 uint32_t deviceCount = 0;
330 vkEnumeratePhysicalDevices(instance, &deviceCount,
nullptr);
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>();
337 std::vector<VkPhysicalDevice> devices(deviceCount);
338 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
339 std::multimap<int, RuntimeDeviceData> deviceMap;
343 if(std::filesystem::exists(
"GPUDevice.cache")){
346 file = std::fstream(
"GPUDevice.cache", std::ios::out | std::ios::binary);
348 file.write((
char*)&deviceCount,
sizeof(
size_t));
352 file = std::fstream(
"GPUDevice.cache", std::ios::out | std::ios::binary);
354 file.write((
char*)&deviceCount,
sizeof(
size_t));
358 for(
const auto& device : devices){
359 VkPhysicalDeviceProperties deviceProperties;
360 vkGetPhysicalDeviceProperties(device, &deviceProperties);
362 Logger::Log(
"(vk)Found Device : " + std::string(deviceProperties.deviceName));
364 VkPhysicalDeviceFeatures deviceFeatures;
365 vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
367 uint32_t extensionCount;
368 vkEnumerateDeviceExtensionProperties(device,
nullptr, &extensionCount,
nullptr);
369 std::vector<VkExtensionProperties> extensions(extensionCount);
370 vkEnumerateDeviceExtensionProperties(device,
nullptr, &extensionCount, extensions.data());
372 Device d = ScoreGPU(deviceProperties, deviceFeatures, extensions);
376 uint32_t queueFamilyCount = 0;
377 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount,
nullptr);
379 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
380 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
386 std::vector<QueueFamily> TransferQueueFamily;
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);
398 if(!PresentQueueFamily.
Index.has_value()){
400 PresentQueueFamily.
Index = queueIndex;
401 PresentQueueFamily.
Count = queueFamily.queueCount;
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){
414 if(!GraphicQueueFamily.
Index.has_value()){
415 GraphicQueueFamily.
Count = queueFamily.queueCount;
416 GraphicQueueFamily.
Index = queueIndex;
418 }
else if(GraphicQueueFamily.
Count < queueFamily.queueCount){
419 GraphicQueueFamily.
Count = queueFamily.queueCount;
420 GraphicQueueFamily.
Index = queueIndex;
422 }
else if(!(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) && !(queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT)){
424 GraphicQueueFamily.
Count = queueFamily.queueCount;
425 GraphicQueueFamily.
Index = queueIndex;
431 if((queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) && !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)){
433 if(!ComputeQueueFamily.
Index.has_value()){
434 ComputeQueueFamily.
Index = queueIndex;
435 ComputeQueueFamily.
Count = queueFamily.queueCount;
440 if(queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT){
441 if(!(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
442 && !(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)){
444 QueueFamily qf{ queueIndex, queueFamily.queueCount, SurfaceSupport};
445 TransferQueueFamily.push_back(qf);
453 RuntimeDeviceData rt_dev = RuntimeDeviceData();
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;
461 deviceMap.insert(std::make_pair(d.
Score, rt_dev));
465 file.write((
char*)&d,
sizeof(
Device));
468 hasvalue = GraphicQueueFamily.
Index.has_value();
469 file.write(
reinterpret_cast<char*
>(&hasvalue),
sizeof(
bool));
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));
475 hasvalue = ComputeQueueFamily.
Index.has_value();
476 file.write((
char*)&hasvalue,
sizeof(
bool));
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));
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));
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));
493 hasvalue = PresentQueueFamily.
Index.has_value();
494 file.write((
char*)&hasvalue,
sizeof(
bool));
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));