endif
MAIN = main.o
-OBJ = log.o real.o bezier.o objectrenderer.o view.o screen.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o path.o document.o debugscript.o paranoidnumber.o
+OBJ = log.o profiler.o real.o bezier.o objectrenderer.o view.o screen.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o path.o document.o debugscript.o paranoidnumber.o
QT_INCLUDE := -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -Itests -I.
QT_DEF := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB
#include "document.h"
#include "bezier.h"
+#include "profiler.h"
#include <cstdio>
#include <fstream>
int Document::ClipObjectToQuadChild(int object_id, QuadTreeNodeChildren type)
{
+ PROFILE_SCOPE("Document::ClipObjectToQuadChild");
switch (m_objects.types[object_id])
{
case RECT_FILLED:
}
QuadTreeIndex Document::GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type)
{
+ PROFILE_SCOPE("Document::GenQuadChild()");
QuadTreeIndex new_index = m_quadtree.nodes.size();
Debug("-------------- Generating Quadtree Node %d (parent %d, type %d) ----------------------", new_index, parent, type);
m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, parent, type, 0, 0, -1});
void Document::OverlayQuadChildren(QuadTreeIndex orig_parent, QuadTreeIndex parent, QuadTreeNodeChildren type)
{
+ PROFILE_SCOPE("Document::OverlayQuadChildren()");
QuadTreeIndex new_index = m_quadtree.nodes.size();
Debug("-------------- Generating Quadtree Node %d (orig %d parent %d, type %d) ----------------------", new_index, orig_parent, parent, type);
m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, orig_parent, type, 0, 0, -1});
unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index, QuadTreeIndex qti)
{
+ PROFILE_SCOPE("Document::Add");
m_objects.types.push_back(type);
m_objects.bounds.push_back(bounds);
m_objects.data_indices.push_back(data_index);
#include "view.h"
#include "screen.h"
#include "debugscript.h"
+#include "profiler.h"
#include <unistd.h>
real_clock_prev = real_clock_now;
#endif
++frames;
+ g_profiler.BeginZone("scr.Clear()");
scr.Clear();
+ g_profiler.EndZone();
//view.ForceBoundsDirty();
//view.ForceBufferDirty();
//view.ForceRenderDirty();
return;
}
+ g_profiler.BeginZone("view.Render");
view.Render(scr.ViewportWidth(), scr.ViewportHeight());
+ g_profiler.EndZone();
double cpu_frame = scr.GetLastFrameTimeCPU();
double gpu_frame = scr.GetLastFrameTimeGPU();
}
#endif // 0
+ g_profiler.BeginZone("scr.Present()");
scr.Present();
+ g_profiler.EndZone();
+ g_profiler.EndFrame();
}
}
--- /dev/null
+#include "profiler.h"
+#include "log.h"
+
+#include "SDL.h"
+
+using namespace IPDF;
+
+Profiler IPDF::g_profiler;
+
+void Profiler::BeginZone(std::string name)
+{
+ if (!m_zones.count(name))
+ m_zones[name] = ProfileZone{0,0,0,0,0,0};
+ m_zones[name].tics_begin = SDL_GetPerformanceCounter();
+ m_zone_stack.push(name);
+}
+
+void Profiler::EndZone()
+{
+ std::string name = m_zone_stack.top();
+ m_zone_stack.pop();
+ m_zones[name].tics_end = SDL_GetPerformanceCounter();
+ m_zones[name].tics_frame += m_zones[name].tics_end - m_zones[name].tics_begin;
+ m_zones[name].tics_total += m_zones[name].tics_end - m_zones[name].tics_begin;
+ m_zones[name].calls_frame++;
+ m_zones[name].calls_total++;
+}
+
+void Profiler::EndFrame()
+{
+ // Zero all of the frame counts
+ for (auto& it : m_zones)
+ {
+#ifndef PROFILER_SILENT
+ Debug("Perf: Zone \"%s\" frame: %d ms (%d calls), total: %d ms (%d calls)", it.first.c_str(), it.second.tics_frame * 1000 / SDL_GetPerformanceFrequency(), it.second.calls_frame, it.second.tics_total * 1000 / SDL_GetPerformanceFrequency(), it.second.calls_total);
+#endif
+ it.second.tics_frame = 0;
+ it.second.calls_frame = 0;
+ }
+}
--- /dev/null
+#ifndef _PROFILER_H
+#define _PROFILER_H
+
+#include <map>
+#include <string>
+#include <stack>
+
+#define PROFILE_SCOPE(name) IPDF::ProfilerScope _localProfZone(name)
+
+namespace IPDF
+{
+ class Profiler
+ {
+ public:
+ Profiler() {}
+
+ void BeginZone(std::string name);
+ void EndZone();
+
+ void EndFrame();
+ private:
+ struct ProfileZone
+ {
+ uint64_t tics_begin;
+ uint64_t tics_end;
+ uint64_t tics_frame;
+ uint64_t tics_total;
+ uint64_t calls_frame;
+ uint64_t calls_total;
+ };
+
+ std::map<std::string, ProfileZone> m_zones;
+ std::stack<std::string> m_zone_stack;
+ };
+
+ extern Profiler g_profiler;
+ struct ProfilerScope
+ {
+ ProfilerScope(std::string name) { g_profiler.BeginZone(name); }
+ ~ProfilerScope() { g_profiler.EndZone(); }
+ };
+
+}
+
+#endif
#include "view.h"
#include "bufferbuilder.h"
#include "screen.h"
+#include "profiler.h"
#include "gl_core44.h"
#ifndef CONTROLPANEL_DISABLED
*/
void View::Translate(Real x, Real y)
{
+ PROFILE_SCOPE("View::Translate");
if (!m_use_gpu_transform)
m_buffer_dirty = true;
m_bounds_dirty = true;
*/
void View::ScaleAroundPoint(Real x, Real y, Real scale_amount)
{
-
+ PROFILE_SCOPE("View::ScaleAroundPoint");
// (x0, y0, w, h) -> (x*w - (x*w - x0)*s, y*h - (y*h - y0)*s, w*s, h*s)
// x and y are coordinates in the window
// Convert to local coords.
*/
void View::Render(int width, int height)
{
+ PROFILE_SCOPE("View::Render()");
if (!m_screen.Valid()) return;
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION,42,-1, "Beginning View::Render()");
// View dimensions have changed (ie: Window was resized)
// quadtree node).
if (m_bounds_dirty || !m_lazy_rendering)
{
+ g_profiler.BeginZone("View::Render -- Quadtree view bounds management");
// If we're too far zoomed out, become the parent of the current node.
if ( m_bounds.w > 1.0 || m_bounds.h > 1.0)
{
m_bounds = TransformToQuadChild(m_bounds, QTC_BOTTOM_RIGHT);
m_current_quadtree_node = m_document.GetQuadTree().nodes[m_current_quadtree_node].bottom_right;
}
+ g_profiler.EndZone();
}
m_screen.DebugFontPrintF("Current View QuadTree");
void View::RenderRange(int width, int height, unsigned first_obj, unsigned last_obj)
{
+ PROFILE_SCOPE("View::RenderRange");
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 43, -1, "View::RenderRange()");
if (m_render_dirty) // document has changed
PrepareRender();
void View::UpdateObjBoundsVBO(unsigned first_obj, unsigned last_obj)
{
+ PROFILE_SCOPE("View::UpdateObjBoundsVBO");
if (m_query_gpu_bounds_on_next_frame != NULL)
{
fprintf(m_query_gpu_bounds_on_next_frame,"# View: %s\t%s\t%s\t%s", Str(m_bounds.x).c_str(), Str(m_bounds.y).c_str(), Str(m_bounds.w).c_str(), Str(m_bounds.h).c_str());
*/
void View::PrepareRender()
{
+ PROFILE_SCOPE("View::PrepareRender()");
Debug("Recreate buffers with %u objects", m_document.ObjectCount());
// Prepare bounds vbo
if (UsingGPURendering())