aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-04-30 17:46:18 -0700
committerChris Robinson <[email protected]>2023-04-30 17:46:18 -0700
commit22077687cf4b9fdfd29d78debc2daf044deee81d (patch)
treefc9aab402ea9e33f7cec2e1ef1dfa98203665578
parentf2a0df87916de7b9fa8b65a52814c9a09fc6bee9 (diff)
Implement debug log storage
-rw-r--r--al/debug.cpp93
-rw-r--r--al/debug.h9
-rw-r--r--al/state.cpp61
-rw-r--r--alc/alc.cpp5
-rw-r--r--alc/context.cpp29
-rw-r--r--alc/context.h19
-rw-r--r--alc/inprogext.h6
7 files changed, 220 insertions, 2 deletions
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<DebugSeverity> 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<ALsizei>(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<<idx); });
}
+
+
+FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize,
+ ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths,
+ ALchar *logBuf) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return 0;
+
+ if(logBufSize < 0)
+ {
+ context->setError(AL_INVALID_VALUE, "Negative debug log buffer size");
+ return 0;
+ }
+
+ std::lock_guard<std::mutex> _{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<ALuint>(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<ALsizei>(tocopy);
+ if(logBuf) std::copy_n(entry.mMessage.data(), tocopy, logBuf+logBufWritten);
+
+ logBufWritten += static_cast<ALsizei>(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 <stdint.h>
+
+
+/* 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<ALfloat>(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<std::mutex> __{context->mDebugCbLock};
+ value = static_cast<ALint>(context->mDebugLog.size());
+ break;
+ }
+
+ case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT:
+ {
+ std::lock_guard<std::mutex> __{context->mDebugCbLock};
+ value = context->mDebugLog.empty() ? 0
+ : static_cast<ALint>(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<ALsizei>(newlen);
+ }
+ else if(length > MaxDebugMessageLength) UNLIKELY
+ {
+ ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength);
+ return;
+ }
+
std::unique_lock<std::mutex> 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 <atomic>
+#include <deque>
#include <memory>
#include <mutex>
#include <stdint.h>
@@ -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<typename T>
+ LogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message)
+ : mSource{source}, mType{type}, mSeverity{severity}, mId{id}
+ , mMessage{std::forward<T>(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<ALCcontext>, ContextBase {
ALDEBUGPROCSOFT mDebugCb{};
void *mDebugParam{nullptr};
std::vector<uint> mDebugFilters;
+ std::deque<LogEntry> 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