Vulkan: Replace VK_EXT_debug_report usage with VK_EXT_debug_utils (#3802)

* Vulkan: Replace `VK_EXT_debug_report` usage with `VK_EXT_debug_utils`

[VK_EXT_debug_report](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_debug_report.html)
has been depreciated for quite some time now in favor of the much more
featureful
[VK_EXT_debug_utils](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_debug_utils.html)
extension.

This PR converts our debug-report-callback into the newer
debug-messenger pattern.

`VK_EXT_debug_utils` adds some additional diagnostic tooling for marking
debug-label scopes for queue-operations, command-buffers, and assigning
name-labels to vulkan objects to aid in debugging(for a later PR).

* Vulkan: Fix `DebugMessenger` severity-flag classification

Extension bits between the two flags, for reference:

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDebugUtilsMessageSeverityFlagBitsEXT.html

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDebugReportFlagBitsEXT.html
This commit is contained in:
Wunk 2022-10-29 10:09:25 -07:00 committed by GitHub
parent 59cdf310bd
commit 3fe3598d41
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 49 deletions

View file

@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Vulkan
"VUID-VkSubpassDependency-srcSubpass-00867" "VUID-VkSubpassDependency-srcSubpass-00867"
}; };
internal static Instance CreateInstance(Vk api, GraphicsDebugLevel logLevel, string[] requiredExtensions, out ExtDebugReport debugReport, out DebugReportCallbackEXT debugReportCallback) internal static Instance CreateInstance(Vk api, GraphicsDebugLevel logLevel, string[] requiredExtensions, out ExtDebugUtils debugUtils, out DebugUtilsMessengerEXT debugUtilsMessenger)
{ {
var enabledLayers = new List<string>(); var enabledLayers = new List<string>();
@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.Vulkan
AddAvailableLayer("VK_LAYER_KHRONOS_validation"); AddAvailableLayer("VK_LAYER_KHRONOS_validation");
} }
var enabledExtensions = requiredExtensions.Append(ExtDebugReport.ExtensionName).ToArray(); var enabledExtensions = requiredExtensions.Append(ExtDebugUtils.ExtensionName).ToArray();
var appName = Marshal.StringToHGlobalAnsi(AppName); var appName = Marshal.StringToHGlobalAnsi(AppName);
@ -139,22 +139,18 @@ namespace Ryujinx.Graphics.Vulkan
Marshal.FreeHGlobal(ppEnabledLayers[i]); Marshal.FreeHGlobal(ppEnabledLayers[i]);
} }
CreateDebugCallbacks(api, logLevel, instance, out debugReport, out debugReportCallback); CreateDebugMessenger(api, logLevel, instance, out debugUtils, out debugUtilsMessenger);
return instance; return instance;
} }
private unsafe static uint DebugReport( private unsafe static uint DebugMessenger(
uint flags, DebugUtilsMessageSeverityFlagsEXT messageSeverity,
DebugReportObjectTypeEXT objectType, DebugUtilsMessageTypeFlagsEXT messageTypes,
ulong @object, DebugUtilsMessengerCallbackDataEXT* pCallbackData,
nuint location, void* pUserData)
int messageCode,
byte* layerPrefix,
byte* message,
void* userData)
{ {
var msg = Marshal.PtrToStringAnsi((IntPtr)message); var msg = Marshal.PtrToStringAnsi((IntPtr)pCallbackData->PMessage);
foreach (string excludedMessagePart in _excludedMessages) foreach (string excludedMessagePart in _excludedMessages)
{ {
@ -164,26 +160,20 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
DebugReportFlagsEXT debugFlags = (DebugReportFlagsEXT)flags; if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt))
if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportErrorBitExt))
{ {
Logger.Error?.Print(LogClass.Gpu, msg); Logger.Error?.Print(LogClass.Gpu, msg);
//throw new Exception(msg); //throw new Exception(msg);
} }
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportWarningBitExt)) else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt))
{ {
Logger.Warning?.Print(LogClass.Gpu, msg); Logger.Warning?.Print(LogClass.Gpu, msg);
} }
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportInformationBitExt)) else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt))
{ {
Logger.Info?.Print(LogClass.Gpu, msg); Logger.Info?.Print(LogClass.Gpu, msg);
} }
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt)) else // if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt))
{
Logger.Warning?.Print(LogClass.Gpu, msg);
}
else
{ {
Logger.Debug?.Print(LogClass.Gpu, msg); Logger.Debug?.Print(LogClass.Gpu, msg);
} }
@ -551,46 +541,59 @@ namespace Ryujinx.Graphics.Vulkan
return new CommandBufferPool(api, device, queue, queueLock, queueFamilyIndex); return new CommandBufferPool(api, device, queue, queueLock, queueFamilyIndex);
} }
internal unsafe static void CreateDebugCallbacks( internal unsafe static void CreateDebugMessenger(
Vk api, Vk api,
GraphicsDebugLevel logLevel, GraphicsDebugLevel logLevel,
Instance instance, Instance instance,
out ExtDebugReport debugReport, out ExtDebugUtils debugUtils,
out DebugReportCallbackEXT debugReportCallback) out DebugUtilsMessengerEXT debugUtilsMessenger)
{ {
debugReport = default; debugUtils = default;
if (logLevel != GraphicsDebugLevel.None) if (logLevel != GraphicsDebugLevel.None)
{ {
if (!api.TryGetInstanceExtension(instance, out debugReport)) if (!api.TryGetInstanceExtension(instance, out debugUtils))
{ {
debugReportCallback = default; debugUtilsMessenger = default;
return; return;
} }
var flags = logLevel switch var filterLogType = logLevel switch
{ {
GraphicsDebugLevel.Error => DebugReportFlagsEXT.DebugReportErrorBitExt, GraphicsDebugLevel.Error => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt,
GraphicsDebugLevel.Slowdowns => DebugReportFlagsEXT.DebugReportErrorBitExt | DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt, GraphicsDebugLevel.Slowdowns => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt |
GraphicsDebugLevel.All => DebugReportFlagsEXT.DebugReportInformationBitExt | DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt,
DebugReportFlagsEXT.DebugReportWarningBitExt | GraphicsDebugLevel.All => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt |
DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt | DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt |
DebugReportFlagsEXT.DebugReportErrorBitExt | DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt,
DebugReportFlagsEXT.DebugReportDebugBitExt,
_ => throw new ArgumentException($"Invalid log level \"{logLevel}\".") _ => throw new ArgumentException($"Invalid log level \"{logLevel}\".")
}; };
var debugReportCallbackCreateInfo = new DebugReportCallbackCreateInfoEXT()
var filterLogSeverity = logLevel switch
{ {
SType = StructureType.DebugReportCallbackCreateInfoExt, GraphicsDebugLevel.Error => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt,
Flags = flags, GraphicsDebugLevel.Slowdowns => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt |
PfnCallback = new PfnDebugReportCallbackEXT(DebugReport) DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt,
GraphicsDebugLevel.All => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt |
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt |
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt |
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt,
_ => throw new ArgumentException($"Invalid log level \"{logLevel}\".")
}; };
debugReport.CreateDebugReportCallback(instance, in debugReportCallbackCreateInfo, null, out debugReportCallback).ThrowOnError(); var debugUtilsMessengerCreateInfo = new DebugUtilsMessengerCreateInfoEXT()
{
SType = StructureType.DebugUtilsMessengerCreateInfoExt,
MessageType = filterLogType,
MessageSeverity = filterLogSeverity,
PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(DebugMessenger)
};
debugUtils.CreateDebugUtilsMessenger(instance, in debugUtilsMessengerCreateInfo, null, out debugUtilsMessenger).ThrowOnError();
} }
else else
{ {
debugReportCallback = default; debugUtilsMessenger = default;
} }
} }
} }

