DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarthImGui/SystemGUI
2024-12-25 07:49:36 +08:00

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();
}
};
}