summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-12-25 02:01:13 -0300
committerGravatar ReinUsesLisp2020-12-31 02:07:33 -0300
commit47843b4f097ced5e99c5567b8ac3fd53b80fab0a (patch)
tree190309df63e67b03d651da034c07b0e4a994cc5f /src/video_core
parentrenderer_vulkan: Move instance initialization to a separate file (diff)
downloadyuzu-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')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp37
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.cpp45
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.h11
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp14
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp39
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h15
8 files changed, 88 insertions, 79 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index f8c36947a..9287faee1 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -258,6 +258,8 @@ add_library(video_core STATIC
258 textures/texture.h 258 textures/texture.h
259 video_core.cpp 259 video_core.cpp
260 video_core.h 260 video_core.h
261 vulkan_common/vulkan_debug_callback.cpp
262 vulkan_common/vulkan_debug_callback.h
261 vulkan_common/vulkan_instance.cpp 263 vulkan_common/vulkan_instance.cpp
262 vulkan_common/vulkan_instance.h 264 vulkan_common/vulkan_instance.h
263 vulkan_common/vulkan_library.cpp 265 vulkan_common/vulkan_library.cpp
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 82619bc61..8e01dc191 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -29,6 +29,7 @@
29#include "video_core/renderer_vulkan/vk_scheduler.h" 29#include "video_core/renderer_vulkan/vk_scheduler.h"
30#include "video_core/renderer_vulkan/vk_state_tracker.h" 30#include "video_core/renderer_vulkan/vk_state_tracker.h"
31#include "video_core/renderer_vulkan/vk_swapchain.h" 31#include "video_core/renderer_vulkan/vk_swapchain.h"
32#include "video_core/vulkan_common/vulkan_debug_callback.h"
32#include "video_core/vulkan_common/vulkan_instance.h" 33#include "video_core/vulkan_common/vulkan_instance.h"
33#include "video_core/vulkan_common/vulkan_library.h" 34#include "video_core/vulkan_common/vulkan_library.h"
34#include "video_core/vulkan_common/vulkan_wrapper.h" 35#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -48,24 +49,6 @@
48 49
49namespace Vulkan { 50namespace Vulkan {
50namespace { 51namespace {
51VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
52 VkDebugUtilsMessageTypeFlagsEXT type,
53 const VkDebugUtilsMessengerCallbackDataEXT* data,
54 [[maybe_unused]] void* user_data) {
55 const char* const message{data->pMessage};
56
57 if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
58 LOG_CRITICAL(Render_Vulkan, "{}", message);
59 } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
60 LOG_WARNING(Render_Vulkan, "{}", message);
61 } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
62 LOG_INFO(Render_Vulkan, "{}", message);
63 } else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
64 LOG_DEBUG(Render_Vulkan, "{}", message);
65 }
66 return VK_FALSE;
67}
68
69std::string GetReadableVersion(u32 version) { 52std::string GetReadableVersion(u32 version) {
70 return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), 53 return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
71 VK_VERSION_PATCH(version)); 54 VK_VERSION_PATCH(version));
@@ -158,7 +141,11 @@ bool RendererVulkan::Init() {
158 library = OpenLibrary(); 141 library = OpenLibrary();
159 std::tie(instance, instance_version) = CreateInstance( 142 std::tie(instance, instance_version) = CreateInstance(
160 library, dld, render_window.GetWindowInfo().type, true, Settings::values.renderer_debug); 143 library, dld, render_window.GetWindowInfo().type, true, Settings::values.renderer_debug);
161 if (!instance || !CreateDebugCallback() || !CreateSurface() || !PickDevices()) { 144 if (Settings::values.renderer_debug) {
145 debug_callback = CreateDebugCallback(instance);
146 }
147
148 if (!CreateSurface() || !PickDevices()) {
162 return false; 149 return false;
163 } 150 }
164 151
@@ -201,18 +188,6 @@ void RendererVulkan::ShutDown() {
201 device.reset(); 188 device.reset();
202} 189}
203 190
204bool RendererVulkan::CreateDebugCallback() {
205 if (!Settings::values.renderer_debug) {
206 return true;
207 }
208 debug_callback = instance.TryCreateDebugCallback(DebugCallback);
209 if (!debug_callback) {
210 LOG_ERROR(Render_Vulkan, "Failed to create debug callback");
211 return false;
212 }
213 return true;
214}
215
216bool RendererVulkan::CreateSurface() { 191bool RendererVulkan::CreateSurface() {
217 [[maybe_unused]] const auto& window_info = render_window.GetWindowInfo(); 192 [[maybe_unused]] const auto& window_info = render_window.GetWindowInfo();
218 VkSurfaceKHR unsafe_surface = nullptr; 193 VkSurfaceKHR unsafe_surface = nullptr;
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 4a0abfaad..fa7628d0e 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -56,8 +56,6 @@ public:
56 static std::vector<std::string> EnumerateDevices(); 56 static std::vector<std::string> EnumerateDevices();
57 57
58private: 58private:
59 bool CreateDebugCallback();
60
61 bool CreateSurface(); 59 bool CreateSurface();
62 60
63 bool PickDevices(); 61 bool PickDevices();
@@ -78,7 +76,7 @@ private:
78 76
79 VKScreenInfo screen_info; 77 VKScreenInfo screen_info;
80 78
81 vk::DebugCallback debug_callback; 79 vk::DebugUtilsMessenger debug_callback;
82 std::unique_ptr<VKDevice> device; 80 std::unique_ptr<VKDevice> device;
83 std::unique_ptr<VKMemoryManager> memory_manager; 81 std::unique_ptr<VKMemoryManager> memory_manager;
84 std::unique_ptr<StateTracker> state_tracker; 82 std::unique_ptr<StateTracker> state_tracker;
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
9namespace Vulkan {
10namespace {
11VkBool32 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
29vk::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
7namespace Vulkan {
8
9vk::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
437Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, 437Instance 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
473std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices() { 468std::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
486DebugCallback Instance::TryCreateDebugCallback( 481DebugUtilsMessenger 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
509void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { 488void 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
558using DebugCallback = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>; 558using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
559using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>; 559using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
560using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>; 560using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>;
561using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>; 561using 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
575public: 575public:
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
588class Queue { 591class Queue {