renderer_vulkan: Add suport for VK_EXT_debug_report
* Used in older android devices
This commit is contained in:
@ -119,7 +119,7 @@ void Config::ReadValues() {
|
|||||||
Settings::values.async_command_recording =
|
Settings::values.async_command_recording =
|
||||||
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
|
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
|
||||||
Settings::values.async_shader_compilation =
|
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 =
|
Settings::values.spirv_shader_gen =
|
||||||
sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
||||||
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
|
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
|
||||||
|
@ -15,9 +15,9 @@ namespace Vulkan {
|
|||||||
|
|
||||||
vk::DynamicLoader Instance::dl;
|
vk::DynamicLoader Instance::dl;
|
||||||
|
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL
|
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(
|
||||||
DebugHandler(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type,
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) {
|
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) {
|
||||||
|
|
||||||
switch (callback_data->messageIdNumber) {
|
switch (callback_data->messageIdNumber) {
|
||||||
case 0x609a13b: // Vertex attribute at location not consumed by shader
|
case 0x609a13b: // Vertex attribute at location not consumed by shader
|
||||||
@ -49,6 +49,39 @@ DebugHandler(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessag
|
|||||||
return VK_FALSE;
|
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<VkDebugReportFlagBitsEXT>(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<vk::DebugReportObjectTypeEXT>(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) {
|
vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case VideoCore::PixelFormat::RGBA8:
|
case VideoCore::PixelFormat::RGBA8:
|
||||||
@ -86,7 +119,17 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
|||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
|
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(),
|
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<vk::DebugUtilsMessengerCreateInfoEXT>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
instance = vk::createInstance(instance_chain.get());
|
instance = vk::createInstance(instance_chain.get());
|
||||||
} catch (vk::LayerNotPresentError& err) {
|
} 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 validation is enabled attempt to also enable debug messenger
|
||||||
if (enable_validation) {
|
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) {
|
if (debug_messenger_supported) {
|
||||||
debug_messenger = instance.createDebugUtilsMessengerEXT(MakeDebugUtilsMessengerInfo());
|
debug_messenger = instance.createDebugUtilsMessengerEXT(MakeDebugUtilsMessengerInfo());
|
||||||
} else {
|
} else if (debug_report_supported) {
|
||||||
instance_chain.unlink<vk::DebugUtilsMessengerCreateInfoEXT>();
|
callback = instance.createDebugReportCallbackEXT(MakeDebugReportCallbackInfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +317,9 @@ Instance::~Instance() {
|
|||||||
if (debug_messenger) {
|
if (debug_messenger) {
|
||||||
instance.destroyDebugUtilsMessengerEXT(debug_messenger);
|
instance.destroyDebugUtilsMessengerEXT(debug_messenger);
|
||||||
}
|
}
|
||||||
|
if (callback) {
|
||||||
|
instance.destroyDebugReportCallbackEXT(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
|
@ -240,6 +240,7 @@ private:
|
|||||||
vk::PhysicalDeviceLimits limits;
|
vk::PhysicalDeviceLimits limits;
|
||||||
vk::DriverIdKHR driver_id;
|
vk::DriverIdKHR driver_id;
|
||||||
vk::DebugUtilsMessengerEXT debug_messenger;
|
vk::DebugUtilsMessengerEXT debug_messenger;
|
||||||
|
vk::DebugReportCallbackEXT callback;
|
||||||
std::string vendor_name;
|
std::string vendor_name;
|
||||||
VmaAllocator allocator;
|
VmaAllocator allocator;
|
||||||
vk::Queue present_queue;
|
vk::Queue present_queue;
|
||||||
|
@ -141,6 +141,7 @@ std::vector<const char*> GetInstanceExtensions(Frontend::WindowSystemType window
|
|||||||
|
|
||||||
if (enable_debug_utils) {
|
if (enable_debug_utils) {
|
||||||
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
|
extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize extension list
|
// Sanitize extension list
|
||||||
@ -151,8 +152,7 @@ std::vector<const char*> GetInstanceExtensions(Frontend::WindowSystemType window
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (it == properties.end()) {
|
if (it == properties.end()) {
|
||||||
LOG_WARNING(Render_Vulkan, "Required instance extension {} is not available",
|
LOG_INFO(Render_Vulkan, "Candidate instance extension {} is not available", extension);
|
||||||
extension);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -461,6 +461,7 @@ void RasterizerVulkan::DrawTriangles() {
|
|||||||
|
|
||||||
MICROPROFILE_DEFINE(Vulkan_Drawing, "Vulkan", "Drawing", MP_RGB(128, 128, 192));
|
MICROPROFILE_DEFINE(Vulkan_Drawing, "Vulkan", "Drawing", MP_RGB(128, 128, 192));
|
||||||
bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||||
|
MICROPROFILE_SCOPE(Vulkan_Drawing);
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
|
|
||||||
const bool shadow_rendering = regs.framebuffer.IsShadowRendering();
|
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
|
// 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
|
// 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
|
// 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
|
// In that case select the minimum one to abide by the spec
|
||||||
u32 width = 0;
|
u32 width = 0;
|
||||||
@ -742,6 +717,30 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
|
|
||||||
renderpass_cache.EnterRenderpass(renderpass_info);
|
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
|
// Draw the vertex batch
|
||||||
bool succeeded = true;
|
bool succeeded = true;
|
||||||
if (accelerate) {
|
if (accelerate) {
|
||||||
|
Reference in New Issue
Block a user