Rewrite the analytics intro text to be less of a wall of text

* Also add a preview of what data will be included in any report, both
  in the intro and in the confirmation before sending any report.
This commit is contained in:
baldurk
2018-01-19 16:33:45 +00:00
parent 65ef82466c
commit 33b3176cd4
8 changed files with 267 additions and 29 deletions
+222 -18
View File
@@ -23,15 +23,51 @@
******************************************************************************/
#include <QBuffer>
#include <QDialog>
#include <QDialogButtonBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTextEdit>
#include <QUrlQuery>
#include <QVBoxLayout>
#include "Code/QRDUtils.h"
#include "Windows/Dialogs/AnalyticsConfirmDialog.h"
#include "Windows/Dialogs/AnalyticsPromptDialog.h"
#include "QRDInterface.h"
#if RENDERDOC_ANALYTICS_ENABLE
template <>
inline const char *TypeName<QString>()
{
return "string";
}
template <>
inline const char *TypeName<QStringList>()
{
return "string array";
}
template <>
inline const char *TypeName<bool>()
{
return "bool";
}
template <>
inline const char *TypeName<AnalyticsAverage>()
{
return "Average";
}
template <>
inline const char *TypeName<bool[32]>()
{
// DaysUsed
return "int";
}
namespace
{
enum class AnalyticsState
@@ -46,6 +82,7 @@ enum class AnalyticsSerialiseType
Loading,
Saving,
Reporting,
Documenting,
};
static AnalyticsState analyticsState = AnalyticsState::Nothing;
@@ -139,17 +176,139 @@ void saveTo(QVariantMap &parent, const QString &name, const T &el, bool reportin
parent[name] = analyticsToVar<T>(el, reporting);
}
// add a macro to either load or save, depending on our state.
#define ANALYTIC_SERIALISE(varname) \
if(type == AnalyticsSerialiseType::Loading) \
{ \
loadFrom(values, lit(#varname), Analytics::db->varname); \
} \
else \
{ \
saveTo(values, lit(#varname), Analytics::db->varname, reporting); \
// add a macro to either document, load, or save, depending on our state.
#define ANALYTIC_SERIALISE(varname) \
if(type == AnalyticsSerialiseType::Documenting) \
{ \
QString var = lit(#varname); \
int idx = var.indexOf(QLatin1Char('.')); \
if(idx >= 0) \
var = var.mid(idx + 1); \
doc += lit("<b>%1 (%2)</b>: %3<br>") \
.arg(var) \
.arg(QString::fromUtf8(TypeName<decltype(Analytics::db->varname)>())) \
.arg(docs.varname); \
} \
else if(type == AnalyticsSerialiseType::Loading) \
{ \
loadFrom(values, lit(#varname), Analytics::db->varname); \
} \
else \
{ \
saveTo(values, lit(#varname), Analytics::db->varname, reporting); \
}
// only used during documenting
#define ANALYTIC_SECTION(section) \
if(type == AnalyticsSerialiseType::Documenting) \
{ \
doc += lit("<h2>%1</h2>").arg(docs.section_##section); \
}
// macros for documenting the analytic values
#define DOCUMENT_ANALYTIC(name, docs) QString name = lit(docs);
#define DOCUMENT_ANALYTIC_SECTION(name, docs) \
name; \
QString section_##name = lit(docs);
// must match the properties in Analytics
static struct AnalyticsDocumentation
{
struct
{
DOCUMENT_ANALYTIC(Year, "The year this data was recorded in.");
DOCUMENT_ANALYTIC(Month, "The month this data was recorded in.");
} DOCUMENT_ANALYTIC_SECTION(Date, "Date range");
DOCUMENT_ANALYTIC(Version, "The version number of the analytics data.");
struct
{
DOCUMENT_ANALYTIC(RenderDocVersion, "The RenderDoc build version used to submit the report.");
DOCUMENT_ANALYTIC(DistributionVersion, "The distribution version, if this is a linux build.");
DOCUMENT_ANALYTIC(OSVersion, "OS version as reported by Qt.");
DOCUMENT_ANALYTIC(Bitness, "Whether the build is 64-bit or 32-bit.");
DOCUMENT_ANALYTIC(DevelBuildRun,
"Has a local or nightly or otherwise unofficial build been run?");
DOCUMENT_ANALYTIC(OfficialBuildRun, "Has an officially produced binary build been run?");
DOCUMENT_ANALYTIC(DaysUsed, "How many unique days in this month was the program run?");
} DOCUMENT_ANALYTIC_SECTION(Metadata, "Metadata");
struct
{
DOCUMENT_ANALYTIC(LoadTime, "How long (on average) did captures take to load?");
} DOCUMENT_ANALYTIC_SECTION(Performance, "Performance");
DOCUMENT_ANALYTIC(APIs, "A list of the distinct APIs that were replayed.");
DOCUMENT_ANALYTIC(GPUVendors, "A list of the distinct GPU vendors used for replay.");
struct
{
DOCUMENT_ANALYTIC(Bookmarks, "Did the user set any event bookmarks?");
DOCUMENT_ANALYTIC(ResourceInspect, "Did the user use the resource inspector?");
DOCUMENT_ANALYTIC(ShaderEditing, "Did the user edit a shader (any API)?");
DOCUMENT_ANALYTIC(CallstackResolve, "Did the user capture and resolve CPU callstacks?");
DOCUMENT_ANALYTIC(PixelHistory, "Did the user run a pixel history?");
DOCUMENT_ANALYTIC(DrawcallTimes, "Did the user fetch drawcall timings/durations?");
DOCUMENT_ANALYTIC(PerformanceCounters, "Did the user fetch advanced performance counters?");
DOCUMENT_ANALYTIC(PythonInterop, "Did the user run any python scripts or commands?");
DOCUMENT_ANALYTIC(CustomTextureVisualise,
"Did the user use a custom texture visualisation shader?");
DOCUMENT_ANALYTIC(ImageViewer,
"Did the user employ RenderDoc as an image (DDS/PNG/HDR) viewer?");
DOCUMENT_ANALYTIC(CaptureComments,
"Did the user make and save any comments in a capture file?");
DOCUMENT_ANALYTIC(AndroidRemoteReplay, "Did the user use Android remote replay functionality?");
DOCUMENT_ANALYTIC(NonAndroidRemoteReplay, "Did the user use remote replay on non-Android?");
} DOCUMENT_ANALYTIC_SECTION(UIFeatures, "UI Features");
struct
{
DOCUMENT_ANALYTIC(EventBrowser, "Did the user ever export drawcalls from the event browser?");
DOCUMENT_ANALYTIC(PipelineState, "Did the user ever export the pipeline state (any API)?");
DOCUMENT_ANALYTIC(MeshOutput, "Did the user ever export mesh data (inputs or outputs)?");
DOCUMENT_ANALYTIC(RawBuffer, "Did the user ever export raw buffer data?");
DOCUMENT_ANALYTIC(Texture, "Did the user ever export a texture?");
DOCUMENT_ANALYTIC(Shader, "Did the user ever export a shader?");
} DOCUMENT_ANALYTIC_SECTION(Export, "Data Export");
struct
{
DOCUMENT_ANALYTIC(Vertex, "Did the user ever debug a vertex shader?");
DOCUMENT_ANALYTIC(Pixel, "Did the user ever debug a pixel shader?");
DOCUMENT_ANALYTIC(Compute, "Did the user ever debug a compute shader?");
} DOCUMENT_ANALYTIC_SECTION(ShaderDebug, "Shader Debugging");
struct
{
DOCUMENT_ANALYTIC(Drawcall, "Did the user use the Drawcall overlay?");
DOCUMENT_ANALYTIC(Wireframe, "Did the user use the Wireframe overlay?");
DOCUMENT_ANALYTIC(Depth, "Did the user use the Depth Test overlay?");
DOCUMENT_ANALYTIC(Stencil, "Did the user use the Stencil Test overlay?");
DOCUMENT_ANALYTIC(BackfaceCull, "Did the user use the Backface Culling overlay?");
DOCUMENT_ANALYTIC(ViewportScissor, "Did the user use the Viewport/Scissor overlay?");
DOCUMENT_ANALYTIC(NaN, "Did the user use the NaN/Inf/-ve overlay?");
DOCUMENT_ANALYTIC(Clipping, "Did the user use the Histogram Clipping overlay?");
DOCUMENT_ANALYTIC(ClearBeforePass, "Did the user use the Clear Before Pass overlay?");
DOCUMENT_ANALYTIC(ClearBeforeDraw, "Did the user use the Clear Before Draw overlay?");
DOCUMENT_ANALYTIC(QuadOverdrawPass, "Did the user use the Quad Overdraw (Pass) overlay?");
DOCUMENT_ANALYTIC(QuadOverdrawDraw, "Did the user use the Quad Overdraw (Draw) overlay?");
DOCUMENT_ANALYTIC(TriangleSizePass, "Did the user use the Triangle Size (Pass) overlay?");
DOCUMENT_ANALYTIC(TriangleSizeDraw, "Did the user use the Triangle Size (Draw) overlay?");
} DOCUMENT_ANALYTIC_SECTION(TextureOverlays, "Texture Overlays");
struct
{
DOCUMENT_ANALYTIC(ShaderLinkage, "Did any capture use 'shader linkage' functionality?");
DOCUMENT_ANALYTIC(YUVTextures, "Did any capture use YUV/composite textures?");
DOCUMENT_ANALYTIC(SparseResources, "Did any capture use sparse aka tiled resources?");
DOCUMENT_ANALYTIC(MultiGPU, "Did any capture make use of multiple GPUs?");
DOCUMENT_ANALYTIC(D3D12Bundle, "Did any D3D12 capture use bundles?");
} DOCUMENT_ANALYTIC_SECTION(CaptureFeatures, "Capture API Usage");
} docs;
void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
{
bool reporting = type == AnalyticsSerialiseType::Reporting;
@@ -159,14 +318,19 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
static_assert(sizeof(Analytics) == 147, "Sizeof Analytics has changed - update serialisation.");
// Date
QString doc;
doc += lit("<h1>Report Explained</h1>");
ANALYTIC_SERIALISE(Version);
ANALYTIC_SECTION(Date);
{
ANALYTIC_SERIALISE(Date.Year);
ANALYTIC_SERIALISE(Date.Month);
}
ANALYTIC_SERIALISE(Version);
// Metadata
ANALYTIC_SECTION(Metadata);
{
ANALYTIC_SERIALISE(Metadata.RenderDocVersion);
ANALYTIC_SERIALISE(Metadata.DistributionVersion);
@@ -190,15 +354,17 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
}
}
// Performance
ANALYTIC_SECTION(Performance);
{
ANALYTIC_SERIALISE(Performance.LoadTime);
}
doc += lit("<h2>API/GPU Usage</h2>");
ANALYTIC_SERIALISE(APIs);
ANALYTIC_SERIALISE(GPUVendors);
// UIFeatures
ANALYTIC_SECTION(UIFeatures);
{
ANALYTIC_SERIALISE(UIFeatures.Bookmarks);
ANALYTIC_SERIALISE(UIFeatures.ResourceInspect);
@@ -215,7 +381,7 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
ANALYTIC_SERIALISE(UIFeatures.NonAndroidRemoteReplay);
}
// Export
ANALYTIC_SECTION(Export);
{
ANALYTIC_SERIALISE(Export.EventBrowser);
ANALYTIC_SERIALISE(Export.PipelineState);
@@ -225,14 +391,14 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
ANALYTIC_SERIALISE(Export.Shader);
}
// ShaderDebug
ANALYTIC_SECTION(ShaderDebug);
{
ANALYTIC_SERIALISE(ShaderDebug.Vertex);
ANALYTIC_SERIALISE(ShaderDebug.Pixel);
ANALYTIC_SERIALISE(ShaderDebug.Compute);
}
// TextureOverlays
ANALYTIC_SECTION(TextureOverlays);
{
ANALYTIC_SERIALISE(TextureOverlays.Drawcall);
ANALYTIC_SERIALISE(TextureOverlays.Wireframe);
@@ -250,7 +416,7 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
ANALYTIC_SERIALISE(TextureOverlays.TriangleSizeDraw);
}
// CaptureFeatures
ANALYTIC_SECTION(CaptureFeatures);
{
ANALYTIC_SERIALISE(CaptureFeatures.ShaderLinkage);
ANALYTIC_SERIALISE(CaptureFeatures.YUVTextures);
@@ -258,6 +424,8 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
ANALYTIC_SERIALISE(CaptureFeatures.MultiGPU);
ANALYTIC_SERIALISE(CaptureFeatures.D3D12Bundle);
}
values[lit("doc")] = doc;
}
}; // anonymous namespace
@@ -321,6 +489,38 @@ void Analytics::Load()
}
}
void Analytics::DocumentReport()
{
QVariantMap dummy;
AnalyticsSerialise(dummy, AnalyticsSerialiseType::Documenting);
QString reportText = dummy[lit("doc")].toString();
{
QDialog dialog;
dialog.setWindowTitle(lit("Sample Analytics Report"));
dialog.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
dialog.setFixedSize(600, 500);
QDialogButtonBox buttons;
buttons.addButton(QDialogButtonBox::Ok);
QObject::connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QTextEdit report;
report.setReadOnly(true);
report.setAcceptRichText(true);
report.setText(reportText);
QVBoxLayout layout;
layout.addWidget(&report);
layout.addWidget(&buttons);
dialog.setLayout(&layout);
RDDialog::show(&dialog);
}
}
void Analytics::Prompt(ICaptureContext &ctx, PersistantConfig &config)
{
if(analyticsState == AnalyticsState::PromptFirstTime)
@@ -389,6 +589,10 @@ void Load()
void Prompt(ICaptureContext &ctx, PersistantConfig &config)
{
}
void DocumentReport()
{
}
};
#endif