Skip to content
Permalink
Browse files

Better F6 profiler (#8750)

Update the profiler names to make more sense of what they actually represent
Move the profiler code from header to its source file
Use monospace font to align lines
Format the statistics line to align better with surrounding values
Refresh the profiler each 3 seconds (roughly)
  • Loading branch information...
SmallJoker committed Aug 13, 2019
1 parent e9ceead commit 539f016c1b1a706da2c113435ec60bb39c868f4b
@@ -35,8 +35,7 @@ void ActiveObjectMgr::clear()
void ActiveObjectMgr::step(
float dtime, const std::function<void(ClientActiveObject *)> &f)
{
g_profiler->avg("Client::ActiveObjectMgr: num of objects",
m_active_objects.size());
g_profiler->avg("ActiveObjectMgr: CAO count [#]", m_active_objects.size());
for (auto &ao_it : m_active_objects) {
f(ao_it.second);
}
@@ -366,7 +366,6 @@ void Client::step(float dtime)
*/
const float map_timer_and_unload_dtime = 5.25;
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) {
ScopeProfiler sp(g_profiler, "Client: map timer and unload");
std::vector<v3s16> deleted_blocks;
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
g_settings->getFloat("client_unload_unused_data_timeout"),
@@ -285,15 +285,14 @@ void ClientEnvironment::step(float dtime)
/*
Step and handle simple objects
*/
g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
g_profiler->avg("ClientEnv: CSO count [#]", m_simple_objects.size());
for (auto i = m_simple_objects.begin(); i != m_simple_objects.end();) {
auto cur = i;
ClientSimpleObject *simple = *cur;
ClientSimpleObject *simple = *i;

simple->step(dtime);
if(simple->m_to_be_removed) {
delete simple;
i = m_simple_objects.erase(cur);
i = m_simple_objects.erase(i);
}
else {
++i;
@@ -116,7 +116,6 @@ void ClientMap::getBlocksInViewRange(v3s16 cam_pos_nodes,
void ClientMap::updateDrawList()
{
ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG);
g_profiler->add("CM::updateDrawList() count", 1);

for (auto &i : m_drawlist) {
MapBlock *block = i.second;
@@ -138,23 +137,10 @@ void ClientMap::updateDrawList()
v3s16 p_blocks_max;
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);

// Number of blocks in rendering range
u32 blocks_in_range = 0;
// Number of blocks with mesh in rendering range
u32 blocks_in_range_with_mesh = 0;
// Number of blocks occlusion culled
u32 blocks_occlusion_culled = 0;
// Number of blocks in rendering range but don't have a mesh
u32 blocks_in_range_without_mesh = 0;
// Blocks that had mesh that would have been drawn according to
// rendering range (if max blocks limit didn't kick in)
u32 blocks_would_have_drawn = 0;
// Blocks that were drawn and had a mesh
u32 blocks_drawn = 0;
// Blocks which had a corresponding meshbuffer for this pass
//u32 blocks_had_pass_meshbuf = 0;
// Blocks from which stuff was actually drawn
//u32 blocks_without_stuff = 0;
// Distance to farthest drawn block
float farthest_drawn = 0;

// No occlusion culling when free_move is on and camera is
// inside ground
@@ -185,11 +171,11 @@ void ClientMap::updateDrawList()

u32 sector_blocks_drawn = 0;

for (auto block : sectorblocks) {
for (MapBlock *block : sectorblocks) {
/*
Compare block position to camera position, skip
if not seen on display
*/
Compare block position to camera position, skip
if not seen on display
*/

if (block->mesh)
block->mesh->updateCameraOffset(m_camera_offset);
@@ -203,57 +189,41 @@ void ClientMap::updateDrawList()
camera_direction, camera_fov, range, &d))
continue;

blocks_in_range++;

/*
Ignore if mesh doesn't exist
*/
if (!block->mesh) {
blocks_in_range_without_mesh++;
if (!block->mesh)
continue;
}

blocks_in_range_with_mesh++;

/*
Occlusion culling
*/
if (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes)) {
if ((!m_control.range_all && d > m_control.wanted_range * BS) ||
(occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes))) {
blocks_occlusion_culled++;
continue;
}

// This block is in range. Reset usage timer.
block->resetUsageTimer();

// Limit block count in case of a sudden increase
blocks_would_have_drawn++;
if (blocks_drawn >= m_control.wanted_max_blocks &&
!m_control.range_all &&
d > m_control.wanted_range * BS)
continue;

// Add to set
block->refGrab();
m_drawlist[block->getPos()] = block;

sector_blocks_drawn++;
blocks_drawn++;
if (d / BS > farthest_drawn)
farthest_drawn = d / BS;

} // foreach sectorblocks

if (sector_blocks_drawn != 0)
m_last_drawn_sectors.insert(sp);
}

g_profiler->avg("CM: blocks in range", blocks_in_range);
g_profiler->avg("CM: blocks occlusion culled", blocks_occlusion_culled);
if (blocks_in_range != 0)
g_profiler->avg("CM: blocks in range without mesh (frac)",
(float)blocks_in_range_without_mesh / blocks_in_range);
g_profiler->avg("CM: blocks drawn", blocks_drawn);
g_profiler->avg("CM: farthest drawn", farthest_drawn);
g_profiler->avg("CM: wanted max blocks", m_control.wanted_max_blocks);
g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh);
g_profiler->avg("MapBlocks occlusion culled [#]", blocks_occlusion_culled);
g_profiler->avg("MapBlocks drawn [#]", m_drawlist.size());
}

