223 lines
9.5 KiB
C++
223 lines
9.5 KiB
C++
/* -*-c++-*- */
|
|
/* osgEarth - Geospatial SDK for OpenSceneGraph
|
|
* Copyright 2018 Pelican Mapping
|
|
* http://osgearth.org
|
|
*
|
|
* osgEarth is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
#pragma once
|
|
|
|
#include <osgEarthImGui/ImGuiPanel>
|
|
#include <osgEarth/Threading>
|
|
#include <osgEarth/MemoryUtils>
|
|
#include <osgEarth/GLUtils>
|
|
#include <osgEarth/ShaderLoader>
|
|
#include <osgEarth/Registry>
|
|
#include <osgEarth/Capabilities>
|
|
#include <chrono>
|
|
#include <list>
|
|
#include <vector>
|
|
#include <thread>
|
|
#include <algorithm>
|
|
|
|
namespace osgEarth
|
|
{
|
|
using namespace osgEarth::Threading;
|
|
|
|
namespace
|
|
{
|
|
const int frame_count = 300;
|
|
using Counts = std::vector<unsigned>;
|
|
using Timings = std::vector<std::chrono::nanoseconds>;
|
|
Timings frame_times(frame_count);
|
|
Counts total_jobs(frame_count);
|
|
Counts ico_jobs(frame_count);
|
|
std::chrono::time_point<std::chrono::steady_clock> t_previous;
|
|
int frame_num = 0;
|
|
char buf[256];
|
|
float get_counts(void* data, int index) {
|
|
return (float)(*(Counts*)data)[index];
|
|
};
|
|
unsigned long long get_average_timing_ns(void* data, int count, int start) {
|
|
Timings& t = *(Timings*)(data);
|
|
unsigned long long total = 0;
|
|
int s = start - count; if (s < 0) s += frame_count;
|
|
for (int i = s; i <= s + count; i++)
|
|
total += t[i % frame_count].count();
|
|
return (total / count);
|
|
}
|
|
float get_timing_ms(void* data, int index) {
|
|
return 1e-6 * get_average_timing_ns(data, 4, index - 3);
|
|
};
|
|
};
|
|
|
|
class SystemGUI : public ImGuiPanel
|
|
{
|
|
private:
|
|
std::string _renderMode;
|
|
bool _renderViewNormals;
|
|
bool _renderModelNormals;
|
|
bool _renderWinding;
|
|
bool _renderOutlines;
|
|
bool _showArenaControls;
|
|
|
|
public:
|
|
SystemGUI() : ImGuiPanel("System"),
|
|
_renderViewNormals(false), _renderModelNormals(false),
|
|
_renderWinding(false), _renderOutlines(false),
|
|
_showArenaControls(false) {}
|
|
|
|
void load(const Config& conf) override
|
|
{
|
|
conf.get("ImGui.FontGlobalScale", ImGui::GetIO().FontGlobalScale);
|
|
}
|
|
|
|
void save(Config& conf) override
|
|
{
|
|
conf.set("ImGui.FontGlobalScale", ImGui::GetIO().FontGlobalScale);
|
|
}
|
|
|
|
void draw(osg::RenderInfo& ri) override
|
|
{
|
|
if (!isVisible())
|
|
return;
|
|
|
|
ImGui::Begin(name(), visible());
|
|
{
|
|
auto pb = Memory::getProcessPrivateUsage();
|
|
ImGui::Text("Mem Alloc: %.1lf MB",
|
|
(double)(pb - osgEarth::g_startupPrivateBytes) / 1048576.0);
|
|
ImGui::SameLine();
|
|
ImGui::Text(" Total: %.1lf MB", (double)pb / 1048576.0);
|
|
|
|
ImGui::Separator();
|
|
auto flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg;
|
|
if (ImGui::BeginTable("thread pools", 6, flags))
|
|
{
|
|
auto metrics = jobs::get_metrics();
|
|
|
|
auto all_pool_metrics = metrics->all();
|
|
|
|
ImGui::TableNextColumn(); ImGui::Text("Pool");
|
|
ImGui::TableNextColumn(); ImGui::Text("Run"); //ImGui::SetItemTooltip("Running");
|
|
ImGui::TableNextColumn(); ImGui::Text("Mrg"); //ImGui::SetItemTooltip("Merging / postprocessing");
|
|
ImGui::TableNextColumn(); ImGui::Text("Que"); //ImGui::SetItemTooltip("Queued jobs (waiting to run)");
|
|
//ImGui::TableNextColumn(); ImGui::Text("Can"); //ImGui::SetItemTooltip("Canceled jobs");
|
|
ImGui::TableNextColumn(); ImGui::Text("Max"); //ImGui::SetItemTooltip("Number of available threads");
|
|
ImGui::TableNextColumn();
|
|
|
|
for (auto pool_metrics : all_pool_metrics)
|
|
{
|
|
if (pool_metrics && pool_metrics->total > 0)
|
|
{
|
|
ImGui::TableNextColumn();
|
|
ImGui::Text("%s", (pool_metrics->name.empty() ? "default" : pool_metrics->name.c_str()));
|
|
|
|
ImGui::TableNextColumn(); ImGui::Text("%d", (int)pool_metrics->running);
|
|
ImGui::TableNextColumn(); ImGui::Text("%d", (int)pool_metrics->postprocessing);
|
|
ImGui::TableNextColumn(); ImGui::Text("%d", (int)pool_metrics->pending);
|
|
//ImGui::TableNextColumn(); ImGui::Text("%d", (int)pool_metrics->canceled);
|
|
ImGui::TableNextColumn(); ImGui::Text("%d", (int)pool_metrics->concurrency);
|
|
|
|
ImGui::TableNextColumn();
|
|
ImGui::PushID((std::uintptr_t)pool_metrics);
|
|
int pc = pool_metrics->concurrency;
|
|
if (ImGui::InputInt("", &pc))
|
|
jobs::get_pool(pool_metrics->name)->set_concurrency(
|
|
std::max(1, std::min(pc, (int)std::thread::hardware_concurrency())));
|
|
ImGui::PopID();
|
|
}
|
|
}
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
//OE_HARD_ASSERT(jobs::get_metrics()->total() == jobs::get_metrics()->total_running() + jobs::get_metrics()->total_pending() + jobs::get_metrics()->total_postprocessing());
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGuiLTable::Begin("SystemGUIPlots"))
|
|
{
|
|
int f = frame_num++ % frame_count;
|
|
auto now = std::chrono::steady_clock::now();
|
|
frame_times[f] = now - t_previous;
|
|
t_previous = now;
|
|
auto avg_timing_ms = 1e-6 * (float)get_average_timing_ns(&frame_times, 120, f);
|
|
sprintf(buf, "%.2f ms / %d fps", avg_timing_ms, (int)std::ceil(1000.0 / avg_timing_ms));
|
|
ImGuiLTable::PlotLines("Frame", get_timing_ms, &frame_times, frame_count, frame_num, buf, 0.0f, 32.0f);
|
|
|
|
total_jobs[f] = jobs::get_metrics()->total();
|
|
sprintf(buf, "%d", total_jobs[f]);
|
|
ImGuiLTable::PlotLines("Jobs", get_counts, &total_jobs, frame_count, frame_num, buf, 0u, 100u);
|
|
|
|
auto pager = view(ri)->getDatabasePager();
|
|
if (pager) {
|
|
auto ico = pager->getIncrementalCompileOperation();
|
|
if (ico) {
|
|
ico_jobs[f] = ico->getToCompile().size();
|
|
sprintf(buf, "%d", ico_jobs[f]);
|
|
ImGuiLTable::PlotLines("ICO", get_counts, &ico_jobs, frame_count, frame_num, buf, 0u, 4u);
|
|
}
|
|
}
|
|
|
|
static unsigned zeroJobFrames = 0;
|
|
static unsigned zeroJobFramesThreshold = 3;
|
|
static std::chrono::steady_clock::time_point lastZeroJobTime = now;
|
|
static long long surgeDuration_ms = 0;
|
|
|
|
if (zeroJobFrames < zeroJobFramesThreshold)
|
|
surgeDuration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastZeroJobTime).count();
|
|
else
|
|
lastZeroJobTime = now;
|
|
|
|
if (total_jobs[f] == 0)
|
|
++zeroJobFrames;
|
|
else
|
|
zeroJobFrames = 0;
|
|
|
|
ImGuiLTable::Text("Surge:", "%d ms", surgeDuration_ms);
|
|
|
|
ImGuiLTable::Text("Canceled:", std::to_string(jobs::get_metrics()->total_canceled()).c_str());
|
|
ImGuiLTable::End();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGuiLTable::Begin("FontScale"))
|
|
{
|
|
if (ImGuiLTable::SliderFloat("Font Scale", &ImGui::GetIO().FontGlobalScale, 0.5f, 2.0f))
|
|
dirtySettings();
|
|
|
|
//ImGuiLTable::Text("Dirty timer", "%.1f", ImGui::GetCurrentContext()->SettingsDirtyTimer); // ::GetIO().IniSavingRate);
|
|
|
|
ImGuiLTable::End();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
if (ImGuiLTable::Begin("caps"))
|
|
{
|
|
auto& caps = osgEarth::Registry::capabilities();
|
|
ImGuiLTable::Text("osgEarth", osgEarthGetVersion());
|
|
ImGuiLTable::Text("OSG", osgGetVersion());
|
|
//ImGuiLTable::Text("GL_VENDOR", caps.getVendor().c_str());
|
|
ImGuiLTable::Text("GL_RENDERER", caps.getRenderer().c_str());
|
|
ImGuiLTable::Text("GL_VERSION", caps.getVersion().c_str());
|
|
ImGuiLTable::Text("GL Profile", caps.isCoreProfile() ? "Core" : "Compatibility");
|
|
ImGuiLTable::End();
|
|
}
|
|
}
|
|
ImGui::End();
|
|
}
|
|
};
|
|
}
|