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 <bajones@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Brandon Jones 2021-09-29 19:39:02 +00:00 committed by Dawn LUCI CQ
parent 9b643b72f7
commit d6d2584480
8 changed files with 63 additions and 18 deletions

View File

@ -848,6 +848,7 @@ namespace dawn_native {
} }
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup); allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
mDebugGroupStackSize--; mDebugGroupStackSize--;
mEncodingContext.PopDebugGroupLabel();
return {}; return {};
}, },
@ -866,6 +867,7 @@ namespace dawn_native {
memcpy(label, groupLabel, cmd->length + 1); memcpy(label, groupLabel, cmd->length + 1);
mDebugGroupStackSize++; mDebugGroupStackSize++;
mEncodingContext.PushDebugGroupLabel(groupLabel);
return {}; return {};
}, },

View File

@ -402,22 +402,7 @@ namespace dawn_native {
void DeviceBase::ConsumeError(std::unique_ptr<ErrorData> error) { void DeviceBase::ConsumeError(std::unique_ptr<ErrorData> error) {
ASSERT(error != nullptr); ASSERT(error != nullptr);
std::ostringstream ss; HandleError(error->GetType(), error->GetFormattedMessage().c_str());
ss << error->GetMessage();
// TODO(dawn:563): Print debug groups when avaialble.
const std::vector<std::string>& 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());
} }
void DeviceBase::APISetLoggingCallback(wgpu::LoggingCallback callback, void* userdata) { void DeviceBase::APISetLoggingCallback(wgpu::LoggingCallback callback, void* userdata) {

View File

@ -56,6 +56,12 @@ namespace dawn_native {
} }
void EncodingContext::HandleError(std::unique_ptr<ErrorData> error) { void EncodingContext::HandleError(std::unique_ptr<ErrorData> 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()) { if (!IsFinished()) {
// Encoding should only generate validation errors. // Encoding should only generate validation errors.
ASSERT(error->GetType() == InternalErrorType::Validation); ASSERT(error->GetType() == InternalErrorType::Validation);
@ -65,7 +71,7 @@ namespace dawn_native {
mError = std::move(error); mError = std::move(error);
} }
} else { } 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); return std::move(mComputePassUsages);
} }
void EncodingContext::PushDebugGroupLabel(const char* groupLabel) {
mDebugGroupLabels.emplace_back(groupLabel);
}
void EncodingContext::PopDebugGroupLabel() {
mDebugGroupLabels.pop_back();
}
MaybeError EncodingContext::Finish() { MaybeError EncodingContext::Finish() {
if (IsFinished()) { if (IsFinished()) {
return DAWN_VALIDATION_ERROR("Command encoding already finished"); return DAWN_VALIDATION_ERROR("Command encoding already finished");

View File

@ -124,6 +124,9 @@ namespace dawn_native {
RenderPassUsages AcquireRenderPassUsages(); RenderPassUsages AcquireRenderPassUsages();
ComputePassUsages AcquireComputePassUsages(); ComputePassUsages AcquireComputePassUsages();
void PushDebugGroupLabel(const char* groupLabel);
void PopDebugGroupLabel();
private: private:
void CommitCommands(CommandAllocator allocator); void CommitCommands(CommandAllocator allocator);
@ -155,6 +158,7 @@ namespace dawn_native {
bool mWereCommandsAcquired = false; bool mWereCommandsAcquired = false;
std::unique_ptr<ErrorData> mError; std::unique_ptr<ErrorData> mError;
std::vector<std::string> mDebugGroupLabels;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -47,6 +47,10 @@ namespace dawn_native {
mContexts.push_back(std::move(context)); mContexts.push_back(std::move(context));
} }
void ErrorData::AppendDebugGroup(std::string label) {
mDebugGroups.push_back(std::move(label));
}
InternalErrorType ErrorData::GetType() const { InternalErrorType ErrorData::GetType() const {
return mType; return mType;
} }
@ -63,4 +67,33 @@ namespace dawn_native {
return mContexts; return mContexts;
} }
const std::vector<std::string>& 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 } // namespace dawn_native

View File

@ -49,17 +49,22 @@ namespace dawn_native {
}; };
void AppendBacktrace(const char* file, const char* function, int line); void AppendBacktrace(const char* file, const char* function, int line);
void AppendContext(std::string context); void AppendContext(std::string context);
void AppendDebugGroup(std::string label);
InternalErrorType GetType() const; InternalErrorType GetType() const;
const std::string& GetMessage() const; const std::string& GetMessage() const;
const std::vector<BacktraceRecord>& GetBacktrace() const; const std::vector<BacktraceRecord>& GetBacktrace() const;
const std::vector<std::string>& GetContexts() const; const std::vector<std::string>& GetContexts() const;
const std::vector<std::string>& GetDebugGroups() const;
std::string GetFormattedMessage() const;
private: private:
InternalErrorType mType; InternalErrorType mType;
std::string mMessage; std::string mMessage;
std::vector<BacktraceRecord> mBacktrace; std::vector<BacktraceRecord> mBacktrace;
std::vector<std::string> mContexts; std::vector<std::string> mContexts;
std::vector<std::string> mDebugGroups;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -196,7 +196,7 @@ namespace dawn_native {
std::unique_ptr<ErrorData> error = maybeError.AcquireError(); std::unique_ptr<ErrorData> error = maybeError.AcquireError();
ASSERT(error != nullptr); ASSERT(error != nullptr);
dawn::InfoLog() << error->GetMessage(); dawn::InfoLog() << error->GetFormattedMessage();
return true; return true;
} }

View File

@ -82,6 +82,7 @@ namespace dawn_native {
} }
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup); allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
mDebugGroupStackSize--; mDebugGroupStackSize--;
mEncodingContext->PopDebugGroupLabel();
return {}; return {};
}, },
@ -100,6 +101,7 @@ namespace dawn_native {
memcpy(label, groupLabel, cmd->length + 1); memcpy(label, groupLabel, cmd->length + 1);
mDebugGroupStackSize++; mDebugGroupStackSize++;
mEncodingContext->PushDebugGroupLabel(groupLabel);
return {}; return {};
}, },