/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2016 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/vulkan/vulkan_provider.h" #include #include #include "xenia/base/logging.h" #include "xenia/ui/vulkan/vulkan_context.h" #include "xenia/ui/vulkan/vulkan_device.h" #include "xenia/ui/vulkan/vulkan_instance.h" #include "xenia/ui/vulkan/vulkan_util.h" DEFINE_uint64(vulkan_device_index, 0, "Index of the physical device to use."); namespace xe { namespace ui { namespace vulkan { std::unique_ptr VulkanProvider::Create(Window* main_window) { std::unique_ptr provider(new VulkanProvider(main_window)); if (!provider->Initialize()) { xe::FatalError( "Unable to initialize Vulkan graphics subsystem.\n" "Ensure you have the latest drivers for your GPU and that it " "supports Vulkan. See http://xenia.jp/faq/ for more information and a " "list of supported GPUs."); return nullptr; } return provider; } VulkanProvider::VulkanProvider(Window* main_window) : GraphicsProvider(main_window) {} VulkanProvider::~VulkanProvider() { device_.reset(); instance_.reset(); } bool VulkanProvider::Initialize() { instance_ = std::make_unique(); // Always enable the swapchain. #if XE_PLATFORM_WIN32 instance_->DeclareRequiredExtension("VK_KHR_surface", Version::Make(0, 0, 0), false); instance_->DeclareRequiredExtension("VK_KHR_win32_surface", Version::Make(0, 0, 0), false); #endif // Attempt initialization and device query. if (!instance_->Initialize()) { XELOGE("Failed to initialize vulkan instance"); return false; } // Pick the device to use. auto available_devices = instance_->available_devices(); if (available_devices.empty()) { XELOGE("No devices available for use"); return false; } size_t device_index = std::min(available_devices.size(), FLAGS_vulkan_device_index); auto& device_info = available_devices[device_index]; // Create the device. device_ = std::make_unique(instance_.get()); device_->DeclareRequiredExtension("VK_KHR_swapchain", Version::Make(0, 0, 0), false); if (!device_->Initialize(device_info)) { XELOGE("Unable to initialize device"); return false; } return true; } std::unique_ptr VulkanProvider::CreateContext( Window* target_window) { auto new_context = std::unique_ptr(new VulkanContext(this, target_window)); if (!new_context->Initialize()) { return nullptr; } return std::unique_ptr(new_context.release()); } std::unique_ptr VulkanProvider::CreateOffscreenContext() { auto new_context = std::unique_ptr(new VulkanContext(this, nullptr)); if (!new_context->Initialize()) { return nullptr; } return std::unique_ptr(new_context.release()); } } // namespace vulkan } // namespace ui } // namespace xe