From d6d2584480962a243200e6eb18085e7707d09edd Mon Sep 17 00:00:00 2001 From: Brandon Jones Date: Wed, 29 Sep 2021 19:39:02 +0000 Subject: [PATCH] Add debug group logging to validation errors Updates the formatted error messages to display as: Error message text. - While context 2. - While context 1. Debug group stack: > "Debug Group Label 2" > "Debug Group Label 1" Bug: dawn:563 Change-Id: I66f5ed59d3e6960722c0d1faf7eaa770d9774eb6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65480 Commit-Queue: Brandon Jones Reviewed-by: Corentin Wallez --- src/dawn_native/CommandEncoder.cpp | 2 ++ src/dawn_native/Device.cpp | 17 +---------- src/dawn_native/EncodingContext.cpp | 16 +++++++++- src/dawn_native/EncodingContext.h | 4 +++ src/dawn_native/ErrorData.cpp | 33 +++++++++++++++++++++ src/dawn_native/ErrorData.h | 5 ++++ src/dawn_native/Instance.cpp | 2 +- src/dawn_native/ProgrammablePassEncoder.cpp | 2 ++ 8 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index 2a32c3e47e..7d70b0dc2a 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp @@ -848,6 +848,7 @@ namespace dawn_native { } allocator->Allocate(Command::PopDebugGroup); mDebugGroupStackSize--; + mEncodingContext.PopDebugGroupLabel(); return {}; }, @@ -866,6 +867,7 @@ namespace dawn_native { memcpy(label, groupLabel, cmd->length + 1); mDebugGroupStackSize++; + mEncodingContext.PushDebugGroupLabel(groupLabel); return {}; }, diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index bd84b5e78e..6f9ccff862 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -402,22 +402,7 @@ namespace dawn_native { void DeviceBase::ConsumeError(std::unique_ptr error) { ASSERT(error != nullptr); - std::ostringstream ss; - ss << error->GetMessage(); - - // TODO(dawn:563): Print debug groups when avaialble. - const std::vector& contexts = error->GetContexts(); - if (!contexts.empty()) { - for (auto context : contexts) { - ss << "\n - While " << context; - } - } else { - for (const auto& callsite : error->GetBacktrace()) { - ss << "\n at " << callsite.function << " (" << callsite.file << ":" - << callsite.line << ")"; - } - } - HandleError(error->GetType(), ss.str().c_str()); + HandleError(error->GetType(), error->GetFormattedMessage().c_str()); } void DeviceBase::APISetLoggingCallback(wgpu::LoggingCallback callback, void* userdata) { diff --git a/src/dawn_native/EncodingContext.cpp b/src/dawn_native/EncodingContext.cpp index 9e7b960345..2724291234 100644 --- a/src/dawn_native/EncodingContext.cpp +++ b/src/dawn_native/EncodingContext.cpp @@ -56,6 +56,12 @@ namespace dawn_native { } void EncodingContext::HandleError(std::unique_ptr error) { + // Append in reverse so that the most recently set debug group is printed first, like a + // call stack. + for (auto iter = mDebugGroupLabels.rbegin(); iter != mDebugGroupLabels.rend(); ++iter) { + error->AppendDebugGroup(*iter); + } + if (!IsFinished()) { // Encoding should only generate validation errors. ASSERT(error->GetType() == InternalErrorType::Validation); @@ -65,7 +71,7 @@ namespace dawn_native { mError = std::move(error); } } else { - mDevice->HandleError(error->GetType(), error->GetMessage().c_str()); + mDevice->HandleError(error->GetType(), error->GetFormattedMessage().c_str()); } } @@ -146,6 +152,14 @@ namespace dawn_native { return std::move(mComputePassUsages); } + void EncodingContext::PushDebugGroupLabel(const char* groupLabel) { + mDebugGroupLabels.emplace_back(groupLabel); + } + + void EncodingContext::PopDebugGroupLabel() { + mDebugGroupLabels.pop_back(); + } + MaybeError EncodingContext::Finish() { if (IsFinished()) { return DAWN_VALIDATION_ERROR("Command encoding already finished"); diff --git a/src/dawn_native/EncodingContext.h b/src/dawn_native/EncodingContext.h index 87dfecb4ff..b058e2bc61 100644 --- a/src/dawn_native/EncodingContext.h +++ b/src/dawn_native/EncodingContext.h @@ -124,6 +124,9 @@ namespace dawn_native { RenderPassUsages AcquireRenderPassUsages(); ComputePassUsages AcquireComputePassUsages(); + void PushDebugGroupLabel(const char* groupLabel); + void PopDebugGroupLabel(); + private: void CommitCommands(CommandAllocator allocator); @@ -155,6 +158,7 @@ namespace dawn_native { bool mWereCommandsAcquired = false; std::unique_ptr mError; + std::vector mDebugGroupLabels; }; } // namespace dawn_native diff --git a/src/dawn_native/ErrorData.cpp b/src/dawn_native/ErrorData.cpp index f1c57c8f4d..8c9bbf6ed9 100644 --- a/src/dawn_native/ErrorData.cpp +++ b/src/dawn_native/ErrorData.cpp @@ -47,6 +47,10 @@ namespace dawn_native { mContexts.push_back(std::move(context)); } + void ErrorData::AppendDebugGroup(std::string label) { + mDebugGroups.push_back(std::move(label)); + } + InternalErrorType ErrorData::GetType() const { return mType; } @@ -63,4 +67,33 @@ namespace dawn_native { return mContexts; } + const std::vector& ErrorData::GetDebugGroups() const { + return mDebugGroups; + } + + std::string ErrorData::GetFormattedMessage() const { + std::ostringstream ss; + ss << mMessage; + + if (!mContexts.empty()) { + for (auto context : mContexts) { + ss << "\n - While " << context; + } + } else { + for (const auto& callsite : mBacktrace) { + ss << "\n at " << callsite.function << " (" << callsite.file << ":" + << callsite.line << ")"; + } + } + + if (!mDebugGroups.empty()) { + ss << "\n\nDebug group stack: "; + for (auto label : mDebugGroups) { + ss << "\n > \"" << label << "\""; + } + } + + return ss.str(); + } + } // namespace dawn_native diff --git a/src/dawn_native/ErrorData.h b/src/dawn_native/ErrorData.h index fa130b119e..477a7e721b 100644 --- a/src/dawn_native/ErrorData.h +++ b/src/dawn_native/ErrorData.h @@ -49,17 +49,22 @@ namespace dawn_native { }; void AppendBacktrace(const char* file, const char* function, int line); void AppendContext(std::string context); + void AppendDebugGroup(std::string label); InternalErrorType GetType() const; const std::string& GetMessage() const; const std::vector& GetBacktrace() const; const std::vector& GetContexts() const; + const std::vector& GetDebugGroups() const; + + std::string GetFormattedMessage() const; private: InternalErrorType mType; std::string mMessage; std::vector mBacktrace; std::vector mContexts; + std::vector mDebugGroups; }; } // namespace dawn_native diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index b400f4081d..a89396abd3 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -196,7 +196,7 @@ namespace dawn_native { std::unique_ptr error = maybeError.AcquireError(); ASSERT(error != nullptr); - dawn::InfoLog() << error->GetMessage(); + dawn::InfoLog() << error->GetFormattedMessage(); return true; } diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp index de2803375a..5f7ed7710f 100644 --- a/src/dawn_native/ProgrammablePassEncoder.cpp +++ b/src/dawn_native/ProgrammablePassEncoder.cpp @@ -82,6 +82,7 @@ namespace dawn_native { } allocator->Allocate(Command::PopDebugGroup); mDebugGroupStackSize--; + mEncodingContext->PopDebugGroupLabel(); return {}; }, @@ -100,6 +101,7 @@ namespace dawn_native { memcpy(label, groupLabel, cmd->length + 1); mDebugGroupStackSize++; + mEncodingContext->PushDebugGroupLabel(groupLabel); return {}; },