This commit is contained in:
Emil Axelsson
2016-06-08 15:02:10 +02:00
14 changed files with 695 additions and 226 deletions
+6
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
+50
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
+167
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
@@ -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
+12
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>
@@ -150,6 +152,8 @@ void FramebufferRenderer::raycastersChanged(VolumeRaycaster& raycaster, bool att
}
void FramebufferRenderer::update() {
PerfMeasure("FramebufferRenderer::update");
if (_dirtyResolution) {
updateResolution();
}
@@ -202,6 +206,8 @@ void FramebufferRenderer::update() {
void FramebufferRenderer::updateResolution() {
int nSamples = _nAaSamples;
PerfMeasure("FramebufferRenderer::updateResolution");
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture);
glTexImage2DMultisample(
@@ -256,6 +262,8 @@ void FramebufferRenderer::updateResolution() {
}
void FramebufferRenderer::updateRaycastData() {
PerfMeasure("FramebufferRenderer::updateRaycastData");
_raycastData.clear();
_exitPrograms.clear();
_raycastPrograms.clear();
@@ -310,6 +318,8 @@ void FramebufferRenderer::updateRaycastData() {
}
void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) {
PerfMeasure("FramebufferRenderer::render");
if (!_scene)
return;
if (!_camera)
@@ -450,6 +460,8 @@ void FramebufferRenderer::setNAaSamples(int nAaSamples) {
}
void FramebufferRenderer::updateRendererData() {
PerfMeasure("FramebufferRenderer::updateRendererData");
ghoul::Dictionary dict;
dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath));
dict.setValue("postFragmentRendererPath", std::string(PostRenderFragmentShaderPath));
+16 -104
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() {
@@ -230,7 +224,6 @@ bool RenderEngine::initializeGL() {
// development
OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f);
try {
const float fontSizeTime = 15.f;
_fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime);
@@ -366,7 +359,7 @@ void RenderEngine::postSynchronizationPreDraw() {
Time::ref().currentTime(),
Time::ref().timeJumped(),
Time::ref().deltaTime(),
_doPerformanceMeasurements
_performanceManager != nullptr
});
_sceneGraph->evaluate(_mainCamera);
@@ -400,7 +393,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
@@ -427,8 +420,8 @@ void RenderEngine::postDraw() {
_takeScreenshot = false;
}
if (_doPerformanceMeasurements)
storePerformanceMeasurements();
if (_performanceManager)
_performanceManager->storeScenePerformanceMeasurements(scene()->allSceneGraphNodes());
}
void RenderEngine::takeScreenshot() {
@@ -730,101 +723,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