mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-30 07:49:31 -05:00
Merge branch 'feature/performancemeasuring' into develop
This commit is contained in:
@@ -34,6 +34,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ghoul {
|
||||
class SharedMemory;
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace properties {
|
||||
@@ -67,10 +71,21 @@ public:
|
||||
static scripting::ScriptEngine::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
void renderMainWindow();
|
||||
|
||||
void renderPropertyWindow();
|
||||
void renderPerformanceWindow();
|
||||
|
||||
bool _isEnabled;
|
||||
|
||||
bool _showPropertyWindow;
|
||||
bool _showPerformanceWindow;
|
||||
bool _showHelp;
|
||||
|
||||
|
||||
ghoul::SharedMemory* _performanceMemory;
|
||||
float _minMaxValues[2];
|
||||
|
||||
std::set<properties::Property*> _boolProperties;
|
||||
std::set<properties::Property*> _intProperties;
|
||||
std::set<properties::Property*> _floatProperties;
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
virtual bool deinitialize() = 0;
|
||||
|
||||
virtual bool isReady() const = 0;
|
||||
bool isEnabled() const;
|
||||
|
||||
void setBoundingSphere(const PowerScaledScalar& boundingSphere);
|
||||
const PowerScaledScalar& getBoundingSphere();
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
namespace ghoul {
|
||||
class SharedMemory;
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
// Forward declare to minimize dependencies
|
||||
@@ -39,6 +43,8 @@ class ScreenLog;
|
||||
|
||||
class RenderEngine {
|
||||
public:
|
||||
static const std::string PerformanceMeasurementSharedData;
|
||||
|
||||
RenderEngine();
|
||||
~RenderEngine();
|
||||
|
||||
@@ -59,6 +65,9 @@ public:
|
||||
void takeScreenshot();
|
||||
void toggleVisualizeABuffer(bool b);
|
||||
|
||||
void setPerformanceMeasurements(bool performanceMeasurements);
|
||||
bool doesPerformanceMeasurements() const;
|
||||
|
||||
void serialize(SyncBuffer* syncBuffer);
|
||||
void deserialize(SyncBuffer* syncBuffer);
|
||||
|
||||
@@ -72,8 +81,9 @@ public:
|
||||
*/
|
||||
static scripting::ScriptEngine::LuaLibrary luaLibrary();
|
||||
|
||||
|
||||
private:
|
||||
void storePerformanceMeasurements();
|
||||
|
||||
Camera* _mainCamera;
|
||||
SceneGraph* _sceneGraph;
|
||||
ABuffer* _abuffer;
|
||||
@@ -83,6 +93,9 @@ private:
|
||||
bool _showScreenLog;
|
||||
bool _takeScreenshot;
|
||||
|
||||
bool _doPerformanceMeasurements;
|
||||
ghoul::SharedMemory* _performanceMemory;
|
||||
|
||||
void generateGlslConfig();
|
||||
|
||||
bool _visualizeABuffer;
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
@@ -44,6 +43,8 @@ namespace openspace {
|
||||
|
||||
class SceneGraphNode;
|
||||
|
||||
// Notifications:
|
||||
// SceneGraphFinishedLoading
|
||||
class SceneGraph {
|
||||
public:
|
||||
// constructors & destructor
|
||||
@@ -99,6 +100,8 @@ public:
|
||||
*/
|
||||
SceneGraphNode* sceneGraphNode(const std::string& name) const;
|
||||
|
||||
std::vector<SceneGraphNode*> allSceneGraphNodes() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to change the
|
||||
* scene graph. The functions contained are
|
||||
|
||||
@@ -44,9 +44,14 @@ namespace openspace {
|
||||
|
||||
class SceneGraphNode : public properties::PropertyOwner {
|
||||
public:
|
||||
struct PerformanceRecord {
|
||||
long long renderTime; // time in ns
|
||||
long long updateTimeRenderable; // time in ns
|
||||
long long updateTimeEphemeris; // time in ns
|
||||
};
|
||||
|
||||
static std::string RootNodeName;
|
||||
|
||||
// constructors & destructor
|
||||
SceneGraphNode();
|
||||
~SceneGraphNode();
|
||||
|
||||
@@ -55,12 +60,10 @@ public:
|
||||
bool initialize();
|
||||
bool deinitialize();
|
||||
|
||||
// essential
|
||||
void update(const UpdateData& data);
|
||||
void evaluate(const Camera* camera, const psc& parentPosition = psc());
|
||||
void render(const RenderData& data);
|
||||
|
||||
// set & get
|
||||
void addNode(SceneGraphNode* child);
|
||||
|
||||
void setParent(SceneGraphNode* parent);
|
||||
@@ -70,7 +73,6 @@ public:
|
||||
SceneGraphNode* parent() const;
|
||||
const std::vector<SceneGraphNode*>& children() const;
|
||||
|
||||
// bounding sphere
|
||||
PowerScaledScalar calculateBoundingSphere();
|
||||
PowerScaledScalar boundingSphere() const;
|
||||
|
||||
@@ -78,27 +80,26 @@ public:
|
||||
|
||||
void print() const;
|
||||
|
||||
// renderable
|
||||
const PerformanceRecord& performanceRecord() const { return _performanceRecord; }
|
||||
|
||||
void setRenderable(Renderable* renderable);
|
||||
const Renderable* renderable() const;
|
||||
Renderable* renderable();
|
||||
|
||||
private:
|
||||
// essential
|
||||
std::vector<SceneGraphNode*> _children;
|
||||
bool sphereInsideFrustum(const psc s_pos, const PowerScaledScalar& s_rad, const Camera* camera);
|
||||
|
||||
std::vector<SceneGraphNode*> _children;
|
||||
SceneGraphNode* _parent;
|
||||
Ephemeris* _ephemeris;
|
||||
|
||||
// renderable
|
||||
PerformanceRecord _performanceRecord;
|
||||
|
||||
Renderable* _renderable;
|
||||
bool _renderableVisible;
|
||||
|
||||
// bounding sphere
|
||||
bool _boundingSphereVisible;
|
||||
PowerScaledScalar _boundingSphere;
|
||||
|
||||
// private helper methods
|
||||
bool sphereInsideFrustum(const psc s_pos, const PowerScaledScalar& s_rad, const Camera* camera);
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -33,12 +33,13 @@ namespace openspace {
|
||||
struct UpdateData {
|
||||
double time;
|
||||
double delta;
|
||||
bool doPerformanceMeasurement;
|
||||
};
|
||||
|
||||
struct RenderData {
|
||||
const Camera& camera;
|
||||
psc position;
|
||||
|
||||
bool doPerformanceMeasurement;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ interaction_speed = 2.75
|
||||
|
||||
-- Key Bindings
|
||||
openspace.bindKey("f1", "openspace.gui.toggle()")
|
||||
openspace.bindKey("f3", "openspace.setPropertyValue('Earth.renderable.enabled', true)")
|
||||
openspace.bindKey("f4", "openspace.setPropertyValue('Earth.renderable.enabled', false)")
|
||||
openspace.bindKey("f2", "openspace.setPerformanceMeasurement(true)")
|
||||
openspace.bindKey("f3", "openspace.setPerformanceMeasurement(false)")
|
||||
openspace.bindKey("f5", "loadKeyBindings()")
|
||||
|
||||
|
||||
|
||||
+145
-90
@@ -32,6 +32,7 @@
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/misc/sharedmemory.h>
|
||||
|
||||
#include <openspace/properties/scalarproperty.h>
|
||||
#include <openspace/properties/vectorproperty.h>
|
||||
@@ -95,7 +96,8 @@ static void ImImpl_RenderDrawLists(ImDrawList** const commandLists, int nCommand
|
||||
for (int n = 0; n < nCommandLists; n++)
|
||||
total_vtx_count += commandLists[n]->vtx_buffer.size();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert);
|
||||
// @BUGFIX @HACK The imgui crashes on complex scenes without the * 2 ---abock
|
||||
size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert) * 2;
|
||||
if (neededBufferSize > vboMaxSize) {
|
||||
vboMaxSize = neededBufferSize + 5000; // Grow buffer
|
||||
glBufferData(GL_ARRAY_BUFFER, neededBufferSize, NULL, GL_STREAM_DRAW);
|
||||
@@ -105,8 +107,10 @@ static void ImImpl_RenderDrawLists(ImDrawList** const commandLists, int nCommand
|
||||
unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
if (!buffer_data)
|
||||
return;
|
||||
int totalSize = 0;
|
||||
for (int n = 0; n < nCommandLists; ++n) {
|
||||
const ImDrawList* cmd_list = commandLists[n];
|
||||
totalSize += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert));
|
||||
buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
}
|
||||
@@ -132,16 +136,87 @@ static void ImImpl_RenderDrawLists(ImDrawList** const commandLists, int nCommand
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
using namespace openspace::properties;
|
||||
|
||||
void renderBoolProperty(Property* prop, const std::string& ownerName) {
|
||||
BoolProperty* p = static_cast<BoolProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
BoolProperty::ValueType value = *p;
|
||||
ImGui::Checkbox((ownerName + "." + name).c_str(), &value);
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderOptionProperty(Property* prop, const std::string& ownerName) {
|
||||
OptionProperty* p = static_cast<OptionProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
int value = *p;
|
||||
std::vector<OptionProperty::Option> options = p->options();
|
||||
for (auto o : options) {
|
||||
ImGui::RadioButton((ownerName + "." + name).c_str(), &value, o.value);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(o.description.c_str());
|
||||
}
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderIntProperty(Property* prop, const std::string& ownerName) {
|
||||
IntProperty* p = static_cast<IntProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
IntProperty::ValueType value = *p;
|
||||
ImGui::SliderInt((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue());
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderFloatProperty(Property* prop, const std::string& ownerName) {
|
||||
FloatProperty* p = static_cast<FloatProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
FloatProperty::ValueType value = *p;
|
||||
ImGui::SliderFloat((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue());
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderVec2Property(Property* prop, const std::string& ownerName) {
|
||||
Vec2Property* p = static_cast<Vec2Property*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
Vec2Property::ValueType value = *p;
|
||||
|
||||
ImGui::SliderFloat2((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x);
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
|
||||
void renderVec3Property(Property* prop, const std::string& ownerName) {
|
||||
Vec3Property* p = static_cast<Vec3Property*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
Vec3Property::ValueType value = *p;
|
||||
|
||||
ImGui::SliderFloat3((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x);
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
GUI::GUI()
|
||||
: _isEnabled(false)
|
||||
, _showPropertyWindow(false)
|
||||
, _showHelp(false)
|
||||
, _performanceMemory(nullptr)
|
||||
{
|
||||
_minMaxValues[0] = 100.f;
|
||||
_minMaxValues[1] = 1000.f;
|
||||
}
|
||||
|
||||
GUI::~GUI() {
|
||||
delete _performanceMemory;
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
@@ -257,8 +332,11 @@ void GUI::startFrame(float deltaTime,
|
||||
void GUI::endFrame() {
|
||||
static bool show = true;
|
||||
//ImGui::ShowTestWindow(&show);
|
||||
|
||||
renderPropertyWindow();
|
||||
renderMainWindow();
|
||||
if (_showPropertyWindow)
|
||||
renderPropertyWindow();
|
||||
if (_showPerformanceWindow)
|
||||
renderPerformanceWindow();
|
||||
|
||||
ImGui::Render();
|
||||
}
|
||||
@@ -336,73 +414,26 @@ void GUI::registerProperty(properties::Property* prop) {
|
||||
|
||||
}
|
||||
|
||||
void renderBoolProperty(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::BoolProperty* p = static_cast<properties::BoolProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
void GUI::renderMainWindow() {
|
||||
ImGui::Begin("OpenSpace GUI", nullptr);
|
||||
|
||||
properties::BoolProperty::ValueType value = *p;
|
||||
ImGui::Checkbox((ownerName + "." + name).c_str(), &value);
|
||||
p->set(value);
|
||||
}
|
||||
ImGui::Checkbox("Properties", &_showPropertyWindow);
|
||||
ImGui::Checkbox("Performance", &_showPerformanceWindow);
|
||||
ImGui::Checkbox("Help", &_showHelp);
|
||||
|
||||
void renderOptionProperty(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::OptionProperty* p = static_cast<properties::OptionProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
int value = *p;
|
||||
std::vector<properties::OptionProperty::Option> options = p->options();
|
||||
for (auto o : options) {
|
||||
ImGui::RadioButton((ownerName + "." + name).c_str(), &value, o.value);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(o.description.c_str());
|
||||
if (_showHelp) {
|
||||
ImGui::Separator();
|
||||
ImGui::ShowUserGuide();
|
||||
ImGui::ShowTestWindow();
|
||||
}
|
||||
p->set(value);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void renderIntProperty(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::IntProperty* p = static_cast<properties::IntProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
properties::IntProperty::ValueType value = *p;
|
||||
ImGui::SliderInt((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue());
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderFloatProperty(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::FloatProperty* p = static_cast<properties::FloatProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
properties::FloatProperty::ValueType value = *p;
|
||||
ImGui::SliderFloat((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue());
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
void renderVec2Property(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::Vec2Property* p = static_cast<properties::Vec2Property*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
properties::Vec2Property::ValueType value = *p;
|
||||
|
||||
ImGui::SliderFloat2((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x);
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
|
||||
void renderVec3Property(properties::Property* prop, const std::string& ownerName) {
|
||||
properties::Vec3Property* p = static_cast<properties::Vec3Property*>(prop);
|
||||
std::string name = p->guiName();
|
||||
|
||||
properties::Vec3Property::ValueType value = *p;
|
||||
|
||||
ImGui::SliderFloat3((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x);
|
||||
p->set(value);
|
||||
}
|
||||
|
||||
|
||||
void GUI::renderPropertyWindow() {
|
||||
using namespace properties;
|
||||
|
||||
ImGui::Begin("Properties", nullptr, size, 0.5f);
|
||||
ImGui::Begin("Properties", &_showPropertyWindow, size, 0.5f);
|
||||
|
||||
//ImGui::ShowUserGuide();
|
||||
ImGui::Spacing();
|
||||
@@ -444,46 +475,70 @@ void GUI::renderPropertyWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
//for (auto pair : _propertiesByOwner) {
|
||||
// auto p = _propertiesByOwner.equal_range(pair);
|
||||
void GUI::renderPerformanceWindow() {
|
||||
// Copy and paste from renderengine.cpp::storePerformanceMeasurements method
|
||||
const int8_t Version = 0;
|
||||
const int nValues = 250;
|
||||
const int lengthName = 256;
|
||||
const int maxValues = 50;
|
||||
|
||||
// if (ImGui::CollapsingHeader(pair->first.c_str())) {
|
||||
// for ()
|
||||
// if (_boolProperties.find(p->second) != _boolProperties.end()) {
|
||||
struct PerformanceLayout {
|
||||
int8_t version;
|
||||
int32_t nValuesPerEntry;
|
||||
int32_t nEntries;
|
||||
int32_t maxNameLength;
|
||||
int32_t maxEntries;
|
||||
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
struct PerformanceLayoutEntry {
|
||||
char name[lengthName];
|
||||
float renderTime[nValues];
|
||||
float updateRenderable[nValues];
|
||||
float updateEphemeris[nValues];
|
||||
|
||||
//for (auto prop : _boolProperties) {
|
||||
// BoolProperty* p = static_cast<BoolProperty*>(prop);
|
||||
// std::string name = p->fullyQualifiedIdentifier();
|
||||
int32_t currentRenderTime;
|
||||
int32_t currentUpdateRenderable;
|
||||
int32_t currentUpdateEphemeris;
|
||||
};
|
||||
|
||||
// BoolProperty::ValueType value = *p;
|
||||
// ImGui::Checkbox(name.c_str(), &value);
|
||||
// p->set(value);
|
||||
PerformanceLayoutEntry entries[maxValues];
|
||||
};
|
||||
|
||||
//}
|
||||
ImGui::Begin("Performance", &_showPerformanceWindow);
|
||||
if (OsEng.renderEngine().doesPerformanceMeasurements() &&
|
||||
ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData))
|
||||
{
|
||||
ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f);
|
||||
_minMaxValues[1] = std::max(_minMaxValues[0], _minMaxValues[1]);
|
||||
|
||||
//for (auto prop : _intProperties) {
|
||||
// IntProperty* p = static_cast<IntProperty*>(prop);
|
||||
// std::string name = p->fullyQualifiedIdentifier();
|
||||
if (!_performanceMemory)
|
||||
_performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData);
|
||||
|
||||
// IntProperty::ValueType value = *p;
|
||||
// ImGui::SliderInt(name.c_str(), &value, p->minValue(), p->maxValue());
|
||||
// p->set(value);
|
||||
//}
|
||||
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(_performanceMemory->pointer());
|
||||
|
||||
//for (auto prop : _StringProperties) {
|
||||
// StringProperty* p = static_cast<StringProperty*>(prop);
|
||||
// std::string name = p->fullyQualifiedIdentifier();
|
||||
for (int i = 0; i < layout->nEntries; ++i) {
|
||||
const PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i];
|
||||
|
||||
// //ImGui::TextUnformatted()
|
||||
//}
|
||||
if (ImGui::CollapsingHeader(entry.name)) {
|
||||
std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us";
|
||||
ImGui::PlotLines("UpdateEphemeris", &entry.updateEphemeris[0], layout->nValuesPerEntry, 0, updateEphemerisTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40));
|
||||
|
||||
std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us";
|
||||
ImGui::PlotLines("UpdateRender", &entry.updateRenderable[0], layout->nValuesPerEntry, 0, updateRenderableTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40));
|
||||
|
||||
std::string renderTime = std::to_string(entry.renderTime[entry.currentRenderTime - 1]) + "us";
|
||||
ImGui::PlotLines("RenderTime", &entry.renderTime[0], layout->nValuesPerEntry, 0, renderTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ImGui::TextWrapped("Performance monitoring is disabled. Enable with "
|
||||
"'openspace.setPerformanceMeasurement(true)'");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -122,4 +122,8 @@ bool Renderable::isReady() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderable::isEnabled() const {
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <openspace/util/syncbuffer.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
#include <ghoul/misc/sharedmemory.h>
|
||||
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#ifdef GHOUL_USE_DEVIL
|
||||
@@ -72,6 +73,9 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
const std::string RenderEngine::PerformanceMeasurementSharedData =
|
||||
"OpenSpacePerformanceMeasurementSharedData";
|
||||
|
||||
namespace luascriptfunctions {
|
||||
|
||||
/**
|
||||
@@ -103,6 +107,21 @@ int visualizeABuffer(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* visualizeABuffer(bool):
|
||||
* Toggle the visualization of the ABuffer
|
||||
*/
|
||||
int setPerformanceMeasurement(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
bool b = lua_toboolean(L, -1) != 0;
|
||||
OsEng.renderEngine().setPerformanceMeasurements(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace luascriptfunctions
|
||||
|
||||
|
||||
@@ -114,6 +133,8 @@ RenderEngine::RenderEngine()
|
||||
, _showInfo(true)
|
||||
, _showScreenLog(true)
|
||||
, _takeScreenshot(false)
|
||||
, _doPerformanceMeasurements(false)
|
||||
, _performanceMemory(nullptr)
|
||||
, _visualizeABuffer(false)
|
||||
, _visualizer(nullptr)
|
||||
{
|
||||
@@ -124,6 +145,10 @@ RenderEngine::~RenderEngine()
|
||||
delete _mainCamera;
|
||||
if (_visualizer)
|
||||
delete _visualizer;
|
||||
|
||||
delete _performanceMemory;
|
||||
if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData))
|
||||
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
|
||||
}
|
||||
|
||||
bool RenderEngine::initialize()
|
||||
@@ -266,7 +291,11 @@ void RenderEngine::postSynchronizationPreDraw()
|
||||
UpdateData a = { Time::ref().currentTime(), Time::ref().deltaTime() };
|
||||
|
||||
// update and evaluate the scene starting from the root node
|
||||
_sceneGraph->update(a);
|
||||
_sceneGraph->update({
|
||||
Time::ref().currentTime(),
|
||||
Time::ref().deltaTime(),
|
||||
_doPerformanceMeasurements
|
||||
});
|
||||
_sceneGraph->evaluate(_mainCamera);
|
||||
|
||||
// clear the abuffer before rendering the scene
|
||||
@@ -320,7 +349,11 @@ void RenderEngine::render()
|
||||
// render the scene starting from the root node
|
||||
if (!_visualizeABuffer) {
|
||||
_abuffer->preRender();
|
||||
_sceneGraph->render({ *_mainCamera, psc() });
|
||||
_sceneGraph->render({
|
||||
*_mainCamera,
|
||||
psc(),
|
||||
_doPerformanceMeasurements
|
||||
});
|
||||
_abuffer->postRender();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
@@ -447,6 +480,9 @@ void RenderEngine::postDraw() {
|
||||
sgct::Engine::instance()->takeScreenshot();
|
||||
_takeScreenshot = false;
|
||||
}
|
||||
|
||||
if (_doPerformanceMeasurements)
|
||||
storePerformanceMeasurements();
|
||||
}
|
||||
|
||||
void RenderEngine::takeScreenshot() {
|
||||
@@ -549,9 +585,100 @@ scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() {
|
||||
&luascriptfunctions::visualizeABuffer,
|
||||
"bool",
|
||||
"Toggles the visualization of the ABuffer"
|
||||
},
|
||||
{
|
||||
"setPerformanceMeasurement",
|
||||
&luascriptfunctions::setPerformanceMeasurement,
|
||||
"bool",
|
||||
"Sets the performance measurements"
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) {
|
||||
_doPerformanceMeasurements = performanceMeasurements;
|
||||
}
|
||||
|
||||
bool RenderEngine::doesPerformanceMeasurements() const {
|
||||
return _doPerformanceMeasurements;
|
||||
}
|
||||
|
||||
void RenderEngine::storePerformanceMeasurements() {
|
||||
const int8_t Version = 0;
|
||||
const int nValues = 250;
|
||||
const int lengthName = 256;
|
||||
const int maxValues = 50;
|
||||
|
||||
struct PerformanceLayout {
|
||||
int8_t version;
|
||||
int32_t nValuesPerEntry;
|
||||
int32_t nEntries;
|
||||
int32_t maxNameLength;
|
||||
int32_t maxEntries;
|
||||
|
||||
struct PerformanceLayoutEntry {
|
||||
char name[lengthName];
|
||||
float renderTime[nValues];
|
||||
float updateRenderable[nValues];
|
||||
float updateEphemeris[nValues];
|
||||
|
||||
int32_t currentRenderTime;
|
||||
int32_t currentUpdateRenderable;
|
||||
int32_t currentUpdateEphemeris;
|
||||
};
|
||||
|
||||
PerformanceLayoutEntry entries[maxValues];
|
||||
};
|
||||
|
||||
const int nNodes = sceneGraph()->allSceneGraphNodes().size();
|
||||
if (!_performanceMemory) {
|
||||
|
||||
// Compute the total size
|
||||
const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) +
|
||||
maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry);
|
||||
LINFO("Create shared memory of " << totalSize << " bytes");
|
||||
|
||||
ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize);
|
||||
_performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData);
|
||||
|
||||
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(_performanceMemory->pointer());
|
||||
layout->version = Version;
|
||||
layout->nValuesPerEntry = nValues;
|
||||
layout->nEntries = nNodes;
|
||||
layout->maxNameLength = lengthName;
|
||||
layout->maxEntries = maxValues;
|
||||
|
||||
memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry));
|
||||
|
||||
for (int i = 0; i < nNodes; ++i) {
|
||||
SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i];
|
||||
|
||||
memset(layout->entries[i].name, 0, lengthName);
|
||||
strcpy(layout->entries[i].name, node->name().c_str());
|
||||
|
||||
layout->entries[i].currentRenderTime = 0;
|
||||
layout->entries[i].currentUpdateRenderable = 0;
|
||||
layout->entries[i].currentUpdateEphemeris = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(_performanceMemory->pointer());
|
||||
_performanceMemory->acquireLock();
|
||||
for (int i = 0; i < nNodes; ++i) {
|
||||
SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i];
|
||||
SceneGraphNode::PerformanceRecord r = node->performanceRecord();
|
||||
PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i];
|
||||
|
||||
entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f;
|
||||
entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f;
|
||||
entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f;
|
||||
|
||||
entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues;
|
||||
entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues;
|
||||
entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues;
|
||||
}
|
||||
_performanceMemory->releaseLock();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
// open space includes
|
||||
#include <openspace/scenegraph/scenegraph.h>
|
||||
#include <openspace/scenegraph/scenegraphnode.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -34,7 +33,6 @@
|
||||
#include <openspace/abuffer/abuffer.h>
|
||||
#include <openspace/engine/gui.h>
|
||||
|
||||
// ghoul includes
|
||||
#include "ghoul/logging/logmanager.h"
|
||||
#include "ghoul/opengl/programobject.h"
|
||||
#include "ghoul/io/texture/texturereader.h"
|
||||
@@ -526,6 +524,10 @@ SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> SceneGraph::allSceneGraphNodes() const {
|
||||
return _nodes;
|
||||
}
|
||||
|
||||
scripting::ScriptEngine::LuaLibrary SceneGraph::luaLibrary() {
|
||||
return {
|
||||
"",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ghoul/opengl/shadermanager.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/shaderobject.h>
|
||||
#include <ghoul/misc/highresclock.h>
|
||||
|
||||
#include <openspace/scenegraph/staticephemeris.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -128,6 +129,7 @@ SceneGraphNode::SceneGraphNode()
|
||||
, _renderable(nullptr)
|
||||
, _renderableVisible(false)
|
||||
, _boundingSphereVisible(false)
|
||||
, _performanceRecord({0, 0, 0})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -170,17 +172,39 @@ bool SceneGraphNode::deinitialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
// essential
|
||||
void SceneGraphNode::update(const UpdateData& data)
|
||||
{
|
||||
if (_ephemeris)
|
||||
_ephemeris->update(data);
|
||||
if (_renderable && _renderable->isReady())
|
||||
_renderable->update(data);
|
||||
void SceneGraphNode::update(const UpdateData& data) {
|
||||
if (_ephemeris) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point start = ghoul::HighResClock::now();
|
||||
|
||||
_ephemeris->update(data);
|
||||
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point end = ghoul::HighResClock::now();
|
||||
_performanceRecord.updateTimeEphemeris = (end - start).count();
|
||||
}
|
||||
else
|
||||
_ephemeris->update(data);
|
||||
}
|
||||
|
||||
if (_renderable && _renderable->isReady()) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point start = ghoul::HighResClock::now();
|
||||
|
||||
_renderable->update(data);
|
||||
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point end = ghoul::HighResClock::now();
|
||||
_performanceRecord.updateTimeRenderable = (end - start).count();
|
||||
}
|
||||
else
|
||||
_renderable->update(data);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition)
|
||||
{
|
||||
void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) {
|
||||
//const psc thisPosition = parentPosition + _ephemeris->position();
|
||||
//const psc camPos = camera->position();
|
||||
//const psc toCamera = thisPosition - camPos;
|
||||
@@ -221,20 +245,25 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition)
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::render(const RenderData& data)
|
||||
{
|
||||
void SceneGraphNode::render(const RenderData& data) {
|
||||
const psc thisPosition = data.position + _ephemeris->position();
|
||||
|
||||
RenderData newData = {data.camera, thisPosition};
|
||||
RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement};
|
||||
|
||||
// check if camera is outside the node boundingsphere
|
||||
/*if (!_boundingSphereVisible) {
|
||||
return;
|
||||
}*/
|
||||
_performanceRecord.renderTime = 0.f;
|
||||
if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point start = ghoul::HighResClock::now();
|
||||
|
||||
if (_renderableVisible && _renderable->isVisible() && _renderable->isReady()) {
|
||||
// LDEBUG("Render");
|
||||
_renderable->render(newData);
|
||||
_renderable->render(newData);
|
||||
|
||||
glFinish();
|
||||
ghoul::HighResClock::time_point end = ghoul::HighResClock::now();
|
||||
_performanceRecord.renderTime = (end - start).count();
|
||||
}
|
||||
else
|
||||
_renderable->render(newData);
|
||||
}
|
||||
|
||||
// evaluate all the children, tail-recursive function(?)
|
||||
|
||||
Reference in New Issue
Block a user