mirror of
https://github.com/overte-org/overte.git
synced 2025-08-03 22:43:15 +02:00
Working on overlays and stats
This commit is contained in:
parent
4762e1a00c
commit
2bf53b625e
6 changed files with 306 additions and 251 deletions
|
@ -11,19 +11,22 @@ Hifi.Stats {
|
|||
readonly property int sTATS_PING_MIN_WIDTH: 190
|
||||
readonly property int sTATS_GEO_MIN_WIDTH: 240
|
||||
readonly property int sTATS_OCTREE_MIN_WIDTH: 410
|
||||
readonly property int fontSize: 12
|
||||
readonly property string fontColor: "white"
|
||||
readonly property string bgColor: "#99333333"
|
||||
|
||||
onParentChanged: {
|
||||
root.x = parent.width - root.width;
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
z: 100
|
||||
id: row
|
||||
spacing: 8
|
||||
Rectangle {
|
||||
width: generalCol.width + 8;
|
||||
height: generalCol.height + 8;
|
||||
color: "#99333333";
|
||||
color: root.bgColor;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
@ -34,18 +37,38 @@ Hifi.Stats {
|
|||
id: generalCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_GENERAL_MIN_WIDTH
|
||||
Text { color: "white"; text: "Servers: " + root.serverCount }
|
||||
Text { color: "white"; text: "Avatars: " + root.avatarCount }
|
||||
Text { color: "white"; text: "Framerate: " + root.framerate }
|
||||
Text { color: "white"; text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount }
|
||||
Text { color: "white"; text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) }
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Servers: " + root.serverCount
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Avatars: " + root.avatarCount
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Framerate: " + root.framerate
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: pingCol.width + 8
|
||||
height: pingCol.height + 8
|
||||
color: "#99333333"
|
||||
color: root.bgColor;
|
||||
visible: root.audioPing != -2
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
@ -55,45 +78,68 @@ Hifi.Stats {
|
|||
id: pingCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_PING_MIN_WIDTH
|
||||
Text { color: "white"; text: "Audio ping: " + root.audioPing }
|
||||
Text { color: "white"; text: "Avatar ping: " + root.avatarPing }
|
||||
Text { color: "white"; text: "Entities avg ping: " + root.entitiesPing }
|
||||
Text { color: "white"; text: "Voxel max ping: " + 0; visible: root.expanded; }
|
||||
Text {
|
||||
color: root.fontColor
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Audio ping: " + root.audioPing
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Avatar ping: " + root.avatarPing
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Entities avg ping: " + root.entitiesPing
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded;
|
||||
text: "Voxel max ping: " + 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: geoCol.width
|
||||
height: geoCol.height
|
||||
color: "#99333333"
|
||||
width: geoCol.width + 8
|
||||
height: geoCol.height + 8
|
||||
color: root.bgColor;
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: { root.expanded = !root.expanded; }
|
||||
}
|
||||
Column {
|
||||
spacing: 4
|
||||
id: geoCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_GEO_MIN_WIDTH
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Position: " + root.position.x.toFixed(1) + ", " +
|
||||
root.position.y.toFixed(1) + ", " + root.position.z.toFixed(1)
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Velocity: " + root.velocity.toFixed(1)
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Yaw: " + root.yaw.toFixed(1)
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded;
|
||||
text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " +
|
||||
root.avatarMixerPps + "pps";
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded;
|
||||
text: "Downloads: ";
|
||||
}
|
||||
|
@ -102,7 +148,7 @@ Hifi.Stats {
|
|||
Rectangle {
|
||||
width: octreeCol.width + 8
|
||||
height: octreeCol.height + 8
|
||||
color: "#99333333"
|
||||
color: root.bgColor;
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: { root.expanded = !root.expanded; }
|
||||
|
@ -112,31 +158,93 @@ Hifi.Stats {
|
|||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_OCTREE_MIN_WIDTH
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Triangles: " + root.triangles +
|
||||
" / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded;
|
||||
text: "\tMesh Parts Rendered Opaque: " + root.meshOpaque +
|
||||
" / Translucent: " + root.meshTranslucent;
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
visible: root.expanded;
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded;
|
||||
text: "\tOpaque considered: " + root.opaqueConsidered +
|
||||
" / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall;
|
||||
}
|
||||
Text {
|
||||
color: "white";
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: !root.expanded
|
||||
text: "Octree Elements Server: ";
|
||||
text: "Octree Elements Server: " + root.serverElements +
|
||||
" Local: " + root.localElements;
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "Octree Sending Mode: " + root.sendingMode;
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "Octree Packets to Process: " + root.packetStats;
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "Octree Elements - ";
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "\tServer: " + root.serverElements +
|
||||
" Internal: " + root.serverInternal +
|
||||
" Leaves: " + root.serverLeaves;
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "\tLocal: " + root.localElements +
|
||||
" Internal: " + root.localInternal +
|
||||
" Leaves: " + root.localLeaves;
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
visible: root.expanded
|
||||
text: "LOD: " + root.lodStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
y: 250
|
||||
width: perfText.width + 8
|
||||
height: perfText.height + 8
|
||||
color: root.bgColor;
|
||||
anchors.top: row.bottom + 16
|
||||
Text {
|
||||
x: 4; y: 4
|
||||
id: perfText
|
||||
color: root.fontColor
|
||||
font.family: "Lucida Console"
|
||||
text: "-------------------------------------------------------- Function " +
|
||||
"------------------------------------------------------- --msecs- -calls--\n" +
|
||||
root.timingStats;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.parent
|
||||
onWidthChanged: {
|
||||
|
|
|
@ -1817,6 +1817,7 @@ void Application::idle() {
|
|||
targetFramePeriod = 1000.0 / targetFramerate;
|
||||
}
|
||||
double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0;
|
||||
//if (true) {
|
||||
if (timeSinceLastUpdate > targetFramePeriod) {
|
||||
_lastTimeUpdated.start();
|
||||
{
|
||||
|
@ -1843,7 +1844,7 @@ void Application::idle() {
|
|||
}
|
||||
|
||||
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
|
||||
idleTimer->start(2);
|
||||
idleTimer->start(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,6 @@ ApplicationOverlay::~ApplicationOverlay() {
|
|||
void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
||||
|
||||
Stats::getInstance()->updateStats();
|
||||
glm::vec2 size = qApp->getCanvasSize();
|
||||
// TODO Handle fading and deactivation/activation of UI
|
||||
|
||||
|
@ -104,8 +103,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
|||
//renderOverlays(renderArgs);
|
||||
//renderAudioMeter(renderArgs);
|
||||
//renderCameraToggle(renderArgs);
|
||||
//renderStatsAndLogs(renderArgs);
|
||||
|
||||
renderStatsAndLogs(renderArgs);
|
||||
|
||||
renderDomainConnectionStatusBorder(renderArgs);
|
||||
renderQmlUi(renderArgs);
|
||||
|
@ -370,14 +368,9 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) {
|
|||
// Display stats and log text onscreen
|
||||
|
||||
// Determine whether to compute timing details
|
||||
bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Stats); //&&
|
||||
// Stats::getInstance()->isExpanded();
|
||||
if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) {
|
||||
PerformanceTimer::setActive(shouldDisplayTimingDetail);
|
||||
}
|
||||
Stats::getInstance()->updateStats();
|
||||
|
||||
/*
|
||||
// Show on-screen msec timer
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) {
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
|
@ -401,6 +394,7 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) {
|
|||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
*/
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) {
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "Stats.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/component_wise.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
@ -41,7 +43,6 @@ Stats* Stats::getInstance() {
|
|||
if (!INSTANCE) {
|
||||
Stats::registerType();
|
||||
Stats::show();
|
||||
//Stats::toggle();
|
||||
Q_ASSERT(INSTANCE);
|
||||
}
|
||||
return INSTANCE;
|
||||
|
@ -104,6 +105,13 @@ void Stats::updateStats() {
|
|||
}
|
||||
}
|
||||
|
||||
bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Stats) && isExpanded();
|
||||
if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) {
|
||||
PerformanceTimer::setActive(shouldDisplayTimingDetail);
|
||||
}
|
||||
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
// we need to take one avatar out so we don't include ourselves
|
||||
|
@ -144,7 +152,7 @@ void Stats::updateStats() {
|
|||
pingVoxel = totalPingOctree / octreeServerCount;
|
||||
}
|
||||
|
||||
STAT_UPDATE(entitiesPing, pingVoxel);
|
||||
//STAT_UPDATE(entitiesPing, pingVoxel);
|
||||
//if (_expanded) {
|
||||
// QString voxelMaxPing;
|
||||
// if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid.
|
||||
|
@ -202,22 +210,137 @@ void Stats::updateStats() {
|
|||
} // expanded avatar column
|
||||
|
||||
// Fourth column, octree stats
|
||||
int serverCount = 0;
|
||||
int movingServerCount = 0;
|
||||
unsigned long totalNodes = 0;
|
||||
unsigned long totalInternal = 0;
|
||||
unsigned long totalLeaves = 0;
|
||||
std::stringstream sendingModeStream("");
|
||||
sendingModeStream << "[";
|
||||
NodeToOctreeSceneStats* octreeServerSceneStats = Application::getInstance()->getOcteeSceneStats();
|
||||
for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
OctreeSceneStats& stats = i->second;
|
||||
serverCount++;
|
||||
if (_expanded) {
|
||||
if (serverCount > 1) {
|
||||
sendingModeStream << ",";
|
||||
}
|
||||
if (stats.isMoving()) {
|
||||
sendingModeStream << "M";
|
||||
movingServerCount++;
|
||||
} else {
|
||||
sendingModeStream << "S";
|
||||
}
|
||||
}
|
||||
|
||||
// calculate server node totals
|
||||
totalNodes += stats.getTotalElements();
|
||||
if (_expanded) {
|
||||
totalInternal += stats.getTotalInternal();
|
||||
totalLeaves += stats.getTotalLeaves();
|
||||
}
|
||||
}
|
||||
if (_expanded) {
|
||||
if (serverCount == 0) {
|
||||
sendingModeStream << "---";
|
||||
}
|
||||
sendingModeStream << "] " << serverCount << " servers";
|
||||
if (movingServerCount > 0) {
|
||||
sendingModeStream << " <SCENE NOT STABLE>";
|
||||
} else {
|
||||
sendingModeStream << " <SCENE STABLE>";
|
||||
}
|
||||
QString sendingModeResult = sendingModeStream.str().c_str();
|
||||
STAT_UPDATE(sendingMode, sendingModeResult);
|
||||
}
|
||||
|
||||
// Incoming packets
|
||||
QLocale locale(QLocale::English);
|
||||
auto voxelPacketsToProcess = qApp->getOctreePacketProcessor().packetsToProcessCount();
|
||||
if (_expanded) {
|
||||
std::stringstream octreeStats;
|
||||
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
||||
QString maxString = locale.toString((int)_recentMaxPackets);
|
||||
octreeStats << "Octree Packets to Process: " << qPrintable(packetsString)
|
||||
<< " [Recent Max: " << qPrintable(maxString) << "]";
|
||||
QString str = octreeStats.str().c_str();
|
||||
STAT_UPDATE(packetStats, str);
|
||||
// drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||
_recentMaxPackets = 0;
|
||||
_resetRecentMaxPacketsSoon = false;
|
||||
}
|
||||
if (voxelPacketsToProcess == 0) {
|
||||
_resetRecentMaxPacketsSoon = true;
|
||||
} else if (voxelPacketsToProcess > _recentMaxPackets) {
|
||||
_recentMaxPackets = voxelPacketsToProcess;
|
||||
}
|
||||
|
||||
// Server Octree Elements
|
||||
STAT_UPDATE(serverElements, totalNodes);
|
||||
STAT_UPDATE(localElements, OctreeElement::getNodeCount());
|
||||
|
||||
if (_expanded) {
|
||||
STAT_UPDATE(serverInternal, totalInternal);
|
||||
STAT_UPDATE(serverLeaves, totalLeaves);
|
||||
// Local Voxels
|
||||
STAT_UPDATE(localInternal, OctreeElement::getInternalNodeCount());
|
||||
STAT_UPDATE(localLeaves, OctreeElement::getLeafNodeCount());
|
||||
// LOD Details
|
||||
STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get<LODManager>()->getLODFeedbackText());
|
||||
}
|
||||
|
||||
bool performanceTimerIsActive = PerformanceTimer::isActive();
|
||||
bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails);
|
||||
if (displayPerf && performanceTimerIsActive) {
|
||||
PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up
|
||||
|
||||
// we will also include room for 1 line per timing record and a header of 4 lines
|
||||
// Timing details...
|
||||
|
||||
// First iterate all the records, and for the ones that should be included, insert them into
|
||||
// a new Map sorted by average time...
|
||||
bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen);
|
||||
QMap<float, QString> sortedRecords;
|
||||
const QMap<QString, PerformanceTimerRecord>& allRecords = PerformanceTimer::getAllTimerRecords();
|
||||
QMapIterator<QString, PerformanceTimerRecord> i(allRecords);
|
||||
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (includeTimingRecord(i.key())) {
|
||||
float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC;
|
||||
sortedRecords.insertMulti(averageTime, i.key());
|
||||
}
|
||||
}
|
||||
|
||||
int linesDisplayed = 0;
|
||||
QMapIterator<float, QString> j(sortedRecords);
|
||||
j.toBack();
|
||||
QString perfLines;
|
||||
while (j.hasPrevious()) {
|
||||
j.previous();
|
||||
static const QChar noBreakingSpace = QChar::Nbsp;
|
||||
QString functionName = j.value();
|
||||
const PerformanceTimerRecord& record = allRecords.value(functionName);
|
||||
perfLines += QString("%1: %2 [%3]\n").
|
||||
arg(QString(qPrintable(functionName)), 120, noBreakingSpace).
|
||||
arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace).
|
||||
arg((int)record.getCount(), 6, 10, noBreakingSpace);
|
||||
linesDisplayed++;
|
||||
if (onlyDisplayTopTen && linesDisplayed == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_timingStats = perfLines;
|
||||
emit timingStatsChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Stats::setRenderDetails(const RenderDetails& details) {
|
||||
//STATS_PROPERTY(int, triangles, 0)
|
||||
//STATS_PROPERTY(int, quads, 0)
|
||||
//STATS_PROPERTY(int, materialSwitches, 0)
|
||||
//STATS_PROPERTY(int, meshOpaque, 0)
|
||||
//STATS_PROPERTY(int, meshTranslucent, 0)
|
||||
//STATS_PROPERTY(int, opaqueConsidered, 0)
|
||||
//STATS_PROPERTY(int, opaqueOutOfView, 0)
|
||||
//STATS_PROPERTY(int, opaqueTooSmall, 0)
|
||||
//STATS_PROPERTY(int, translucentConsidered, 0)
|
||||
//STATS_PROPERTY(int, translucentOutOfView, 0)
|
||||
//STATS_PROPERTY(int, translucentTooSmall, 0)
|
||||
//STATS_PROPERTY(int, octreeElementsServer, 0)
|
||||
//STATS_PROPERTY(int, octreeElementsLocal, 0)
|
||||
STAT_UPDATE(triangles, details._trianglesRendered);
|
||||
STAT_UPDATE(quads, details._quadsRendered);
|
||||
STAT_UPDATE(materialSwitches, details._materialSwitches);
|
||||
|
@ -240,200 +363,8 @@ void Stats::display(
|
|||
int voxelPacketsToProcess)
|
||||
{
|
||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||
std::stringstream sendingMode("");
|
||||
sendingMode << "Octree Sending Mode: [";
|
||||
int serverCount = 0;
|
||||
int movingServerCount = 0;
|
||||
unsigned long totalNodes = 0;
|
||||
unsigned long totalInternal = 0;
|
||||
unsigned long totalLeaves = 0;
|
||||
NodeToOctreeSceneStats* octreeServerSceneStats = Application::getInstance()->getOcteeSceneStats();
|
||||
for(NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
OctreeSceneStats& stats = i->second;
|
||||
serverCount++;
|
||||
if (_expanded) {
|
||||
if (serverCount > 1) {
|
||||
sendingMode << ",";
|
||||
}
|
||||
if (stats.isMoving()) {
|
||||
sendingMode << "M";
|
||||
movingServerCount++;
|
||||
} else {
|
||||
sendingMode << "S";
|
||||
}
|
||||
}
|
||||
|
||||
// calculate server node totals
|
||||
totalNodes += stats.getTotalElements();
|
||||
if (_expanded) {
|
||||
totalInternal += stats.getTotalInternal();
|
||||
totalLeaves += stats.getTotalLeaves();
|
||||
}
|
||||
}
|
||||
if (_expanded) {
|
||||
if (serverCount == 0) {
|
||||
sendingMode << "---";
|
||||
}
|
||||
sendingMode << "] " << serverCount << " servers";
|
||||
if (movingServerCount > 0) {
|
||||
sendingMode << " <SCENE NOT STABLE>";
|
||||
} else {
|
||||
sendingMode << " <SCENE STABLE>";
|
||||
}
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)sendingMode.str().c_str(), color);
|
||||
}
|
||||
|
||||
// Incoming packets
|
||||
if (_expanded) {
|
||||
octreeStats.str("");
|
||||
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
||||
QString maxString = locale.toString((int)_recentMaxPackets);
|
||||
octreeStats << "Octree Packets to Process: " << qPrintable(packetsString)
|
||||
<< " [Recent Max: " << qPrintable(maxString) << "]";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||
_recentMaxPackets = 0;
|
||||
_resetRecentMaxPacketsSoon = false;
|
||||
}
|
||||
if (voxelPacketsToProcess == 0) {
|
||||
_resetRecentMaxPacketsSoon = true;
|
||||
} else {
|
||||
if (voxelPacketsToProcess > _recentMaxPackets) {
|
||||
_recentMaxPackets = voxelPacketsToProcess;
|
||||
}
|
||||
}
|
||||
|
||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||
unsigned long localTotal = OctreeElement::getNodeCount();
|
||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||
|
||||
// Server Octree Elements
|
||||
if (!_expanded) {
|
||||
octreeStats.str("");
|
||||
octreeStats << "Octree Elements Server: " << qPrintable(serversTotalString)
|
||||
<< " Local:" << qPrintable(localTotalString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_expanded) {
|
||||
octreeStats.str("");
|
||||
octreeStats << "Octree Elements -";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||
|
||||
octreeStats.str("");
|
||||
octreeStats << " Server: " << qPrintable(serversTotalString) <<
|
||||
" Internal: " << qPrintable(serversInternalString) <<
|
||||
" Leaves: " << qPrintable(serversLeavesString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
// Local Voxels
|
||||
unsigned long localInternal = OctreeElement::getInternalNodeCount();
|
||||
unsigned long localLeaves = OctreeElement::getLeafNodeCount();
|
||||
QString localInternalString = locale.toString((uint)localInternal);
|
||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||
|
||||
octreeStats.str("");
|
||||
octreeStats << " Local: " << qPrintable(serversTotalString) <<
|
||||
" Internal: " << qPrintable(localInternalString) <<
|
||||
" Leaves: " << qPrintable(localLeavesString) << "";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
// LOD Details
|
||||
octreeStats.str("");
|
||||
QString displayLODDetails = DependencyManager::get<LODManager>()->getLODFeedbackText();
|
||||
octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
|
||||
//// Performance timer
|
||||
|
||||
|
||||
bool performanceTimerIsActive = PerformanceTimer::isActive();
|
||||
bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails);
|
||||
if (displayPerf && performanceTimerIsActive) {
|
||||
PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up
|
||||
columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide...
|
||||
// we will also include room for 1 line per timing record and a header of 4 lines
|
||||
lines += 4;
|
||||
|
||||
const QMap<QString, PerformanceTimerRecord>& allRecords = PerformanceTimer::getAllTimerRecords();
|
||||
QMapIterator<QString, PerformanceTimerRecord> i(allRecords);
|
||||
bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen);
|
||||
int statsLines = 0;
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (includeTimingRecord(i.key())) {
|
||||
lines++;
|
||||
statsLines++;
|
||||
if (onlyDisplayTopTen && statsLines == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: the display of these timing details should all be moved to JavaScript
|
||||
if (displayPerf && performanceTimerIsActive) {
|
||||
bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen);
|
||||
// Timing details...
|
||||
verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns
|
||||
drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font,
|
||||
"-------------------------------------------------------- Function "
|
||||
"------------------------------------------------------- --msecs- -calls--", color);
|
||||
|
||||
// First iterate all the records, and for the ones that should be included, insert them into
|
||||
// a new Map sorted by average time...
|
||||
QMap<float, QString> sortedRecords;
|
||||
const QMap<QString, PerformanceTimerRecord>& allRecords = PerformanceTimer::getAllTimerRecords();
|
||||
QMapIterator<QString, PerformanceTimerRecord> i(allRecords);
|
||||
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (includeTimingRecord(i.key())) {
|
||||
float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC;
|
||||
sortedRecords.insertMulti(averageTime, i.key());
|
||||
}
|
||||
}
|
||||
|
||||
int linesDisplayed = 0;
|
||||
QMapIterator<float, QString> j(sortedRecords);
|
||||
j.toBack();
|
||||
while (j.hasPrevious()) {
|
||||
j.previous();
|
||||
QChar noBreakingSpace = QChar::Nbsp;
|
||||
QString functionName = j.value();
|
||||
const PerformanceTimerRecord& record = allRecords.value(functionName);
|
||||
|
||||
QString perfLine = QString("%1: %2 [%3]").
|
||||
arg(QString(qPrintable(functionName)), 120, noBreakingSpace).
|
||||
arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace).
|
||||
arg((int)record.getCount(), 6, 10, noBreakingSpace);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color);
|
||||
linesDisplayed++;
|
||||
if (onlyDisplayTopTen && linesDisplayed == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
*/
|
|
@ -30,7 +30,7 @@ private: \
|
|||
class Stats : public QQuickItem {
|
||||
Q_OBJECT
|
||||
HIFI_QML_DECL
|
||||
Q_PROPERTY(bool expanded READ isExpanded NOTIFY expandedChanged)
|
||||
Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged)
|
||||
STATS_PROPERTY(int, serverCount, 0)
|
||||
STATS_PROPERTY(int, framerate, 0)
|
||||
STATS_PROPERTY(int, avatarCount, 0)
|
||||
|
@ -61,8 +61,16 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(int, translucentConsidered, 0)
|
||||
STATS_PROPERTY(int, translucentOutOfView, 0)
|
||||
STATS_PROPERTY(int, translucentTooSmall, 0)
|
||||
STATS_PROPERTY(int, octreeElementsServer, 0)
|
||||
STATS_PROPERTY(int, octreeElementsLocal, 0)
|
||||
STATS_PROPERTY(QString, sendingMode, QString())
|
||||
STATS_PROPERTY(QString, packetStats, QString())
|
||||
STATS_PROPERTY(QString, lodStatus, QString())
|
||||
STATS_PROPERTY(QString, timingStats, QString())
|
||||
STATS_PROPERTY(int, serverElements, 0)
|
||||
STATS_PROPERTY(int, serverInternal, 0)
|
||||
STATS_PROPERTY(int, serverLeaves, 0)
|
||||
STATS_PROPERTY(int, localElements, 0)
|
||||
STATS_PROPERTY(int, localInternal, 0)
|
||||
STATS_PROPERTY(int, localLeaves, 0)
|
||||
|
||||
public:
|
||||
static Stats* getInstance();
|
||||
|
@ -76,8 +84,9 @@ public:
|
|||
bool isExpanded() { return _expanded; }
|
||||
|
||||
void setExpanded(bool expanded) {
|
||||
if (expanded != _expanded) {
|
||||
if (_expanded != expanded) {
|
||||
_expanded = expanded;
|
||||
emit expandedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,8 +122,16 @@ signals:
|
|||
void translucentConsideredChanged();
|
||||
void translucentOutOfViewChanged();
|
||||
void translucentTooSmallChanged();
|
||||
void octreeElementsServerChanged();
|
||||
void octreeElementsLocalChanged();
|
||||
void sendingModeChanged();
|
||||
void packetStatsChanged();
|
||||
void lodStatusChanged();
|
||||
void serverElementsChanged();
|
||||
void serverInternalChanged();
|
||||
void serverLeavesChanged();
|
||||
void localElementsChanged();
|
||||
void localInternalChanged();
|
||||
void localLeavesChanged();
|
||||
void timingStatsChanged();
|
||||
|
||||
private:
|
||||
int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <QOpenGLDebugLogger>
|
||||
#include <QGLWidget>
|
||||
#include <QtQml>
|
||||
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus)
|
||||
|
@ -212,6 +215,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
|
|||
|
||||
|
||||
void OffscreenQmlSurface::updateQuick() {
|
||||
PerformanceTimer perfTimer("qmlUpdate");
|
||||
if (_paused) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue