Adding monitoring for (approximate) VRAM used by textures. The information is current...
authorMitchell Stokes <mogurijin@gmail.com>
Wed, 17 Nov 2010 05:28:25 +0000 (05:28 +0000)
committerMitchell Stokes <mogurijin@gmail.com>
Wed, 17 Nov 2010 05:28:25 +0000 (05:28 +0000)
Here is a image of it in action:
http://www.pasteall.org/pic/show.php?id=6351

What it monitors:
  * VRAM used by textures created via bf_gpu and BL_Textures

What it does not monitor:
  * VRAM used by the Blender ui
  * VRAM used by 2d filters
  * VRAM allocated by the user via KX_Scene.pre_draw and KX_Scene.pre_draw

source/blender/gpu/GPU_extensions.h
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_extensions.c
source/gameengine/Ketsji/BL_Texture.cpp
source/gameengine/Ketsji/BL_Texture.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp

index a7f43d3b0aee0021d8e04c1f55bde3804e54f29f..d545a553da959436c4d961c2669bd9e52149f66e 100644 (file)
@@ -104,6 +104,10 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
        - if created with from_blender, will not free the texture
 */
 
+unsigned int GPU_texture_vram_usage(void);
+void GPU_texture_vram_add(unsigned int amount);
+void GPU_texture_vram_subtract(unsigned int amount);
+
 GPUTexture *GPU_texture_create_1D(int w, float *pixels);
 GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels);
 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels);
index a93d8cbbb8e7e594ca1081500b4fc6a669875c79..2d15d3efae92218c6628bc18c2bf048197d7acef 100644 (file)
@@ -540,11 +540,13 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
 
        if (!(gpu_get_mipmap() && mipmap)) {
                glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               GPU_texture_vram_add(rectw*recth*4);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
        }
        else {
                gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               GPU_texture_vram_add((rectw*recth*4) + (rectw*recth*4)/3);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
 
@@ -817,6 +819,8 @@ void GPU_free_unused_buffers(void)
 
 void GPU_free_image(Image *ima)
 {
+       ImBuf *ibuf;
+
        if(!BLI_thread_is_main()) {
                gpu_queue_image_for_free(ima);
                return;
@@ -827,6 +831,13 @@ void GPU_free_image(Image *ima)
                glDeleteTextures(1, (GLuint *)&ima->bindcode);
                ima->bindcode= 0;
                ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+
+               // Calculate how much vram was freed
+               ibuf = BKE_image_get_ibuf(ima, NULL);
+               if (!gpu_get_mipmap())
+                       GPU_texture_vram_subtract(ibuf->x*ibuf->y*4);
+               else
+                       GPU_texture_vram_subtract((ibuf->x*ibuf->y*4)+(ibuf->x*ibuf->y*4)/3);
        }
 
        /* free glsl image binding */
index 70a74aafead7247731135288062f1598a2062f1a..4298ec8d44d81379066f488ab7765a6d190d1114 100644 (file)
@@ -66,11 +66,12 @@ static struct GPUGlobal {
        GLuint currentfb;
        int glslsupport;
        int extdisabled;
+       unsigned int texturevram; // An approximation of how much vram is being used for textures
        int colordepth;
        GPUDeviceType device;
        GPUOSType os;
        GPUDriverType driver;
-} GG = {1, 0, 0, 0};
+} GG = {1, 0, 0, 0, 0};
 
 /* GPU Types */
 
@@ -185,6 +186,21 @@ int GPU_color_depth()
     return GG.colordepth;
 }
 
