Merge pull request #7704 from samcake/lemon

Exposing the CPU TIming of the Render Jobs to the JS API
This commit is contained in:
Brad Hefta-Gaub 2016-04-18 18:12:14 -07:00
commit a572ac31dc
6 changed files with 65 additions and 12 deletions

View file

@ -39,6 +39,7 @@ Column {
"Shadow", "Shadow",
"Pyramid Depth", "Pyramid Depth",
"Ambient Occlusion", "Ambient Occlusion",
"Ambient Occlusion Blurred",
"Custom Shader" "Custom Shader"
] ]
RadioButton { RadioButton {

View file

@ -178,9 +178,10 @@ Item {
title: "Items" title: "Items"
height: parent.evalEvenHeight() height: parent.evalEvenHeight()
object: parent.drawOpaqueConfig object: parent.drawOpaqueConfig
plots: [ plots: [
{ {
object: Render.getConfig("DrawOpaqueDeferred"), object: parent.drawOpaqueConfig,
prop: "numDrawn", prop: "numDrawn",
label: "Opaques", label: "Opaques",
color: "#1AC567" color: "#1AC567"
@ -199,6 +200,41 @@ Item {
} }
] ]
} }
PlotPerf {
title: "Timing"
height: parent.evalEvenHeight()
object: parent.drawOpaqueConfig
valueUnit: "ms"
valueScale: 1000
valueNumDigits: "1"
plots: [
{
object: Render.getConfig("DrawOpaqueDeferred"),
prop: "cpuRunTime",
label: "Opaques",
color: "#1AC567"
},
{
object: Render.getConfig("DrawTransparentDeferred"),
prop: "cpuRunTime",
label: "Translucents",
color: "#00B4EF"
},
{
object: Render.getConfig("RenderDeferred"),
prop: "cpuRunTime",
label: "Lighting",
color: "#FED959"
},
{
object: Render.getConfig("RenderDeferredTask"),
prop: "cpuRunTime",
label: "RenderFrame",
color: "#E2334D"
}
]
}
} }
} }

View file

@ -90,6 +90,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// Specular highlight from ambient // Specular highlight from ambient
vec3 direction = -reflect(fragEyeDir, fragNormal); vec3 direction = -reflect(fragEyeDir, fragNormal);
float levels = getLightAmbientMapNumMips(light); float levels = getLightAmbientMapNumMips(light);
float lod = min(floor((roughness) * levels), levels); float lod = min(floor((roughness) * levels), levels);
vec4 skyboxLight = evalSkyboxLight(direction, lod); vec4 skyboxLight = evalSkyboxLight(direction, lod);

View file

@ -185,9 +185,6 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
batch.setViewportTransform(args->_viewport); batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport); batch.setStateScissorRect(args->_viewport);
config->setNumDrawn((int)inItems.size());
emit config->numDrawnChanged();
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
@ -199,6 +196,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
args->_batch = nullptr; args->_batch = nullptr;
}); });
config->setNumDrawn((int)inItems.size());
} }
DrawOverlay3D::DrawOverlay3D(bool opaque) : DrawOverlay3D::DrawOverlay3D(bool opaque) :

View file

@ -22,6 +22,7 @@ public:
using JobModel = render::Job::Model<SetupDeferred>; using JobModel = render::Job::Model<SetupDeferred>;
}; };
class PrepareDeferred { class PrepareDeferred {
public: public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
@ -29,32 +30,31 @@ public:
using JobModel = render::Job::Model<PrepareDeferred>; using JobModel = render::Job::Model<PrepareDeferred>;
}; };
class RenderDeferred { class RenderDeferred {
public: public:
using JobModel = render::Job::Model<RenderDeferred>; using JobModel = render::Job::Model<RenderDeferred>;
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
}; };
class DrawConfig : public render::Job::Config { class DrawConfig : public render::Job::Config {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats)
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
public: public:
int getNumDrawn() { return numDrawn; } int getNumDrawn() { return _numDrawn; }
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } void setNumDrawn(int numDrawn) { _numDrawn = numDrawn; emit newStats(); }
int maxDrawn{ -1 }; int maxDrawn{ -1 };
signals: signals:
void numDrawnChanged(); void newStats();
void dirty(); void dirty();
protected: protected:
int numDrawn{ 0 }; int _numDrawn{ 0 };
}; };
class DrawDeferred { class DrawDeferred {

View file

@ -127,6 +127,9 @@ protected:
// A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled)
class JobConfig : public QObject { class JobConfig : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(quint64 cpuRunTime READ getCPUTRunTime NOTIFY newStats())
quint64 _CPURunTime{ 0 };
public: public:
using Persistent = PersistentConfig<JobConfig>; using Persistent = PersistentConfig<JobConfig>;
@ -151,11 +154,17 @@ public:
Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); }
Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); }
// Running Time measurement
// The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated
void setCPURunTime(quint64 ustime) { _CPURunTime = ustime; emit newStats(); }
quint64 getCPUTRunTime() const { return _CPURunTime; }
public slots: public slots:
void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); }
signals: signals:
void loaded(); void loaded();
void newStats();
}; };
class TaskConfig : public JobConfig { class TaskConfig : public JobConfig {
@ -223,7 +232,11 @@ public:
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
protected: protected:
void setCPURunTime(quint64 ustime) { std::static_pointer_cast<Config>(_config)->setCPURunTime(ustime); }
QConfigPointer _config; QConfigPointer _config;
friend class Job;
}; };
using ConceptPointer = std::shared_ptr<Concept>; using ConceptPointer = std::shared_ptr<Concept>;
@ -278,8 +291,11 @@ public:
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer(_name.c_str()); PerformanceTimer perfTimer(_name.c_str());
PROFILE_RANGE(_name.c_str()); PROFILE_RANGE(_name.c_str());
auto start = usecTimestampNow();
_concept->run(sceneContext, renderContext); _concept->run(sceneContext, renderContext);
_concept->setCPURunTime(usecTimestampNow() - start);
} }
protected: protected: