Add basic instrumentation options to the renderengine and globebrowsing module

Instrumentation is disabled on default, but can be enabled in CMake
This commit is contained in:
Alexander Bock
2019-07-19 09:55:41 +02:00
parent 2a30b499d8
commit fc28b98db9
16 changed files with 255 additions and 26 deletions

View File

@@ -285,6 +285,11 @@ if (OPENSPACE_WITH_ABUFFER_RENDERER)
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_ABUFFER_RENDERER")
endif ()
option(OPENSPACE_WITH_INSTRUMENTATION "Add instrumentation options" OFF)
if (OPENSPACE_WITH_INSTRUMENTATION)
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_INSTRUMENTATION")
endif ()
# Just in case, create the bin directory
add_custom_command(

View File

@@ -187,7 +187,21 @@ private:
properties::TriggerProperty _takeScreenshot;
bool _shouldTakeScreenshot = false;
properties::BoolProperty _applyWarping;
properties::BoolProperty _showFrameNumber;
properties::BoolProperty _showFrameInformation;
#ifdef OPENSPACE_WITH_INSTRUMENTATION
struct FrameInfo {
uint64_t iFrame;
double deltaTime;
double avgDeltaTime;
};
struct {
std::vector<FrameInfo> frames;
uint64_t lastSavedFrame = 0;
uint16_t saveEveryNthFrame = 2048;
} _frameInfo;
properties::BoolProperty _saveFrameInformation;
#endif // OPENSPACE_WITH_INSTRUMENTATION
properties::BoolProperty _disableMasterRendering;
properties::FloatProperty _globalBlackOutFactor;
@@ -205,7 +219,7 @@ private:
std::vector<ghoul::opengl::ProgramObject*> _programs;
std::shared_ptr<ghoul::fontrendering::Font> _fontBig;
std::shared_ptr<ghoul::fontrendering::Font> _fontFrameInfo;
std::shared_ptr<ghoul::fontrendering::Font> _fontInfo;
std::shared_ptr<ghoul::fontrendering::Font> _fontDate;
std::shared_ptr<ghoul::fontrendering::Font> _fontLog;

View File

@@ -109,6 +109,11 @@ create_new_module(
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)
option(OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION "Instrumentation for GlobeBrowsing Performance" OFF)
if (OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION)
target_compile_definitions(openspace-module-globebrowsing INTERFACE "OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION")
endif ()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/gdal_data DESTINATION modules/globebrowsing)
if (WIN32)

View File

@@ -101,6 +101,14 @@ namespace {
"The maximum size of the MemoryAwareTileCache, on the CPU and GPU."
};
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
constexpr const openspace::properties::Property::PropertyInfo InstrumentationInfo = {
"SaveInstrumentationInfo",
"Save Instrumentation Info",
"If enabled, the instrumentation data is saved to disk at the end of the frame."
};
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
openspace::GlobeBrowsingModule::Capabilities
parseSubDatasets(char** subDatasets, int nSubdatasets)
@@ -163,12 +171,24 @@ GlobeBrowsingModule::GlobeBrowsingModule()
, _wmsCacheLocation(WMSCacheLocationInfo, "${BASE}/cache_gdal")
, _wmsCacheSizeMB(WMSCacheSizeInfo, 1024)
, _tileCacheSizeMB(TileCacheSizeInfo, 1024)
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
, _saveInstrumentation(InstrumentationInfo, false)
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
{
addProperty(_wmsCacheEnabled);
addProperty(_offlineMode);
addProperty(_wmsCacheLocation);
addProperty(_wmsCacheSizeMB);
addProperty(_tileCacheSizeMB);
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
_saveInstrumentation.onChange([&]() {
if (_saveInstrumentation) {
_frameInfo.lastSavedFrame = global::renderEngine.frameNumber();
}
});
addProperty(_saveInstrumentation);
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
}
void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
@@ -235,6 +255,43 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
// Render
global::callback::render.emplace_back([&]() { _tileCache->update(); });
// Postdraw
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
global::callback::postDraw.emplace_back([&]() {
// >= as we might have multiple frames per postDraw call (stereo rendering,
// fisheye, etc)
const uint16_t next = _frameInfo.lastSavedFrame + _frameInfo.saveEveryNthFrame;
const bool shouldSave = _saveInstrumentation &&
global::renderEngine.frameNumber() >= next;
if (shouldSave) {
using K = const globebrowsing::RenderableGlobe*;
using V = std::vector<FrameInfo>;
for (const std::pair<K, V>& i : _frameInfo.frames) {
std::string filename = fmt::format(
"_inst_globebrowsing_{}_{}_{}.txt",
i.first->owner()->identifier(), // Owner of the renderable has a name
_frameInfo.lastSavedFrame,
_frameInfo.saveEveryNthFrame
);
std::ofstream file(absPath("${BIN}/" + filename));
for (const FrameInfo& f : i.second) {
std::string line = fmt::format(
"{}\t{}\t{}\t{}",
f.iFrame,
f.nTilesRenderedLocal,
f.nTilesRenderedGlobal,
f.nTilesUploaded
);
file << line << '\n';
}
}
_frameInfo.frames.clear();
_frameInfo.lastSavedFrame = global::renderEngine.frameNumber();
}
});
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
// Deinitialize
global::callback::deinitialize.emplace_back([&]() { GdalWrapper::destroy(); });
@@ -729,4 +786,27 @@ uint64_t GlobeBrowsingModule::wmsCacheSize() const {
return size * 1024 * 1024;
}
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
void GlobeBrowsingModule::addFrameInfo(globebrowsing::RenderableGlobe* globe,
uint32_t nTilesRenderedLocal,
uint32_t nTilesRenderedGlobal,
uint32_t nTilesUploaded)
{
auto it = _frameInfo.frames.find(globe);
if (it == _frameInfo.frames.end()) {
_frameInfo.frames[globe] = std::vector<FrameInfo>();
_frameInfo.frames[globe].reserve(_frameInfo.saveEveryNthFrame);
}
else {
it->second.push_back({
global::renderEngine.frameNumber(),
nTilesRenderedLocal,
nTilesRenderedGlobal,
nTilesUploaded
});
}
}
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
} // namespace openspace

