Merge branch 'develop' into feature/PlanetShadows

This commit is contained in:
Jonathas Costa
2016-06-07 09:12:18 -04:00
15 changed files with 696 additions and 227 deletions

View File

@@ -0,0 +1,61 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __PERFORMANCELAYOUT_H__
#define __PERFORMANCELAYOUT_H__
#include <cstdint>
namespace openspace {
namespace performance {
struct PerformanceLayout {
static const int8_t Version = 0;
static const int LengthName = 256;
static const int NumberValues = 256;
static const int MaxValues = 256;
PerformanceLayout();
struct SceneGraphPerformanceLayout {
char name[LengthName];
float renderTime[NumberValues];
float updateRenderable[NumberValues];
float updateEphemeris[NumberValues];
};
SceneGraphPerformanceLayout sceneGraphEntries[MaxValues];
int16_t nScaleGraphEntries;
struct FunctionPerformanceLayout {
char name[LengthName];
float time[NumberValues];
};
FunctionPerformanceLayout functionEntries[MaxValues];
int16_t nFunctionEntries;
};
} // namespace performance
} // namespace openspace
#endif // __PERFORMANCELAYOUT_H__

View File

@@ -0,0 +1,67 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __PERFORMANCEMANAGER_H__
#define __PERFORMANCEMANAGER_H__
#include <chrono>
#include <map>
#include <vector>
namespace ghoul {
class SharedMemory;
}
namespace openspace {
class SceneGraphNode;
namespace performance {
class PerformanceManager {
public:
static const std::string PerformanceMeasurementSharedData;
PerformanceManager();
~PerformanceManager();
void resetPerformanceMeasurements();
bool isMeasuringPerformance() const;
void storeIndividualPerformanceMeasurement(std::string identifier, long long nanoseconds);
void storeScenePerformanceMeasurements(const std::vector<SceneGraphNode*>& sceneNodes);
private:
bool _doPerformanceMeasurements;
std::map<std::string, size_t> individualPerformanceLocations;
ghoul::SharedMemory* _performanceMemory;
};
} // namespace performance
} // namespace openspace
#endif // __PERFORMANCEMANAGER_H__

View File

@@ -0,0 +1,57 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __PERFORMANCEMEASUREMENT_H__
#define __PERFORMANCEMEASUREMENT_H__
#include <chrono>
#include <string>
namespace openspace {
namespace performance {
class PerformanceManager;
class PerformanceMeasurement {
public:
PerformanceMeasurement(std::string identifier, performance::PerformanceManager* manager);
~PerformanceMeasurement();
private:
std::string _identifier;
performance::PerformanceManager* _manager;
std::chrono::high_resolution_clock::time_point _startTime;
};
#define __MERGE(a,b) a##b
#define __LABEL(a) __MERGE(unique_name_, a)
/// Declare a new variable for measuring the performance of the current block
#define PerfMeasure(name) auto __LABEL(__LINE__) = openspace::performance::PerformanceMeasurement((name), OsEng.renderEngine().performanceManager())
} // namespace performance
} // namespace openspace
#endif // __PERFORMANCEMEASUREMENTHELPER_H__

View File

@@ -31,6 +31,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/performance/performancemanager.h>
namespace ghoul {
namespace fontrendering {
@@ -67,9 +68,6 @@ public:
Post
};
static const std::string PerformanceMeasurementSharedData;
static const std::string KeyFontMono;
static const std::string KeyFontLight;
@@ -97,8 +95,10 @@ public:
void takeScreenshot();
void toggleInfoText(bool b);
// Performance measurements
void setPerformanceMeasurements(bool performanceMeasurements);
bool doesPerformanceMeasurements() const;
performance::PerformanceManager* performanceManager();
void serialize(SyncBuffer* syncBuffer);
void deserialize(SyncBuffer* syncBuffer);
@@ -178,7 +178,7 @@ public:
private:
void setRenderer(std::unique_ptr<Renderer> renderer);
RendererImplementation rendererFromString(const std::string& method);
void storePerformanceMeasurements();
void renderInformation();
void renderScreenLog();
@@ -186,6 +186,8 @@ private:
Scene* _sceneGraph;
RaycasterManager* _raycasterManager;
std::unique_ptr<performance::PerformanceManager> _performanceManager;
std::unique_ptr<Renderer> _renderer;
RendererImplementation _rendererImplementation;
ghoul::Dictionary _rendererData;
@@ -196,9 +198,6 @@ private:
bool _showLog;
bool _takeScreenshot;
bool _doPerformanceMeasurements;
ghoul::SharedMemory* _performanceMemory;
float _globalBlackOutFactor;
float _fadeDuration;
float _currentFadeTime;

View File

@@ -22,6 +22,9 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __SCREENLOG_H__
#define __SCREENLOG_H__
#include <ghoul/logging/log.h>
#include <chrono>
@@ -110,4 +113,6 @@ private:
LogLevel _logLevel;
};
} // namespace openspace
} // namespace openspace
#endif // __SCREENLOG_H__

