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
#endif
ulong FrameBuffer::total_mem_usage = 0;
ulong FrameBuffer::memory_usage()
{
return total_mem_usage;
}
FrameBuffer::FrameBuffer(glm::vec3 resolution, FrameBufferFlags flags): flags_(flags),
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)
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
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -113,7 +118,7 @@ void FrameBuffer::init()
glBindFramebuffer(GL_FRAMEBUFFER, multisampling_framebufferid_);
// 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
g_printerr("multi sampling (%d) - ", Settings::application.render.multisampling);
@@ -133,18 +138,20 @@ void FrameBuffer::init()
for(int i=1; i < MIPMAP_LEVEL; ++i) {
width = MAX(1, (width / 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
g_printerr("mipmap (%d) - ", MIPMAP_LEVEL);
#endif
}
total_mem_usage += mem_usage_;
if ( !checkFramebufferStatus() )
reset();
#ifdef FRAMEBUFFER_DEBUG
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
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -152,8 +159,11 @@ void FrameBuffer::init()
FrameBuffer::~FrameBuffer()
{
total_mem_usage -= mem_usage_;
#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
reset();
@@ -361,17 +371,18 @@ bool FrameBuffer::checkFramebufferStatus()
{
// success
ret = true;
// test available memory if created buffer is big (more than 8MB)
if ( mem_usage_ > 8000 ) {
// test available memory if created buffer is big (more than 20 MByte)
if ( mem_usage_ > (20000000) ) {
// Obtain RAM usage in GPU (if possible)
glm::ivec2 RAM = Rendering::getGPUMemoryInformation();
// bad case: not enough RAM, we should warn the user
if ( uint(RAM.x) < mem_usage_ * 3 ) {
Log::Warning("Critical allocation of frame buffer: only %d kB RAM remaining in graphics card.", RAM.x );
// bad case: not enough RAM, we should warn the user (testing values in KByte, for twice needed space)
if ( uint(RAM.x) < mem_usage_ / 2000 ) {
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)
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();
bool fill(FrameBufferImage *image);
// how much memory used, in Bytes
static ulong memory_usage();
private:
void init();
void reset();
@@ -106,7 +109,8 @@ private:
glm::vec4 projection_area_;
uint textureid_, multisampling_textureid_;
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 refresh_rate = -1.f;
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
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);
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);
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::End();