+unsigned int GPU_texture_vram_usage()
+{
+       return GG.texturevram;
+}
+
+void GPU_texture_vram_add(unsigned int amount)
+{
+       GG.texturevram += amount;
+}
+
+void GPU_texture_vram_subtract(unsigned int amount)
+{
+       GG.texturevram -= amount;
+}
+
 int GPU_print_error(char *str)
 {
        GLenum errCode;
@@ -343,6 +359,8 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
        if (tex->target == GL_TEXTURE_1D) {
                glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0);
 
+               GPU_texture_vram_add(tex->w*4);
+
                if (fpixels) {
                        glTexSubImage1D(tex->target, 0, 0, w, format, type,
                                pixels? pixels: fpixels);
@@ -356,6 +374,8 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
                glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
                        format, type, 0);
 
+               GPU_texture_vram_add(tex->w*tex->h*4);
+
                if (fpixels) {
                        glTexSubImage2D(tex->target, 0, 0, 0, w, h,
                                format, type, pixels? pixels: fpixels);
@@ -620,8 +640,15 @@ void GPU_texture_free(GPUTexture *tex)
                if (tex->fb)
                        GPU_framebuffer_texture_detach(tex->fb, tex);
                if (tex->bindcode && !tex->fromblender)
+               {
                        glDeleteTextures(1, &tex->bindcode);
 
+                       if (tex->target == GL_TEXTURE_2D)
+                               GPU_texture_vram_subtract(tex->w*tex->h*4);
+                       else
+                               GPU_texture_vram_subtract(tex->w*4);
+               }
+
                MEM_freeN(tex);
        }
 }
index e708775b184bf951a471ff59458c9ad3ba115a49..446ad0c47d50080c5fd47bfd6302184bc3cf956a 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "KX_GameObject.h"
 
+#include "GPU_extensions.h"
+
 #define spit(x) std::cout << x << std::endl;
 
 #include "MEM_guardedalloc.h"
@@ -61,7 +63,8 @@ BL_Texture::BL_Texture()
        mNeedsDeleted(0),
        mType(0),
        mUnit(0),
-       mEnvState(0)
+       mEnvState(0),
+       mTexSize(0)
 {
        // --
 }
@@ -77,6 +80,9 @@ void BL_Texture::DeleteTex()
                glDeleteTextures(1, (GLuint*)&mTexture);
                mNeedsDeleted = 0;
                mOk = 0;
+
+               GPU_texture_vram_subtract(mTexSize);
+               mTexSize = 0;
        }
 
        if(mEnvState) {
@@ -165,11 +171,15 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
+               mTexSize = (x*y*4)+(x*y*4)/3;
+               GPU_texture_vram_add(mTexSize);
        } 
        else {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix );
+               mTexSize = x*y*4;
+               GPU_texture_vram_add(mTexSize);
        }
 
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@@ -190,11 +200,15 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+               mTexSize = (x*y*4)+(x*y*4)/3;
+               GPU_texture_vram_add(mTexSize);
        }
        else {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+               mTexSize = x*y*4;
+               GPU_texture_vram_add(mTexSize);
        }
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        free(newPixels);
index eb3888b486263f0825121f65eff2cbfb4fe8ddba..93204910e5488748c2e8820ecdd26fac99fe1e86 100644 (file)
@@ -27,6 +27,7 @@ private:
        int                                     mUnit;                  // Texture unit associated with mTexture
        unsigned int            mEnvState;              // cache textureEnv
        static unsigned int     mDisableState;  // speed up disabling calls
+       unsigned int            mTexSize;               // Size of texture in video ram
 
        void InitNonPow2Tex(unsigned int *p,int x,int y,bool mipmap );
        void InitGLTex(unsigned int *p,int x,int y,bool mipmap );
index a1c7957dc720c46c863b1f7f5462fc024e47a49a..fc43c03df31bf8894265476c1c9e9d07b1e2c638 100644 (file)
@@ -75,6 +75,8 @@
 #include "DNA_world_types.h"
 #include "DNA_scene_types.h"
 
+#include "GPU_extensions.h"
+
 // If define: little test for Nzc: guarded drawing. If the canvas is
 // not valid, skip rendering this frame.
 //#define NZC_GUARDED_OUTPUT
@@ -1439,6 +1441,18 @@ void KX_KetsjiEngine::RenderDebugProperties()
                                                                                m_canvas->GetHeight());
                        ycoord += 14;
                }
+
+               // Put an extra gap in the printed results
+               ycoord += 14;
+
+               /* Print texture vram usage */
+               debugtxt.Format("Texture VRAM: %.2f MB", GPU_texture_vram_usage()/1048576.f);
+               m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+                                                                               debugtxt.Ptr(),
+                                                                               xcoord, ycoord,
+                                                                               m_canvas->GetWidth(),
+                                                                               m_canvas->GetHeight());
+               ycoord += 14;
        }
 
        /* Property display*/