Draw Manager: Add a memory stats to debug view.

Adds 2 static unsigned int to Gawain and GPUTexture to roughly keep track of the memory stats on the GPU.

Stats can be view at the bottom of the GPU stats with debug value > 20.
This commit is contained in:
2017-05-04 21:22:41 +02:00
parent 4bd2429f35
commit 6f5307e74d
5 changed files with 121 additions and 5 deletions

View File

@@ -71,6 +71,10 @@ void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src);
unsigned VertexFormat_add_attrib(VertexFormat*, const char* name, VertexCompType, unsigned comp_ct, VertexFetchMode);
// Memory Management
unsigned VertexBuffer_get_memory_usage(void);
// format conversion
#if USE_10_10_10

View File

@@ -17,6 +17,8 @@
#define KEEP_SINGLE_COPY 1
static unsigned vbo_memory_usage;
VertexBuffer* VertexBuffer_create(void)
{
VertexBuffer* verts = malloc(sizeof(VertexBuffer));
@@ -51,14 +53,17 @@ void VertexBuffer_init_with_format(VertexBuffer* verts, const VertexFormat* form
void VertexBuffer_discard(VertexBuffer* verts)
{
if (verts->vbo_id)
if (verts->vbo_id) {
buffer_id_free(verts->vbo_id);
vbo_memory_usage -= VertexBuffer_size(verts);
}
#if KEEP_SINGLE_COPY
else
#endif
if (verts->data)
free(verts->data);
free(verts);
}
@@ -155,6 +160,8 @@ static void VertexBuffer_prime(VertexBuffer* verts)
// fill with delicious data & send to GPU the first time only
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size(format, verts->vertex_ct), verts->data, GL_STATIC_DRAW);
vbo_memory_usage += VertexBuffer_size(verts);
#if KEEP_SINGLE_COPY
// now that GL has a copy, discard original
free(verts->data);
@@ -169,3 +176,8 @@ void VertexBuffer_use(VertexBuffer* verts)
else
VertexBuffer_prime(verts);
}
unsigned VertexBuffer_get_memory_usage(void)
{
return vbo_memory_usage;
}

View File

@@ -2330,7 +2330,7 @@ static void DRW_debug_gpu_stats(void)
UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
char time_to_txt[16];
char pass_name[MAX_PASS_NAME + 8];
char pass_name[MAX_PASS_NAME + 16];
int v = BLI_listbase_count(&DST.enabled_engines) + 3;
GLuint64 tot_time = 0;
@@ -2372,7 +2372,25 @@ static void DRW_debug_gpu_stats(void)
}
sprintf(pass_name, "Total GPU time %.2fms (%.1f fps)", tot_time / 1000000.0, 1000000000.0 / tot_time);
draw_stat(&rect, 0, v++, pass_name, sizeof(pass_name));
v++;
/* Memory Stats */
unsigned int tex_mem = GPU_texture_memory_usage_get();
unsigned int vbo_mem = VertexBuffer_get_memory_usage();
sprintf(pass_name, "GPU Memory");
draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
sprintf(pass_name, "%.2fMB", (float)(tex_mem + vbo_mem) / 1000000.0);
draw_stat(&rect, 1, v++, pass_name, sizeof(pass_name));
sprintf(pass_name, " |--> Textures");
draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
sprintf(pass_name, "%.2fMB", (float)tex_mem / 1000000.0);
draw_stat(&rect, 1, v++, pass_name, sizeof(pass_name));
sprintf(pass_name, " |--> Meshes");
draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
sprintf(pass_name, "%.2fMB", (float)vbo_mem / 1000000.0);
draw_stat(&rect, 1, v++, pass_name, sizeof(pass_name));
}

View File

@@ -143,6 +143,8 @@ typedef enum GPUTextureFormat {
GPU_DEPTH_COMPONENT16,
} GPUTextureFormat;
unsigned int GPU_texture_memory_usage_get(void);
GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_1D_custom(
int w, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]);

View File

@@ -63,11 +63,55 @@ struct GPUTexture {
int fb_attachment; /* slot the texture is attached to */
bool depth; /* is a depth texture? */
bool stencil; /* is a stencil texture? */
unsigned int bytesize; /* number of byte for one pixel */
};
/* ------ Memory Management ------- */
/* Records every texture allocation / free
* to estimate the Texture Pool Memory consumption */
static unsigned int memory_usage;
static unsigned int gpu_texture_memory_footprint_compute(GPUTexture *tex)
{
switch (tex->target) {
case GL_TEXTURE_1D:
return tex->bytesize * tex->w;
case GL_TEXTURE_1D_ARRAY:
case GL_TEXTURE_2D:
return tex->bytesize * tex->w * tex->h;
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
return tex->bytesize * tex->w * tex->h * tex->d;
case GL_TEXTURE_CUBE_MAP:
return tex->bytesize * 6 * tex->w * tex->h;
case GL_TEXTURE_CUBE_MAP_ARRAY:
return tex->bytesize * 6 * tex->w * tex->h * tex->d;
default:
return 0;
}
}
static void gpu_texture_memory_footprint_add(GPUTexture *tex)
{
memory_usage += gpu_texture_memory_footprint_compute(tex);
}
static void gpu_texture_memory_footprint_remove(GPUTexture *tex)
{
memory_usage -= gpu_texture_memory_footprint_compute(tex);
}
unsigned int GPU_texture_memory_usage_get(void)
{
return memory_usage;
}
/* -------------------------------- */
static GLenum gpu_texture_get_format(
int components, GPUTextureFormat data_type,
GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil)
GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil, unsigned int *bytesize)
{
if (data_type == GPU_DEPTH_COMPONENT24 ||
data_type == GPU_DEPTH_COMPONENT16 ||
@@ -98,6 +142,35 @@ static GLenum gpu_texture_get_format(
}
}
switch (data_type) {
case GPU_RG32F:
case GPU_RGBA16F:
*bytesize = 16;
break;
case GPU_RGB16F:
*bytesize = 12;
break;
case GPU_RG16F:
case GPU_DEPTH24_STENCIL8:
case GPU_DEPTH_COMPONENT32F:
case GPU_RGBA8:
*bytesize = 4;
break;
case GPU_DEPTH_COMPONENT24:
*bytesize = 3;
break;
case GPU_DEPTH_COMPONENT16:
case GPU_R16F:
*bytesize = 2;
break;
case GPU_R8:
*bytesize = 1;
break;
default:
*bytesize = 0;
break;
}
/* You can add any of the available type to this list
* For available types see GPU_texture.h */
switch (data_type) {
@@ -267,7 +340,9 @@ static GPUTexture *GPU_texture_create_nD(
tex->target = GL_TEXTURE_2D_MULTISAMPLE;
GLenum format, internalformat, data_format;
internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
glGenTextures(1, &tex->bindcode);
@@ -392,7 +467,9 @@ static GPUTexture *GPU_texture_cube_create(
// tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
}
internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
glGenTextures(1, &tex->bindcode);
@@ -622,6 +699,7 @@ GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char
void GPU_invalid_tex_init(void)
{
memory_usage = 0;
const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
@@ -828,6 +906,8 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
gpu_texture_memory_footprint_remove(tex);
MEM_freeN(tex);
}
}