View file

@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Vulkan
internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal KhrPushDescriptor PushDescriptorApi { get; private set; }
internal ExtTransformFeedback TransformFeedbackApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; } internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
internal ExtDebugReport DebugReportApi { get; private set; } internal ExtDebugUtils DebugUtilsApi { get; private set; }
internal uint QueueFamilyIndex { get; private set; } internal uint QueueFamilyIndex { get; private set; }
internal Queue Queue { get; private set; } internal Queue Queue { get; private set; }
@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.Vulkan
private SyncManager _syncManager; private SyncManager _syncManager;
private PipelineFull _pipeline; private PipelineFull _pipeline;
private DebugReportCallbackEXT _debugReportCallback; private DebugUtilsMessengerEXT _debugUtilsMessenger;
internal HelperShader HelperShader { get; private set; } internal HelperShader HelperShader { get; private set; }
internal PipelineFull PipelineInternal => _pipeline; internal PipelineFull PipelineInternal => _pipeline;
@ -237,9 +237,9 @@ namespace Ryujinx.Graphics.Vulkan
Api = api; Api = api;
_instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions(), out ExtDebugReport debugReport, out _debugReportCallback); _instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions(), out ExtDebugUtils debugUtils, out _debugUtilsMessenger);
DebugReportApi = debugReport; DebugUtilsApi = debugUtils;
if (api.TryGetInstanceExtension(_instance, out KhrSurface surfaceApi)) if (api.TryGetInstanceExtension(_instance, out KhrSurface surfaceApi))
{ {
@ -584,9 +584,9 @@ namespace Ryujinx.Graphics.Vulkan
MemoryAllocator.Dispose(); MemoryAllocator.Dispose();
if (_debugReportCallback.Handle != 0) if (_debugUtilsMessenger.Handle != 0)
{ {
DebugReportApi.DestroyDebugReportCallback(_instance, _debugReportCallback, null); DebugUtilsApi.DestroyDebugUtilsMessenger(_instance, _debugUtilsMessenger, null);
} }
foreach (var shader in Shaders) foreach (var shader in Shaders)