Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve fps counter #1886

Merged
merged 9 commits into from
Jan 12, 2025
1 change: 1 addition & 0 deletions vtkext/private/module/Testing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(test_sources
TestF3DOpenGLGridMapper.cxx
TestF3DRenderPass.cxx
TestF3DRendererWithColoring.cxx
TestF3DFpsCounter.cxx
)

if(F3D_MODULE_EXR)
Expand Down
54 changes: 54 additions & 0 deletions vtkext/private/module/Testing/TestF3DFpsCounter.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <vtkNew.h>
#include <vtkObjectFactory.h>

#include "vtkF3DUIActor.h"

#include <iostream>

// subclass to retrieve internal protected values
class vtkF3DTestUIActor : public vtkF3DUIActor
{
public:
static vtkF3DTestUIActor* New();
vtkTypeMacro(vtkF3DTestUIActor, vtkF3DUIActor);

size_t GetNumberOfFrameTimes() { return this->FrameTimes.size(); }
double GetTotalFrameTimes() { return this->TotalFrameTimes; }
int GetFpsValue() { return this->FpsValue; }
};

vtkObjectFactoryNewMacro(vtkF3DTestUIActor);

int TestF3DFpsCounter(int argc, char* argv[])
{
vtkNew<vtkF3DTestUIActor> uiActor;

// add 1000 frames at 0.01s
for (int i = 0; i < 1000; i++)
{
uiActor->UpdateFpsValue(0.01);
}

// make sure only the 100 last records are kept
if (uiActor->GetNumberOfFrameTimes() > 100)
{
std::cerr << "Number of frame times must be at most 100" << std::endl;
return EXIT_FAILURE;
}

// make sure only the total time kept doesn't exceed 1 second
if (uiActor->GetTotalFrameTimes() > 1.0)
{
std::cerr << "Number of total frame times must be at most 1.0" << std::endl;
return EXIT_FAILURE;
}

// make sure the FPS value is exactly 100
if (uiActor->GetFpsValue() != 100)
{
std::cerr << "Number of FPS value must be exactly 100" << std::endl;
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
24 changes: 15 additions & 9 deletions vtkext/private/module/vtkF3DRenderer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1541,20 +1541,26 @@ void vtkF3DRenderer::Render()

auto cpuElapsed = std::chrono::high_resolution_clock::now() - cpuStart;

// Get CPU frame per seconds
int fps = static_cast<int>(std::round(
1.0 / (std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6)));
vtkInformation *info = this->GetInformation();

bool uiOnly = info->Get(vtkF3DRenderPass::RENDER_UI_ONLY());

if (!uiOnly)
{
// Get CPU frame time
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6;
Comment on lines +1550 to +1551
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get CPU frame time
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6;
// Get CPU frame time
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6;


#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);
mwestphal marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +1554 to +1556
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);


// Get min between CPU frame per seconds and GPU frame per seconds
fps = std::min(fps, static_cast<int>(std::round(1.0 / (elapsed * 1e-9))));
// Get min between CPU frame time and GPU frame time
elapsedTime = std::min(elapsedTime, elapsed * 1e-9);
mwestphal marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +1558 to +1559
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get min between CPU frame time and GPU frame time
elapsedTime = std::min(elapsedTime, elapsed * 1e-9);
// Get min between CPU frame time and GPU frame time
elapsedTime = std::min(elapsedTime, elapsed * 1e-9);

#endif

this->UIActor->SetFpsValue(fps);
this->UIActor->UpdateFpsValue(elapsedTime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this->UIActor->UpdateFpsValue(elapsedTime);
this->UIActor->UpdateFpsValue(elapsedTime);

}
}

//----------------------------------------------------------------------------
Expand Down
16 changes: 14 additions & 2 deletions vtkext/private/module/vtkF3DUIActor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,21 @@ void vtkF3DUIActor::SetFpsCounterVisibility(bool show)
}

//----------------------------------------------------------------------------
void vtkF3DUIActor::SetFpsValue(int fps)
void vtkF3DUIActor::UpdateFpsValue(const double elapsedFrameTime)
{
this->FpsValue = fps;
this->TotalFrameTimes += elapsedFrameTime;
this->FrameTimes.push_back(elapsedFrameTime);

while (this->TotalFrameTimes > 1.0)
{
double oldestFrameTime = this->FrameTimes.front();

this->FrameTimes.pop_front();
this->TotalFrameTimes -= oldestFrameTime;
}

double averageFrameTime = this->TotalFrameTimes / this->FrameTimes.size();
this->FpsValue = static_cast<int>(std::round(1.0 / averageFrameTime));
}

//----------------------------------------------------------------------------
Expand Down
10 changes: 8 additions & 2 deletions vtkext/private/module/vtkF3DUIActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define vtkF3DUIActor_h

#include <vtkProp.h>
#include <deque>

class vtkOpenGLRenderWindow;

Expand Down Expand Up @@ -81,10 +82,10 @@ class vtkF3DUIActor : public vtkProp
void SetFpsCounterVisibility(bool show);

/**
* Set the fps value
* Updates the fps value
* 0 by default
*/
void SetFpsValue(int fps);
void UpdateFpsValue(const double elapsedFrameTime);

/**
* Set the font file path
Expand Down Expand Up @@ -159,6 +160,11 @@ class vtkF3DUIActor : public vtkProp
bool ConsoleBadgeEnabled = false;

bool FpsCounterVisible = false;

// deque instead of queue to allow for iteration
std::deque<double> FrameTimes;

double TotalFrameTimes = 0.0;
int FpsValue = 0;

std::string FontFile = "";
Expand Down
Loading