[vulkan] support VK_EXT_fault_info when VK_ERROR_DEVICE_LOST is incurred

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2026-04-25 08:02:00 +00:00
parent 26ce96297c
commit 4e6d495c98
4 changed files with 52 additions and 0 deletions

View File

@@ -25,6 +25,7 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "vulkan/vulkan_core.h"
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
#include <adrenotools/bcenabler.h>
@@ -772,6 +773,54 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
void Device::ReportLoss() const {
LOG_CRITICAL(Render_Vulkan, "Device loss occurred!");
if (extensions.device_fault) {
VkDeviceFaultCountsEXT fault_counts{
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT
};
dld.vkGetDeviceFaultInfoEXT(VkDevice(GetLogical().address()), &fault_counts, nullptr);
std::vector<VkDeviceFaultAddressInfoEXT> address_info(fault_counts.addressInfoCount);
std::vector<VkDeviceFaultVendorInfoEXT> vendor_info(fault_counts.vendorInfoCount);
std::vector<u8> vendor_binary_data(fault_counts.vendorBinarySize);
VkDeviceFaultInfoEXT fault_info{
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT,
.pAddressInfos = address_info.data(),
.pVendorInfos = vendor_info.data(),
.pVendorBinaryData = vendor_binary_data.data()
};
dld.vkGetDeviceFaultInfoEXT(VkDevice(GetLogical().address()), &fault_counts, &fault_info);
std::string s = "Fault report\n";
if (address_info.size() > 0) {
s += "address-info\n";
for (auto const& ai : address_info) {
s += fmt::format("{:#x} => {}\n", ai.reportedAddress, [t = ai.addressType] {
switch (t) {
#define VKFATC(n) case n: return #n;
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT)
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT)
#undef VKFATC
default: return "unknown";
}
}());
}
}
if (vendor_info.size() > 0) {
s += "vendor-info\n";
for (auto const& vi : vendor_info)
s += fmt::format("{:#x}-{:#x}: {}\n", vi.vendorFaultCode, vi.vendorFaultCode, vi.description);
}
if (vendor_binary_data.size() > 0) {
s += "vendor-binary-data\n";
for (size_t i = 0; i < vendor_binary_data.size(); ++i)
s += fmt::format("{:02x} ", vendor_binary_data[i]);
s += "\n";
}
}
// Wait for the log to flush and for Nsight Aftermath to dump the results
std::this_thread::sleep_for(std::chrono::seconds{15});
}

View File

@@ -82,6 +82,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
EXTENSION(EXT, SHADER_STENCIL_EXPORT, shader_stencil_export) \
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
EXTENSION(EXT, TOOLING_INFO, tooling_info) \
EXTENSION(EXT, DEVICE_FAULT, device_fault) \
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \

View File

@@ -236,6 +236,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkUpdateDescriptorSets);
X(vkWaitForFences);
X(vkWaitSemaphores);
X(vkGetDeviceFaultInfoEXT);
// Support for timeline semaphores is mandatory in Vulkan 1.2
if (!dld.vkGetSemaphoreCounterValue) {

View File

@@ -338,6 +338,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
PFN_vkWaitForFences vkWaitForFences{};
PFN_vkWaitSemaphores vkWaitSemaphores{};
PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT{};
};
/// Loads instance agnostic function pointers.