diff --git a/src/libANGLE/Debug.cpp b/src/libANGLE/Debug.cpp index bc9f4c93f..24d3c58b5 100644 --- a/src/libANGLE/Debug.cpp +++ b/src/libANGLE/Debug.cpp @@ -353,25 +353,10 @@ size_t Debug::getGroupStackDepth() const return mGroups.size(); } -void Debug::insertPerfWarning(GLenum severity, const char *message, uint32_t *repeatCount) const +void Debug::insertPerfWarning(GLenum severity, bool isLastRepeat, const char *message) const { - bool repeatLast; - - { - constexpr uint32_t kMaxRepeat = 4; - std::lock_guard lock(GetDebugMutex()); - - if (*repeatCount >= kMaxRepeat) - { - return; - } - - ++*repeatCount; - repeatLast = (*repeatCount == kMaxRepeat); - } - std::string msg = message; - if (repeatLast) + if (isLastRepeat) { msg += " (this message will no longer repeat)"; } diff --git a/src/libANGLE/Debug.h b/src/libANGLE/Debug.h index 7aff676ae..49cfc957e 100644 --- a/src/libANGLE/Debug.h +++ b/src/libANGLE/Debug.h @@ -85,7 +85,7 @@ class Debug : angle::NonCopyable size_t getGroupStackDepth() const; // Helper for ANGLE_PERF_WARNING - void insertPerfWarning(GLenum severity, const char *message, uint32_t *repeatCount) const; + void insertPerfWarning(GLenum severity, bool isLastRepeat, const char *message) const; private: bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const; @@ -170,12 +170,41 @@ class Debug : angle::NonCopyable }; } // namespace egl +namespace +{ +ANGLE_INLINE bool PerfCounterBelowMaxRepeat(std::atomic *counter, bool *isLastRepeat) +{ + constexpr uint32_t kMaxPerfRepeat = 4; + // Stop incrementing the counter after max value to avoid unnecessary cache effects + if (counter->load(std::memory_order_relaxed) < kMaxPerfRepeat) + { + uint32_t count = counter->fetch_add(1, std::memory_order_relaxed); + // Check not strictly necessary as worst case is an additional log, but is good practice. + if (count < kMaxPerfRepeat) + { + if (count == kMaxPerfRepeat - 1) + { + *isLastRepeat = true; + } + return true; + } + } + return false; +} +} // namespace + // Generate a perf warning. Only outputs the same message a few times to avoid spamming the logs. -#define ANGLE_PERF_WARNING(debug, severity, message) \ - do \ - { \ - static uint32_t sRepeatCount = 0; \ - (debug).insertPerfWarning(severity, message, &sRepeatCount); \ +#define ANGLE_PERF_WARNING(debug, severity, ...) \ + do \ + { \ + static std::atomic sRepeatCount = 0; \ + bool isLastRepeat = false; \ + if (PerfCounterBelowMaxRepeat(&sRepeatCount, &isLastRepeat)) \ + { \ + char ANGLE_MESSAGE[200]; \ + snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \ + (debug).insertPerfWarning(severity, isLastRepeat, ANGLE_MESSAGE); \ + } \ } while (0) #endif // LIBANGLE_DEBUG_H_ diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp index e444bbbd6..22bd9323f 100644 --- a/src/libANGLE/Program.cpp +++ b/src/libANGLE/Program.cpp @@ -2110,11 +2110,9 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi ASSERT(binaryOut); if (!binaryOut->resize(stream.length())) { - std::stringstream sstream; - sstream << "Failed to allocate enough memory to serialize a program. (" << stream.length() - << " bytes )"; ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, - sstream.str().c_str()); + "Failed to allocate enough memory to serialize a program. (%zu bytes)", + stream.length()); return angle::Result::Incomplete; } memcpy(binaryOut->data(), stream.data(), stream.length()); diff --git a/src/libANGLE/Shader.cpp b/src/libANGLE/Shader.cpp index 8703dcf60..17a45a006 100644 --- a/src/libANGLE/Shader.cpp +++ b/src/libANGLE/Shader.cpp @@ -680,11 +680,9 @@ angle::Result Shader::serialize(const Context *context, angle::MemoryBuffer *bin ASSERT(binaryOut); if (!binaryOut->resize(stream.length())) { - std::stringstream sstream; - sstream << "Failed to allocate enough memory to serialize a shader. (" << stream.length() - << " bytes )"; ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, - sstream.str().c_str()); + "Failed to allocate enough memory to serialize a shader. (%zu bytes)", + stream.length()); return angle::Result::Incomplete; } diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp index a6ca022d6..5f6ec1752 100644 --- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp +++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -659,12 +659,11 @@ angle::Result ProgramD3D::link(const gl::Context *context, std::shared_ptrslowCompilingUniformBlockSet) { - std::ostringstream stream; - stream << "Uniform block '" << slowBlock << "' will be slow to compile. " - << "See UniformBlockToStructuredBufferTranslation.md " - << "(https://shorturl.at/drFY7) for details."; ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_MEDIUM, - stream.str().c_str()); + "Uniform block '%s' will be slow to compile. " + "See UniformBlockToStructuredBufferTranslation.md " + "(https://shorturl.at/drFY7) for details.", + slowBlock.c_str()); } } } diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index 5cb1b22e6..14302d1bb 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -4513,7 +4513,7 @@ angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker) void ContextVk::insertEventMarkerImpl(GLenum source, const char *marker) { - if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode()) + if (!isDebugEnabled()) { return; } @@ -4556,7 +4556,7 @@ angle::Result ContextVk::popDebugGroup(const gl::Context *context) angle::Result ContextVk::pushDebugGroupImpl(GLenum source, GLuint id, const char *message) { - if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode()) + if (!isDebugEnabled()) { return angle::Result::Continue; } @@ -4578,7 +4578,7 @@ angle::Result ContextVk::pushDebugGroupImpl(GLenum source, GLuint id, const char angle::Result ContextVk::popDebugGroupImpl() { - if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode()) + if (!isDebugEnabled()) { return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h index 0c57a1028..8727aef27 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.h +++ b/src/libANGLE/renderer/vulkan/ContextVk.h @@ -235,6 +235,11 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText // Device loss gl::GraphicsResetStatus getResetStatus() override; + bool isDebugEnabled() + { + return mRenderer->enableDebugUtils() || mRenderer->angleDebuggerMode(); + } + // EXT_debug_marker angle::Result insertEventMarker(GLsizei length, const char *marker) override; angle::Result pushGroupMarker(GLsizei length, const char *marker) override; @@ -1730,14 +1735,16 @@ uint32_t GetDriverUniformSize(vk::Context *context, PipelineType pipelineType); } // namespace rx // Generate a perf warning, and insert an event marker in the command buffer. -#define ANGLE_VK_PERF_WARNING(contextVk, severity, ...) \ - do \ - { \ - char ANGLE_MESSAGE[200]; \ - snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \ - ANGLE_PERF_WARNING(contextVk->getDebug(), severity, ANGLE_MESSAGE); \ - \ - contextVk->insertEventMarkerImpl(GL_DEBUG_SOURCE_OTHER, ANGLE_MESSAGE); \ +#define ANGLE_VK_PERF_WARNING(contextVk, severity, ...) \ + do \ + { \ + ANGLE_PERF_WARNING(contextVk->getDebug(), severity, __VA_ARGS__); \ + if (contextVk->isDebugEnabled()) \ + { \ + char ANGLE_MESSAGE[200]; \ + snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \ + contextVk->insertEventMarkerImpl(GL_DEBUG_SOURCE_OTHER, ANGLE_MESSAGE); \ + } \ } while (0) // Generate a trace event for graphics profiler, and insert an event marker in the command buffer.