summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h9
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp36
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.h16
4 files changed, 82 insertions, 1 deletions
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index 92854a4b3..939eebe83 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -3,12 +3,15 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bitset> 5#include <bitset>
6#include <chrono>
6#include <cstdlib> 7#include <cstdlib>
7#include <optional> 8#include <optional>
8#include <set> 9#include <set>
9#include <string_view> 10#include <string_view>
11#include <thread>
10#include <vector> 12#include <vector>
11#include "common/assert.h" 13#include "common/assert.h"
14#include "core/settings.h"
12#include "video_core/renderer_vulkan/declarations.h" 15#include "video_core/renderer_vulkan/declarations.h"
13#include "video_core/renderer_vulkan/vk_device.h" 16#include "video_core/renderer_vulkan/vk_device.h"
14 17
@@ -201,6 +204,22 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
201 return wanted_format; 204 return wanted_format;
202} 205}
203 206
207void VKDevice::ReportLoss() const {
208 LOG_CRITICAL(Render_Vulkan, "Device loss occured!");
209
210 // Wait some time to let the log flush
211 std::this_thread::sleep_for(std::chrono::seconds{1});
212
213 if (!nv_device_diagnostic_checkpoints) {
214 return;
215 }
216
217 [[maybe_unused]] const std::vector data = graphics_queue.getCheckpointDataNV(dld);
218 // Catch here in debug builds (or with optimizations disabled) the last graphics pipeline to be
219 // executed. It can be done on a debugger by evaluating the expression:
220 // *(VKGraphicsPipeline*)data[0]
221}
222
204bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features, 223bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features,
205 const vk::DispatchLoaderDynamic& dldi) const { 224 const vk::DispatchLoaderDynamic& dldi) const {
206 // Disable for now to avoid converting ASTC twice. 225 // Disable for now to avoid converting ASTC twice.
@@ -381,6 +400,8 @@ std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynami
381 VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true); 400 VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true);
382 Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, 401 Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
383 false); 402 false);
403 Test(extension, nv_device_diagnostic_checkpoints,
404 VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, true);
384 } 405 }
385 406
386 if (khr_shader_float16_int8) { 407 if (khr_shader_float16_int8) {
@@ -464,6 +485,7 @@ std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() con
464std::unordered_map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties( 485std::unordered_map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties(
465 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) { 486 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) {
466 static constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32, 487 static constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32,
488 vk::Format::eA8B8G8R8UintPack32,
467 vk::Format::eA8B8G8R8SnormPack32, 489 vk::Format::eA8B8G8R8SnormPack32,
468 vk::Format::eA8B8G8R8SrgbPack32, 490 vk::Format::eA8B8G8R8SrgbPack32,
469 vk::Format::eB5G6R5UnormPack16, 491 vk::Format::eB5G6R5UnormPack16,
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index a844c52df..72603f9f6 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -39,6 +39,9 @@ public:
39 vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage, 39 vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage,
40 FormatType format_type) const; 40 FormatType format_type) const;
41 41
42 /// Reports a device loss.
43 void ReportLoss() const;
44
42 /// Returns the dispatch loader with direct function pointers of the device. 45 /// Returns the dispatch loader with direct function pointers of the device.
43 const vk::DispatchLoaderDynamic& GetDispatchLoader() const { 46 const vk::DispatchLoaderDynamic& GetDispatchLoader() const {
44 return dld; 47 return dld;
@@ -159,6 +162,11 @@ public:
159 return ext_shader_viewport_index_layer; 162 return ext_shader_viewport_index_layer;
160 } 163 }
161 164
165 /// Returns true if the device supports VK_NV_device_diagnostic_checkpoints.
166 bool IsNvDeviceDiagnosticCheckpoints() const {
167 return nv_device_diagnostic_checkpoints;
168 }
169
162 /// Returns the vendor name reported from Vulkan. 170 /// Returns the vendor name reported from Vulkan.
163 std::string_view GetVendorName() const { 171 std::string_view GetVendorName() const {
164 return vendor_name; 172 return vendor_name;
@@ -218,6 +226,7 @@ private:
218 bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8. 226 bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
219 bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted. 227 bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted.
220 bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer. 228 bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer.
229 bool nv_device_diagnostic_checkpoints{}; ///< Support for VK_NV_device_diagnostic_checkpoints.
221 230
222 // Telemetry parameters 231 // Telemetry parameters
223 std::string vendor_name; ///< Device's driver name. 232 std::string vendor_name; ///< Device's driver name.
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
index 13c46e5b8..525b4bb46 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -72,12 +72,22 @@ VKFence::VKFence(const VKDevice& device, UniqueFence handle)
72VKFence::~VKFence() = default; 72VKFence::~VKFence() = default;
73 73
74void VKFence::Wait() { 74void VKFence::Wait() {
75 static constexpr u64 timeout = std::numeric_limits<u64>::max();
75 const auto dev = device.GetLogical(); 76 const auto dev = device.GetLogical();
76 const auto& dld = device.GetDispatchLoader(); 77 const auto& dld = device.GetDispatchLoader();
77 dev.waitForFences({*handle}, true, std::numeric_limits<u64>::max(), dld); 78 switch (const auto result = dev.waitForFences(1, &*handle, true, timeout, dld)) {
79 case vk::Result::eSuccess:
80 return;
81 case vk::Result::eErrorDeviceLost:
82 device.ReportLoss();
83 [[fallthrough]];
84 default:
85 vk::throwResultException(result, "vk::waitForFences");
86 }
78} 87}
79 88
80void VKFence::Release() { 89void VKFence::Release() {
90 ASSERT(is_owned);
81 is_owned = false; 91 is_owned = false;
82} 92}
83 93
@@ -133,8 +143,32 @@ void VKFence::Unprotect(VKResource* resource) {
133 protected_resources.erase(it); 143 protected_resources.erase(it);
134} 144}
135 145
146void VKFence::RedirectProtection(VKResource* old_resource, VKResource* new_resource) noexcept {
147 std::replace(std::begin(protected_resources), std::end(protected_resources), old_resource,
148 new_resource);
149}
150
136VKFenceWatch::VKFenceWatch() = default; 151VKFenceWatch::VKFenceWatch() = default;
137 152
153VKFenceWatch::VKFenceWatch(VKFence& initial_fence) {
154 Watch(initial_fence);
155}
156
157VKFenceWatch::VKFenceWatch(VKFenceWatch&& rhs) noexcept {
158 fence = std::exchange(rhs.fence, nullptr);
159 if (fence) {
160 fence->RedirectProtection(&rhs, this);
161 }
162}
163
164VKFenceWatch& VKFenceWatch::operator=(VKFenceWatch&& rhs) noexcept {
165 fence = std::exchange(rhs.fence, nullptr);
166 if (fence) {
167 fence->RedirectProtection(&rhs, this);
168 }
169 return *this;
170}
171
138VKFenceWatch::~VKFenceWatch() { 172VKFenceWatch::~VKFenceWatch() {
139 if (fence) { 173 if (fence) {
140 fence->Unprotect(this); 174 fence->Unprotect(this);
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.h b/src/video_core/renderer_vulkan/vk_resource_manager.h
index 08ee86fa6..d4cbc95a5 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.h
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.h
@@ -65,6 +65,9 @@ public:
65 /// Removes protection for a resource. 65 /// Removes protection for a resource.
66 void Unprotect(VKResource* resource); 66 void Unprotect(VKResource* resource);
67 67
68 /// Redirects one protected resource to a new address.
69 void RedirectProtection(VKResource* old_resource, VKResource* new_resource) noexcept;
70
68 /// Retreives the fence. 71 /// Retreives the fence.
69 operator vk::Fence() const { 72 operator vk::Fence() const {
70 return *handle; 73 return *handle;
@@ -97,8 +100,13 @@ private:
97class VKFenceWatch final : public VKResource { 100class VKFenceWatch final : public VKResource {
98public: 101public:
99 explicit VKFenceWatch(); 102 explicit VKFenceWatch();
103 VKFenceWatch(VKFence& initial_fence);
104 VKFenceWatch(VKFenceWatch&&) noexcept;
105 VKFenceWatch(const VKFenceWatch&) = delete;
100 ~VKFenceWatch() override; 106 ~VKFenceWatch() override;
101 107
108 VKFenceWatch& operator=(VKFenceWatch&&) noexcept;
109
102 /// Waits for the fence to be released. 110 /// Waits for the fence to be released.
103 void Wait(); 111 void Wait();
104 112
@@ -116,6 +124,14 @@ public:
116 124
117 void OnFenceRemoval(VKFence* signaling_fence) override; 125 void OnFenceRemoval(VKFence* signaling_fence) override;
118 126
127 /**
128 * Do not use it paired with Watch. Use TryWatch instead.
129 * Returns true when the watch is free.
130 */
131 bool IsUsed() const {
132 return fence != nullptr;
133 }
134
119private: 135private:
120 VKFence* fence{}; ///< Fence watching this resource. nullptr when the watch is free. 136 VKFence* fence{}; ///< Fence watching this resource. nullptr when the watch is free.
121}; 137};