View File

@@ -33,9 +33,12 @@
#include <set>
namespace ccmc {
class Kameleon;
} // namespace ccmc
namespace openspace {
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
class ccmc::Kameleon;
#endif
class TransformationManager : public ghoul::Singleton<TransformationManager> {
friend class ghoul::Singleton<TransformationManager>;

View File

@@ -43,8 +43,10 @@ public:
protected:
ghoul::SharedMemory* _performanceMemory = nullptr;
float _minMaxValues[2];
int _sortingSelection;
bool _sceneGraphIsEnabled;
bool _functionsIsEnabled;
};
} // namespace gui

View File

@@ -25,7 +25,10 @@
#include <modules/onscreengui/include/guiperformancecomponent.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/performance/performancelayout.h>
#include <openspace/performance/performancemanager.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/misc/sharedmemory.h>
#include <imgui.h>
@@ -42,9 +45,10 @@ namespace openspace {
namespace gui {
void GuiPerformanceComponent::initialize() {
_minMaxValues[0] = 100.f;
_minMaxValues[1] = 250.f;
_sortingSelection = -1;
_sceneGraphIsEnabled = false;
_functionsIsEnabled = false;
}
void GuiPerformanceComponent::deinitialize() {
@@ -53,143 +57,208 @@ void GuiPerformanceComponent::deinitialize() {
}
void GuiPerformanceComponent::render() {
// Copy and paste from renderengine.cpp::storePerformanceMeasurements method
// const int8_t Version = 0;
const int nValues = 250;
const int lengthName = 256;
const int maxValues = 256;
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];
};
using namespace performance;
ImGui::Begin("Performance", &_isEnabled);
if (OsEng.renderEngine().doesPerformanceMeasurements() &&
ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData))
ghoul::SharedMemory::exists(PerformanceManager::PerformanceMeasurementSharedData))
{
ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f);
_minMaxValues[1] = fmaxf(_minMaxValues[0], _minMaxValues[1]);
ImGui::Checkbox("SceneGraph", &_sceneGraphIsEnabled);
ImGui::Checkbox("Functions", &_functionsIsEnabled);
// The indices correspond to the index into the average array further below
ImGui::Text("Sorting");
ImGui::RadioButton("No Sorting", &_sortingSelection, -1);
ImGui::RadioButton("UpdateEphemeris", &_sortingSelection, 0);
ImGui::RadioButton("UpdateRender", &_sortingSelection, 1);
ImGui::RadioButton("RenderTime", &_sortingSelection, 2);
ImGui::Spacing();
if (ImGui::Button("Reset measurements")) {
OsEng.renderEngine().performanceManager()->resetPerformanceMeasurements();
}
if (_sceneGraphIsEnabled) {
ImGui::Begin("SceneGraph", &_sceneGraphIsEnabled);
// The indices correspond to the index into the average array further below
ImGui::Text("Sorting");
ImGui::RadioButton("No Sorting", &_sortingSelection, -1);
ImGui::RadioButton("UpdateEphemeris", &_sortingSelection, 0);
ImGui::RadioButton("UpdateRender", &_sortingSelection, 1);
ImGui::RadioButton("RenderTime", &_sortingSelection, 2);
if (!_performanceMemory)
_performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData);
if (!_performanceMemory)
_performanceMemory = new ghoul::SharedMemory(PerformanceManager::PerformanceMeasurementSharedData);
void* ptr = _performanceMemory->memory();
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
PerformanceLayout layout = *reinterpret_cast<PerformanceLayout*>(ptr);
std::vector<size_t> indices(layout->nScaleGraphEntries);
std::iota(indices.begin(), indices.end(), 0);
std::vector<size_t> indices(layout.nEntries);
std::iota(indices.begin(), indices.end(), 0);
// Ordering:
// updateEphemeris
// UpdateRender
// RenderTime
std::vector<std::array<float, 3>> averages(layout->nScaleGraphEntries, { 0.f, 0.f, 0.f });
std::vector<std::array<std::pair<float, float>, 3>> minMax(
layout->nScaleGraphEntries
);
for (int i = 0; i < layout->nScaleGraphEntries; ++i) {
const PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[i];
// Ordering:
// updateEphemeris
// UpdateRender
// RenderTime
std::vector<std::array<float, 3>> averages(layout.nEntries, { 0.f, 0.f, 0.f });
int v[3] = { 0, 0, 0 };
for (int i = 0; i < layout.nEntries; ++i) {
const PerformanceLayout::PerformanceLayoutEntry& entry = layout.entries[i];
for (int j = 0; j < PerformanceLayout::NumberValues; ++j) {
averages[i][0] += entry.updateEphemeris[j];
if (entry.updateEphemeris[j] != 0.f)
++(v[0]);
averages[i][1] += entry.updateRenderable[j];
if (entry.updateRenderable[j] != 0.f)
++(v[1]);
averages[i][2] += entry.renderTime[j];
if (entry.renderTime[j] != 0.f)
++(v[2]);
}
int v[3] = { 0, 0, 0 };
if (v[0] != 0)
averages[i][0] /= static_cast<float>(v[0]);
if (v[1] != 0)
averages[i][1] /= static_cast<float>(v[1]);
if (v[2] != 0)
averages[i][2] /= static_cast<float>(v[2]);
auto minmaxEphemeris = std::minmax_element(
std::begin(entry.updateEphemeris),
std::end(entry.updateEphemeris)
);
minMax[i][0] = std::make_pair(
*(minmaxEphemeris.first),
*(minmaxEphemeris.second)
);
auto minmaxUpdateRenderable = std::minmax_element(
std::begin(entry.updateRenderable),
std::end(entry.updateRenderable)
);
minMax[i][1] = std::make_pair(
*(minmaxUpdateRenderable.first),
*(minmaxUpdateRenderable.second)
);
auto minmaxRendering = std::minmax_element(
std::begin(entry.renderTime),
std::end(entry.renderTime)
);
minMax[i][2] = std::make_pair(
*(minmaxRendering.first),
*(minmaxRendering.second)
);
for (int j = 0; j < nValues; ++j) {
averages[i][0] += entry.updateEphemeris[j];
if (entry.updateEphemeris[j] != 0.f)
++v[0];
averages[i][1] += entry.updateRenderable[j];
if (entry.updateRenderable[j] != 0.f)
++v[1];
averages[i][2] += entry.renderTime[j];
if (entry.renderTime[j] != 0.f)
++v[2];
}
if (v[0] != 0)
averages[i][0] /= static_cast<float>(v[0]);
if (v[1] != 0)
averages[i][1] /= static_cast<float>(v[1]);
if (v[2] != 0)
averages[i][2] /= static_cast<float>(v[2]);
}
if (_sortingSelection != -1) {
int sortIndex = _sortingSelection;
if (_sortingSelection != -1) {
int sortIndex = _sortingSelection;
std::sort(
indices.begin(),
indices.end(),
[sortIndex, &averages](size_t a, size_t b) {
return averages[a][sortIndex] > averages[b][sortIndex];
}
);
std::sort(
indices.begin(),
indices.end(),
[sortIndex, &averages](size_t a, size_t b) {
return averages[a][sortIndex] > averages[b][sortIndex];
}
for (int i = 0; i < layout->nScaleGraphEntries; ++i) {
const PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[indices[i]];
if (ImGui::CollapsingHeader(entry.name)) {
std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[PerformanceLayout::NumberValues - 1]) + "us";
;
ImGui::PlotLines(
fmt::format("UpdateEphemeris\nAverage: {}us", averages[indices[i]][0]).c_str(),
&entry.updateEphemeris[0],
PerformanceLayout::NumberValues,
0,
updateEphemerisTime.c_str(),
minMax[indices[i]][0].first,
minMax[indices[i]][0].second,
ImVec2(0, 40)
);
std::string updateRenderableTime = std::to_string(entry.updateRenderable[PerformanceLayout::NumberValues - 1]) + "us";
ImGui::PlotLines(
fmt::format("UpdateRender\nAverage: {}us", averages[indices[i]][1]).c_str(),
&entry.updateRenderable[0],
PerformanceLayout::NumberValues,
0,
updateRenderableTime.c_str(),
minMax[indices[i]][1].first,
minMax[indices[i]][1].second,
ImVec2(0, 40)
);
std::string renderTime = std::to_string(entry.renderTime[PerformanceLayout::NumberValues - 1]) + "us";
ImGui::PlotLines(
fmt::format("RenderTime\nAverage: {}us", averages[indices[i]][2]).c_str(),
&entry.renderTime[0],
PerformanceLayout::NumberValues,
0,
renderTime.c_str(),
minMax[indices[i]][2].first,
minMax[indices[i]][2].second,
ImVec2(0, 40)
);
}
);
}
ImGui::End();
}
if (_functionsIsEnabled) {
ImGui::Begin("Functions", &_functionsIsEnabled);
using namespace performance;
if (!_performanceMemory)
_performanceMemory = new ghoul::SharedMemory(PerformanceManager::PerformanceMeasurementSharedData);
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
for (int i = 0; i < layout.nEntries; ++i) {
const PerformanceLayout::PerformanceLayoutEntry& entry = layout.entries[indices[i]];
if (ImGui::CollapsingHeader(entry.name)) {
std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us";
;
ImGui::PlotLines(
fmt::format("UpdateEphemeris\nAverage: {}us", averages[i][0]).c_str(),
&entry.updateEphemeris[0],
layout.nValuesPerEntry,
0,
updateEphemerisTime.c_str(),
_minMaxValues[0],
_minMaxValues[1],
ImVec2(0, 40)
for (int i = 0; i < layout->nFunctionEntries; ++i) {
const PerformanceLayout::FunctionPerformanceLayout& entry = layout->functionEntries[i];
float avg = 0.f;
int count = 0;
for (int j = 0; j < PerformanceLayout::NumberValues; ++j) {
avg += layout->functionEntries[i].time[j];
if (layout->functionEntries[i].time[j] != 0.f)
++count;
}
avg /= count;
auto minmax = std::minmax_element(
std::begin(layout->functionEntries[i].time),
std::end(layout->functionEntries[i].time)
);
std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us";
const PerformanceLayout::FunctionPerformanceLayout& f = layout->functionEntries[i];
std::string renderTime = std::to_string(entry.time[PerformanceLayout::NumberValues - 1]) + "us";
ImGui::PlotLines(
fmt::format("UpdateRender\nAverage: {}us", averages[i][1]).c_str(),
&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(
fmt::format("RenderTime\nAverage: {}us", averages[i][2]).c_str(),
&entry.renderTime[0],
layout.nValuesPerEntry,
fmt::format("{}\nAverage: {}us", entry.name, avg).c_str(),
&entry.time[0],
PerformanceLayout::NumberValues,
0,
renderTime.c_str(),
_minMaxValues[0],
_minMaxValues[1],
*(minmax.first),
*(minmax.second),
ImVec2(0, 40)
);
}
ImGui::End();
}
}
else {
@@ -200,6 +269,5 @@ void GuiPerformanceComponent::render() {
ImGui::End();
}
} // namespace gui
} // namespace openspace

View File

@@ -50,6 +50,9 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/network/networkengine.cpp
${OPENSPACE_BASE_DIR}/src/network/parallelconnection.cpp
${OPENSPACE_BASE_DIR}/src/network/parallelconnection_lua.inl
${OPENSPACE_BASE_DIR}/src/performance/performancemeasurement.cpp
${OPENSPACE_BASE_DIR}/src/performance/performancelayout.cpp
${OPENSPACE_BASE_DIR}/src/performance/performancemanager.cpp
${OPENSPACE_BASE_DIR}/src/properties/matrixproperty.cpp
${OPENSPACE_BASE_DIR}/src/properties/optionproperty.cpp
${OPENSPACE_BASE_DIR}/src/properties/property.cpp
@@ -119,6 +122,9 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/network/networkengine.h
${OPENSPACE_BASE_DIR}/include/openspace/network/parallelconnection.h
${OPENSPACE_BASE_DIR}/include/openspace/network/messagestructures.h
${OPENSPACE_BASE_DIR}/include/openspace/performance/performancemeasurement.h
${OPENSPACE_BASE_DIR}/include/openspace/performance/performancelayout.h
${OPENSPACE_BASE_DIR}/include/openspace/performance/performancemanager.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/matrixproperty.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/numericalproperty.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/numericalproperty.inl

View File

@@ -0,0 +1,50 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/performance/performancelayout.h>
#include <cstring>
namespace openspace {
namespace performance {
PerformanceLayout::PerformanceLayout()
: nScaleGraphEntries(0)
, nFunctionEntries(0)
{
std::memset(
sceneGraphEntries,
0,
MaxValues * sizeof(SceneGraphPerformanceLayout)
);
std::memset(
functionEntries,
0,
MaxValues * sizeof(FunctionPerformanceLayout)
);
}
} // namespace performance
} // namespace openspace

View File

@@ -0,0 +1,167 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/performance/performancemanager.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/performance/performancelayout.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/sharedmemory.h>
namespace {
const std::string _loggerCat = "PerformanceManager";
}
namespace openspace {
namespace performance {
const std::string PerformanceManager::PerformanceMeasurementSharedData =
"OpenSpacePerformanceMeasurementSharedData";
PerformanceManager::PerformanceManager()
: _performanceMemory(nullptr)
{
// Compute the total size
const int totalSize = sizeof(PerformanceLayout);
LINFO("Create shared memory of " << totalSize << " bytes");
try {
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
}
catch (const ghoul::SharedMemory::SharedMemoryError& e) {
LINFOC(e.component, e.what());
}
ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize);
_performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData);
void* ptr = _performanceMemory->memory();
// Using the placement-new to create a PerformanceLayout in the shared memory
PerformanceLayout* layout = new (ptr) PerformanceLayout;
}
PerformanceManager::~PerformanceManager() {
if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData))
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
}
void PerformanceManager::resetPerformanceMeasurements() {
// Using the placement-new to create a PerformanceLayout in the shared memory
_performanceMemory->acquireLock();
void* ptr = _performanceMemory->memory();
new (ptr) PerformanceLayout;
_performanceMemory->releaseLock();
individualPerformanceLocations.clear();
}
bool PerformanceManager::isMeasuringPerformance() const {
return _doPerformanceMeasurements;
}
void PerformanceManager::storeIndividualPerformanceMeasurement
(std::string identifier, long long microseconds)
{
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
_performanceMemory->acquireLock();
auto it = individualPerformanceLocations.find(identifier);
PerformanceLayout::FunctionPerformanceLayout* p = nullptr;
if (it == individualPerformanceLocations.end()) {
p = &(layout->functionEntries[layout->nFunctionEntries]);
individualPerformanceLocations[identifier] = layout->nFunctionEntries;
++(layout->nFunctionEntries);
}
else {
p = &(layout->functionEntries[it->second]);
}
#ifdef _MSC_VER
strcpy_s(p->name, identifier.length() + 1, identifier.c_str());
#else
strcpy(p->name, identifier.c_str());
#endif
std::rotate(
std::begin(p->time),
std::next(std::begin(p->time)),
std::end(p->time)
);
p->time[PerformanceLayout::NumberValues - 1] =
static_cast<float>(microseconds);
_performanceMemory->releaseLock();
}
void PerformanceManager::storeScenePerformanceMeasurements(
const std::vector<SceneGraphNode*>& sceneNodes)
{
using namespace performance;
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
_performanceMemory->acquireLock();
int nNodes = static_cast<int>(sceneNodes.size());
layout->nScaleGraphEntries = nNodes;
for (int i = 0; i < nNodes; ++i) {
SceneGraphNode* node = sceneNodes[i];
memset(layout->sceneGraphEntries[i].name, 0, PerformanceLayout::LengthName);
#ifdef _MSC_VER
strcpy_s(layout->sceneGraphEntries[i].name, node->name().length() + 1, node->name().c_str());
#else
strcpy(layout->sceneGraphEntries[i].name, node->name().c_str());
#endif
SceneGraphNode::PerformanceRecord r = node->performanceRecord();
PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[i];
std::rotate(
std::begin(entry.renderTime),
std::next(std::begin(entry.renderTime)),
std::end(entry.renderTime)
);
entry.renderTime[PerformanceLayout::NumberValues - 1] = r.renderTime / 1000.f;
std::rotate(
std::begin(entry.updateEphemeris),
std::next(std::begin(entry.updateEphemeris)),
std::end(entry.updateEphemeris)
);
entry.updateEphemeris[PerformanceLayout::NumberValues - 1] = r.updateTimeEphemeris / 1000.f;
std::rotate(
std::begin(entry.updateRenderable),
std::next(std::begin(entry.updateRenderable)),
std::end(entry.updateRenderable)
);
entry.updateRenderable[PerformanceLayout::NumberValues - 1] = r.updateTimeRenderable / 1000.f;
}
_performanceMemory->releaseLock();
}
} // namespace performance
} // namespace openspace

