From 138a9960137d2f4343a872e9735eb4762df1e52c Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 23 Mar 2016 15:46:17 -0700 Subject: [PATCH] First draft of monitoring the memeory consumption --- .../utilities/tools/render/renderStats.js | 20 +++++ examples/utilities/tools/render/stats.qml | 40 +++++++++ interface/src/Application.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.h | 6 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 23 +++++- libraries/gpu/src/gpu/Texture.cpp | 22 +++-- libraries/gpu/src/gpu/Texture.h | 7 +- libraries/render/src/render/Engine.cpp | 16 ++++ libraries/render/src/render/Engine.h | 81 +++++++++++++------ libraries/script-engine/src/ScriptEngine.cpp | 2 +- 10 files changed, 184 insertions(+), 35 deletions(-) create mode 100644 examples/utilities/tools/render/renderStats.js create mode 100644 examples/utilities/tools/render/stats.qml diff --git a/examples/utilities/tools/render/renderStats.js b/examples/utilities/tools/render/renderStats.js new file mode 100644 index 0000000000..da12ad1b31 --- /dev/null +++ b/examples/utilities/tools/render/renderStats.js @@ -0,0 +1,20 @@ +// +// renderStats.js +// examples/utilities/tools/render +// +// Sam Gateau, created on 3/22/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Set up the qml ui +var qml = Script.resolvePath('stats.qml'); +var window = new OverlayWindow({ + title: 'Render Stats', + source: qml, + width: 300 +}); +window.setPosition(500, 50); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/examples/utilities/tools/render/stats.qml b/examples/utilities/tools/render/stats.qml new file mode 100644 index 0000000000..eb7bb44a73 --- /dev/null +++ b/examples/utilities/tools/render/stats.qml @@ -0,0 +1,40 @@ +// +// stats.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Column { + spacing: 8 + Column { + id: stats + property var config: Render.getConfig("Stats") + + Repeater { + model: [ + "num Textures:numTextures", + "Sysmem Usage:textureSysmemUsage", + "num GPU Textures:numGPUTextures", + "Vidmem Usage:textureVidmemUsage" + ] + Row { + Label { + text: qsTr(modelData.split(":")[0]) + } + property var value: stats.config[modelData.split(":")[1]] + Label { + text: value + horizontalAlignment: AlignRight + } + + } + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 65a8f83871..61d92cebe7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -268,7 +268,7 @@ public: void run() override { while (!_quit) { QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS); -#ifdef NDEBUG +#ifdef ____NDEBUG auto now = usecTimestampNow(); auto lastHeartbeatAge = now - _heartbeat; if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) { diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 39b54c109b..d93962f5a1 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -72,12 +72,16 @@ public: static GLuint getBufferID(const Buffer& buffer); class GLTexture : public GPUObject { + GLuint _size; public: Stamp _storageStamp; Stamp _contentStamp; GLuint _texture; GLenum _target; - GLuint _size; + + + void setSize(GLuint size); + GLuint size() const { return _size; } GLTexture(); ~GLTexture(); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index fe3c6cd6d1..6a96c5a651 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -19,12 +19,29 @@ GLBackend::GLTexture::GLTexture() : _texture(0), _target(GL_TEXTURE_2D), _size(0) -{} +{ + Texture::_numGPUTextures++; +} GLBackend::GLTexture::~GLTexture() { if (_texture != 0) { glDeleteTextures(1, &_texture); } + Texture::_textureVideoMemoryUsage.fetch_sub(_size); + Texture::_numGPUTextures--; +} + +void GLBackend::GLTexture::setSize(GLuint size) { + if (_size == size) { + return; + } + if (size > _size) { + Texture::_textureVideoMemoryUsage.fetch_add(size - _size); + } else { + Texture::_textureVideoMemoryUsage.fetch_sub(_size - size); + } + + _size = size; } class GLTexelFormat { @@ -483,7 +500,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { object->_storageStamp = texture.getStamp(); object->_contentStamp = texture.getDataStamp(); - object->_size = (GLuint)texture.getSize(); + object->setSize((GLuint)texture.getSize()); } glBindTexture(GL_TEXTURE_2D, boundTex); @@ -561,7 +578,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { object->_storageStamp = texture.getStamp(); object->_contentStamp = texture.getDataStamp(); - object->_size = (GLuint)texture.getSize(); + object->setSize((GLuint)texture.getSize()); } glBindTexture(GL_TEXTURE_CUBE_MAP, boundTex); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 7f697c223d..7a0e198ec9 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -17,12 +17,24 @@ using namespace gpu; -std::atomic Texture::_textureSystemMemoryUsage{ 0 }; -std::atomic Texture::_textureVideoMemoryUsage{ 0 }; +std::atomic Texture::_numTextures{ 0 }; +std::atomic Texture::_numGPUTextures{ 0 }; +std::atomic Texture::_textureSystemMemoryUsage{ 0 }; +std::atomic Texture::_textureVideoMemoryUsage{ 0 }; + + +int Texture::getCurrentNumTextures() { + return _numTextures.load(); +} Texture::Size Texture::getCurrentSystemMemoryUsage() { return _textureSystemMemoryUsage.load(); } + +int Texture::getCurrentNumGPUTextures() { + return _numGPUTextures.load(); +} + Texture::Size Texture::getCurrentVideoMemoryUsage() { return _textureVideoMemoryUsage.load(); } @@ -43,8 +55,6 @@ void Texture::updateSystemMemoryUsage(Size prevObjectSize, Size newObjectSize) { } else { addSystemMemoryUsage(newObjectSize - prevObjectSize); } - - qCDebug(gpulogging) << "Texture::SysMem = " << getCurrentSystemMemoryUsage(); } void Texture::addVideoMemoryUsage(Size memorySize) { @@ -122,7 +132,7 @@ const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 fa void Texture::Storage::notifyMipFaceGPULoaded(uint16 level, uint8 face) const { PixelsPointer mipFace = getMipFace(level, face); // if (mipFace && (_type != TEX_CUBE)) { - if (mipFaced) { + if (mipFace) { mipFace->notifyGPULoaded(); } } @@ -229,10 +239,12 @@ Texture* Texture::createFromStorage(Storage* storage) { Texture::Texture(): Resource() { + _numTextures++; } Texture::~Texture() { + _numTextures--; } Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index b5a6f5ed7c..06b0077458 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -139,9 +139,12 @@ protected: }; class Texture : public Resource { + static std::atomic _numTextures; static std::atomic _textureSystemMemoryUsage; +public: + static std::atomic _numGPUTextures; static std::atomic _textureVideoMemoryUsage; - +private: static void addSystemMemoryUsage(Size memorySize); static void subSystemMemoryUsage(Size memorySize); static void updateSystemMemoryUsage(Size prevObjectSize, Size newObjectSize); @@ -151,7 +154,9 @@ class Texture : public Resource { public: + static int getCurrentNumTextures(); static Size getCurrentSystemMemoryUsage(); + static int getCurrentNumGPUTextures(); static Size getCurrentVideoMemoryUsage(); class Usage { diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 806c964ec0..2118c3c734 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -23,6 +23,7 @@ using namespace render; Engine::Engine() : _sceneContext(std::make_shared()), _renderContext(std::make_shared()) { + addJob("Stats"); } void Engine::load() { @@ -57,4 +58,19 @@ void Engine::run() { for (auto job : _jobs) { job.run(_sceneContext, _renderContext); } + +} + +#include +void EngineStats::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + const size_t KILO_BYTES = 1024; + // Update the stats + auto config = std::static_pointer_cast(renderContext->jobConfig); + + config->numTextures = gpu::Texture::getCurrentNumTextures(); + config->textureSysmemUsage = gpu::Texture::getCurrentSystemMemoryUsage(); + config->numGPUTextures = gpu::Texture::getCurrentNumGPUTextures(); + config->textureVidmemUsage = gpu::Texture::getCurrentVideoMemoryUsage(); + + config->emitDirty(); } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 1af0e6d76f..71c52c5910 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -19,34 +19,69 @@ namespace render { -// The render engine holds all render tasks, and is itself a render task. -// State flows through tasks to jobs via the render and scene contexts - -// the engine should not be known from its jobs. -class Engine : public Task { -public: - Engine(); - ~Engine() = default; + // The render engine holds all render tasks, and is itself a render task. + // State flows through tasks to jobs via the render and scene contexts - + // the engine should not be known from its jobs. + class Engine : public Task { + public: - // Load any persisted settings, and set up the presets - // This should be run after adding all jobs, and before building ui - void load(); + Engine(); + ~Engine() = default; - // Register the scene - void registerScene(const ScenePointer& scene) { _sceneContext->_scene = scene; } + // Load any persisted settings, and set up the presets + // This should be run after adding all jobs, and before building ui + void load(); - // Push a RenderContext - void setRenderContext(const RenderContext& renderContext) { (*_renderContext) = renderContext; } - RenderContextPointer getRenderContext() const { return _renderContext; } + // Register the scene + void registerScene(const ScenePointer& scene) { _sceneContext->_scene = scene; } - // Render a frame - // A frame must have a scene registered and a context set to render - void run(); + // Push a RenderContext + void setRenderContext(const RenderContext& renderContext) { (*_renderContext) = renderContext; } + RenderContextPointer getRenderContext() const { return _renderContext; } + + // Render a frame + // A frame must have a scene registered and a context set to render + void run(); + + protected: + SceneContextPointer _sceneContext; + RenderContextPointer _renderContext; + }; + using EnginePointer = std::shared_ptr; + + + // A simple job collecting global stats on the Engine / Scene / GPU + class EngineStatsConfig : public Job::Config{ + Q_OBJECT + Q_PROPERTY(int numTextures MEMBER numTextures NOTIFY dirty) + Q_PROPERTY(int numGPUTextures MEMBER numGPUTextures NOTIFY dirty) + Q_PROPERTY(qint64 textureSysmemUsage MEMBER textureSysmemUsage NOTIFY dirty) + Q_PROPERTY(qint64 textureVidmemUsage MEMBER textureVidmemUsage NOTIFY dirty) + public: + EngineStatsConfig() : Job::Config(true) {} + + int numTextures{ 0 }; + int numGPUTextures{ 0 }; + qint64 textureSysmemUsage{ 0 }; + qint64 textureVidmemUsage{ 0 }; + + void emitDirty() { emit dirty(); } + + signals: + void dirty(); + }; + + class EngineStats { + public: + using Config = EngineStatsConfig; + using JobModel = Job::Model; + + EngineStats() {} + + void configure(const Config& configuration) {} + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); + }; -protected: - SceneContextPointer _sceneContext; - RenderContextPointer _renderContext; -}; -using EnginePointer = std::shared_ptr; } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e17332a20f..61ebfe4515 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1,4 +1,4 @@ -d// +// // ScriptEngine.cpp // libraries/script-engine/src //