struct MeshBufList
@@ -306,24 +276,16 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)

std::string prefix;
if (pass == scene::ESNRP_SOLID)
prefix = "CM: solid: ";
prefix = "renderMap(SOLID): ";
else
prefix = "CM: transparent: ";
prefix = "renderMap(TRANSPARENT): ";

/*
This is called two times per frame, reset on the non-transparent one
*/
if (pass == scene::ESNRP_SOLID)
m_last_drawn_sectors.clear();

/*
Get time for measuring timeout.
Measuring time is very useful for long delays when the
machine is swapping a lot.
*/
std::time_t time1 = time(0);

/*
Get animation parameters
*/
@@ -340,26 +302,15 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
*/

u32 vertex_count = 0;
u32 meshbuffer_count = 0;

// For limiting number of mesh animations per frame
u32 mesh_animate_count = 0;
u32 mesh_animate_count_far = 0;

// Blocks that were drawn and had a mesh
u32 blocks_drawn = 0;
// Blocks which had a corresponding meshbuffer for this pass
u32 blocks_had_pass_meshbuf = 0;
// Blocks from which stuff was actually drawn
u32 blocks_without_stuff = 0;
//u32 mesh_animate_count_far = 0;

/*
Draw the selected MapBlocks
*/

{
ScopeProfiler sp(g_profiler, prefix + "drawing blocks", SPT_AVG);

MeshBufListList drawbufs;

for (auto &i : m_drawlist) {
@@ -381,15 +332,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
assert(mapBlockMesh);
// Pretty random but this should work somewhat nicely
bool faraway = d >= BS * 50;
//bool faraway = d >= m_control.wanted_range * BS;
if (mapBlockMesh->isAnimationForced() || !faraway ||
mesh_animate_count_far < (m_control.range_all ? 200 : 50)) {
mesh_animate_count < (m_control.range_all ? 200 : 50)) {

bool animated = mapBlockMesh->animate(faraway, animation_time,
crack, daynight_ratio);
if (animated)
mesh_animate_count++;
if (animated && faraway)
mesh_animate_count_far++;
} else {
mapBlockMesh->decreaseAnimationForceTimer();
}
@@ -437,46 +386,33 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
}
}

TimeTaker draw("Drawing mesh buffers");

// Render all layers in order
for (auto &lists : drawbufs.lists) {
int timecheck_counter = 0;
for (MeshBufList &list : lists) {
timecheck_counter++;
if (timecheck_counter > 50) {
timecheck_counter = 0;
std::time_t time2 = time(0);
if (time2 > time1 + 4) {
infostream << "ClientMap::renderMap(): "
"Rendering takes ages, returning."
<< std::endl;
return;
}
// Check and abort if the machine is swapping a lot
if (draw.getTimerTime() > 2000) {
infostream << "ClientMap::renderMap(): Rendering took >2s, " <<
"returning." << std::endl;
return;
}

driver->setMaterial(list.m);

for (scene::IMeshBuffer *buf : list.bufs) {
driver->drawMeshBuffer(buf);
vertex_count += buf->getVertexCount();
meshbuffer_count++;
}
}
}
} // ScopeProfiler
g_profiler->avg(prefix + "draw meshes [ms]", draw.stop(true));

// Log only on solid pass because values are the same
if (pass == scene::ESNRP_SOLID) {
g_profiler->avg("CM: animated meshes", mesh_animate_count);
g_profiler->avg("CM: animated meshes (far)", mesh_animate_count_far);
g_profiler->avg("renderMap(): animated meshes [#]", mesh_animate_count);
}

g_profiler->avg(prefix + "vertices drawn", vertex_count);
if (blocks_had_pass_meshbuf != 0)
g_profiler->avg(prefix + "meshbuffers per block",
(float)meshbuffer_count / (float)blocks_had_pass_meshbuf);
if (blocks_drawn != 0)
g_profiler->avg(prefix + "empty blocks (frac)",
(float)blocks_without_stuff / blocks_drawn);
g_profiler->avg(prefix + "vertices drawn [#]", vertex_count);
}

static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
@@ -555,6 +491,7 @@ static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
int oldvalue, bool *sunlight_seen_result)
{
ScopeProfiler sp(g_profiler, "CM::getBackgroundBrightness", SPT_AVG);
static v3f z_directions[50] = {
v3f(-100, 0, 0)
};
@@ -31,8 +31,6 @@ struct MapDrawControl
bool range_all = false;
// Wanted drawing range
float wanted_range = 0.0f;
// Maximum number of blocks to draw
u32 wanted_max_blocks = 0;
// show a wire frame for debugging
bool show_wireframe = false;
};
@@ -99,7 +99,7 @@ void Clouds::render()
//if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
return;

ScopeProfiler sp(g_profiler, "Rendering of clouds, avg", SPT_AVG);
ScopeProfiler sp(g_profiler, "Clouds::render()", SPT_AVG);

int num_faces_to_draw = m_enable_3d ? 6 : 1;

0 comments on commit 539f016

Please sign in to comment.
You can’t perform that action at this time.