BugFix Improve GPU Memory Framebuffer monitoring

Count allocation of framebuffers in Bytes and draw plot in ToolBox.
This commit is contained in:
Bruno Herbelin
2024-01-27 13:00:38 +01:00
parent fe623d93a1
commit 36f8ea8df0
3 changed files with 29 additions and 14 deletions

View File

@@ -34,6 +34,11 @@
#define FRAMEBUFFER_DEBUG #define FRAMEBUFFER_DEBUG
#endif #endif
ulong FrameBuffer::total_mem_usage = 0;
ulong FrameBuffer::memory_usage()
{
return total_mem_usage;
}
FrameBuffer::FrameBuffer(glm::vec3 resolution, FrameBufferFlags flags): flags_(flags), FrameBuffer::FrameBuffer(glm::vec3 resolution, FrameBufferFlags flags): flags_(flags),
textureid_(0), multisampling_textureid_(0), framebufferid_(0), multisampling_framebufferid_(0), mem_usage_(0) textureid_(0), multisampling_textureid_(0), framebufferid_(0), multisampling_framebufferid_(0), mem_usage_(0)
@@ -71,7 +76,7 @@ void FrameBuffer::init()
} }
// calculate GPU memory usage (for debug only) // calculate GPU memory usage (for debug only)
mem_usage_ += ( attrib_.viewport.x * attrib_.viewport.y * (flags_ & FrameBuffer_alpha?4:3) ) / 1024; mem_usage_ += ( attrib_.viewport.x * attrib_.viewport.y * (flags_ & FrameBuffer_alpha?4:3) );
// common texture parameters // common texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -113,7 +118,7 @@ void FrameBuffer::init()
glBindFramebuffer(GL_FRAMEBUFFER, multisampling_framebufferid_); glBindFramebuffer(GL_FRAMEBUFFER, multisampling_framebufferid_);
// calculate GPU memory usage // calculate GPU memory usage
mem_usage_ += ( Settings::application.render.multisampling * attrib_.viewport.x * attrib_.viewport.y * (flags_ & FrameBuffer_alpha?4:3) ) / 1024; mem_usage_ += ( Settings::application.render.multisampling * attrib_.viewport.x * attrib_.viewport.y * (flags_ & FrameBuffer_alpha?4:3) );
#ifdef FRAMEBUFFER_DEBUG #ifdef FRAMEBUFFER_DEBUG
g_printerr("multi sampling (%d) - ", Settings::application.render.multisampling); g_printerr("multi sampling (%d) - ", Settings::application.render.multisampling);
@@ -133,18 +138,20 @@ void FrameBuffer::init()
for(int i=1; i < MIPMAP_LEVEL; ++i) { for(int i=1; i < MIPMAP_LEVEL; ++i) {
width = MAX(1, (width / 2)); width = MAX(1, (width / 2));
height = MAX(1, (height / 2)); height = MAX(1, (height / 2));
mem_usage_ += ( width * height * (flags_ & FrameBuffer_alpha?4:3) ) / 1024; mem_usage_ += ( width * height * (flags_ & FrameBuffer_alpha?4:3) );
} }
#ifdef FRAMEBUFFER_DEBUG #ifdef FRAMEBUFFER_DEBUG
g_printerr("mipmap (%d) - ", MIPMAP_LEVEL); g_printerr("mipmap (%d) - ", MIPMAP_LEVEL);
#endif #endif
} }
total_mem_usage += mem_usage_;
if ( !checkFramebufferStatus() ) if ( !checkFramebufferStatus() )
reset(); reset();
#ifdef FRAMEBUFFER_DEBUG #ifdef FRAMEBUFFER_DEBUG
else else
g_printerr("~%d kB allocated\n", mem_usage_); g_printerr("~%lu Bytes allocated (%lu kB total)\n", mem_usage_, total_mem_usage / 1000);
#endif #endif
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -152,8 +159,11 @@ void FrameBuffer::init()
FrameBuffer::~FrameBuffer() FrameBuffer::~FrameBuffer()
{ {
total_mem_usage -= mem_usage_;
#ifdef FRAMEBUFFER_DEBUG #ifdef FRAMEBUFFER_DEBUG
g_printerr("Framebuffer %d deleted - ~%d kB freed\n", framebufferid_, mem_usage_); if (framebufferid_)
g_printerr("Framebuffer %d deleted - ~%lu B freed (%lu kB total)\n", framebufferid_, mem_usage_, total_mem_usage / 1000);
#endif #endif
reset(); reset();
@@ -361,17 +371,18 @@ bool FrameBuffer::checkFramebufferStatus()
{ {
// success // success
ret = true; ret = true;
// test available memory if created buffer is big (more than 8MB) // test available memory if created buffer is big (more than 20 MByte)
if ( mem_usage_ > 8000 ) { if ( mem_usage_ > (20000000) ) {
// Obtain RAM usage in GPU (if possible) // Obtain RAM usage in GPU (if possible)
glm::ivec2 RAM = Rendering::getGPUMemoryInformation(); glm::ivec2 RAM = Rendering::getGPUMemoryInformation();
// bad case: not enough RAM, we should warn the user // bad case: not enough RAM, we should warn the user (testing values in KByte, for twice needed space)
if ( uint(RAM.x) < mem_usage_ * 3 ) { if ( uint(RAM.x) < mem_usage_ / 2000 ) {
Log::Warning("Critical allocation of frame buffer: only %d kB RAM remaining in graphics card.", RAM.x ); Log::Warning("Critical allocation of frame buffer: only %d kB RAM in "
"graphics card to allocate %lu framebuffer.", RAM.x, mem_usage_ / 1000);
if (RAM.y < INT_MAX) if (RAM.y < INT_MAX)
Log::Warning("Only %.1f %% of %d kB available.", 100.f*float(RAM.x)/float(RAM.y), RAM.y); Log::Warning("Only %.1f %% of %d kB GPU RAM available.", 100.f*float(RAM.x)/float(RAM.y), RAM.y);
} }
} }
} }

View File

@@ -95,6 +95,9 @@ public:
FrameBufferImage *image(); FrameBufferImage *image();
bool fill(FrameBufferImage *image); bool fill(FrameBufferImage *image);
// how much memory used, in Bytes
static ulong memory_usage();
private: private:
void init(); void init();
void reset(); void reset();
@@ -106,7 +109,8 @@ private:
glm::vec4 projection_area_; glm::vec4 projection_area_;
uint textureid_, multisampling_textureid_; uint textureid_, multisampling_textureid_;
uint framebufferid_, multisampling_framebufferid_; uint framebufferid_, multisampling_framebufferid_;
uint mem_usage_; ulong mem_usage_;
static ulong total_mem_usage;
}; };

