From d7e22a8ada669910882ae34e0b57da6712629e72 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 03:13:37 -0700 Subject: Implement non-ID based debug message filtering --- alc/alc.cpp | 21 ++++++++ alc/context.cpp | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- alc/context.h | 9 ++++ alc/inprogext.h | 3 ++ 4 files changed, 179 insertions(+), 1 deletion(-) diff --git a/alc/alc.cpp b/alc/alc.cpp index 33531afb..b6dc111d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -461,6 +461,8 @@ const struct { DECL(alBufferDataStatic), DECL(alDebugMessageCallbackSOFT), + DECL(alDebugMessageInsertSOFT), + DECL(alDebugMessageControlSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -917,7 +919,26 @@ constexpr struct { DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + DECL(AL_DONT_CARE_SOFT), DECL(AL_DEBUG_OUTPUT_SOFT), + DECL(AL_DEBUG_CALLBACK_FUNCTION_SOFT), + DECL(AL_DEBUG_CALLBACK_USER_PARAM_SOFT), + DECL(AL_DEBUG_SOURCE_API_SOFT), + DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT), + DECL(AL_DEBUG_SOURCE_THIRD_PARTY_SOFT), + DECL(AL_DEBUG_SOURCE_APPLICATION_SOFT), + DECL(AL_DEBUG_SOURCE_OTHER_SOFT), + DECL(AL_DEBUG_TYPE_ERROR_SOFT), + DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), + DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), + DECL(AL_DEBUG_TYPE_MARKER_SOFT), + DECL(AL_DEBUG_TYPE_OTHER_SOFT), + DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), + DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), + DECL(AL_DEBUG_SEVERITY_LOW_SOFT), + DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index e2a2e2d2..3f7b456d 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -4,11 +4,13 @@ #include "context.h" #include +#include #include #include #include #include #include +#include #include "AL/efx.h" @@ -19,6 +21,7 @@ #include "al/listener.h" #include "albit.h" #include "alc/alu.h" +#include "alspan.h" #include "core/async_event.h" #include "core/device.h" #include "core/effectslot.h" @@ -27,6 +30,7 @@ #include "core/voice_change.h" #include "device.h" #include "ringbuffer.h" +#include "threads.h" #include "vecmat.h" #ifdef ALSOFT_EAX @@ -295,11 +299,45 @@ void ALCcontext::applyAllUpdates() mHoldUpdates.store(false, std::memory_order_release); } + void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { + static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + std::lock_guard _{mDebugCbLock}; - if(!mDebugEnabled.load()) + if(!mDebugEnabled.load()) UNLIKELY + return; + + uint filter{0}; + switch(source) + { + case DebugSource::API: filter |= 1<<(DebugSourceBase+0); break; + case DebugSource::System: filter |= 1<<(DebugSourceBase+1); break; + case DebugSource::ThirdParty: filter |= 1<<(DebugSourceBase+2); break; + case DebugSource::Application: filter |= 1<<(DebugSourceBase+3); break; + case DebugSource::Other: filter |= 1<<(DebugSourceBase+4); break; + } + switch(type) + { + case DebugType::Error: filter |= 1<<(DebugTypeBase+0); break; + case DebugType::DeprecatedBehavior: filter |= 1<<(DebugTypeBase+1); break; + case DebugType::UndefinedBehavior: filter |= 1<<(DebugTypeBase+2); break; + case DebugType::Portability: filter |= 1<<(DebugTypeBase+3); break; + case DebugType::Performance: filter |= 1<<(DebugTypeBase+4); break; + case DebugType::Marker: filter |= 1<<(DebugTypeBase+5); break; + case DebugType::Other: filter |= 1<<(DebugTypeBase+6); break; + } + switch(severity) + { + case DebugSeverity::High: filter |= 1<<(DebugSeverityBase+0); break; + case DebugSeverity::Medium: filter |= 1<<(DebugSeverityBase+1); break; + case DebugSeverity::Low: filter |= 1<<(DebugSeverityBase+2); break; + case DebugSeverity::Notification: filter |= 1<<(DebugSeverityBase+3); break; + } + + auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); + if(iter != mDebugFilters.cend() && *iter == filter) return; if(mDebugCb) @@ -371,6 +409,113 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type context->debugMessage(dsource, dtype, id, dseverity, length, message); } + +namespace { + +template +constexpr auto make_array(std::integer_sequence) +{ return std::array{Vals...}; } + +template> +constexpr auto make_array() +{ return make_array(Indices{}); } + +} // namespace + +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, + ALsizei count, const ALuint *ids, ALboolean enable) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(count > 0) + { + if(!ids) + return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); + if(source == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); + if(type == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); + if(severity != AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug severity must be AL_DONT_CARE_SOFT with IDs"); + + return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); + return; + } + + if(enable != AL_TRUE && enable != AL_FALSE) + return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); + + static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; + static constexpr auto Values = make_array(); + + al::span srcIndices{al::as_span(Values).subspan()}; + switch(source) + { + case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; + case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); + } + + al::span typeIndices{al::as_span(Values).subspan()}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; + case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; + case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); + } + + al::span svrIndices{al::as_span(Values).subspan()}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; + case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); + } + + std::lock_guard _{context->mDebugCbLock}; + auto apply_filter = [enable,&context](const uint filter) + { + auto iter = std::lower_bound(context->mDebugFilters.cbegin(), + context->mDebugFilters.cend(), filter); + if(enable && (iter == context->mDebugFilters.cend() || *iter != filter)) + context->mDebugFilters.insert(iter, filter); + else if(!enable && iter != context->mDebugFilters.cend() && *iter == filter) + context->mDebugFilters.erase(iter); + }; + auto apply_severity = [apply_filter,svrIndices](const uint filter) + { + std::for_each(svrIndices.cbegin(), svrIndices.cend(), + [apply_filter,filter](const uint idx){ apply_filter(filter | (1<, ContextBase { std::mutex mDebugCbLock; ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; + std::vector mDebugFilters; ALlistener mListener{}; diff --git a/alc/inprogext.h b/alc/inprogext.h index 53dc9f0c..a4e2c353 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -56,6 +56,7 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #ifndef AL_SOFT_debug #define AL_SOFT_debug +#define AL_DONT_CARE_SOFT 0x0002 #define AL_DEBUG_OUTPUT_SOFT 0x19B2 #define AL_DEBUG_CALLBACK_FUNCTION_SOFT 0x19B3 #define AL_DEBUG_CALLBACK_USER_PARAM_SOFT 0x19B4 @@ -79,9 +80,11 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; #endif #endif -- cgit v1.2.3