/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "Context.hpp" #include "Base/Utils.hpp" #include "Base/Logger.hpp" #include "Base/IGraphicsApp.hpp" #include "Base/IGraphicsAppManager.hpp" #include "Base/EngineConstants.hpp" #include "Base/UI/IVulkanWindow.hpp" #include "Debuging/ValidationLayer.hpp" #if __has_include("vulkan/vulkan_metal.h") #include #endif namespace OpenVulkano::Vulkan { void Context::Init(IGraphicsAppManager* graphicsAppManager, IVulkanWindow* window) { if (initialized) throw std::runtime_error("The context is already initialized"); this->graphicsAppManager = graphicsAppManager; this->window = window; // Get the extensions required to display on the window for (const auto& requiredExtension : window->GetRequiredInstanceExtensions()) { RequireExtension(requiredExtension.c_str()); } CreateInstance(); // Create the vulkan instance surface = window->CreateSurface(instance); // Create the surface from the window CreateDevice(); swapChain.Init(device.get(), surface, window); swapChainRenderPass.Init(device.get(), &swapChain, true, true); initialized = true; } void Context::Close() { if (!initialized) return; device->WaitIdle(); swapChainRenderPass.Close(); swapChain.Close(); deviceManager.Close(); vkDestroySurfaceKHR(static_cast(instance), surface, nullptr); //TODO if (enableValidationLayer) Debug::CloseValidationLayers(instance); initialized = false; } void Context::Resize(const uint32_t newWidth, const uint32_t newHeight) { device->WaitIdle(); swapChain.Resize(newWidth, newHeight); } void Context::CreateInstance() { if (enableValidationLayer) RequireExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); vk::ApplicationInfo appInfo(graphicsAppManager->GetGraphicsApp()->GetAppName().c_str(), static_cast(graphicsAppManager->GetGraphicsApp()->GetAppVersion()), ENGINE_NAME, ENGINE_VERSION.intVersion, VK_MAKE_VERSION(1, 1, 0)); std::vector extensions = Utils::toCString(requiredExtensions), layers = Debug::GetValidationLayers(); vk::InstanceCreateInfo createInfo(vk::InstanceCreateFlags(), &appInfo, enableValidationLayer ? layers.size() : 0, layers.data(), extensions.size(), extensions.data()); #ifdef __APPLE__ VkExportMetalObjectCreateInfoEXT metalExportInfo { VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT, nullptr, VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT }; createInfo.pNext = &metalExportInfo; #endif instance = vk::createInstance(createInfo); if (enableValidationLayer) Debug::SetupValidationLayers(instance, vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning /*| vk::DebugReportFlagBitsEXT::eInformation | vk::DebugReportFlagBitsEXT::eDebug*/); dynamicDispatch.init(instance, &vkGetInstanceProcAddr); } void Context::CreateDevice() { const std::vector neededExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; deviceManager.Init(instance); device = deviceManager.GetCompatibleDevice(neededExtensions); device->PrepareDevice(neededExtensions, surface); dynamicDispatch.init(instance, &vkGetInstanceProcAddr, device->device, &vkGetDeviceProcAddr); Logger::RENDER->info("Found device: {0}", device->GetDeviceName()); } }