Compare commits

...

7 Commits

Author SHA1 Message Date
lizzie b71ddb302a sds 2026-08-29 06:29:31 +00:00
lizzie 00243891d1 oops, fixup 2026-08-29 06:29:31 +00:00
lizzie 5d42bfba0d fx 2026-08-29 06:29:05 +00:00
lizzie 42db87998f fix device fault? 2026-08-29 06:29:05 +00:00
lizzie 9a8477eb43 fix logged 2026-08-29 06:28:26 +00:00
lizzie 565b04fd12 fx 2026-08-29 06:28:26 +00:00
lizzie 9941453610 [vulkan] support VK_EXT_fault_info when VK_ERROR_DEVICE_LOST is incurred
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-08-29 06:28:26 +00:00
4 changed files with 81 additions and 23 deletions
+69 -13
View File
@@ -25,6 +25,7 @@
#include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/gpu_logging/gpu_logging.h" #include "video_core/gpu_logging/gpu_logging.h"
#include "vulkan/vulkan_core.h"
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64) #if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
#include <adrenotools/bcenabler.h> #include <adrenotools/bcenabler.h>
@@ -794,8 +795,55 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
} }
void Device::ReportLoss() const { void Device::ReportLoss() const {
LOG_CRITICAL(Render_Vulkan, "Device loss occurred!"); LOG_CRITICAL(Render_Vulkan, "Device loss occurred! {},{}", extensions.device_fault, features.device_fault.deviceFault);
if (extensions.device_fault && features.device_fault.deviceFault) {
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.vendorFaultData, 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";
}
LOG_INFO(Render_Vulkan, "{}", s);
}
// Wait for the log to flush and for Nsight Aftermath to dump the results // Wait for the log to flush and for Nsight Aftermath to dump the results
std::this_thread::sleep_for(std::chrono::seconds{15}); std::this_thread::sleep_for(std::chrono::seconds{15});
} }
@@ -926,13 +974,13 @@ bool Device::GetSuitability(bool requires_swapchain) {
#define EXTENSION(prefix, macro_name, var_name) \ #define EXTENSION(prefix, macro_name, var_name) \
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \ if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \ loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
extensions.var_name = true; \ extensions.var_name = true; \
} }
#define FEATURE_EXTENSION(prefix, struct_name, macro_name, var_name) \ #define FEATURE_EXTENSION(prefix, struct_name, macro_name, var_name) \
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \ if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \ loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
extensions.var_name = true; \ extensions.var_name = true; \
} }
if (instance_version < VK_API_VERSION_1_2) { if (instance_version < VK_API_VERSION_1_2) {
@@ -962,19 +1010,24 @@ bool Device::GetSuitability(bool requires_swapchain) {
extensions.robustness_2 = false; extensions.robustness_2 = false;
} }
// different namings
if (supported_extensions.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {
loaded_extensions.insert(VK_EXT_DEVICE_FAULT_EXTENSION_NAME);
extensions.device_fault = true;
}
#undef FEATURE_EXTENSION #undef FEATURE_EXTENSION
#undef EXTENSION #undef EXTENSION
// Some extensions are mandatory. Check those. // Some extensions are mandatory. Check those.
#define CHECK_EXTENSION(extension_name) \ #define CHECK_EXTENSION(extension_name) \
if (!loaded_extensions.contains(extension_name)) { \ if (!loaded_extensions.contains(extension_name)) { \
LOG_ERROR(Render_Vulkan, "Missing required extension {}", extension_name); \ LOG_ERROR(Render_Vulkan, "Missing required extension {}", extension_name); \
suitable = false; \ suitable = false; \
} }
#define LOG_EXTENSION(extension_name) \ #define LOG_EXTENSION(extension_name) \
if (!loaded_extensions.contains(extension_name)) { \ if (!loaded_extensions.contains(extension_name)) { \
LOG_INFO(Render_Vulkan, "Device doesn't support extension {}", extension_name); \ LOG_INFO(Render_Vulkan, "Device doesn't support extension {}", extension_name); \
} }
FOR_EACH_VK_RECOMMENDED_EXTENSION(LOG_EXTENSION); FOR_EACH_VK_RECOMMENDED_EXTENSION(LOG_EXTENSION);
@@ -1016,9 +1069,9 @@ bool Device::GetSuitability(bool requires_swapchain) {
#define EXT_FEATURE(prefix, struct_name, macro_name, var_name) \ #define EXT_FEATURE(prefix, struct_name, macro_name, var_name) \
if (extensions.var_name) { \ if (extensions.var_name) { \
features.var_name.sType = \ features.var_name.sType = \
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##macro_name##_FEATURES_##prefix; \ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##macro_name##_FEATURES_##prefix; \
SetNext(next, features.var_name); \ SetNext(next, features.var_name); \
} }
FOR_EACH_VK_FEATURE_1_1(FEATURE); FOR_EACH_VK_FEATURE_1_1(FEATURE);
@@ -1033,7 +1086,10 @@ bool Device::GetSuitability(bool requires_swapchain) {
} else { } else {
FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE); FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE);
} }
if (extensions.device_fault) {
features.device_fault.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
SetNext(next, features.device_fault);
}
#undef EXT_FEATURE #undef EXT_FEATURE
#undef FEATURE #undef FEATURE
+10 -10
View File
@@ -18,6 +18,7 @@
#include "common/logging.h" #include "common/logging.h"
#include "common/settings.h" #include "common/settings.h"
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
#include "vulkan/vulkan_core.h"
VK_DEFINE_HANDLE(VmaAllocator) VK_DEFINE_HANDLE(VmaAllocator)
@@ -93,8 +94,12 @@ VK_DEFINE_HANDLE(VmaAllocator)
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \ EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
EXTENSION(EXT, TOOLING_INFO, tooling_info) \ EXTENSION(EXT, TOOLING_INFO, tooling_info) \
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \ EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
<<<<<<< HEAD
EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \ EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \
EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \ EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \
EXTENSION(EXT, DEVICE_FAULT, device_fault) \
=======
>>>>>>> 6e75e5837b (oops, fixup)
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \ EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \ EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \
EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \ EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \
@@ -1142,33 +1147,28 @@ private:
struct Extensions { struct Extensions {
#define EXTENSION(prefix, macro_name, var_name) bool var_name{}; #define EXTENSION(prefix, macro_name, var_name) bool var_name{};
#define FEATURE(prefix, struct_name, macro_name, var_name) bool var_name{}; #define FEATURE(prefix, struct_name, macro_name, var_name) bool var_name{};
FOR_EACH_VK_FEATURE_1_1(FEATURE); FOR_EACH_VK_FEATURE_1_1(FEATURE);
FOR_EACH_VK_FEATURE_1_2(FEATURE); FOR_EACH_VK_FEATURE_1_2(FEATURE);
FOR_EACH_VK_FEATURE_1_3(FEATURE); FOR_EACH_VK_FEATURE_1_3(FEATURE);
FOR_EACH_VK_FEATURE_1_4(FEATURE); FOR_EACH_VK_FEATURE_1_4(FEATURE);
FOR_EACH_VK_FEATURE_EXT(FEATURE); FOR_EACH_VK_FEATURE_EXT(FEATURE);
FOR_EACH_VK_EXTENSION(EXTENSION); FOR_EACH_VK_EXTENSION(EXTENSION);
#undef EXTENSION #undef EXTENSION
#undef FEATURE #undef FEATURE
bool device_fault;
}; };
struct Features { struct Features {
#define FEATURE_CORE(prefix, struct_name, macro_name, var_name) \ #define FEATURE_CORE(prefix, struct_name, macro_name, var_name) VkPhysicalDevice##struct_name##Features var_name{};
VkPhysicalDevice##struct_name##Features var_name{}; #define FEATURE_EXT(prefix, struct_name, macro_name, var_name) VkPhysicalDevice##struct_name##Features##prefix var_name{};
#define FEATURE_EXT(prefix, struct_name, macro_name, var_name) \
VkPhysicalDevice##struct_name##Features##prefix var_name{};
FOR_EACH_VK_FEATURE_1_1(FEATURE_CORE); FOR_EACH_VK_FEATURE_1_1(FEATURE_CORE);
FOR_EACH_VK_FEATURE_1_2(FEATURE_CORE); FOR_EACH_VK_FEATURE_1_2(FEATURE_CORE);
FOR_EACH_VK_FEATURE_1_3(FEATURE_CORE); FOR_EACH_VK_FEATURE_1_3(FEATURE_CORE);
FOR_EACH_VK_FEATURE_1_4(FEATURE_CORE); FOR_EACH_VK_FEATURE_1_4(FEATURE_CORE);
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXT); FOR_EACH_VK_FEATURE_EXT(FEATURE_EXT);
#undef FEATURE_CORE #undef FEATURE_CORE
#undef FEATURE_EXT #undef FEATURE_EXT
VkPhysicalDeviceFaultFeaturesEXT device_fault{};
VkPhysicalDeviceFeatures features{}; VkPhysicalDeviceFeatures features{};
}; };
@@ -1183,7 +1183,7 @@ private:
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{}; VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{}; VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color{}; VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color{};
VkPhysicalDeviceFaultFeaturesEXT device_fault{};
VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceProperties properties{};
}; };
@@ -246,6 +246,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetDescriptorBufferOffsetsEXT); X(vkCmdSetDescriptorBufferOffsetsEXT);
X(vkWaitForFences); X(vkWaitForFences);
X(vkWaitSemaphores); X(vkWaitSemaphores);
X(vkGetDeviceFaultInfoEXT);
// Support for timeline semaphores is mandatory in Vulkan 1.2 // Support for timeline semaphores is mandatory in Vulkan 1.2
if (!dld.vkGetSemaphoreCounterValue) { if (!dld.vkGetSemaphoreCounterValue) {
@@ -362,6 +362,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{}; PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
PFN_vkWaitForFences vkWaitForFences{}; PFN_vkWaitForFences vkWaitForFences{};
PFN_vkWaitSemaphores vkWaitSemaphores{}; PFN_vkWaitSemaphores vkWaitSemaphores{};
PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT{};
}; };
/// Loads instance agnostic function pointers. /// Loads instance agnostic function pointers.