View File

@@ -93,6 +93,11 @@ public:
std::string wmsCacheLocation() const;
uint64_t wmsCacheSize() const; // bytes
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
void addFrameInfo(globebrowsing::RenderableGlobe* globe, uint32_t nTilesRenderedLocal,
uint32_t nTilesRenderedGlobal, uint32_t nTilesUploaded);
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
protected:
void internalInitialize(const ghoul::Dictionary&) override;
@@ -134,6 +139,26 @@ private:
std::map<std::string, Capabilities> _capabilitiesMap;
std::multimap<std::string, UrlInfo> _urlList;
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
struct FrameInfo {
uint64_t iFrame = 0;
uint32_t nTilesRenderedLocal = 0;
uint32_t nTilesRenderedGlobal = 0;
uint32_t nTilesUploaded = 0;
};
struct {
std::unordered_map<
globebrowsing::RenderableGlobe*,
std::vector<FrameInfo>
> frames;
uint64_t lastSavedFrame = 0;
const uint16_t saveEveryNthFrame = 2048;
} _frameInfo;
properties::BoolProperty _saveInstrumentation;
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
};
} // namespace openspace

View File

@@ -341,9 +341,12 @@ void Layer::onChange(std::function<void(Layer*)> callback) {
_onChangeCallback = std::move(callback);
}
void Layer::update() {
int Layer::update() {
if (_tileProvider) {
tileprovider::update(*_tileProvider);
return tileprovider::update(*_tileProvider);
}
else {
return 0;
}
}

View File

@@ -64,7 +64,8 @@ public:
void onChange(std::function<void(Layer*)> callback);
void update();
// Return: number of tiles that were updated
int update();
glm::ivec2 tilePixelStartOffset() const;
glm::ivec2 tilePixelSizeDifference() const;

View File

@@ -91,15 +91,18 @@ void LayerGroup::deinitialize() {
}
}
void LayerGroup::update() {
int LayerGroup::update() {
int res = 0;
_activeLayers.clear();
for (const std::unique_ptr<Layer>& layer : _layers) {
if (layer->enabled()) {
layer->update();
res += layer->update();
_activeLayers.push_back(layer.get());
}
}
return res;
}
Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {

View File

@@ -48,7 +48,8 @@ struct LayerGroup : public properties::PropertyOwner {
void deinitialize();
/// Updates all layers tile providers within this group
void update();
/// Return: Number of tiles that were updated
int update();
Layer* addLayer(const ghoul::Dictionary& layerDict);
void deleteLayer(const std::string& layerName);

View File

@@ -111,10 +111,12 @@ std::array<LayerGroup*, LayerManager::NumLayerGroups> LayerManager::layerGroups(
return res;
}
void LayerManager::update() {
int LayerManager::update() {
int res = 0;
for (std::unique_ptr<LayerGroup>& layerGroup : _layerGroups) {
layerGroup->update();
res += layerGroup->update();
}
return res;
}
void LayerManager::reset(bool includeDisabled) {

View File

@@ -63,7 +63,8 @@ public:
std::array<LayerGroup*, NumLayerGroups> layerGroups() const;
void update();
// Return: Number of tiles updated
int update();
void reset(bool includeDisabled = false);
void onChange(std::function<void(Layer* l)> callback);

View File

@@ -47,6 +47,13 @@
#include <numeric>
#include <queue>
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
#include <openspace/engine/moduleengine.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
openspace::GlobeBrowsingModule* _module = nullptr;
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
namespace {
// Global flags to modify the RenderableGlobe
constexpr const bool LimitLevelByAvailableData = true;
@@ -595,10 +602,13 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyLabels)) {
_labelsDictionary = dictionary.value<ghoul::Dictionary>(KeyLabels);
}
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
_module = global::moduleEngine.module<GlobeBrowsingModule>();
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
}
void RenderableGlobe::initializeGL() {
if (!_labelsDictionary.empty()) {
_globeLabelsComponent.initialize(_labelsDictionary, this);
addPropertySubOwner(_globeLabelsComponent);
@@ -745,7 +755,11 @@ void RenderableGlobe::update(const UpdateData& data) {
_layerManager.reset();
_debugProperties.resetTileProviders = false;
}
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
_nUploadedTiles = _layerManager.update();
#else
_layerManager.update();
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
if (_nLayersIsDirty) {
std::array<LayerGroup*, LayerManager::NumLayerGroups> lgs =
@@ -1034,6 +1048,14 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
}
_localRenderer.program->deactivate();
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
_module->addFrameInfo(
this,
std::min(localCount, ChunkBufferSize),
std::min(globalCount, ChunkBufferSize),
_nUploadedTiles
);
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
if (_debugProperties.showChunkBounds || _debugProperties.showChunkAABB) {
for (int i = 0; i < std::min(globalCount, ChunkBufferSize); ++i) {

View File

@@ -274,6 +274,10 @@ private:
// Labels
GlobeLabelsComponent _globeLabelsComponent;
ghoul::Dictionary _labelsDictionary;
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
int _nUploadedTiles = 0;
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
};
} // namespace openspace::globebrowsing

View File

@@ -162,15 +162,17 @@ void initAsyncTileDataReader(DefaultTileProvider& t, TileTextureInitData initDat
);
}
void initTexturesFromLoadedData(DefaultTileProvider& t) {
bool initTexturesFromLoadedData(DefaultTileProvider& t) {
if (t.asyncTextureDataProvider) {
std::optional<RawTile> tile = t.asyncTextureDataProvider->popFinishedRawTile();
if (tile) {
const cache::ProviderTileKey key = { tile->tileIndex, t.uniqueIdentifier };
ghoul_assert(!t.tileCache->exist(key), "Tile must not be existing in cache");
t.tileCache->createTileAndPut(key, std::move(tile.value()));
return true;
}
}
return false;
}
@@ -1073,7 +1075,7 @@ TileDepthTransform depthTransform(TileProvider& tp) {
void update(TileProvider& tp) {
int update(TileProvider& tp) {
switch (tp.type) {
case Type::DefaultTileProvider: {
DefaultTileProvider& t = static_cast<DefaultTileProvider&>(tp);
@@ -1082,7 +1084,7 @@ void update(TileProvider& tp) {
}
t.asyncTextureDataProvider->update();
initTexturesFromLoadedData(t);
bool hasUploaded = initTexturesFromLoadedData(t);
if (t.asyncTextureDataProvider->shouldBeDeleted()) {
t.asyncTextureDataProvider = nullptr;
@@ -1091,6 +1093,9 @@ void update(TileProvider& tp) {
tileTextureInitData(t.layerGroupID, t.padTiles, t.tilePixelSize)
);
}
if (hasUploaded) {
return 1;
}
break;
}
case Type::SingleImageTileProvider:
@@ -1132,6 +1137,7 @@ void update(TileProvider& tp) {
default:
throw ghoul::MissingCaseException();
}
return 0;
}

View File

@@ -222,8 +222,10 @@ TileDepthTransform depthTransform(TileProvider& tp);
/**
* This method should be called once per frame. Here, TileProviders
* are given the opportunity to update their internal state.
*
* \return The number of tiles that have been updated in this call
*/
void update(TileProvider& tp);
int update(TileProvider& tp);
/**
* Provides a uniform way of all TileProviders to reload or

View File

@@ -144,11 +144,20 @@ namespace {
};
constexpr openspace::properties::Property::PropertyInfo ShowFrameNumberInfo = {
"ShowFrameNumber",
"Show Frame Number",
"If this value is enabled, the current frame number is rendered into the window."
"ShowFrameInformation",
"Show Frame Information",
"If this value is enabled, the current frame number and frame times are rendered "
"into the window."
};
#ifdef OPENSPACE_WITH_INSTRUMENTATION
constexpr openspace::properties::Property::PropertyInfo SaveFrameInfo = {
"SaveFrameInformation",
"Save Frame Information",
"Saves the frame information to disk"
};
#endif // OPENSPACE_WITH_INSTRUMENTATION
constexpr openspace::properties::Property::PropertyInfo DisableMasterInfo = {
"DisableMasterRendering",
"Disable Master Rendering",
@@ -239,7 +248,10 @@ RenderEngine::RenderEngine()
, _showCameraInfo(ShowCameraInfo, true)
, _takeScreenshot(TakeScreenshotInfo)
, _applyWarping(ApplyWarpingInfo, false)
, _showFrameNumber(ShowFrameNumberInfo, false)
, _showFrameInformation(ShowFrameNumberInfo, false)
#ifdef OPENSPACE_WITH_INSTRUMENTATION
, _saveFrameInformation(SaveFrameInfo, false)
#endif // OPENSPACE_WITH_INSTRUMENTATION
, _disableMasterRendering(DisableMasterInfo, false)
, _globalBlackOutFactor(GlobalBlackoutFactorInfo, 1.f, 0.f, 1.f)
, _nAaSamples(AaSamplesInfo, 4, 1, 8)
@@ -317,7 +329,15 @@ RenderEngine::RenderEngine()
_takeScreenshot.onChange([this](){ _shouldTakeScreenshot = true; });
addProperty(_takeScreenshot);
addProperty(_showFrameNumber);
addProperty(_showFrameInformation);
#ifdef OPENSPACE_WITH_INSTRUMENTATION
_saveFrameInformation.onChange([&]() {
if (_saveFrameInformation) {
_frameInfo.lastSavedFrame = frameNumber();
}
});
addProperty(_saveFrameInformation);
#endif // OPENSPACE_WITH_INSTRUMENTATION
addProperty(_globalRotation);
addProperty(_screenSpaceRotation);
@@ -415,12 +435,12 @@ void RenderEngine::initializeGL() {
// development
global::windowDelegate.setNearFarClippingPlane(0.001f, 1000.f);
//Set horizontal FOV value with whatever the field of view (in degrees) is of the
// Set horizontal FOV value with whatever the field of view (in degrees) is of the
// initialized window
_horizFieldOfView = static_cast<float>(global::windowDelegate.getHorizFieldOfView());
constexpr const float FontSizeBig = 50.f;
_fontBig = global::fontManager.font(KeyFontMono, FontSizeBig);
constexpr const float FontSizeFrameinfo = 32.f;
_fontFrameInfo = global::fontManager.font(KeyFontMono, FontSizeFrameinfo);
constexpr const float FontSizeTime = 15.f;
_fontDate = global::fontManager.font(KeyFontMono, FontSizeTime);
constexpr const float FontSizeMono = 10.f;
@@ -582,13 +602,18 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat
);
}
if (_showFrameNumber) {
if (_showFrameInformation) {
glm::vec2 penPosition = glm::vec2(
fontResolution().x / 2 - 50,
fontResolution().y / 3
);
RenderFont(*_fontBig, penPosition, std::to_string(_frameNumber));
std::string fn = std::to_string(_frameNumber);
std::string dt = std::to_string(global::windowDelegate.deltaTime());
std::string avgDt = std::to_string(global::windowDelegate.averageDeltaTime());
std::string res = "Frame: " + fn + '\n' + "Dt: " + dt + '\n' + "Avg Dt: " + avgDt;
RenderFont(*_fontFrameInfo, penPosition, res);
}
++_frameNumber;
@@ -794,6 +819,36 @@ void RenderEngine::postDraw() {
scene()->allSceneGraphNodes()
);
}
if (_saveFrameInformation) {
_frameInfo.frames.push_back({
frameNumber(),
global::windowDelegate.deltaTime(),
global::windowDelegate.averageDeltaTime()
});
}
#ifdef OPENSPACE_WITH_INSTRUMENTATION
const uint16_t next = _frameInfo.lastSavedFrame + _frameInfo.saveEveryNthFrame;
const bool shouldSave = _saveFrameInformation && frameNumber() >= next;
if (shouldSave) {
std::string filename = fmt::format(
"_inst_renderengine_{}_{}.txt",
_frameInfo.lastSavedFrame, _frameInfo.saveEveryNthFrame
);
std::ofstream file(absPath("${BIN}/" + filename));
for (const FrameInfo& i : _frameInfo.frames) {
std::string line = fmt::format(
"{}\t{}\t{}", i.iFrame, i.deltaTime, i.avgDeltaTime
);
file << line << '\n';
}
_frameInfo.frames.clear();
_frameInfo.lastSavedFrame = frameNumber();
}
#endif // OPENSPACE_WITH_INSTRUMENTATION
}
Scene* RenderEngine::scene() {