diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index a574280598..939eebe83b 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -3,12 +3,15 @@
 // Refer to the license.txt file included.
 
 #include <bitset>
+#include <chrono>
 #include <cstdlib>
 #include <optional>
 #include <set>
 #include <string_view>
+#include <thread>
 #include <vector>
 #include "common/assert.h"
+#include "core/settings.h"
 #include "video_core/renderer_vulkan/declarations.h"
 #include "video_core/renderer_vulkan/vk_device.h"
 
@@ -201,6 +204,22 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
     return wanted_format;
 }
 
+void VKDevice::ReportLoss() const {
+    LOG_CRITICAL(Render_Vulkan, "Device loss occured!");
+
+    // Wait some time to let the log flush
+    std::this_thread::sleep_for(std::chrono::seconds{1});
+
+    if (!nv_device_diagnostic_checkpoints) {
+        return;
+    }
+
+    [[maybe_unused]] const std::vector data = graphics_queue.getCheckpointDataNV(dld);
+    // Catch here in debug builds (or with optimizations disabled) the last graphics pipeline to be
+    // executed. It can be done on a debugger by evaluating the expression:
+    // *(VKGraphicsPipeline*)data[0]
+}
+
 bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features,
                                       const vk::DispatchLoaderDynamic& dldi) const {
     // Disable for now to avoid converting ASTC twice.
@@ -381,6 +400,8 @@ std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynami
              VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true);
         Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
              false);
+        Test(extension, nv_device_diagnostic_checkpoints,
+             VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, true);
     }
 
     if (khr_shader_float16_int8) {
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index a844c52dfb..72603f9f62 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -39,6 +39,9 @@ public:
     vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage,
                                   FormatType format_type) const;
 
+    /// Reports a device loss.
+    void ReportLoss() const;
+
     /// Returns the dispatch loader with direct function pointers of the device.
     const vk::DispatchLoaderDynamic& GetDispatchLoader() const {
         return dld;
@@ -159,6 +162,11 @@ public:
         return ext_shader_viewport_index_layer;
     }
 
+    /// Returns true if the device supports VK_NV_device_diagnostic_checkpoints.
+    bool IsNvDeviceDiagnosticCheckpoints() const {
+        return nv_device_diagnostic_checkpoints;
+    }
+
     /// Returns the vendor name reported from Vulkan.
     std::string_view GetVendorName() const {
         return vendor_name;
@@ -218,6 +226,7 @@ private:
     bool ext_index_type_uint8{};               ///< Support for VK_EXT_index_type_uint8.
     bool ext_depth_range_unrestricted{};       ///< Support for VK_EXT_depth_range_unrestricted.
     bool ext_shader_viewport_index_layer{};    ///< Support for VK_EXT_shader_viewport_index_layer.
+    bool nv_device_diagnostic_checkpoints{};   ///< Support for VK_NV_device_diagnostic_checkpoints.
 
     // Telemetry parameters
     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 13c46e5b8c..a0ca5f2ae1 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -72,9 +72,18 @@ VKFence::VKFence(const VKDevice& device, UniqueFence handle)
 VKFence::~VKFence() = default;
 
 void VKFence::Wait() {
+    static constexpr u64 timeout = std::numeric_limits<u64>::max();
     const auto dev = device.GetLogical();
     const auto& dld = device.GetDispatchLoader();
-    dev.waitForFences({*handle}, true, std::numeric_limits<u64>::max(), dld);
+    switch (const auto result = dev.waitForFences(1, &*handle, true, timeout, dld)) {
+    case vk::Result::eSuccess:
+        return;
+    case vk::Result::eErrorDeviceLost:
+        device.ReportLoss();
+        [[fallthrough]];
+    default:
+        vk::throwResultException(result, "vk::waitForFences");
+    }
 }
 
 void VKFence::Release() {