vk_device: Add entry to catch device losses
VK_NV_device_diagnostic_checkpoints allows us to push data to a Vulkan queue and then query it even after a device loss. This allows us to push the current pipeline object and see what was the call that killed the device.
This commit is contained in:
parent
f4a25f854c
commit
54747d60bc
|
@ -3,12 +3,15 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "core/settings.h"
|
||||||
#include "video_core/renderer_vulkan/declarations.h"
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
#include "video_core/renderer_vulkan/vk_device.h"
|
#include "video_core/renderer_vulkan/vk_device.h"
|
||||||
|
|
||||||
|
@ -201,6 +204,22 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
|
||||||
return 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,
|
bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features,
|
||||||
const vk::DispatchLoaderDynamic& dldi) const {
|
const vk::DispatchLoaderDynamic& dldi) const {
|
||||||
// Disable for now to avoid converting ASTC twice.
|
// 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);
|
VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true);
|
||||||
Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
|
Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
|
||||||
false);
|
false);
|
||||||
|
Test(extension, nv_device_diagnostic_checkpoints,
|
||||||
|
VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (khr_shader_float16_int8) {
|
if (khr_shader_float16_int8) {
|
||||||
|
|
|
@ -39,6 +39,9 @@ public:
|
||||||
vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage,
|
vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage,
|
||||||
FormatType format_type) const;
|
FormatType format_type) const;
|
||||||
|
|
||||||
|
/// Reports a device loss.
|
||||||
|
void ReportLoss() const;
|
||||||
|
|
||||||
/// Returns the dispatch loader with direct function pointers of the device.
|
/// Returns the dispatch loader with direct function pointers of the device.
|
||||||
const vk::DispatchLoaderDynamic& GetDispatchLoader() const {
|
const vk::DispatchLoaderDynamic& GetDispatchLoader() const {
|
||||||
return dld;
|
return dld;
|
||||||
|
@ -159,6 +162,11 @@ public:
|
||||||
return ext_shader_viewport_index_layer;
|
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.
|
/// Returns the vendor name reported from Vulkan.
|
||||||
std::string_view GetVendorName() const {
|
std::string_view GetVendorName() const {
|
||||||
return vendor_name;
|
return vendor_name;
|
||||||
|
@ -218,6 +226,7 @@ private:
|
||||||
bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
|
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_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 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
|
// Telemetry parameters
|
||||||
std::string vendor_name; ///< Device's driver name.
|
std::string vendor_name; ///< Device's driver name.
|
||||||
|
|
|
@ -72,9 +72,18 @@ VKFence::VKFence(const VKDevice& device, UniqueFence handle)
|
||||||
VKFence::~VKFence() = default;
|
VKFence::~VKFence() = default;
|
||||||
|
|
||||||
void VKFence::Wait() {
|
void VKFence::Wait() {
|
||||||
|
static constexpr u64 timeout = std::numeric_limits<u64>::max();
|
||||||
const auto dev = device.GetLogical();
|
const auto dev = device.GetLogical();
|
||||||
const auto& dld = device.GetDispatchLoader();
|
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() {
|
void VKFence::Release() {
|
||||||
|
|
Reference in New Issue