diff --git a/rpcs3/Emu/RSX/VK/VulkanAPI.h b/rpcs3/Emu/RSX/VK/VulkanAPI.h index f6383c78c1..804b76ca97 100644 --- a/rpcs3/Emu/RSX/VK/VulkanAPI.h +++ b/rpcs3/Emu/RSX/VK/VulkanAPI.h @@ -21,39 +21,65 @@ #include -#ifndef VK_EXT_attachment_feedback_loop_layout +// Requires SDK ver 230 which is not supported by CI currently +#ifndef VK_EXT_device_fault -#define VK_EXT_attachment_feedback_loop_layout 1 -#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_layout" -#define VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT static_cast(1000339000) -#define VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT 0x00080000 -#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT static_cast(1000339000) +#define VK_EXT_device_fault 1 +#define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" +#define VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT static_cast(1000341002) +#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT static_cast(1000341000) -typedef struct VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT { +typedef enum VkDeviceFaultAddressTypeEXT { + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = 0, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = 1, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = 2, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = 3, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = 4, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = 5, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = 6, +} VkDeviceFaultAddressTypeEXT; + +typedef struct VkPhysicalDeviceFaultFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 attachmentFeedbackLoopLayout; -} VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT; - -#endif - -#ifndef VK_KHR_fragment_shader_barycentric - -#define VK_KHR_fragment_shader_barycentric 1 -#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 -#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_KHR_fragment_shader_barycentric" -#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR static_cast(1000203000) - -typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 fragmentShaderBarycentric; -} VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR; - -typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { - VkStructureType sType; - void* pNext; - VkBool32 triStripVertexOrderIndependentOfProvokingVertex; -} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR; + VkBool32 deviceFault; + VkBool32 deviceFaultVendorBinary; +} VkPhysicalDeviceFaultFeaturesEXT; + +typedef struct VkDeviceFaultCountsEXT { + VkStructureType sType; + void* pNext; + uint32_t addressInfoCount; + uint32_t vendorInfoCount; + VkDeviceSize vendorBinarySize; +} VkDeviceFaultCountsEXT; + +typedef struct VkDeviceFaultAddressInfoEXT { + VkDeviceFaultAddressTypeEXT addressType; + VkDeviceAddress reportedAddress; + VkDeviceSize addressPrecision; +} VkDeviceFaultAddressInfoEXT; + +typedef struct VkDeviceFaultVendorInfoEXT { + char description[VK_MAX_DESCRIPTION_SIZE]; + uint64_t vendorFaultCode; + uint64_t vendorFaultData; +} VkDeviceFaultVendorInfoEXT; + +typedef struct VkDeviceFaultInfoEXT { + VkStructureType sType; + void* pNext; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkDeviceFaultAddressInfoEXT* pAddressInfos; + VkDeviceFaultVendorInfoEXT* pVendorInfos; + void* pVendorBinaryData; +} VkDeviceFaultInfoEXT; + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultInfoEXT( + VkDevice device, + VkDeviceFaultCountsEXT* pFaultCounts, + VkDeviceFaultInfoEXT* pFaultInfo); + +typedef VkResult (VKAPI_PTR* PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); #endif diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/Emu/RSX/VK/vkutils/device.cpp index 58e3a8df47..928fc10ef6 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -35,6 +35,7 @@ namespace vk VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR shader_barycentric_info{}; VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border_color_info{}; VkPhysicalDeviceBorderColorSwizzleFeaturesEXT border_color_swizzle_info{}; + VkPhysicalDeviceFaultFeaturesEXT device_fault_info{}; if (device_extensions.is_supported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) { @@ -78,6 +79,13 @@ namespace vk features2.pNext = &border_color_swizzle_info; } + if (device_extensions.is_supported(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) + { + device_fault_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT; + device_fault_info.pNext = features2.pNext; + features2.pNext = &device_fault_info; + } + auto _vkGetPhysicalDeviceFeatures2KHR = reinterpret_cast(vkGetInstanceProcAddr(parent, "vkGetPhysicalDeviceFeatures2KHR")); ensure(_vkGetPhysicalDeviceFeatures2KHR); // "vkGetInstanceProcAddress failed to find entry point!" _vkGetPhysicalDeviceFeatures2KHR(dev, &features2); @@ -92,6 +100,7 @@ namespace vk optional_features_support.barycentric_coords = !!shader_barycentric_info.fragmentShaderBarycentric; optional_features_support.framebuffer_loops = !!fbo_loops_info.attachmentFeedbackLoopLayout; + optional_features_support.extended_device_fault = !!device_fault_info.deviceFault; features = features2.features; @@ -754,6 +763,11 @@ namespace vk _vkCmdPipelineBarrier2KHR = reinterpret_cast(vkGetDeviceProcAddr(dev, "vkCmdPipelineBarrier2KHR")); } + if (pgpu->optional_features_support.extended_device_fault) + { + _vkGetDeviceFaultInfoEXT = reinterpret_cast(vkGetDeviceProcAddr(dev, "vkGetDeviceFaultInfoEXT")); + } + memory_map = vk::get_memory_mapping(pdev); m_formats_support = vk::get_optimal_tiling_supported_formats(pdev); m_pipeline_binding_table = vk::get_pipeline_binding_table(pdev); diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.h b/rpcs3/Emu/RSX/VK/vkutils/device.h index 3b0a10f44b..98f97e6e19 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.h +++ b/rpcs3/Emu/RSX/VK/vkutils/device.h @@ -91,6 +91,7 @@ namespace vk bool surface_capabilities_2 = false; bool synchronization_2 = false; bool unrestricted_depth_range = false; + bool extended_device_fault = false; } optional_features_support; friend class render_device; @@ -153,6 +154,7 @@ namespace vk PFN_vkCmdSetEvent2KHR _vkCmdSetEvent2KHR = nullptr; PFN_vkCmdWaitEvents2KHR _vkCmdWaitEvents2KHR = nullptr; PFN_vkCmdPipelineBarrier2KHR _vkCmdPipelineBarrier2KHR = nullptr; + PFN_vkGetDeviceFaultInfoEXT _vkGetDeviceFaultInfoEXT = nullptr; public: render_device() = default; @@ -187,6 +189,7 @@ namespace vk bool get_framebuffer_loops_support() const { return pgpu->optional_features_support.framebuffer_loops; } bool get_barycoords_support() const { return pgpu->optional_features_support.barycentric_coords; } bool get_synchronization2_support() const { return pgpu->optional_features_support.synchronization_2; } + bool get_extended_device_fault_support() const { return pgpu->optional_features_support.extended_device_fault; } u64 get_descriptor_update_after_bind_support() const { return pgpu->descriptor_indexing_support.update_after_bind_mask; } u32 get_descriptor_max_draw_calls() const { return pgpu->descriptor_max_draw_calls; } diff --git a/rpcs3/Emu/RSX/VK/vkutils/shared.cpp b/rpcs3/Emu/RSX/VK/vkutils/shared.cpp index 9f2d315305..205b3e8ac5 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/shared.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/shared.cpp @@ -1,3 +1,4 @@ +#include "device.h" #include "shared.h" #include "util/logs.hpp" @@ -9,9 +10,84 @@ namespace vk { extern void print_debug_markers(); - void die_with_error(VkResult error_code, std::string message, std::source_location src_loc) + std::string retrieve_device_fault_info() { - std::string error_message; + if (!g_render_device || !g_render_device->get_extended_device_fault_support()) + { + return {}; + } + + ensure(g_render_device->_vkGetDeviceFaultInfoEXT); + + std::string fault_message = "Device Fault Information:"; + VkDeviceFaultCountsEXT fault_counts{}; + g_render_device->_vkGetDeviceFaultInfoEXT(*g_render_device, &fault_counts, NULL); + + std::vector address_info(fault_counts.addressInfoCount, VkDeviceFaultAddressInfoEXT{}); + std::vector vendor_info(fault_counts.vendorInfoCount, VkDeviceFaultVendorInfoEXT{}); + VkDeviceFaultInfoEXT fault_info + { + .sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT, + .pAddressInfos = address_info.data(), + .pVendorInfos = vendor_info.data() + }; + + fault_counts.vendorInfoCount = 0; + g_render_device->_vkGetDeviceFaultInfoEXT(*g_render_device, &fault_counts, &fault_info); + + fault_message += fmt::format("Fault Summary:\n %s\n\n", fault_info.description); + + if (!address_info.empty()) + { + fault_message += fmt::format(" Address Fault Information:\n", fault_info.description); + + for (const auto& fault : address_info) + { + std::string access_type = "unknown"; + switch (fault.addressType) + { + case VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT: + access_type = "none"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT: + access_type = "read"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT: + access_type = "write"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT: + access_type = "execute"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT: + access_type = "instruction_pointer_unknown"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT: + access_type = "instruction_pointer_invalid"; break; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT: + access_type = "instruction_pointer_fault"; break; + default: + break; + } + + fault_message += fmt::format(" - Fault at address 0x%llx caused by %s\n", fault.reportedAddress, access_type); + } + } + + if (!vendor_info.empty()) + { + fault_message += fmt::format(" Vendor Fault Information:\n", fault_info.description); + + for (const auto& fault : vendor_info) + { + fault_message += fmt::format(" - [0x%llx, 0x%llx] %s\n", fault.vendorFaultCode, fault.vendorFaultData, fault.description); + } + } + + return fault_message; + } + + void die_with_error(VkResult error_code, std::string message, + const char* file, + const char* func, + u32 line, + u32 col) + { + std::string error_message, extra_info; int severity = 0; // 0 - die, 1 - warn, 2 - nothing switch (error_code) @@ -42,6 +118,7 @@ namespace vk break; case VK_ERROR_DEVICE_LOST: error_message = "Device lost (Driver crashed with unspecified error or stopped responding and recovered) (VK_ERROR_DEVICE_LOST)"; + extra_info = retrieve_device_fault_info(); break; case VK_ERROR_MEMORY_MAP_FAILED: error_message = "Memory map failed (VK_ERROR_MEMORY_MAP_FAILED)"; @@ -100,6 +177,11 @@ namespace vk break; } + if (!extra_info.empty()) + { + error_message = fmt::format("%s\n---------------- EXTRA INFORMATION --------------------\n%s", error_message, extra_info); + } + switch (severity) { default: