From ab73566acc56e5cc25a530571db8b5b9092da1b8 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Thu, 19 Jan 2023 23:19:55 +0200 Subject: [PATCH] renderer_vulkan: Add suport for VK_EXT_debug_report * Used in older android devices --- src/android/app/src/main/jni/config.cpp | 2 +- .../renderer_vulkan/vk_instance.cpp | 82 ++++++++++++++++--- src/video_core/renderer_vulkan/vk_instance.h | 1 + .../renderer_vulkan/vk_platform.cpp | 4 +- .../renderer_vulkan/vk_rasterizer.cpp | 51 ++++++------ 5 files changed, 99 insertions(+), 41 deletions(-) diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index e58be9ec0..e39ff4f90 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -119,7 +119,7 @@ void Config::ReadValues() { Settings::values.async_command_recording = sdl2_config->GetBoolean("Renderer", "async_command_recording", true); Settings::values.async_shader_compilation = - sdl2_config->GetBoolean("Renderer", "async_shader_compilation", true); + sdl2_config->GetBoolean("Renderer", "async_shader_compilation", false); Settings::values.spirv_shader_gen = sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true); Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 89e021968..4a210e1a0 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -15,9 +15,9 @@ namespace Vulkan { vk::DynamicLoader Instance::dl; -static VKAPI_ATTR VkBool32 VKAPI_CALL -DebugHandler(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { +static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { switch (callback_data->messageIdNumber) { case 0x609a13b: // Vertex attribute at location not consumed by shader @@ -49,6 +49,39 @@ DebugHandler(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessag return VK_FALSE; } +static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, void* pUserData) { + + const VkDebugReportFlagBitsEXT severity = static_cast(flags); + Log::Level level{}; + switch (severity) { + case VK_DEBUG_REPORT_ERROR_BIT_EXT: + level = Log::Level::Error; + break; + case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: + level = Log::Level::Warning; + break; + case VK_DEBUG_REPORT_DEBUG_BIT_EXT: + case VK_DEBUG_REPORT_WARNING_BIT_EXT: + case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT: + level = Log::Level::Debug; + break; + default: + level = Log::Level::Info; + } + + const vk::DebugReportObjectTypeEXT type = static_cast(objectType); + LOG_GENERIC(Log::Class::Render_Vulkan, level, + "type = {}, object = {} | MessageCode = {:#x}, LayerPrefix = {} | {}", + vk::to_string(type), object, messageCode, pLayerPrefix, pMessage); + + return VK_FALSE; +} + vk::Format ToVkFormat(VideoCore::PixelFormat format) { switch (format) { case VideoCore::PixelFormat::RGBA8: @@ -86,7 +119,17 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) { vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, - .pfnUserCallback = DebugHandler, + .pfnUserCallback = DebugUtilsCallback, + }; +} + +[[nodiscard]] vk::DebugReportCallbackCreateInfoEXT MakeDebugReportCallbackInfo() { + return vk::DebugReportCallbackCreateInfoEXT{ + .flags = vk::DebugReportFlagBitsEXT::eDebug | vk::DebugReportFlagBitsEXT::eInformation | + vk::DebugReportFlagBitsEXT::eError | + vk::DebugReportFlagBitsEXT::ePerformanceWarning | + vk::DebugReportFlagBitsEXT::eWarning, + .pfnCallback = DebugReportCallback, }; } @@ -207,6 +250,24 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index) MakeDebugUtilsMessengerInfo(), }; + const auto IsSupported = [&extensions](std::string_view requested) { + const auto it = + std::find_if(extensions.begin(), extensions.end(), + [requested](const char* extension) { return requested == extension; }); + + return it != extensions.end(); + }; + + bool debug_messenger_supported{}; + bool debug_report_supported{}; + if (enable_validation) { + debug_messenger_supported = IsSupported(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + debug_report_supported = IsSupported(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + if (!debug_messenger_supported) { + instance_chain.unlink(); + } + } + try { instance = vk::createInstance(instance_chain.get()); } catch (vk::LayerNotPresentError& err) { @@ -219,16 +280,10 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index) // If validation is enabled attempt to also enable debug messenger if (enable_validation) { - const auto it = - std::find_if(extensions.begin(), extensions.end(), [](const char* extension) { - return std::strcmp(extension, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; - }); - - const bool debug_messenger_supported = it != extensions.end(); if (debug_messenger_supported) { debug_messenger = instance.createDebugUtilsMessengerEXT(MakeDebugUtilsMessengerInfo()); - } else { - instance_chain.unlink(); + } else if (debug_report_supported) { + callback = instance.createDebugReportCallbackEXT(MakeDebugReportCallbackInfo()); } } @@ -262,6 +317,9 @@ Instance::~Instance() { if (debug_messenger) { instance.destroyDebugUtilsMessengerEXT(debug_messenger); } + if (callback) { + instance.destroyDebugReportCallbackEXT(callback); + } } instance.destroy(); diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index a590aea2f..0ed17f332 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -240,6 +240,7 @@ private: vk::PhysicalDeviceLimits limits; vk::DriverIdKHR driver_id; vk::DebugUtilsMessengerEXT debug_messenger; + vk::DebugReportCallbackEXT callback; std::string vendor_name; VmaAllocator allocator; vk::Queue present_queue; diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index 88a2eb28b..14cb62841 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -141,6 +141,7 @@ std::vector GetInstanceExtensions(Frontend::WindowSystemType window if (enable_debug_utils) { extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } // Sanitize extension list @@ -151,8 +152,7 @@ std::vector GetInstanceExtensions(Frontend::WindowSystemType window }); if (it == properties.end()) { - LOG_WARNING(Render_Vulkan, "Required instance extension {} is not available", - extension); + LOG_INFO(Render_Vulkan, "Candidate instance extension {} is not available", extension); return true; } return false; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 143f6403a..9f6bde5e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -461,6 +461,7 @@ void RasterizerVulkan::DrawTriangles() { MICROPROFILE_DEFINE(Vulkan_Drawing, "Vulkan", "Drawing", MP_RGB(128, 128, 192)); bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) { + MICROPROFILE_SCOPE(Vulkan_Drawing); const auto& regs = Pica::g_state.regs; const bool shadow_rendering = regs.framebuffer.IsShadowRendering(); @@ -674,32 +675,6 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) { // NOTE: From here onwards its a safe zone to set the draw state, doing that any earlier will // cause issues as the rasterizer cache might cause a scheduler switch and invalidate our state - // Sync the viewport - pipeline_cache.SetViewport(surfaces_rect.left + viewport_rect_unscaled.left * res_scale, - surfaces_rect.bottom + viewport_rect_unscaled.bottom * res_scale, - viewport_rect_unscaled.GetWidth() * res_scale, - viewport_rect_unscaled.GetHeight() * res_scale); - - MICROPROFILE_SCOPE(Vulkan_Drawing); - - // Sync and bind the shader - if (shader_dirty) { - pipeline_cache.UseFragmentShader(regs); - shader_dirty = false; - } - - // Sync the LUTs within the texture buffer - SyncAndUploadLUTs(); - SyncAndUploadLUTsLF(); - - // Sync the uniform data - UploadUniforms(accelerate); - - // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. - // Enable scissor test to prevent drawing outside of the framebuffer region - pipeline_cache.SetScissor(draw_rect.left, draw_rect.bottom, draw_rect.GetWidth(), - draw_rect.GetHeight()); - // Sometimes the dimentions of the color and depth framebuffers might not be the same // In that case select the minimum one to abide by the spec u32 width = 0; @@ -742,6 +717,30 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) { renderpass_cache.EnterRenderpass(renderpass_info); + // Sync and bind the shader + if (shader_dirty) { + pipeline_cache.UseFragmentShader(regs); + shader_dirty = false; + } + + // Sync the LUTs within the texture buffer + SyncAndUploadLUTs(); + SyncAndUploadLUTsLF(); + + // Sync the uniform data + UploadUniforms(accelerate); + + // Sync the viewport + pipeline_cache.SetViewport(surfaces_rect.left + viewport_rect_unscaled.left * res_scale, + surfaces_rect.bottom + viewport_rect_unscaled.bottom * res_scale, + viewport_rect_unscaled.GetWidth() * res_scale, + viewport_rect_unscaled.GetHeight() * res_scale); + + // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. + // Enable scissor test to prevent drawing outside of the framebuffer region + pipeline_cache.SetScissor(draw_rect.left, draw_rect.bottom, draw_rect.GetWidth(), + draw_rect.GetHeight()); + // Draw the vertex batch bool succeeded = true; if (accelerate) {