From 755429798a1dbe658d2a4d342927c9b9272629ee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 03:24:20 -0700 Subject: Move debug functions to their own source --- al/debug.h | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 al/debug.h (limited to 'al/debug.h') diff --git a/al/debug.h b/al/debug.h new file mode 100644 index 00000000..a268f690 --- /dev/null +++ b/al/debug.h @@ -0,0 +1,4 @@ +#ifndef AL_DEBUG_H +#define AL_DEBUG_H + +#endif /* AL_DEBUG_H */ -- cgit v1.2.3 From 22077687cf4b9fdfd29d78debc2daf044deee81d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 17:46:18 -0700 Subject: Implement debug log storage --- al/debug.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ al/debug.h | 9 ++++++ al/state.cpp | 61 ++++++++++++++++++++++++++++++++++++- alc/alc.cpp | 5 ++++ alc/context.cpp | 29 +++++++++++++++++- alc/context.h | 19 ++++++++++++ alc/inprogext.h | 6 ++++ 7 files changed, 220 insertions(+), 2 deletions(-) (limited to 'al/debug.h') diff --git a/al/debug.cpp b/al/debug.cpp index 2694d7b4..ab81f5a8 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -71,6 +71,46 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept } // namespace +ALenum GetDebugSourceEnum(DebugSource source) +{ + switch(source) + { + case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; + case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; + case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; + case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; + case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; + } + throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; +} + +ALenum GetDebugTypeEnum(DebugType type) +{ + switch(type) + { + case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; + case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; + case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; + case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; + case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; + case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; + case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; + } + throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; +} + +ALenum GetDebugSeverityEnum(DebugSeverity severity) +{ + switch(severity) + { + case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; + case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; + case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; + case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; + } + throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; +} + FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept { @@ -91,6 +131,18 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen > MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu > %d)", newlen, + MaxDebugMessageLength); + length = static_cast(newlen); + } + else if(length > MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, + MaxDebugMessageLength); + auto dsource = GetDebugSource(source); if(!dsource) return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); @@ -189,3 +241,44 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ std::for_each(srcIndices.cbegin(), srcIndices.cend(), [apply_type](const uint idx){ apply_type(1<setError(AL_INVALID_VALUE, "Negative debug log buffer size"); + return 0; + } + + std::lock_guard _{context->mDebugCbLock}; + ALsizei logBufWritten{0}; + for(ALuint i{0};i < count;++i) + { + if(context->mDebugLog.empty()) + return i; + + auto &entry = context->mDebugLog.front(); + const size_t tocopy{entry.mMessage.size() + 1}; + const size_t avail{static_cast(logBufSize - logBufWritten)}; + if(avail < tocopy) + return i; + + if(sources) sources[i] = GetDebugSourceEnum(entry.mSource); + if(types) types[i] = GetDebugTypeEnum(entry.mType); + if(ids) ids[i] = entry.mId; + if(severities) severities[i] = GetDebugSeverityEnum(entry.mSeverity); + if(lengths) lengths[i] = static_cast(tocopy); + if(logBuf) std::copy_n(entry.mMessage.data(), tocopy, logBuf+logBufWritten); + + logBufWritten += static_cast(tocopy); + context->mDebugLog.pop_front(); + } + + return count; +} diff --git a/al/debug.h b/al/debug.h index a268f690..23b0ca1b 100644 --- a/al/debug.h +++ b/al/debug.h @@ -1,4 +1,13 @@ #ifndef AL_DEBUG_H #define AL_DEBUG_H +#include + + +/* Somewhat arbitrary. Avoid letting it get out of control if the app enables + * logging but never reads it. + */ +constexpr uint8_t MaxDebugLoggedMessages{64}; +constexpr uint16_t MaxDebugMessageLength{1024}; + #endif /* AL_DEBUG_H */ diff --git a/al/state.cpp b/al/state.cpp index 7b7377f7..1e1a0085 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -33,6 +33,7 @@ #include "AL/alc.h" #include "AL/alext.h" +#include "al/debug.h" #include "alc/alu.h" #include "alc/context.h" #include "alc/inprogext.h" @@ -259,6 +260,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname) != 0; } @@ -299,6 +304,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname); } @@ -325,8 +334,11 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return static_cast(alGetInteger(pname)); - break; case AL_DEFERRED_UPDATES_SOFT: return alGetBoolean(pname) ? 1.0f : 0.0f; @@ -401,6 +413,29 @@ START_API_FUNC value = al::to_underlying(ResamplerDefault); break; + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + { + std::lock_guard __{context->mDebugCbLock}; + value = static_cast(context->mDebugLog.size()); + break; + } + + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + { + std::lock_guard __{context->mDebugCbLock}; + value = context->mDebugLog.empty() ? 0 + : static_cast(context->mDebugLog.front().mMessage.size()+1); + break; + } + + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + value = MaxDebugMessageLength; + break; + + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + value = MaxDebugLoggedMessages; + break; + #ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." @@ -452,6 +487,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname); } @@ -519,6 +558,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetBoolean(pname); return; } @@ -552,6 +595,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetDouble(pname); return; } @@ -585,6 +632,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetFloat(pname); return; } @@ -618,6 +669,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetInteger(pname); return; } @@ -651,6 +706,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetInteger64SOFT(pname); return; } diff --git a/alc/alc.cpp b/alc/alc.cpp index b6dc111d..504737ec 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -463,6 +463,7 @@ const struct { DECL(alDebugMessageCallbackSOFT), DECL(alDebugMessageInsertSOFT), DECL(alDebugMessageControlSOFT), + DECL(alGetDebugMessageLogSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -939,6 +940,10 @@ constexpr struct { DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), DECL(AL_DEBUG_SEVERITY_LOW_SOFT), DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), + DECL(AL_DEBUG_LOGGED_MESSAGES_SOFT), + DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT), + DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT), + DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index 4e5a3ab6..a07e5412 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -15,6 +15,7 @@ #include "AL/efx.h" #include "al/auxeffectslot.h" +#include "al/debug.h" #include "al/source.h" #include "al/effect.h" #include "al/event.h" @@ -342,6 +343,22 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%zu > %d)\n", newlen, MaxDebugMessageLength); + return; + } + length = static_cast(newlen); + } + else if(length > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength); + return; + } + std::unique_lock debuglock{mDebugCbLock}; if(!mDebugEnabled.load()) UNLIKELY return; @@ -364,7 +381,17 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } else { - /* TODO: Store in a log. */ + if(mDebugLog.size() < MaxDebugLoggedMessages) + mDebugLog.emplace_back(source, type, id, severity, message); + else UNLIKELY + ERR("Debug message log overflow. Lost message:\n" + " Source: 0x%04x\n" + " Type: 0x%04x\n" + " ID: %u\n" + " Severity: 0x%04x\n" + " Message: \"%s\"\n", + get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), + message); } } diff --git a/alc/context.h b/alc/context.h index b5ee440b..031e061e 100644 --- a/alc/context.h +++ b/alc/context.h @@ -2,6 +2,7 @@ #define ALC_CONTEXT_H #include +#include #include #include #include @@ -66,6 +67,23 @@ enum class DebugSeverity : uint8_t { }; constexpr uint DebugSeverityCount{4}; +struct LogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + LogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + LogEntry(const LogEntry&) = default; + LogEntry(LogEntry&&) = default; +}; + struct SourceSubList { uint64_t FreeMask{~0_u64}; @@ -127,6 +145,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; std::vector mDebugFilters; + std::deque mDebugLog; ALlistener mListener{}; diff --git a/alc/inprogext.h b/alc/inprogext.h index a4e2c353..f73963cb 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -76,15 +76,21 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C2 #define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C3 #define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C4 +#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C5 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C6 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C7 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19C8 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); +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGSOFT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #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; +ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From bb08a416f1b0e31292b896f2f8845e365daee6b1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 17:11:49 -0700 Subject: Put the debug filters into a group --- al/debug.cpp | 26 +++++++++++----------- al/debug.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ al/error.cpp | 1 + alc/alc.cpp | 1 + alc/context.cpp | 10 +++++---- alc/context.h | 60 +++++++------------------------------------------ 6 files changed, 98 insertions(+), 69 deletions(-) (limited to 'al/debug.h') diff --git a/al/debug.cpp b/al/debug.cpp index 70c7c4db..fc893490 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -222,6 +222,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } std::lock_guard _{context->mDebugCbLock}; + DebugGroup &debug = context->mDebugGroups.back(); if(count > 0) { const uint filterbase{(1u<mDebugIdFilters.cbegin(), - context->mDebugIdFilters.cend(), filter); - if(!enable && (iter == context->mDebugIdFilters.cend() || *iter != filter)) - context->mDebugIdFilters.insert(iter, filter); - else if(enable && iter != context->mDebugIdFilters.cend() && *iter == filter) - context->mDebugIdFilters.erase(iter); + auto iter = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), + filter); + if(!enable && (iter == debug.mIdFilters.cend() || *iter != filter)) + debug.mIdFilters.insert(iter, filter); + else if(enable && iter != debug.mIdFilters.cend() && *iter == filter) + debug.mIdFilters.erase(iter); } } else { - auto apply_filter = [enable,&context](const uint filter) + auto apply_filter = [enable,&debug](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 iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(!enable && (iter == debug.mFilters.cend() || *iter != filter)) + debug.mFilters.insert(iter, filter); + else if(enable && iter != debug.mFilters.cend() && *iter == filter) + debug.mFilters.erase(iter); }; auto apply_severity = [apply_filter,svrIndices](const uint filter) { diff --git a/al/debug.h b/al/debug.h index 23b0ca1b..c2147cf4 100644 --- a/al/debug.h +++ b/al/debug.h @@ -2,6 +2,10 @@ #define AL_DEBUG_H #include +#include +#include + +using uint = unsigned int; /* Somewhat arbitrary. Avoid letting it get out of control if the app enables @@ -10,4 +14,69 @@ constexpr uint8_t MaxDebugLoggedMessages{64}; constexpr uint16_t MaxDebugMessageLength{1024}; + +constexpr uint DebugSourceBase{0}; +enum class DebugSource : uint8_t { + API = 0, + System, + ThirdParty, + Application, + Other, +}; +constexpr uint DebugSourceCount{5}; + +constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; +enum class DebugType : uint8_t { + Error = 0, + DeprecatedBehavior, + UndefinedBehavior, + Portability, + Performance, + Marker, + Other, +}; +constexpr uint DebugTypeCount{7}; + +constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; +enum class DebugSeverity : uint8_t { + High = 0, + Medium, + Low, + Notification, +}; +constexpr uint DebugSeverityCount{4}; + +struct DebugGroup { + const uint mId; + const DebugSource mSource; + std::string mMessage; + std::vector mFilters; + std::vector mIdFilters; + + template + DebugGroup(DebugSource source, uint id, T&& message) + : mId{id}, mSource{source}, mMessage{std::forward(message)} + { } + DebugGroup(const DebugGroup&) = default; + DebugGroup(DebugGroup&&) = default; +}; + + +struct DebugLogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + DebugLogEntry(const DebugLogEntry&) = default; + DebugLogEntry(DebugLogEntry&&) = default; +}; + #endif /* AL_DEBUG_H */ diff --git a/al/error.cpp b/al/error.cpp index 70081a2e..39fd9f0a 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -35,6 +35,7 @@ #include "AL/al.h" #include "AL/alc.h" +#include "al/debug.h" #include "alc/context.h" #include "almalloc.h" #include "core/except.h" diff --git a/alc/alc.cpp b/alc/alc.cpp index 63654b1a..aa65222c 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -61,6 +61,7 @@ #include "al/auxeffectslot.h" #include "al/buffer.h" +#include "al/debug.h" #include "al/effect.h" #include "al/filter.h" #include "al/listener.h" diff --git a/alc/context.cpp b/alc/context.cpp index 7d10a91d..755a1e41 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -122,6 +122,7 @@ void ALCcontext::setThreadContext(ALCcontext *context) noexcept ALCcontext::ALCcontext(al::intrusive_ptr device) : ContextBase{device.get()}, mALDevice{std::move(device)} { + mDebugGroups.emplace_back(DebugSource::Other, 0, std::string{}); } ALCcontext::~ALCcontext() @@ -328,6 +329,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } std::unique_lock debuglock{mDebugCbLock}; + DebugGroup &debug = mDebugGroups.back(); if(!mDebugEnabled.load()) UNLIKELY return; @@ -372,15 +374,15 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) | (1_u64 << (DebugTypeBase+al::to_underlying(type))) | (uint64_t{id} << 32)}; - auto iditer = std::lower_bound(mDebugIdFilters.cbegin(), mDebugIdFilters.cend(), idfilter); - if(iditer != mDebugIdFilters.cend() && *iditer == idfilter) + auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); + if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) return; const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) | (1u << (DebugTypeBase+al::to_underlying(type))) | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; - auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); - if(iter != mDebugFilters.cend() && *iter == filter) + auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(iter != debug.mFilters.cend() && *iter == filter) return; if(mDebugCb) diff --git a/alc/context.h b/alc/context.h index b3f548c8..3e31c9b8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -33,57 +33,14 @@ struct ALeffect; struct ALeffectslot; struct ALsource; +struct DebugGroup; +struct DebugLogEntry; -using uint = unsigned int; - +enum class DebugSource : uint8_t; +enum class DebugType : uint8_t; +enum class DebugSeverity : uint8_t; -constexpr uint DebugSourceBase{0}; -enum class DebugSource : uint8_t { - API = 0, - System, - ThirdParty, - Application, - Other, -}; -constexpr uint DebugSourceCount{5}; - -constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; -enum class DebugType : uint8_t { - Error = 0, - DeprecatedBehavior, - UndefinedBehavior, - Portability, - Performance, - Marker, - Other, -}; -constexpr uint DebugTypeCount{7}; - -constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; -enum class DebugSeverity : uint8_t { - High = 0, - Medium, - Low, - Notification, -}; -constexpr uint DebugSeverityCount{4}; - -struct LogEntry { - const DebugSource mSource; - const DebugType mType; - const DebugSeverity mSeverity; - const uint mId; - - std::string mMessage; - - template - LogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) - : mSource{source}, mType{type}, mSeverity{severity}, mId{id} - , mMessage{std::forward(message)} - { } - LogEntry(const LogEntry&) = default; - LogEntry(LogEntry&&) = default; -}; +using uint = unsigned int; struct SourceSubList { @@ -145,9 +102,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::mutex mDebugCbLock; ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; - std::vector mDebugFilters; - std::vector mDebugIdFilters; - std::deque mDebugLog; + std::vector mDebugGroups; + std::deque mDebugLog; ALlistener mListener{}; -- cgit v1.2.3 From e1b573284b649c6fef42ab5b6ca51978c4a1329a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 19:11:26 -0700 Subject: Implement pushing/popping debug groups --- al/debug.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- al/debug.h | 5 +- al/state.cpp | 23 +++++++++ alc/alc.cpp | 7 +++ alc/context.cpp | 105 ---------------------------------------- alc/context.h | 7 +-- alc/inprogext.h | 27 +++++++---- 7 files changed, 197 insertions(+), 122 deletions(-) (limited to 'al/debug.h') diff --git a/al/debug.cpp b/al/debug.cpp index fc893490..2dd0e7c7 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -17,12 +17,15 @@ #include "alc/inprogext.h" #include "aloptional.h" #include "alspan.h" +#include "core/logging.h" #include "opthelpers.h" #include "threads.h" namespace { +static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + template constexpr auto make_array(std::integer_sequence) { return std::array{Vals...}; } @@ -55,6 +58,8 @@ constexpr al::optional GetDebugType(ALenum type) noexcept case AL_DEBUG_TYPE_PORTABILITY_SOFT: return DebugType::Portability; case AL_DEBUG_TYPE_PERFORMANCE_SOFT: return DebugType::Performance; case AL_DEBUG_TYPE_MARKER_SOFT: return DebugType::Marker; + case AL_DEBUG_TYPE_PUSH_GROUP_SOFT: return DebugType::PushGroup; + case AL_DEBUG_TYPE_POP_GROUP_SOFT: return DebugType::PopGroup; case AL_DEBUG_TYPE_OTHER_SOFT: return DebugType::Other; } return al::nullopt; @@ -72,7 +77,6 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept return al::nullopt; } -} // namespace ALenum GetDebugSourceEnum(DebugSource source) { @@ -97,6 +101,8 @@ ALenum GetDebugTypeEnum(DebugType type) case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; + case DebugType::PushGroup: return AL_DEBUG_TYPE_PUSH_GROUP_SOFT; + case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_SOFT; case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; } throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; @@ -114,6 +120,74 @@ ALenum GetDebugSeverityEnum(DebugSeverity severity) throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; } +} // namespace + + +void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, DebugSource source, + DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) +{ + if(!mDebugEnabled.load()) UNLIKELY + return; + + /* MaxDebugMessageLength is the size including the null terminator, + * does not include the null terminator. + */ + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen >= MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%zu >= %d)\n", newlen, MaxDebugMessageLength); + return; + } + length = static_cast(newlen); + } + else if(length >= MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%d >= %d)\n", length, MaxDebugMessageLength); + return; + } + + DebugGroup &debug = mDebugGroups.back(); + + const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) + | (1_u64 << (DebugTypeBase+al::to_underlying(type))) + | (uint64_t{id} << 32)}; + auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); + if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) + return; + + const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) + | (1u << (DebugTypeBase+al::to_underlying(type))) + | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; + auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(iter != debug.mFilters.cend() && *iter == filter) + return; + + if(mDebugCb) + { + auto callback = mDebugCb; + auto param = mDebugParam; + debuglock.unlock(); + callback(GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, + GetDebugSeverityEnum(severity), length, message, param); + } + else + { + if(mDebugLog.size() < MaxDebugLoggedMessages) + mDebugLog.emplace_back(source, type, id, severity, message); + else UNLIKELY + ERR("Debug message log overflow. Lost message:\n" + " Source: 0x%04x\n" + " Type: 0x%04x\n" + " ID: %u\n" + " Severity: 0x%04x\n" + " Message: \"%s\"\n", + GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, + GetDebugSeverityEnum(severity), message); + } +} + FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept { @@ -134,9 +208,6 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); - /* MaxDebugMessageLength is the size including the null terminator, - * does not include the null terminator. - */ if(length < 0) { size_t newlen{std::strlen(message)}; @@ -265,6 +336,72 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } +FORCE_ALIGN void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", + newlen, MaxDebugMessageLength); + length = static_cast(newlen); + } + else if(length >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, + MaxDebugMessageLength); + + auto dsource = GetDebugSource(source); + if(!dsource) + return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application) + return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source); + + std::unique_lock debuglock{context->mDebugCbLock}; + if(context->mDebugGroups.size() >= MaxDebugGroupDepth) + { + debuglock.unlock(); + return context->setError(AL_STACK_OVERFLOW_SOFT, "Pushing too many debug groups"); + } + + context->mDebugGroups.emplace_back(*dsource, id, message); + auto &oldback = *(context->mDebugGroups.end()-2); + auto &newback = context->mDebugGroups.back(); + + newback.mFilters = oldback.mFilters; + newback.mIdFilters = oldback.mIdFilters; + + context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, + DebugSeverity::Notification, static_cast(newback.mMessage.size()), + newback.mMessage.data()); +} + +FORCE_ALIGN void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + std::unique_lock debuglock{context->mDebugCbLock}; + if(context->mDebugGroups.size() <= 1) + { + debuglock.unlock(); + return context->setError(AL_STACK_UNDERFLOW_SOFT, + "Attempting to pop the default debug group"); + } + + DebugGroup &debug = context->mDebugGroups.back(); + const auto source = debug.mSource; + const auto id = debug.mId; + std::string message{std::move(debug.mMessage)}; + + context->mDebugGroups.pop_back(); + context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, + DebugSeverity::Notification, static_cast(message.size()), message.data()); +} + + FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept diff --git a/al/debug.h b/al/debug.h index c2147cf4..8f83fd5e 100644 --- a/al/debug.h +++ b/al/debug.h @@ -13,6 +13,7 @@ using uint = unsigned int; */ constexpr uint8_t MaxDebugLoggedMessages{64}; constexpr uint16_t MaxDebugMessageLength{1024}; +constexpr uint8_t MaxDebugGroupDepth{64}; constexpr uint DebugSourceBase{0}; @@ -33,9 +34,11 @@ enum class DebugType : uint8_t { Portability, Performance, Marker, + PushGroup, + PopGroup, Other, }; -constexpr uint DebugTypeCount{7}; +constexpr uint DebugTypeCount{9}; constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; enum class DebugSeverity : uint8_t { diff --git a/al/state.cpp b/al/state.cpp index 1e1a0085..2a350646 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -69,6 +69,8 @@ constexpr ALchar alErrInvalidEnum[] = "Invalid Enum"; constexpr ALchar alErrInvalidValue[] = "Invalid Value"; constexpr ALchar alErrInvalidOp[] = "Invalid Operation"; constexpr ALchar alErrOutOfMemory[] = "Out of Memory"; +constexpr ALchar alStackOverflow[] = "Stack Overflow"; +constexpr ALchar alStackUnderflow[] = "Stack Underflow"; /* Resampler strings */ template struct ResamplerName { }; @@ -264,6 +266,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname) != 0; } @@ -308,6 +311,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname); } @@ -338,6 +342,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return static_cast(alGetInteger(pname)); case AL_DEFERRED_UPDATES_SOFT: @@ -436,6 +441,10 @@ START_API_FUNC value = MaxDebugLoggedMessages; break; + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: + value = MaxDebugGroupDepth; + break; + #ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." @@ -491,6 +500,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname); } @@ -562,6 +572,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetBoolean(pname); return; } @@ -599,6 +610,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetDouble(pname); return; } @@ -636,6 +648,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetFloat(pname); return; } @@ -673,6 +686,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetInteger(pname); return; } @@ -710,6 +724,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetInteger64SOFT(pname); return; } @@ -806,6 +821,14 @@ START_API_FUNC value = alErrOutOfMemory; break; + case AL_STACK_OVERFLOW_SOFT: + value = alStackOverflow; + break; + + case AL_STACK_UNDERFLOW_SOFT: + value = alStackUnderflow; + break; + default: context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname); } diff --git a/alc/alc.cpp b/alc/alc.cpp index aa65222c..50982ed2 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -464,6 +464,8 @@ const struct { DECL(alDebugMessageCallbackSOFT), DECL(alDebugMessageInsertSOFT), DECL(alDebugMessageControlSOFT), + DECL(alPushDebugGroupSOFT), + DECL(alPopDebugGroupSOFT), DECL(alGetDebugMessageLogSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { @@ -936,6 +938,8 @@ constexpr struct { DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), DECL(AL_DEBUG_TYPE_MARKER_SOFT), + DECL(AL_DEBUG_TYPE_PUSH_GROUP_SOFT), + DECL(AL_DEBUG_TYPE_POP_GROUP_SOFT), DECL(AL_DEBUG_TYPE_OTHER_SOFT), DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), @@ -945,6 +949,9 @@ constexpr struct { DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT), DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT), DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT), + DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT), + DECL(AL_STACK_OVERFLOW_SOFT), + DECL(AL_STACK_UNDERFLOW_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index 755a1e41..0c8253fb 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -304,111 +304,6 @@ void ALCcontext::applyAllUpdates() } -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"); - - /* MaxDebugMessageLength is the size including the null terminator, - * does not include the null terminator. - */ - if(length < 0) - { - size_t newlen{std::strlen(message)}; - if(newlen >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%zu >= %d)\n", newlen, MaxDebugMessageLength); - return; - } - length = static_cast(newlen); - } - else if(length >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%d >= %d)\n", length, MaxDebugMessageLength); - return; - } - - std::unique_lock debuglock{mDebugCbLock}; - DebugGroup &debug = mDebugGroups.back(); - if(!mDebugEnabled.load()) UNLIKELY - return; - - auto get_source_enum = [source]() - { - switch(source) - { - case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; - case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; - case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; - case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; - case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; - } - throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; - }; - auto get_type_enum = [type]() - { - switch(type) - { - case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; - case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; - case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; - case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; - case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; - case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; - case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; - } - throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; - }; - auto get_severity_enum = [severity]() - { - switch(severity) - { - case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; - case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; - case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; - case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; - } - throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; - }; - - const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) - | (1_u64 << (DebugTypeBase+al::to_underlying(type))) - | (uint64_t{id} << 32)}; - auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); - if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) - return; - - const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) - | (1u << (DebugTypeBase+al::to_underlying(type))) - | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; - auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); - if(iter != debug.mFilters.cend() && *iter == filter) - return; - - if(mDebugCb) - { - auto callback = mDebugCb; - auto param = mDebugParam; - debuglock.unlock(); - callback(get_source_enum(), get_type_enum(), id, get_severity_enum(), length, message, - param); - } - else - { - if(mDebugLog.size() < MaxDebugLoggedMessages) - mDebugLog.emplace_back(source, type, id, severity, message); - else UNLIKELY - ERR("Debug message log overflow. Lost message:\n" - " Source: 0x%04x\n" - " Type: 0x%04x\n" - " ID: %u\n" - " Severity: 0x%04x\n" - " Message: \"%s\"\n", - get_source_enum(), get_type_enum(), id, get_severity_enum(), message); - } -} - - #ifdef ALSOFT_EAX namespace { diff --git a/alc/context.h b/alc/context.h index 3e31c9b8..8757b041 100644 --- a/alc/context.h +++ b/alc/context.h @@ -166,15 +166,16 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { #endif void setError(ALenum errorCode, const char *msg, ...); - void sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, - ALsizei length, const char *message); + void sendDebugMessage(std::unique_lock &debuglock, DebugSource source, + DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message); void debugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { if(!mDebugEnabled.load(std::memory_order_relaxed)) LIKELY return; - sendDebugMessage(source, type, id, severity, length, message); + std::unique_lock debuglock{mDebugCbLock}; + sendDebugMessage(debuglock, source, type, id, severity, length, message); } /* Process-wide current context */ diff --git a/alc/inprogext.h b/alc/inprogext.h index f73963cb..7f9d7766 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -71,25 +71,34 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_DEBUG_TYPE_PORTABILITY_SOFT 0x19BD #define AL_DEBUG_TYPE_PERFORMANCE_SOFT 0x19BE #define AL_DEBUG_TYPE_MARKER_SOFT 0x19BF -#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C0 -#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C1 -#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C2 -#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C3 -#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C4 -#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C5 -#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C6 -#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C7 -#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19C8 +#define AL_DEBUG_TYPE_PUSH_GROUP_SOFT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_SOFT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT 0x19CB +#define AL_STACK_OVERFLOW_SOFT 0x19CC +#define AL_STACK_UNDERFLOW_SOFT 0x19CD 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); +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPSOFT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPSOFT)(void); typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGSOFT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #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; +void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept; ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From d5e5b211b89de63667eab71faa7e9a13a0b7992d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 19:19:41 -0700 Subject: Define a struct where it's needed --- al/debug.h | 18 ------------------ alc/context.h | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 19 deletions(-) (limited to 'al/debug.h') diff --git a/al/debug.h b/al/debug.h index 8f83fd5e..87bc10f6 100644 --- a/al/debug.h +++ b/al/debug.h @@ -64,22 +64,4 @@ struct DebugGroup { DebugGroup(DebugGroup&&) = default; }; - -struct DebugLogEntry { - const DebugSource mSource; - const DebugType mType; - const DebugSeverity mSeverity; - const uint mId; - - std::string mMessage; - - template - DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) - : mSource{source}, mType{type}, mSeverity{severity}, mId{id} - , mMessage{std::forward(message)} - { } - DebugLogEntry(const DebugLogEntry&) = default; - DebugLogEntry(DebugLogEntry&&) = default; -}; - #endif /* AL_DEBUG_H */ diff --git a/alc/context.h b/alc/context.h index 8757b041..20c89a31 100644 --- a/alc/context.h +++ b/alc/context.h @@ -34,7 +34,6 @@ struct ALeffect; struct ALeffectslot; struct ALsource; struct DebugGroup; -struct DebugLogEntry; enum class DebugSource : uint8_t; enum class DebugType : uint8_t; @@ -43,6 +42,24 @@ enum class DebugSeverity : uint8_t; using uint = unsigned int; +struct DebugLogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + DebugLogEntry(const DebugLogEntry&) = default; + DebugLogEntry(DebugLogEntry&&) = default; +}; + + struct SourceSubList { uint64_t FreeMask{~0_u64}; ALsource *Sources{nullptr}; /* 64 */ -- cgit v1.2.3 From 947f87a25390bdb2b4b22952c1ad55a56fe280e4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 May 2023 22:37:06 -0700 Subject: Mark some global constexpr variables inline --- al/debug.h | 18 +++++++++--------- common/alnumbers.h | 16 ++++++++-------- core/ambidefs.h | 18 +++++++++--------- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'al/debug.h') diff --git a/al/debug.h b/al/debug.h index 87bc10f6..0c53f0ae 100644 --- a/al/debug.h +++ b/al/debug.h @@ -11,12 +11,12 @@ using uint = unsigned int; /* Somewhat arbitrary. Avoid letting it get out of control if the app enables * logging but never reads it. */ -constexpr uint8_t MaxDebugLoggedMessages{64}; -constexpr uint16_t MaxDebugMessageLength{1024}; -constexpr uint8_t MaxDebugGroupDepth{64}; +inline constexpr uint8_t MaxDebugLoggedMessages{64}; +inline constexpr uint16_t MaxDebugMessageLength{1024}; +inline constexpr uint8_t MaxDebugGroupDepth{64}; -constexpr uint DebugSourceBase{0}; +inline constexpr uint DebugSourceBase{0}; enum class DebugSource : uint8_t { API = 0, System, @@ -24,9 +24,9 @@ enum class DebugSource : uint8_t { Application, Other, }; -constexpr uint DebugSourceCount{5}; +inline constexpr uint DebugSourceCount{5}; -constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; +inline constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; enum class DebugType : uint8_t { Error = 0, DeprecatedBehavior, @@ -38,16 +38,16 @@ enum class DebugType : uint8_t { PopGroup, Other, }; -constexpr uint DebugTypeCount{9}; +inline constexpr uint DebugTypeCount{9}; -constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; +inline constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; enum class DebugSeverity : uint8_t { High = 0, Medium, Low, Notification, }; -constexpr uint DebugSeverityCount{4}; +inline constexpr uint DebugSeverityCount{4}; struct DebugGroup { const uint mId; diff --git a/common/alnumbers.h b/common/alnumbers.h index 800b1f2a..e92d7b87 100644 --- a/common/alnumbers.h +++ b/common/alnumbers.h @@ -13,21 +13,21 @@ namespace detail_ { } // detail_ template -constexpr auto pi_v = detail_::as_fp(3.141592653589793238462643383279502884L); +inline constexpr auto pi_v = detail_::as_fp(3.141592653589793238462643383279502884L); template -constexpr auto inv_pi_v = detail_::as_fp(0.318309886183790671537767526745028724L); +inline constexpr auto inv_pi_v = detail_::as_fp(0.318309886183790671537767526745028724L); template -constexpr auto sqrt2_v = detail_::as_fp(1.414213562373095048801688724209698079L); +inline constexpr auto sqrt2_v = detail_::as_fp(1.414213562373095048801688724209698079L); template -constexpr auto sqrt3_v = detail_::as_fp(1.732050807568877293527446341505872367L); +inline constexpr auto sqrt3_v = detail_::as_fp(1.732050807568877293527446341505872367L); -constexpr auto pi = pi_v; -constexpr auto inv_pi = inv_pi_v; -constexpr auto sqrt2 = sqrt2_v; -constexpr auto sqrt3 = sqrt3_v; +inline constexpr auto pi = pi_v; +inline constexpr auto inv_pi = inv_pi_v; +inline constexpr auto sqrt2 = sqrt2_v; +inline constexpr auto sqrt3 = sqrt3_v; } // namespace numbers diff --git a/core/ambidefs.h b/core/ambidefs.h index b7d2bcd1..3af26258 100644 --- a/core/ambidefs.h +++ b/core/ambidefs.h @@ -14,26 +14,26 @@ using uint = unsigned int; * needed will be (o+1)**2, thus zero-order has 1, first-order has 4, second- * order has 9, third-order has 16, and fourth-order has 25. */ -constexpr uint8_t MaxAmbiOrder{3}; +inline constexpr uint8_t MaxAmbiOrder{3}; constexpr inline size_t AmbiChannelsFromOrder(size_t order) noexcept { return (order+1) * (order+1); } -constexpr size_t MaxAmbiChannels{AmbiChannelsFromOrder(MaxAmbiOrder)}; +inline constexpr size_t MaxAmbiChannels{AmbiChannelsFromOrder(MaxAmbiOrder)}; /* A bitmask of ambisonic channels for 0 to 4th order. This only specifies up * to 4th order, which is the highest order a 32-bit mask value can specify (a * 64-bit mask could handle up to 7th order). */ -constexpr uint Ambi0OrderMask{0x00000001}; -constexpr uint Ambi1OrderMask{0x0000000f}; -constexpr uint Ambi2OrderMask{0x000001ff}; -constexpr uint Ambi3OrderMask{0x0000ffff}; -constexpr uint Ambi4OrderMask{0x01ffffff}; +inline constexpr uint Ambi0OrderMask{0x00000001}; +inline constexpr uint Ambi1OrderMask{0x0000000f}; +inline constexpr uint Ambi2OrderMask{0x000001ff}; +inline constexpr uint Ambi3OrderMask{0x0000ffff}; +inline constexpr uint Ambi4OrderMask{0x01ffffff}; /* A bitmask of ambisonic channels with height information. If none of these * channels are used/needed, there's no height (e.g. with most surround sound * speaker setups). This is ACN ordering, with bit 0 being ACN 0, etc. */ -constexpr uint AmbiPeriphonicMask{0xfe7ce4}; +inline constexpr uint AmbiPeriphonicMask{0xfe7ce4}; /* The maximum number of ambisonic channels for 2D (non-periphonic) * representation. This is 2 per each order above zero-order, plus 1 for zero- @@ -41,7 +41,7 @@ constexpr uint AmbiPeriphonicMask{0xfe7ce4}; */ constexpr inline size_t Ambi2DChannelsFromOrder(size_t order) noexcept { return order*2 + 1; } -constexpr size_t MaxAmbi2DChannels{Ambi2DChannelsFromOrder(MaxAmbiOrder)}; +inline constexpr size_t MaxAmbi2DChannels{Ambi2DChannelsFromOrder(MaxAmbiOrder)}; /* NOTE: These are scale factors as applied to Ambisonics content. Decoder -- cgit v1.2.3 From 09eff761b8c8a2da79b0083c86a304eb3643b396 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 11 Aug 2023 02:10:26 -0700 Subject: Add AL_EXT_debug functions to set/get object names --- al/auxeffectslot.cpp | 13 +++++++ al/auxeffectslot.h | 3 ++ al/buffer.cpp | 15 ++++++++ al/buffer.h | 3 ++ al/debug.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++++++--- al/debug.h | 1 + al/effect.cpp | 15 ++++++++ al/effect.h | 2 + al/filter.cpp | 15 ++++++++ al/filter.h | 2 + al/source.cpp | 14 +++++++ al/source.h | 5 ++- al/state.cpp | 5 +++ alc/context.h | 3 ++ alc/device.h | 5 +++ alc/export_list.h | 10 +++++ alc/inprogext.h | 30 +++++++++++---- 17 files changed, 228 insertions(+), 14 deletions(-) (limited to 'al/debug.h') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 6f82db71..09db0736 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -286,6 +286,8 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context) void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) { + context->mEffectSlotNames.erase(slot->id); + const ALuint id{slot->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -962,6 +964,17 @@ void ALeffectslot::updateProps(ALCcontext *context) } } +void ALeffectslot::SetName(ALCcontext* context, ALuint id, std::string_view name) +{ + std::lock_guard _{context->mEffectSlotLock}; + + auto slot = LookupEffectSlot(context, id); + if(!slot) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id); + + context->mEffectSlotNames.insert_or_assign(id, name); +} + void UpdateAllEffectSlotProps(ALCcontext *context) { std::lock_guard _{context->mEffectSlotLock}; diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 3e9a2a4e..9038647c 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -3,6 +3,7 @@ #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -76,6 +77,8 @@ struct ALeffectslot { ALenum initEffect(ALenum effectType, const EffectProps &effectProps, ALCcontext *context); void updateProps(ALCcontext *context); + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) diff --git a/al/buffer.cpp b/al/buffer.cpp index 58e8f375..e56aa13e 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -222,6 +222,8 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer) eax_x_ram_clear(*device, *buffer); #endif // ALSOFT_EAX + device->mBufferNames.erase(buffer->id); + const ALuint id{buffer->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -1440,6 +1442,19 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) no } +void ALbuffer::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->BufferLock}; + + auto buffer = LookupBuffer(device, id); + if(!buffer) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", id); + + device->mBufferNames.insert_or_assign(id, name); +} + + BufferSubList::~BufferSubList() { if(!Buffers) diff --git a/al/buffer.h b/al/buffer.h index 3df1fa4c..f936cf98 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -3,6 +3,7 @@ #include #include +#include #include "AL/al.h" @@ -47,6 +48,8 @@ struct ALbuffer : public BufferStorage { /* Self ID */ ALuint id{0}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() #ifdef ALSOFT_EAX diff --git a/al/debug.cpp b/al/debug.cpp index 2d8819f3..62e88914 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -17,9 +17,14 @@ #include "alc/context.h" #include "alc/inprogext.h" #include "alspan.h" +#include "auxeffectslot.h" +#include "buffer.h" #include "core/logging.h" #include "direct_defs.h" +#include "effect.h" +#include "filter.h" #include "opthelpers.h" +#include "source.h" namespace { @@ -242,13 +247,8 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, if(!message) UNLIKELY return context->setError(AL_INVALID_VALUE, "Null message pointer"); - if(length >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length, - MaxDebugMessageLength); - auto msgview = (length < 0) ? std::string_view{message} : std::string_view{message, static_cast(length)}; - if(msgview.length() >= MaxDebugMessageLength) UNLIKELY return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", msgview.length(), MaxDebugMessageLength); @@ -472,3 +472,94 @@ FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context return count; } + +FORCE_ALIGN DECL_FUNCEXT4(void, alObjectLabel,EXT, ALenum, ALuint, ALsizei, const ALchar*) +FORCE_ALIGN void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, + ALuint name, ALsizei length, const ALchar *label) noexcept +{ + if(!label && length != 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Null label pointer"); + + auto objname = (length < 0) ? std::string_view{label} + : std::string_view{label, static_cast(length)}; + if(objname.length() >= MaxObjectLabelLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Object label length too long (%zu >= %d)", + objname.length(), MaxObjectLabelLength); + + if(identifier == AL_SOURCE_EXT) + return ALsource::SetName(context, name, objname); + if(identifier == AL_BUFFER) + return ALbuffer::SetName(context, name, objname); + if(identifier == AL_FILTER_EXT) + return ALfilter::SetName(context, name, objname); + if(identifier == AL_EFFECT_EXT) + return ALeffect::SetName(context, name, objname); + if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) + return ALeffectslot::SetName(context, name, objname); + + return context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); +} + +FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum, ALuint, ALsizei, ALsizei*, ALchar*) +FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, + ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) noexcept +{ + if(bufSize < 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Negative label bufSize"); + + if(!label && !length) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Null length and label"); + if(label && bufSize == 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Zero label bufSize"); + + auto copy_name = [name,bufSize,length,label](std::unordered_map &names) + { + std::string_view objname; + + auto iter = names.find(name); + if(iter != names.end()) + objname = iter->second; + + if(!label) + *length = static_cast(objname.length()); + else + { + const size_t tocopy{minz(objname.length(), static_cast(bufSize)-1)}; + std::memcpy(label, objname.data(), tocopy); + label[tocopy] = '\0'; + if(length) + *length = static_cast(tocopy); + } + }; + + if(identifier == AL_SOURCE_EXT) + { + std::lock_guard _{context->mSourceLock}; + copy_name(context->mSourceNames); + } + else if(identifier == AL_BUFFER) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->BufferLock}; + copy_name(device->mBufferNames); + } + else if(identifier == AL_FILTER_EXT) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->FilterLock}; + copy_name(device->mFilterNames); + } + else if(identifier == AL_EFFECT_EXT) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->EffectLock}; + copy_name(device->mEffectNames); + } + else if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) + { + std::lock_guard _{context->mEffectSlotLock}; + copy_name(context->mEffectSlotNames); + } + else + context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); +} diff --git a/al/debug.h b/al/debug.h index 0c53f0ae..2764bb7f 100644 --- a/al/debug.h +++ b/al/debug.h @@ -14,6 +14,7 @@ using uint = unsigned int; inline constexpr uint8_t MaxDebugLoggedMessages{64}; inline constexpr uint16_t MaxDebugMessageLength{1024}; inline constexpr uint8_t MaxDebugGroupDepth{64}; +inline constexpr uint16_t MaxObjectLabelLength{1024}; inline constexpr uint DebugSourceBase{0}; diff --git a/al/effect.cpp b/al/effect.cpp index 81cbb4c6..5c7f9627 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -207,6 +207,8 @@ ALeffect *AllocEffect(ALCdevice *device) void FreeEffect(ALCdevice *device, ALeffect *effect) { + device->mEffectNames.erase(effect->id); + const ALuint id{effect->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -511,6 +513,19 @@ void InitEffect(ALeffect *effect) InitEffectParams(effect, AL_EFFECT_NULL); } +void ALeffect::SetName(ALCcontext* context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->EffectLock}; + + auto effect = LookupEffect(device, id); + if(!effect) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid effect ID %u", id); + + device->mEffectNames.insert_or_assign(id, name); +} + + EffectSubList::~EffectSubList() { if(!Effects) diff --git a/al/effect.h b/al/effect.h index a1d43313..3d05e692 100644 --- a/al/effect.h +++ b/al/effect.h @@ -50,6 +50,8 @@ struct ALeffect { /* Self ID */ ALuint id{0u}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() }; diff --git a/al/filter.cpp b/al/filter.cpp index 9ad57b54..e6520e6a 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -163,6 +163,8 @@ ALfilter *AllocFilter(ALCdevice *device) void FreeFilter(ALCdevice *device, ALfilter *filter) { + device->mFilterNames.erase(filter->id); + const ALuint id{filter->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -671,6 +673,19 @@ FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint fil } +void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->FilterLock}; + + auto filter = LookupFilter(device, id); + if(!filter) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid filter ID %u", id); + + device->mFilterNames.insert_or_assign(id, name); +} + + FilterSubList::~FilterSubList() { if(!Filters) diff --git a/al/filter.h b/al/filter.h index 2ed483cc..24ebc203 100644 --- a/al/filter.h +++ b/al/filter.h @@ -48,6 +48,8 @@ struct ALfilter { /* Self ID */ ALuint id{0}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() }; diff --git a/al/source.cpp b/al/source.cpp index 70182ec8..6bcb7318 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -764,6 +764,8 @@ ALsource *AllocSource(ALCcontext *context) void FreeSource(ALCcontext *context, ALsource *source) { + context->mSourceNames.erase(source->id); + const ALuint id{source->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -3614,6 +3616,18 @@ void UpdateAllSourceProps(ALCcontext *context) } } +void ALsource::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + std::lock_guard _{context->mSourceLock}; + + auto source = LookupSource(context, id); + if(!source) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid source ID %u", id); + + context->mSourceNames.insert_or_assign(id, name); +} + + SourceSubList::~SourceSubList() { if(!Sources) diff --git a/al/source.h b/al/source.h index ac97c8a7..2bdeb2a3 100644 --- a/al/source.h +++ b/al/source.h @@ -4,9 +4,10 @@ #include #include #include +#include #include #include -#include +#include #include "AL/al.h" #include "AL/alc.h" @@ -157,6 +158,8 @@ struct ALsource { ALsource(const ALsource&) = delete; ALsource& operator=(const ALsource&) = delete; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() #ifdef ALSOFT_EAX diff --git a/al/state.cpp b/al/state.cpp index 5b0772c7..1c41d63c 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -152,6 +152,7 @@ enum PropertyValue : ALenum { MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, + MaxLabelLength = AL_MAX_LABEL_LENGTH_EXT, ContextFlags = AL_CONTEXT_FLAGS_EXT, #ifdef ALSOFT_EAX EaxRamSize = AL_EAX_RAM_SIZE, @@ -245,6 +246,10 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(MaxDebugGroupDepth); return; + case AL_MAX_LABEL_LENGTH_EXT: + *values = cast_value(MaxObjectLabelLength); + return; + case AL_CONTEXT_FLAGS_EXT: *values = cast_value(context->mContextFlags.to_ulong()); return; diff --git a/alc/context.h b/alc/context.h index 0611775a..f936bbe8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -146,6 +147,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::vector mExtensions; std::string mExtensionsString{}; + std::unordered_map mSourceNames; + std::unordered_map mEffectSlotNames; ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); ALCcontext(const ALCcontext&) = delete; diff --git a/alc/device.h b/alc/device.h index c346dc9e..66f37a7e 100644 --- a/alc/device.h +++ b/alc/device.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -133,6 +134,10 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { #endif // ALSOFT_EAX + std::unordered_map mBufferNames; + std::unordered_map mEffectNames; + std::unordered_map mFilterNames; + ALCdevice(DeviceType type); ~ALCdevice(); diff --git a/alc/export_list.h b/alc/export_list.h index ed1165d0..89d394a8 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -367,6 +367,10 @@ inline const FuncExport alcFunctions[]{ DECL(alPushDebugGroupDirectEXT), DECL(alPopDebugGroupDirectEXT), DECL(alGetDebugMessageLogDirectEXT), + DECL(alObjectLabelEXT), + DECL(alObjectLabelDirectEXT), + DECL(alGetObjectLabelEXT), + DECL(alGetObjectLabelDirectEXT), /* Extra functions */ DECL(alsoft_set_log_callback), @@ -862,8 +866,14 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_EXT), DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_EXT), DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT), + DECL(AL_MAX_LABEL_LENGTH_EXT), DECL(AL_STACK_OVERFLOW_EXT), DECL(AL_STACK_UNDERFLOW_EXT), + DECL(AL_BUFFER_EXT), + DECL(AL_SOURCE_EXT), + DECL(AL_FILTER_EXT), + DECL(AL_EFFECT_EXT), + DECL(AL_AUXILIARY_EFFECT_SLOT_EXT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), #ifdef ALSOFT_EAX diff --git a/alc/inprogext.h b/alc/inprogext.h index 7f5458e5..dc1744ee 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -97,9 +97,15 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 #define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA #define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB -#define AL_STACK_OVERFLOW_EXT 0x19CC -#define AL_STACK_UNDERFLOW_EXT 0x19CD -#define AL_CONTEXT_FLAGS_EXT 0x19CE +#define AL_MAX_LABEL_LENGTH_EXT 0x19CC +#define AL_STACK_OVERFLOW_EXT 0x19CD +#define AL_STACK_UNDERFLOW_EXT 0x19CE +#define AL_CONTEXT_FLAGS_EXT 0x19CF +#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ +#define AL_SOURCE_EXT 0x19D0 +#define AL_FILTER_EXT 0x19D1 +#define AL_EFFECT_EXT 0x19D2 +#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; @@ -108,6 +114,8 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; @@ -115,6 +123,8 @@ void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum sev void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; #endif #endif @@ -236,6 +246,8 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; /* AL_EXT_FOLDBACK */ typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; @@ -401,6 +413,8 @@ void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum sour void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; @@ -447,11 +461,11 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #ifndef ALC_SOFT_system_events #define ALC_SOFT_system_events -#define ALC_PLAYBACK_DEVICE_SOFT 0x19CF -#define ALC_CAPTURE_DEVICE_SOFT 0x19D0 -#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D1 -#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D2 -#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D3 +#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 +#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; -- cgit v1.2.3 From 6435744f7a1f7995a80309eb8b66468c0c7e732b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 22 Oct 2023 20:05:00 -0700 Subject: Don't inline a destructor --- al/debug.cpp | 5 +++++ al/debug.h | 1 + 2 files changed, 6 insertions(+) (limited to 'al/debug.h') diff --git a/al/debug.cpp b/al/debug.cpp index f5914767..b76ec9af 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -27,6 +27,11 @@ #include "source.h" +/* Declared here to prevent compilers from thinking it should be inlined, which + * GCC warns about increasing code size. + */ +DebugGroup::~DebugGroup() = default; + namespace { static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); diff --git a/al/debug.h b/al/debug.h index 2764bb7f..351be9c0 100644 --- a/al/debug.h +++ b/al/debug.h @@ -63,6 +63,7 @@ struct DebugGroup { { } DebugGroup(const DebugGroup&) = default; DebugGroup(DebugGroup&&) = default; + ~DebugGroup(); }; #endif /* AL_DEBUG_H */ -- cgit v1.2.3