View File

@@ -0,0 +1,60 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/performance/performancemeasurement.h>
#include <openspace/performance/performancemanager.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <iostream>
namespace openspace {
namespace performance {
PerformanceMeasurement::PerformanceMeasurement(std::string identifier,
performance::PerformanceManager* manager)
: _identifier(std::move(identifier))
, _manager(manager)
{
if (_manager) {
glFinish();
_startTime = std::chrono::high_resolution_clock::now();
}
}
PerformanceMeasurement::~PerformanceMeasurement() {
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
endTime - _startTime).count();
if (_manager) {
_manager->storeIndividualPerformanceMeasurement(std::move(_identifier), duration);
}
}
} // namespace performance
} // namespace openspace

View File

@@ -33,6 +33,8 @@
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/rendering/raycastermanager.h>
#include <openspace/performance/performancemeasurement.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/opengl/textureunit.h>
#include <vector>
@@ -157,6 +159,8 @@ void FramebufferRenderer::raycastersChanged(VolumeRaycaster& raycaster, bool att
}
void FramebufferRenderer::update() {
PerfMeasure("FramebufferRenderer::update");
if (_dirtyResolution) {
updateResolution();
}
@@ -197,6 +201,8 @@ void FramebufferRenderer::update() {
}
void FramebufferRenderer::updateResolution() {
PerfMeasure("FramebufferRenderer::updateResolution");
int nSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture);
@@ -252,6 +258,8 @@ void FramebufferRenderer::updateResolution() {
}
void FramebufferRenderer::updateRaycastData() {
PerfMeasure("FramebufferRenderer::updateRaycastData");
_raycastData.clear();
_exitPrograms.clear();
_raycastPrograms.clear();
@@ -296,6 +304,8 @@ void FramebufferRenderer::updateRaycastData() {
}
void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) {
PerfMeasure("FramebufferRenderer::render");
if (!_scene)
return;
if (!_camera)
@@ -398,6 +408,8 @@ void FramebufferRenderer::setResolution(glm::ivec2 res) {
}
void FramebufferRenderer::updateRendererData() {
PerfMeasure("FramebufferRenderer::updateRendererData");
ghoul::Dictionary dict;
dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath));
dict.setValue("postFragmentRendererPath", std::string(PostRenderFragmentShaderPath));

View File

@@ -36,6 +36,8 @@
#include <modules/base/rendering/screenspaceimage.h>
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <openspace/performance/performancemanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/scene/scene.h>
@@ -58,7 +60,6 @@
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/io/texture/texturewriter.h>
#ifdef GHOUL_USE_DEVIL
@@ -102,9 +103,6 @@ namespace {
namespace openspace {
const std::string RenderEngine::PerformanceMeasurementSharedData =
"OpenSpacePerformanceMeasurementSharedData";
const std::string RenderEngine::KeyFontMono = "Mono";
const std::string RenderEngine::KeyFontLight = "Light";
@@ -113,12 +111,11 @@ RenderEngine::RenderEngine()
, _sceneGraph(nullptr)
, _renderer(nullptr)
, _rendererImplementation(RendererImplementation::Invalid)
, _performanceManager(nullptr)
, _log(nullptr)
, _showInfo(true)
, _showLog(true)
, _takeScreenshot(false)
, _doPerformanceMeasurements(false)
, _performanceMemory(nullptr)
, _globalBlackOutFactor(1.f)
, _fadeDuration(2.f)
, _currentFadeTime(0.f)
@@ -137,11 +134,8 @@ RenderEngine::~RenderEngine() {
_sceneGraph = nullptr;
delete _mainCamera;
delete _performanceMemory;
delete _raycasterManager;
if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData))
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
}
bool RenderEngine::deinitialize() {
@@ -229,7 +223,6 @@ bool RenderEngine::initializeGL() {
// development
OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f);
try {
const float fontSizeTime = 15.f;
_fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime);
@@ -365,7 +358,7 @@ void RenderEngine::postSynchronizationPreDraw() {
Time::ref().currentTime(),
Time::ref().timeJumped(),
Time::ref().deltaTime(),
_doPerformanceMeasurements
_performanceManager != nullptr
});
_sceneGraph->evaluate(_mainCamera);
@@ -399,7 +392,7 @@ void RenderEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &vi
if (!(OsEng.isMaster() && _disableMasterRendering)) {
_renderer->render(_globalBlackOutFactor, _doPerformanceMeasurements);
_renderer->render(_globalBlackOutFactor, _performanceManager != nullptr);
}
// Print some useful information on the master viewport
@@ -426,8 +419,8 @@ void RenderEngine::postDraw() {
_takeScreenshot = false;
}
if (_doPerformanceMeasurements)
storePerformanceMeasurements();
if (_performanceManager)
_performanceManager->storeScenePerformanceMeasurements(scene()->allSceneGraphNodes());
}
void RenderEngine::takeScreenshot() {
@@ -714,101 +707,20 @@ scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() {
}
void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) {
_doPerformanceMeasurements = performanceMeasurements;
if (performanceMeasurements) {
if (!_performanceManager)
_performanceManager = std::make_unique<performance::PerformanceManager>();
}
else
_performanceManager = nullptr;
}
bool RenderEngine::doesPerformanceMeasurements() const {
return _doPerformanceMeasurements;
return _performanceManager != nullptr;
}
void RenderEngine::storePerformanceMeasurements() {
const int8_t Version = 0;
const int nValues = 250;
const int lengthName = 256;
const int maxValues = 256;
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 = static_cast<int>(scene()->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");
try {
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
}
catch (const ghoul::SharedMemory::SharedMemoryError& e) {
LINFOC(e.component, e.what());
}
ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize);
_performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData);
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
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 = scene()->allSceneGraphNodes()[i];
memset(layout->entries[i].name, 0, lengthName);
#ifdef _MSC_VER
strcpy_s(layout->entries[i].name, node->name().length() + 1, node->name().c_str());
#else
strcpy(layout->entries[i].name, node->name().c_str());
#endif
layout->entries[i].currentRenderTime = 0;
layout->entries[i].currentUpdateRenderable = 0;
layout->entries[i].currentUpdateEphemeris = 0;
}
}
void* ptr = _performanceMemory->memory();
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(ptr);
_performanceMemory->acquireLock();
for (int i = 0; i < nNodes; ++i) {
SceneGraphNode* node = scene()->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();
performance::PerformanceManager* RenderEngine::performanceManager() {
return _performanceManager.get();
}
// This method is temporary and will be removed once the scalegraph is in effect ---abock