| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- using Ryujinx.Common.Configuration;
- using Ryujinx.Common.Logging;
- using Ryujinx.Common.Utilities;
- using Silk.NET.Vulkan;
- using Silk.NET.Vulkan.Extensions.EXT;
- using System;
- using System.Runtime.InteropServices;
- namespace Ryujinx.Graphics.Vulkan
- {
- class VulkanDebugMessenger : IDisposable
- {
- private static string[] _excludedMessages = new string[]
- {
- // NOTE: Done on purpose right now.
- "UNASSIGNED-CoreValidation-Shader-OutputNotConsumed",
- // TODO: Figure out if fixable
- "VUID-vkCmdDrawIndexed-None-04584",
- // TODO: Might be worth looking into making this happy to possibly optimize copies.
- "UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout",
- // TODO: Fix this, it's causing too much noise right now.
- "VUID-VkSubpassDependency-srcSubpass-00867"
- };
- private readonly Vk _api;
- private readonly Instance _instance;
- private readonly GraphicsDebugLevel _logLevel;
- private readonly ExtDebugUtils _debugUtils;
- private readonly DebugUtilsMessengerEXT? _debugUtilsMessenger;
- private bool _disposed;
- public VulkanDebugMessenger(Vk api, Instance instance, GraphicsDebugLevel logLevel)
- {
- _api = api;
- _instance = instance;
- _logLevel = logLevel;
- _api.TryGetInstanceExtension(instance, out _debugUtils);
- Result result = TryInitialize(out _debugUtilsMessenger);
- if (result != Result.Success)
- {
- Logger.Error?.Print(LogClass.Gpu, $"Vulkan debug messenger initialization failed with error {result}");
- }
- }
- private Result TryInitialize(out DebugUtilsMessengerEXT? debugUtilsMessengerHandle)
- {
- debugUtilsMessengerHandle = null;
-
- if (_debugUtils != null && _logLevel != GraphicsDebugLevel.None)
- {
- var messageType = _logLevel switch
- {
- GraphicsDebugLevel.Error => DebugUtilsMessageTypeFlagsEXT.ValidationBitExt,
- GraphicsDebugLevel.Slowdowns => DebugUtilsMessageTypeFlagsEXT.ValidationBitExt |
- DebugUtilsMessageTypeFlagsEXT.PerformanceBitExt,
- GraphicsDebugLevel.All => DebugUtilsMessageTypeFlagsEXT.GeneralBitExt |
- DebugUtilsMessageTypeFlagsEXT.ValidationBitExt |
- DebugUtilsMessageTypeFlagsEXT.PerformanceBitExt,
- _ => throw new ArgumentException($"Invalid log level \"{_logLevel}\".")
- };
- var messageSeverity = _logLevel switch
- {
- GraphicsDebugLevel.Error => DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt,
- GraphicsDebugLevel.Slowdowns => DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt |
- DebugUtilsMessageSeverityFlagsEXT.WarningBitExt,
- GraphicsDebugLevel.All => DebugUtilsMessageSeverityFlagsEXT.InfoBitExt |
- DebugUtilsMessageSeverityFlagsEXT.WarningBitExt |
- DebugUtilsMessageSeverityFlagsEXT.VerboseBitExt |
- DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt,
- _ => throw new ArgumentException($"Invalid log level \"{_logLevel}\".")
- };
- var debugUtilsMessengerCreateInfo = new DebugUtilsMessengerCreateInfoEXT()
- {
- SType = StructureType.DebugUtilsMessengerCreateInfoExt,
- MessageType = messageType,
- MessageSeverity = messageSeverity
- };
- unsafe
- {
- debugUtilsMessengerCreateInfo.PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(UserCallback);
- }
- DebugUtilsMessengerEXT messengerHandle = default;
- Result result = _debugUtils.CreateDebugUtilsMessenger(_instance, SpanHelpers.AsReadOnlySpan(ref debugUtilsMessengerCreateInfo), ReadOnlySpan<AllocationCallbacks>.Empty, SpanHelpers.AsSpan(ref messengerHandle));
- if (result == Result.Success)
- {
- debugUtilsMessengerHandle = messengerHandle;
- }
- return result;
- }
- return Result.Success;
- }
- private unsafe static uint UserCallback(
- DebugUtilsMessageSeverityFlagsEXT messageSeverity,
- DebugUtilsMessageTypeFlagsEXT messageTypes,
- DebugUtilsMessengerCallbackDataEXT* pCallbackData,
- void* pUserData)
- {
- var msg = Marshal.PtrToStringAnsi((IntPtr)pCallbackData->PMessage);
- foreach (string excludedMessagePart in _excludedMessages)
- {
- if (msg.Contains(excludedMessagePart))
- {
- return 0;
- }
- }
- if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt))
- {
- Logger.Error?.Print(LogClass.Gpu, msg);
- }
- else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.WarningBitExt))
- {
- Logger.Warning?.Print(LogClass.Gpu, msg);
- }
- else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.InfoBitExt))
- {
- Logger.Info?.Print(LogClass.Gpu, msg);
- }
- else // if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.VerboseBitExt))
- {
- Logger.Debug?.Print(LogClass.Gpu, msg);
- }
- return 0;
- }
- public void Dispose()
- {
- if (!_disposed)
- {
- if (_debugUtilsMessenger.HasValue)
- {
- _debugUtils.DestroyDebugUtilsMessenger(_instance, _debugUtilsMessenger.Value, Span<AllocationCallbacks>.Empty);
- }
- _disposed = true;
- }
- }
- }
- }
|