summaryrefslogtreecommitdiff
path: root/src/video_core/vulkan_common
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/vulkan_common
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/vulkan_common')
-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
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
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 {