View File

@@ -2309,7 +2309,7 @@ void ToolBox::Render()
static float recorded_bounds[3][2] = { {40.f, 65.f}, {1.f, 50.f}, {0.f, 50.f} }; static float recorded_bounds[3][2] = { {40.f, 65.f}, {1.f, 50.f}, {0.f, 50.f} };
static float refresh_rate = -1.f; static float refresh_rate = -1.f;
static int values_index = 0; static int values_index = 0;
float megabyte = static_cast<float>( static_cast<double>(SystemToolkit::memory_usage()) / 1048576.0 ); float megabyte = static_cast<float>( static_cast<double>(FrameBuffer::memory_usage()) / 1000000.0 );
// init // init
if (refresh_rate < 0.f) { if (refresh_rate < 0.f) {
@@ -2369,7 +2369,7 @@ void ToolBox::Render()
ImGui::PlotLines("LinesRender", recorded_values[0], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[0][0], recorded_bounds[0][1], plot_size); ImGui::PlotLines("LinesRender", recorded_values[0], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[0][0], recorded_bounds[0][1], plot_size);
snprintf(overlay, 128, "Update time %.1f ms (%.1f FPS)", recorded_sum[1] / float(PLOT_ARRAY_SIZE), (float(PLOT_ARRAY_SIZE) * 1000.f) / recorded_sum[1]); snprintf(overlay, 128, "Update time %.1f ms (%.1f FPS)", recorded_sum[1] / float(PLOT_ARRAY_SIZE), (float(PLOT_ARRAY_SIZE) * 1000.f) / recorded_sum[1]);
ImGui::PlotHistogram("LinesMixer", recorded_values[1], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[1][0], recorded_bounds[1][1], plot_size); ImGui::PlotHistogram("LinesMixer", recorded_values[1], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[1][0], recorded_bounds[1][1], plot_size);
snprintf(overlay, 128, "Memory %.1f MB", recorded_values[2][(values_index+PLOT_ARRAY_SIZE-1) % PLOT_ARRAY_SIZE] ); snprintf(overlay, 128, "Framebuffers %.1f MB", recorded_values[2][(values_index+PLOT_ARRAY_SIZE-1) % PLOT_ARRAY_SIZE] );
ImGui::PlotLines("LinesMemo", recorded_values[2], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[2][0], recorded_bounds[2][1], plot_size); ImGui::PlotLines("LinesMemo", recorded_values[2], PLOT_ARRAY_SIZE, values_index, overlay, recorded_bounds[2][0], recorded_bounds[2][1], plot_size);
ImGui::End(); ImGui::End();