diff options
| author | 2020-12-25 02:01:13 -0300 | |
|---|---|---|
| committer | 2020-12-31 02:07:33 -0300 | |
| commit | 47843b4f097ced5e99c5567b8ac3fd53b80fab0a (patch) | |
| tree | 190309df63e67b03d651da034c07b0e4a994cc5f /src/video_core/vulkan_common | |
| parent | renderer_vulkan: Move instance initialization to a separate file (diff) | |
| download | yuzu-47843b4f097ced5e99c5567b8ac3fd53b80fab0a.tar.gz yuzu-47843b4f097ced5e99c5567b8ac3fd53b80fab0a.tar.xz yuzu-47843b4f097ced5e99c5567b8ac3fd53b80fab0a.zip | |
renderer_vulkan: Create debug callback on separate file and throw
Initialize debug callbacks (messenger) from a separate file. This allows
sharing code with different backends.
Change our Vulkan error handling to use exceptions instead of error
codes, simplifying the initialization process.
Diffstat (limited to 'src/video_core/vulkan_common')
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_debug_callback.cpp | 45 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_debug_callback.h | 11 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_instance.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.cpp | 39 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 15 |
5 files changed, 79 insertions, 45 deletions
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp new file mode 100644 index 000000000..ea7af8ad4 --- /dev/null +++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <string_view> | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "video_core/vulkan_common/vulkan_debug_callback.h" | ||
| 8 | |||
| 9 | namespace Vulkan { | ||
| 10 | namespace { | ||
| 11 | VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, | ||
| 12 | VkDebugUtilsMessageTypeFlagsEXT type, | ||
| 13 | const VkDebugUtilsMessengerCallbackDataEXT* data, | ||
| 14 | [[maybe_unused]] void* user_data) { | ||
| 15 | const std::string_view message{data->pMessage}; | ||
| 16 | if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { | ||
| 17 | LOG_CRITICAL(Render_Vulkan, "{}", message); | ||
| 18 | } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { | ||
| 19 | LOG_WARNING(Render_Vulkan, "{}", message); | ||
| 20 | } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { | ||
| 21 | LOG_INFO(Render_Vulkan, "{}", message); | ||
| 22 | } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { | ||
| 23 | LOG_DEBUG(Render_Vulkan, "{}", message); | ||
| 24 | } | ||
| 25 | return VK_FALSE; | ||
| 26 | } | ||
| 27 | } // Anonymous namespace | ||
| 28 | |||
| 29 | vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance) { | ||
| 30 | return instance.CreateDebugUtilsMessenger(VkDebugUtilsMessengerCreateInfoEXT{ | ||
| 31 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, | ||
| 32 | .pNext = nullptr, | ||
| 33 | .flags = 0, | ||
| 34 | .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | | ||
| 35 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | | ||
| 36 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | | ||
| 37 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, | ||
| 38 | .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | | ||
| 39 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | | ||
| 40 | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, | ||
| 41 | .pfnUserCallback = Callback, | ||
| 42 | }); | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace Vulkan | ||
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.h b/src/video_core/vulkan_common/vulkan_debug_callback.h new file mode 100644 index 000000000..2efcd244c --- /dev/null +++ b/src/video_core/vulkan_common/vulkan_debug_callback.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 6 | |||
| 7 | namespace Vulkan { | ||
| 8 | |||
| 9 | vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance); | ||
| 10 | |||
| 11 | } // namespace Vulkan | ||
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index c19f93e0a..d3d8630e5 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp | |||
| @@ -117,21 +117,20 @@ std::pair<vk::Instance, u32> CreateInstance(Common::DynamicLibrary& library, | |||
| 117 | bool enable_debug_utils, bool enable_layers) { | 117 | bool enable_debug_utils, bool enable_layers) { |
| 118 | if (!library.IsOpen()) { | 118 | if (!library.IsOpen()) { |
| 119 | LOG_ERROR(Render_Vulkan, "Vulkan library not available"); | 119 | LOG_ERROR(Render_Vulkan, "Vulkan library not available"); |
| 120 | return {}; | 120 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 121 | } | 121 | } |
| 122 | if (!library.GetSymbol("vkGetInstanceProcAddr", &dld.vkGetInstanceProcAddr)) { | 122 | if (!library.GetSymbol("vkGetInstanceProcAddr", &dld.vkGetInstanceProcAddr)) { |
| 123 | LOG_ERROR(Render_Vulkan, "vkGetInstanceProcAddr not present in Vulkan"); | 123 | LOG_ERROR(Render_Vulkan, "vkGetInstanceProcAddr not present in Vulkan"); |
| 124 | return {}; | 124 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 125 | } | 125 | } |
| 126 | if (!vk::Load(dld)) { | 126 | if (!vk::Load(dld)) { |
| 127 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); | 127 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); |
| 128 | return {}; | 128 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 129 | } | 129 | } |
| 130 | const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_debug_utils); | 130 | const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_debug_utils); |
| 131 | if (!AreExtensionsSupported(dld, extensions)) { | 131 | if (!AreExtensionsSupported(dld, extensions)) { |
| 132 | return {}; | 132 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
| 133 | } | 133 | } |
| 134 | |||
| 135 | std::vector<const char*> layers = Layers(enable_layers); | 134 | std::vector<const char*> layers = Layers(enable_layers); |
| 136 | RemoveUnavailableLayers(dld, layers); | 135 | RemoveUnavailableLayers(dld, layers); |
| 137 | 136 | ||
| @@ -139,12 +138,9 @@ std::pair<vk::Instance, u32> CreateInstance(Common::DynamicLibrary& library, | |||
| 139 | const u32 version = std::min(vk::AvailableVersion(dld), VK_API_VERSION_1_1); | 138 | const u32 version = std::min(vk::AvailableVersion(dld), VK_API_VERSION_1_1); |
| 140 | 139 | ||
| 141 | vk::Instance instance = vk::Instance::Create(version, layers, extensions, dld); | 140 | vk::Instance instance = vk::Instance::Create(version, layers, extensions, dld); |
| 142 | if (!instance) { | ||
| 143 | LOG_ERROR(Render_Vulkan, "Failed to create Vulkan instance"); | ||
| 144 | return {}; | ||
| 145 | } | ||
| 146 | if (!vk::Load(*instance, dld)) { | 141 | if (!vk::Load(*instance, dld)) { |
| 147 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers"); | 142 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers"); |
| 143 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | ||
| 148 | } | 144 | } |
| 149 | return std::make_pair(std::move(instance), version); | 145 | return std::make_pair(std::move(instance), version); |
| 150 | } | 146 | } |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 478402bbd..f4177537b 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -435,7 +435,7 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe | |||
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, | 437 | Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, |
| 438 | InstanceDispatch& dispatch) noexcept { | 438 | InstanceDispatch& dispatch) { |
| 439 | const VkApplicationInfo application_info{ | 439 | const VkApplicationInfo application_info{ |
| 440 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, | 440 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, |
| 441 | .pNext = nullptr, | 441 | .pNext = nullptr, |
| @@ -455,22 +455,17 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char | |||
| 455 | .enabledExtensionCount = extensions.size(), | 455 | .enabledExtensionCount = extensions.size(), |
| 456 | .ppEnabledExtensionNames = extensions.data(), | 456 | .ppEnabledExtensionNames = extensions.data(), |
| 457 | }; | 457 | }; |
| 458 | |||
| 459 | VkInstance instance; | 458 | VkInstance instance; |
| 460 | if (dispatch.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) { | 459 | Check(dispatch.vkCreateInstance(&ci, nullptr, &instance)); |
| 461 | // Failed to create the instance. | ||
| 462 | return {}; | ||
| 463 | } | ||
| 464 | if (!Proc(dispatch.vkDestroyInstance, dispatch, "vkDestroyInstance", instance)) { | 460 | if (!Proc(dispatch.vkDestroyInstance, dispatch, "vkDestroyInstance", instance)) { |
| 465 | // We successfully created an instance but the destroy function couldn't be loaded. | 461 | // We successfully created an instance but the destroy function couldn't be loaded. |
| 466 | // This is a good moment to panic. | 462 | // This is a good moment to panic. |
| 467 | return {}; | 463 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 468 | } | 464 | } |
| 469 | |||
| 470 | return Instance(instance, dispatch); | 465 | return Instance(instance, dispatch); |
| 471 | } | 466 | } |
| 472 | 467 | ||
| 473 | std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices() { | 468 | std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices() const { |
| 474 | u32 num; | 469 | u32 num; |
| 475 | if (dld->vkEnumeratePhysicalDevices(handle, &num, nullptr) != VK_SUCCESS) { | 470 | if (dld->vkEnumeratePhysicalDevices(handle, &num, nullptr) != VK_SUCCESS) { |
| 476 | return std::nullopt; | 471 | return std::nullopt; |
| @@ -483,27 +478,11 @@ std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices( | |||
| 483 | return std::make_optional(std::move(physical_devices)); | 478 | return std::make_optional(std::move(physical_devices)); |
| 484 | } | 479 | } |
| 485 | 480 | ||
| 486 | DebugCallback Instance::TryCreateDebugCallback( | 481 | DebugUtilsMessenger Instance::CreateDebugUtilsMessenger( |
| 487 | PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept { | 482 | const VkDebugUtilsMessengerCreateInfoEXT& create_info) const { |
| 488 | const VkDebugUtilsMessengerCreateInfoEXT ci{ | 483 | VkDebugUtilsMessengerEXT object; |
| 489 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, | 484 | Check(dld->vkCreateDebugUtilsMessengerEXT(handle, &create_info, nullptr, &object)); |
| 490 | .pNext = nullptr, | 485 | return DebugUtilsMessenger(object, handle, *dld); |
| 491 | .flags = 0, | ||
| 492 | .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | | ||
| 493 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | | ||
| 494 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | | ||
| 495 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, | ||
| 496 | .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | | ||
| 497 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, | ||
| 498 | .pfnUserCallback = callback, | ||
| 499 | .pUserData = nullptr, | ||
| 500 | }; | ||
| 501 | |||
| 502 | VkDebugUtilsMessengerEXT messenger; | ||
| 503 | if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) { | ||
| 504 | return {}; | ||
| 505 | } | ||
| 506 | return DebugCallback(messenger, handle, *dld); | ||
| 507 | } | 486 | } |
| 508 | 487 | ||
| 509 | void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { | 488 | void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index f9a184e00..03ca97ac0 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -555,7 +555,7 @@ private: | |||
| 555 | const DeviceDispatch* dld = nullptr; | 555 | const DeviceDispatch* dld = nullptr; |
| 556 | }; | 556 | }; |
| 557 | 557 | ||
| 558 | using DebugCallback = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>; | 558 | using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>; |
| 559 | using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>; | 559 | using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>; |
| 560 | using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>; | 560 | using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>; |
| 561 | using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>; | 561 | using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>; |
| @@ -573,16 +573,19 @@ class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> { | |||
| 573 | using Handle<VkInstance, NoOwner, InstanceDispatch>::Handle; | 573 | using Handle<VkInstance, NoOwner, InstanceDispatch>::Handle; |
| 574 | 574 | ||
| 575 | public: | 575 | public: |
| 576 | /// Creates a Vulkan instance. Use "operator bool" for error handling. | 576 | /// Creates a Vulkan instance. |
| 577 | /// @throw Exception on initialization error. | ||
| 577 | static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions, | 578 | static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions, |
| 578 | InstanceDispatch& dispatch) noexcept; | 579 | InstanceDispatch& dispatch); |
| 579 | 580 | ||
| 580 | /// Enumerates physical devices. | 581 | /// Enumerates physical devices. |
| 581 | /// @return Physical devices and an empty handle on failure. | 582 | /// @return Physical devices and an empty handle on failure. |
| 582 | std::optional<std::vector<VkPhysicalDevice>> EnumeratePhysicalDevices(); | 583 | std::optional<std::vector<VkPhysicalDevice>> EnumeratePhysicalDevices() const; |
| 583 | 584 | ||
| 584 | /// Tries to create a debug callback messenger. Returns an empty handle on failure. | 585 | /// Creates a debug callback messenger. |
| 585 | DebugCallback TryCreateDebugCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept; | 586 | /// @throw Exception on creation failure. |
| 587 | DebugUtilsMessenger CreateDebugUtilsMessenger( | ||
| 588 | const VkDebugUtilsMessengerCreateInfoEXT& create_info) const; | ||
| 586 | }; | 589 | }; |
| 587 | 590 | ||
| 588 | class Queue { | 591 | class Queue { |