Skip to content

Commit

Permalink
Add frame timing option to viewer
Browse files Browse the repository at this point in the history
This changelist adds a frame timing option to the MaterialX Viewer, allowing basic performance profiling from within the application.

To enable frame timing, launch the MaterialX Viewer with "--frameTiming true".
  • Loading branch information
jstone-lucasfilm committed Mar 13, 2024
1 parent a09b9a4 commit 78fab2c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 1 deletion.
11 changes: 11 additions & 0 deletions source/MaterialXView/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const std::string options =
" --bakeHeight [INTEGER] Specify the target height for texture baking (defaults to maximum image height of the source document)\n"
" --bakeFilename [STRING] Specify the output document filename for texture baking\n"
" --refresh [FLOAT] Specify the refresh period for the viewer in milliseconds (defaults to 50, set to -1 to disable)\n"
" --frameTiming [BOOLEAN] Specify whether the frame timing display is enabled (defaults to false)\n"
" --remap [TOKEN1:TOKEN2] Specify the remapping from one token to another when MaterialX document is loaded\n"
" --skip [NAME] Specify to skip elements matching the given name attribute\n"
" --terminator [STRING] Specify to enforce the given terminator string for file prefixes\n"
Expand Down Expand Up @@ -99,6 +100,7 @@ int main(int argc, char* const argv[])
int bakeHeight = 0;
std::string bakeFilename;
float refresh = 50.0f;
bool frameTiming = false;

for (size_t i = 0; i < tokens.size(); i++)
{
Expand Down Expand Up @@ -212,6 +214,14 @@ int main(int argc, char* const argv[])
{
parseToken(nextToken, "float", refresh);
}
else if (token == "--frameTiming")
{
parseToken(nextToken, "boolean", frameTiming);
if (frameTiming)
{
refresh = 0;
}
}
else if (token == "--remap")
{
mx::StringVec vec = mx::splitString(nextToken, ":");
Expand Down Expand Up @@ -285,6 +295,7 @@ int main(int argc, char* const argv[])
viewer->setBakeWidth(bakeWidth);
viewer->setBakeHeight(bakeHeight);
viewer->setBakeFilename(bakeFilename);
viewer->setFrameTiming(frameTiming);
viewer->initialize();

if (!captureFilename.empty())
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXView/RenderPipelineGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ mx::ImagePtr GLRenderPipeline::getShadowMap(int shadowMapSize)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
}

// Reset frame timing after shadow generation.
_viewer->resetFrameTiming();
}

return _viewer->_shadowMap;
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXView/RenderPipelineMetal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@

[renderpassDesc release];
}

// Reset frame timing after shadow generation.
_viewer->resetFrameTiming();
}

_viewer->_shadowMap = _shadowMap[_viewer->_shadowSoftness % 2];
Expand Down
33 changes: 32 additions & 1 deletion source/MaterialXView/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,12 @@ Viewer::Viewer(const std::string& materialFilename,
_bakeRequested(false),
_bakeWidth(0),
_bakeHeight(0),
_bakeDocumentPerMaterial(false)
_bakeDocumentPerMaterial(false),
_frameTiming(false),
_timingLabel(nullptr),
_timingPanel(nullptr),
_timingText(nullptr),
_avgFrameTime(0.0)
{
// Resolve input filenames, taking both the provided search path and
// current working directory into account.
Expand Down Expand Up @@ -327,6 +332,21 @@ void Viewer::initialize()
}
});

// Create frame timing display
if (_frameTiming)
{
_timingLabel = new ng::Label(_window, "Timing");
_timingPanel = new ng::Widget(_window);
_timingPanel->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal,
ng::Alignment::Middle, 0, 6));
new ng::Label(_timingPanel, "Frame time:");
_timingText = new ng::TextBox(_timingPanel);
_timingText->set_value("0");
_timingText->set_units(" ms");
_timingText->set_fixed_size(ng::Vector2i(80, 25));
_timingText->set_alignment(ng::TextBox::Alignment::Right);
}

// Create geometry handler.
mx::TinyObjLoaderPtr objLoader = mx::TinyObjLoader::create();
mx::CgltfLoaderPtr gltfLoader = mx::CgltfLoader::create();
Expand Down Expand Up @@ -2078,6 +2098,17 @@ void Viewer::draw_contents()
#endif
}

// Update frame timing.
if (_frameTiming)
{
const double DEFAULT_SMOOTHING_BIAS = 0.9;
double elapsedTime = _frameTimer.elapsedTime() * 1000.0;
double bias = (_avgFrameTime > 0.0) ? DEFAULT_SMOOTHING_BIAS : 0.0;
_avgFrameTime = bias * _avgFrameTime + (1.0 - bias) * elapsedTime;
_timingText->set_value(std::to_string((int) _avgFrameTime));
_frameTimer.startTimer();
}

// Capture the current frame.
if (_captureRequested && !_turntableEnabled)
{
Expand Down
24 changes: 24 additions & 0 deletions source/MaterialXView/Viewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ class Viewer : public ng::Screen
_bakeFilename = bakeFilename;
}

// Enable or disable frame timing.
void setFrameTiming(bool enable)
{
_frameTiming = enable;
}

// Reset frame timing after a blocking event.
void resetFrameTiming()
{
if (_frameTiming)
{
_frameTimer.startTimer();
_avgFrameTime = 0.0;
}
}

// Return true if all inputs should be shown in the property editor.
bool getShowAllInputs() const
{
Expand Down Expand Up @@ -450,6 +466,14 @@ class Viewer : public ng::Screen
unsigned int _bakeHeight;
bool _bakeDocumentPerMaterial;
mx::FilePath _bakeFilename;

// Frame timing
bool _frameTiming;
ng::Label* _timingLabel;
ng::Widget* _timingPanel;
ng::TextBox* _timingText;
mx::ScopedTimer _frameTimer;
double _avgFrameTime;
};

extern const mx::Vector3 DEFAULT_CAMERA_POSITION;
Expand Down

0 comments on commit 78fab2c

Please sign in to comment.