Add string messages to returned result codes to display to user

* Most of the main entry points that can fail with relevant reasons now has a
  way of specifying a message to return with it. This message can be displayed
  to the user to give more information or context about an error.
This commit is contained in:
baldurk
2022-04-26 16:21:54 +01:00
parent 10dd4c194c
commit 8aa0390948
145 changed files with 2978 additions and 1874 deletions
+65 -81
View File
@@ -101,47 +101,54 @@ CaptureContext::CaptureContext(PersistantConfig &cfg) : m_Config(cfg)
m_Replay.SetFatalErrorCallback([this]() {
GUIInvoke::call(m_MainWindow, [this]() {
RefreshUIStatus({}, true, true);
ResultDetails err = GetFatalError();
ReplayStatus err = GetFatalError();
// if we encountered a fatal error during shutdown just ignore it, there's not much point in
// alerting the user and the recorded error will be gone already
if(!m_Replay.IsRunning())
return;
RefreshUIStatus({}, true, true);
QString title;
QString text;
if(err == ReplayStatus::RemoteServerConnectionLost)
if(err.code == ResultCode::RemoteServerConnectionLost)
{
QString serverName = Replay().CurrentRemote().Name();
title = tr("Connection lost to %1").arg(serverName);
text =
tr("Connection to %1 was lost while analysing capture.\n"
tr("%1.\n\n"
"This is most commonly caused by a crash, but that can't be verified and it may be "
"a connection issue.")
.arg(serverName);
.arg(err.Message());
}
else if(err == ReplayStatus::ReplayDeviceLost)
else if(err.code == ResultCode::ReplayDeviceLost)
{
title = tr("Device Lost error");
text =
tr("The capture analysis encountered a device lost error. This may be due to an "
"application bug, a RenderDoc bug, or insufficient resources on the system to "
"analyse the capture.\n\n"
"It is recommended that you run your application with API validation enabled, as "
"API use errors can cause this kind of problem.");
text = tr("%1.\n\n"
"This may be due to an application bug, a RenderDoc bug, or insufficient "
"resources on the system to analyse the capture.\n\n"
"It is recommended that you run your application with API validation enabled, as "
"API usage errors can cause this kind of problem.")
.arg(err.Message());
}
else if(err == ReplayStatus::ReplayOutOfMemory)
else if(err.code == ResultCode::ReplayOutOfMemory)
{
title = tr("Out of GPU memory");
text = tr(
"While analysing the capture it ran out of GPU memory. This is most likely caused by "
"insufficient resources on the system to analyse the capture, which is possible if "
"there is memory pressure from other applications or if the capture is heavyweight.");
title = tr("Out of memory");
text =
tr("%1.\n\n"
"This is most likely caused by "
"insufficient resources on the system to analyse the capture, which is possible if "
"there is memory pressure from other applications or if the capture is heavyweight.")
.arg(err.Message());
}
else
{
title = tr("Unrecoverable error");
text = tr("While analysing the capture we encountered an unrecoverable error:\n\n%1")
.arg(QString(ToStr(err)));
.arg(err.Message());
}
text +=
@@ -445,9 +452,9 @@ bool CaptureContext::IsExtensionLoaded(rdcstr name)
return m_ExtensionObjects.contains(name);
}
bool CaptureContext::LoadExtension(rdcstr name)
rdcstr CaptureContext::LoadExtension(rdcstr name)
{
bool ret = false;
QString ret;
PythonContext::ProcessExtensionWork([this, &ret, name]() {
for(QObject *o : m_ExtensionObjects[name])
@@ -457,7 +464,7 @@ bool CaptureContext::LoadExtension(rdcstr name)
ret = PythonContext::LoadExtension(*this, name);
if(ret)
if(ret.isEmpty())
{
m_ExtensionObjects[name].swap(m_PendingExtensionObjects);
}
@@ -944,17 +951,15 @@ void CaptureContext::LoadCaptureThreaded(const QString &captureFile, const Repla
// this function call will block until the capture is either loaded, or there's some failure
m_Replay.OpenCapture(captureFile, opts, [this](float p) { m_LoadProgress = p; });
QString filename = QFileInfo(origFilename).fileName();
// if the renderer isn't running, we hit a failure case so display an error message
if(!m_Replay.IsRunning())
{
QString errmsg = ToQStr(m_Replay.GetCreateStatus());
QString messageText = tr("%1\nFailed to open capture for replay: %2.\n\n"
"Check diagnostic log in Help menu for more details.")
.arg(captureFile)
.arg(errmsg);
RDDialog::critical(NULL, tr("Error opening capture"), messageText);
RDDialog::critical(NULL, tr("Error opening capture"),
tr("Failed to open '%1' for replay\n\n%2")
.arg(filename)
.arg(m_Replay.GetCreateStatus().Message()));
m_LoadInProgress = false;
return;
@@ -1343,7 +1348,9 @@ bool CaptureContext::SaveCaptureTo(const rdcstr &captureFile)
if(capFile)
{
// this will overwrite
success = capFile->CopyFileTo(captureFile);
ResultDetails result = capFile->CopyFileTo(captureFile);
success = result.OK();
error = result.Message();
}
else
{
@@ -1351,18 +1358,17 @@ bool CaptureContext::SaveCaptureTo(const rdcstr &captureFile)
// prompted for overwrite)
QFile::remove(captureFile);
success = QFile::copy(GetCaptureFilename(), captureFile);
error = tr("File move failed");
}
error = tr("Couldn't save to %1").arg(captureFile);
error = tr("Couldn't save to %1: %2").arg(captureFile).arg(error);
}
}
else
{
RDDialog::critical(
NULL, tr("File not found"),
error =
tr("Capture '%1' couldn't be found on disk, cannot save.").arg(GetCaptureFilename()));
error = tr("Capture '%1' couldn't be found on disk, cannot save.").arg(GetCaptureFilename());
success = false;
RDDialog::critical(NULL, tr("File not found"), error);
}
}
else
@@ -1463,29 +1469,27 @@ bool CaptureContext::ImportCapture(const CaptureFileFormat &fmt, const rdcstr &i
QString ext = fmt.extension;
ReplayStatus status = ReplayStatus::UnknownError;
QString message;
ResultDetails result;
// shorten the filename after here for error messages
QString filename = QFileInfo(importfile).fileName();
float progress = 0.0f;
LambdaThread *th = new LambdaThread([rdcfile, importfile, ext, &message, &progress, &status]() {
LambdaThread *th = new LambdaThread([rdcfile, importfile, ext, &progress, &result]() {
ICaptureFile *file = RENDERDOC_OpenCaptureFile();
status = file->OpenFile(importfile, ext.toUtf8().data(),
result = file->OpenFile(importfile, ext.toUtf8().data(),
[&progress](float p) { progress = p * 0.5f; });
if(status != ReplayStatus::Succeeded)
if(result.code != ResultCode::Succeeded)
{
message = file->ErrorString();
file->Shutdown();
return;
}
status =
result =
file->Convert(rdcfile, "rdc", NULL, [&progress](float p) { progress = 0.5f + p * 0.5f; });
file->Shutdown();
});
@@ -1500,15 +1504,10 @@ bool CaptureContext::ImportCapture(const CaptureFileFormat &fmt, const rdcstr &i
}
th->deleteLater();
if(status != ReplayStatus::Succeeded)
if(!result.OK())
{
QString text = tr("Couldn't convert file '%1'\n").arg(filename);
if(message.isEmpty())
text += tr("%1").arg(ToQStr(status));
else
text += tr("%1: %2").arg(ToQStr(status)).arg(message);
RDDialog::critical(m_MainWindow, tr("Error converting capture"), text);
RDDialog::critical(m_MainWindow, tr("Error converting capture"),
tr("Couldn't convert file '%1'\n%2").arg(filename).arg(result.Message()));
return false;
}
@@ -1524,7 +1523,7 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
ICaptureFile *local = NULL;
ICaptureFile *file = NULL;
ReplayStatus status = ReplayStatus::Succeeded;
ResultDetails result = {ResultCode::Succeeded};
const SDFile *sdfile = NULL;
@@ -1538,21 +1537,16 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
if(!file)
{
local = file = RENDERDOC_OpenCaptureFile();
status = file->OpenFile(m_CaptureFile, "rdc", NULL);
result = file->OpenFile(m_CaptureFile, "rdc", NULL);
}
QString filename = QFileInfo(m_CaptureFile).fileName();
if(status != ReplayStatus::Succeeded)
if(!result.OK())
{
QString text = tr("Couldn't open file '%1' for export\n").arg(filename);
QString message = file->ErrorString();
if(message.isEmpty())
text += tr("%1").arg(ToQStr(status));
else
text += tr("%1: %2").arg(ToQStr(status)).arg(message);
RDDialog::critical(m_MainWindow, tr("Error opening file"), text);
RDDialog::critical(
m_MainWindow, tr("Error opening file"),
tr("Couldn't open file '%1' for export\n%2").arg(filename).arg(result.Message()));
if(local)
local->Shutdown();
@@ -1561,8 +1555,8 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
float progress = 0.0f;
LambdaThread *th = new LambdaThread([file, sdfile, ext, exportfile, &progress, &status]() {
status = file->Convert(exportfile, ext, sdfile, [&progress](float p) { progress = p; });
LambdaThread *th = new LambdaThread([file, sdfile, ext, exportfile, &progress, &result]() {
result = file->Convert(exportfile, ext, sdfile, [&progress](float p) { progress = p; });
});
th->setName(lit("ExportCapture"));
th->start();
@@ -1576,19 +1570,13 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
}
th->deleteLater();
QString message = file->ErrorString();
if(local)
local->Shutdown();
if(status != ReplayStatus::Succeeded)
if(!result.OK())
{
QString text = tr("Couldn't convert file '%1'\n").arg(filename);
if(message.isEmpty())
text += tr("%1").arg(ToQStr(status));
else
text += tr("%1: %2").arg(ToQStr(status)).arg(message);
RDDialog::critical(m_MainWindow, tr("Error converting capture"), text);
RDDialog::critical(m_MainWindow, tr("Error converting capture"),
tr("Couldn't convert file '%1'\n%2").arg(filename).arg(result.Message()));
}
}
@@ -1840,7 +1828,7 @@ bool CaptureContext::SaveRenames()
props.type = SectionType::ResourceRenames;
props.version = 1;
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8()).OK();
}
void CaptureContext::LoadRenames(const QString &data)
@@ -1892,7 +1880,7 @@ bool CaptureContext::SaveBookmarks()
props.type = SectionType::Bookmarks;
props.version = 1;
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8()).OK();
}
void CaptureContext::LoadBookmarks(const QString &data)
@@ -1932,7 +1920,7 @@ bool CaptureContext::SaveNotes()
ANALYTIC_SET(UIFeatures.CaptureComments, true);
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8()).OK();
}
void CaptureContext::LoadNotes(const QString &data)
@@ -1967,7 +1955,7 @@ bool CaptureContext::SaveEdits()
props.type = SectionType::EditedShaders;
props.version = 1;
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8()).OK();
}
void CaptureContext::LoadEdits(const QString &data)
@@ -2655,10 +2643,6 @@ QWidget *CaptureContext::CreateBuiltinWindow(const rdcstr &objectName)
{
return GetDebugMessageView()->Widget();
}
else if(objectName == "diagnosticLogView")
{
return GetDiagnosticLogView()->Widget();
}
else if(objectName == "commentView")
{
return GetCommentView()->Widget();