Performance measurement hotkey added. Press ctrl+k in debug mode to grab a sample.
On level exit, it writes a .csv file with your samples. Also, for each sample it writes a screenshot with a custom filename, so you can match up the sample with a picture of what you sampled. For analysing where we have graphics performance problems.master
parent
6f1666fde0
commit
5f32c3eafe
|
@ -96,6 +96,7 @@ void pie_ScreenFlip(int clearMode)
|
|||
|
||||
screenDoDumpToDiskIfRequired();
|
||||
wzScreenFlip();
|
||||
wzPerfFrame();
|
||||
if (clearMode & CLEAR_OFF_AND_NO_BUFFER_DOWNLOAD)
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "lib/framework/opengl.h"
|
||||
|
@ -55,6 +56,12 @@ static bool screendump_required = false;
|
|||
|
||||
static GFX *backdropGfx = NULL;
|
||||
|
||||
static bool perfStarted = false;
|
||||
static GLuint perfpos[PERF_COUNT];
|
||||
struct PERF_STORE { GLuint64 counters[PERF_COUNT]; };
|
||||
static QList<PERF_STORE> perfList;
|
||||
static PERF_POINT queryActive = PERF_COUNT;
|
||||
|
||||
static int preview_width = 0, preview_height = 0;
|
||||
static Vector2i player_pos[MAX_PLAYERS];
|
||||
static bool mappreview = false;
|
||||
|
@ -139,6 +146,7 @@ bool screenInitialise()
|
|||
debug(LOG_3D, " * texture cube_map %s supported.", GLEW_ARB_texture_cube_map ? "is" : "is NOT");
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &glMaxTUs);
|
||||
debug(LOG_3D, " * Total number of Texture Units (TUs) supported is %d.", (int) glMaxTUs);
|
||||
debug(LOG_3D, " * GL_ARB_timer_query %s supported!", GLEW_ARB_timer_query ? "is" : "is NOT");
|
||||
|
||||
screenWidth = MAX(screenWidth, 640);
|
||||
screenHeight = MAX(screenHeight, 480);
|
||||
|
@ -186,10 +194,112 @@ bool screenInitialise()
|
|||
// Generate backdrop render
|
||||
backdropGfx = new GFX(GFX_TEXTURE, GL_TRIANGLE_STRIP, 2);
|
||||
|
||||
if (GLEW_ARB_timer_query)
|
||||
{
|
||||
glGenQueries(PERF_COUNT, perfpos);
|
||||
}
|
||||
|
||||
glErrors();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wzPerfAvailable()
|
||||
{
|
||||
return GLEW_ARB_timer_query;
|
||||
}
|
||||
|
||||
void wzPerfStart()
|
||||
{
|
||||
if (GLEW_ARB_timer_query)
|
||||
{
|
||||
char text[80];
|
||||
ssprintf(text, "Starting performance sample %02d", perfList.size());
|
||||
GL_DEBUG(text);
|
||||
perfStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void wzPerfShutdown()
|
||||
{
|
||||
if (perfList.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// write performance counter list to file
|
||||
QFile perf("gfx-performance.csv");
|
||||
perf.open(QIODevice::WriteOnly);
|
||||
perf.write("START, EFF, TERRAIN, LOAD, PRTCL, WATER, MODELS, MISC\n");
|
||||
for (int i = 0; i < perfList.size(); i++)
|
||||
{
|
||||
QString line;
|
||||
line += QString::number(perfList[i].counters[PERF_START_FRAME]);
|
||||
for (int j = 1; j < PERF_COUNT; j++)
|
||||
{
|
||||
line += ", " + QString::number(perfList[i].counters[j]);
|
||||
}
|
||||
line += "\n";
|
||||
perf.write(line.toUtf8());
|
||||
}
|
||||
// all done, clear data
|
||||
perfStarted = false;
|
||||
perfList.clear();
|
||||
queryActive = PERF_COUNT;
|
||||
}
|
||||
|
||||
// call after swap buffers
|
||||
void wzPerfFrame()
|
||||
{
|
||||
if (!perfStarted)
|
||||
{
|
||||
return; // not started yet
|
||||
}
|
||||
ASSERT(queryActive == PERF_COUNT, "Missing wfPerfEnd() call");
|
||||
PERF_STORE store;
|
||||
for (int i = 0; i < PERF_COUNT; i++)
|
||||
{
|
||||
glGetQueryObjectui64v(perfpos[i], GL_QUERY_RESULT, &store.counters[i]);
|
||||
}
|
||||
glErrors();
|
||||
perfList.append(store);
|
||||
perfStarted = false;
|
||||
|
||||
// Make a screenshot to document sample content
|
||||
time_t aclock;
|
||||
struct tm *t;
|
||||
|
||||
time(&aclock); /* Get time in seconds */
|
||||
t = localtime(&aclock); /* Convert time to struct */
|
||||
|
||||
ssprintf(screendump_filename, "screenshots/wz2100-perf-sample-%02d-%04d%02d%02d_%02d%02d%02d-%s.png", perfList.size() - 1,
|
||||
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, getLevelName());
|
||||
screendump_required = true;
|
||||
GL_DEBUG("Performance sample complete");
|
||||
}
|
||||
|
||||
void wzPerfBegin(PERF_POINT pp, const char *descr)
|
||||
{
|
||||
GL_DEBUG(descr);
|
||||
if (!perfStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ASSERT(queryActive == PERF_COUNT || pp > queryActive, "Out of order timer query call");
|
||||
glBeginQuery(GL_TIME_ELAPSED, perfpos[pp]);
|
||||
queryActive = pp;
|
||||
glErrors();
|
||||
}
|
||||
|
||||
void wzPerfEnd(PERF_POINT pp)
|
||||
{
|
||||
if (!perfStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ASSERT(queryActive == pp, "Mismatched wzPerfBegin...End");
|
||||
glEndQuery(GL_TIME_ELAPSED);
|
||||
queryActive = PERF_COUNT;
|
||||
}
|
||||
|
||||
void screenShutDown(void)
|
||||
{
|
||||
pie_Skybox_Shutdown();
|
||||
|
@ -198,6 +308,7 @@ void screenShutDown(void)
|
|||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glErrors();
|
||||
}
|
||||
|
||||
// Make OpenGL's VBO functions available under the core names for drivers that support OpenGL 1.4 only but have the VBO extension
|
||||
|
|
|
@ -63,6 +63,28 @@ void screen_enableMapPreview(int width, int height, Vector2i *playerpositions);
|
|||
void screen_disableMapPreview(void);
|
||||
void screen_EnableMissingFunctions();
|
||||
|
||||
/// gaphics performance measurement points
|
||||
enum PERF_POINT
|
||||
{
|
||||
PERF_START_FRAME,
|
||||
PERF_EFFECTS,
|
||||
PERF_TERRAIN,
|
||||
PERF_MODEL_INIT,
|
||||
PERF_PARTICLES,
|
||||
PERF_WATER,
|
||||
PERF_MODELS,
|
||||
PERF_MISC,
|
||||
PERF_COUNT
|
||||
};
|
||||
|
||||
void wzPerfBegin(PERF_POINT pp, const char *descr);
|
||||
void wzPerfEnd(PERF_POINT pp);
|
||||
void wzPerfStart();
|
||||
void wzPerfShutdown();
|
||||
void wzPerfFrame();
|
||||
/// Are performance measurements available?
|
||||
bool wzPerfAvailable();
|
||||
|
||||
struct OPENGL_DATA
|
||||
{
|
||||
char vendor[256];
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "lib/ivis_opengl/piemode.h"
|
||||
#include "lib/framework/fixedpoint.h"
|
||||
#include "lib/ivis_opengl/piefunc.h"
|
||||
#include "lib/ivis_opengl/screen.h"
|
||||
|
||||
#include "lib/gamelib/gtime.h"
|
||||
#include "lib/gamelib/animobj.h"
|
||||
|
@ -677,7 +678,7 @@ static void setupConnectionStatusForm(void)
|
|||
/// Render the 3D world
|
||||
void draw3DScene( void )
|
||||
{
|
||||
GL_DEBUG("Draw 3D scene - start");
|
||||
wzPerfBegin(PERF_START_FRAME, "Start 3D scene");
|
||||
|
||||
/* What frame number are we on? */
|
||||
currentGameFrame = frameGetFrameNumber();
|
||||
|
@ -704,10 +705,12 @@ void draw3DScene( void )
|
|||
pie_Begin3DScene();
|
||||
/* Set 3D world origins */
|
||||
pie_SetGeometricOffset(rendSurface.width / 2, geoOffset);
|
||||
wzPerfEnd(PERF_START_FRAME);
|
||||
|
||||
// draw terrain
|
||||
displayTerrain();
|
||||
|
||||
wzPerfBegin(PERF_MISC, "3D scene - misc text");
|
||||
pie_BeginInterface();
|
||||
drawDroidSelections();
|
||||
|
||||
|
@ -726,7 +729,6 @@ void draw3DScene( void )
|
|||
pie_SetFogStatus(true);
|
||||
}
|
||||
|
||||
GL_DEBUG("Draw 3D scene - text");
|
||||
if (!bRender3DOnly)
|
||||
{
|
||||
/* Ensure that any text messages are displayed at bottom of screen */
|
||||
|
@ -856,6 +858,7 @@ void draw3DScene( void )
|
|||
showDroidPaths();
|
||||
}
|
||||
|
||||
wzPerfEnd(PERF_MISC);
|
||||
GL_DEBUG("Draw 3D scene - end");
|
||||
}
|
||||
|
||||
|
@ -1017,12 +1020,14 @@ static void drawTiles(iView *player)
|
|||
}
|
||||
|
||||
/* This is done here as effects can light the terrain - pause mode problems though */
|
||||
wzPerfBegin(PERF_EFFECTS, "3D scene - effects");
|
||||
processEffects();
|
||||
atmosUpdateSystem();
|
||||
avUpdateTiles();
|
||||
wzPerfEnd(PERF_EFFECTS);
|
||||
|
||||
// now we are about to draw the terrain
|
||||
GL_DEBUG("Draw 3D scene - terrain");
|
||||
wzPerfBegin(PERF_TERRAIN, "3D scene - terrain");
|
||||
pie_SetFogStatus(true);
|
||||
|
||||
pie_MatBegin();
|
||||
|
@ -1034,12 +1039,13 @@ static void drawTiles(iView *player)
|
|||
|
||||
// and to the warzone modelview transform
|
||||
pie_MatEnd();
|
||||
wzPerfEnd(PERF_TERRAIN);
|
||||
|
||||
// draw skybox
|
||||
renderSurroundings();
|
||||
|
||||
// and prepare for rendering the models
|
||||
GL_DEBUG("Draw 3D scene - models");
|
||||
wzPerfBegin(PERF_MODEL_INIT, "Draw 3D scene - model init");
|
||||
pie_SetRendMode(REND_OPAQUE);
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
@ -1056,10 +1062,13 @@ static void drawTiles(iView *player)
|
|||
displayDelivPoints();
|
||||
display3DProjectiles(); // may be bucket render implemented
|
||||
pie_MatEnd();
|
||||
wzPerfEnd(PERF_MODEL_INIT);
|
||||
|
||||
GL_DEBUG("Draw 3D scene - particles");
|
||||
wzPerfBegin(PERF_PARTICLES, "3D scene - particles");
|
||||
atmosDrawParticles();
|
||||
wzPerfEnd(PERF_PARTICLES);
|
||||
|
||||
wzPerfBegin(PERF_WATER, "3D scene - water");
|
||||
// prepare for the water and the lightmap
|
||||
pie_SetFogStatus(true);
|
||||
|
||||
|
@ -1071,11 +1080,12 @@ static void drawTiles(iView *player)
|
|||
|
||||
// and to the warzone modelview transform
|
||||
pie_MatEnd();
|
||||
wzPerfEnd(PERF_WATER);
|
||||
|
||||
GL_DEBUG("Draw 3D scene - bucket render");
|
||||
wzPerfBegin(PERF_MODELS, "3D scene - models");
|
||||
bucketRenderCurrentList();
|
||||
|
||||
GL_DEBUG("Draw 3D scene - blue prints");
|
||||
GL_DEBUG("Draw 3D scene - blueprints");
|
||||
displayBlueprints();
|
||||
|
||||
pie_RemainingPasses(); // draws shadows and transparent shapes
|
||||
|
@ -1088,8 +1098,7 @@ static void drawTiles(iView *player)
|
|||
/* Clear the matrix stack */
|
||||
pie_MatEnd();
|
||||
locateMouse();
|
||||
|
||||
GL_DEBUG("Draw 3D scene - end of tiles");
|
||||
wzPerfEnd(PERF_MODELS);
|
||||
}
|
||||
|
||||
/// Initialise the fog, skybox and some other stuff
|
||||
|
|
|
@ -931,6 +931,7 @@ bool stageOneShutDown(void)
|
|||
debug(LOG_WZ, "== stageOneShutDown ==");
|
||||
|
||||
atmosSetWeatherType(WT_NONE); // reset weather and free its data
|
||||
wzPerfShutdown();
|
||||
|
||||
pie_FreeShaders();
|
||||
|
||||
|
|
|
@ -182,6 +182,11 @@ void kf_ToggleShowPath(void)
|
|||
showPath = !showPath;
|
||||
}
|
||||
|
||||
void kf_PerformanceSample()
|
||||
{
|
||||
wzPerfStart();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
void kf_ToggleRadarJump( void )
|
||||
{
|
||||
|
|
|
@ -262,4 +262,6 @@ void kf_BuildPrevPage( void );
|
|||
extern void kf_DamageMe(void);
|
||||
extern void kf_AutoGame(void);
|
||||
|
||||
void kf_PerformanceSample();
|
||||
|
||||
#endif // __INCLUDED_SRC_KEYBIND_H__
|
||||
|
|
|
@ -252,7 +252,7 @@ _keymapsave keyMapSaveTable[] =
|
|||
kf_ToggleDrivingMode,
|
||||
kf_ToggleShowGateways,
|
||||
kf_ToggleShowPath,
|
||||
kf_MapCheck,
|
||||
kf_PerformanceSample,
|
||||
kf_SetDroidGoToTransport,
|
||||
kf_NOOP,
|
||||
kf_toggleTrapCursor,
|
||||
|
@ -469,7 +469,7 @@ void keyInitMappings( bool bForceDefaults )
|
|||
keyAddMapping(KEYMAP__DEBUG, KEY_LCTRL, KEY_J, KEYMAP_PRESSED, kf_ToggleFog, N_("Toggles All fog"));
|
||||
keyAddMapping(KEYMAP__DEBUG, KEY_LCTRL, KEY_Q, KEYMAP_PRESSED, kf_ToggleWeather, N_("Trigger some weather"));
|
||||
keyAddMapping(KEYMAP__DEBUG, KEY_IGNORE, KEY_K, KEYMAP_PRESSED, kf_TriFlip, N_("Flip terrain triangle"));
|
||||
keyAddMapping(KEYMAP__DEBUG, KEY_LCTRL, KEY_K, KEYMAP_PRESSED, kf_MapCheck, N_("Realign height of all objects on the map"));
|
||||
keyAddMapping(KEYMAP__DEBUG, KEY_LCTRL, KEY_K, KEYMAP_PRESSED, kf_PerformanceSample, N_("Make a performance measurement sample"));
|
||||
|
||||
//These ones are necessary for debugging
|
||||
keyAddMapping(KEYMAP__DEBUG, KEY_LALT, KEY_A, KEYMAP_PRESSED, kf_AllAvailable, N_("Make all items available"));
|
||||
|
|
Loading…
Reference in New Issue