Change MAX_TEXTUREUNITS from 16 to 32 - this fixes a memory corruption that was causi...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 30 Jun 2018 21:59:21 +0000 (21:59 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 30 Jun 2018 21:59:21 +0000 (21:59 +0000)
Get rid of vid.texarrayunits, vid.teximageunits, vid.texunits variables as they are meaningless, assume 32 (because that is how many GL enums exist).

Don't clear texture units on reset, we don't know how many texture units really exist and it's largely pointless.

Do a more thorough unbind of textures on deletion, just for good measure.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12437 d7cf8633-e32d-0410-b094-e92efae38249

draw.h
gl_backend.c
gl_draw.c
gl_rmain.c
vid.h
vid_sdl.c
vid_shared.c

diff --git a/draw.h b/draw.h
index 3857e98..5e023da 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -39,7 +39,6 @@ typedef enum cachepicflags_e
 }
 cachepicflags_t;
 
-void Draw_Init (void);
 void Draw_Frame (void);
 cachepic_t *Draw_CachePic_Flags (const char *path, unsigned int cachepicflags);
 cachepic_t *Draw_CachePic (const char *path); // standard function with no options, used throughout engine
index fcaeeb2..6048716 100644 (file)
@@ -1108,7 +1108,7 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
        // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
        for (j = 0;j < 5;j++)
                if (textures[j])
-                       for (i = 0;i < vid.teximageunits;i++)
+                       for (i = 0;i < MAX_TEXTUREUNITS;i++)
                                if (gl_state.units[i].texture == textures[j])
                                        R_Mesh_TexBind(i, NULL);
        // set up framebuffer object or render targets for the active rendering API
@@ -1127,7 +1127,6 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
 
 static void GL_Backend_ResetState(void)
 {
-       unsigned int i;
        gl_state.active = true;
        gl_state.depthtest = true;
        gl_state.alphatest = false;
@@ -1171,18 +1170,6 @@ static void GL_Backend_ResetState(void)
                qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
                gl_state.unit = MAX_TEXTUREUNITS;
                gl_state.clientunit = MAX_TEXTUREUNITS;
-               for (i = 0;i < vid.teximageunits;i++)
-               {
-                       GL_ActiveTexture(i);
-                       qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
-                       qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
-                       qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
-               }
-               for (i = 0;i < vid.texarrayunits;i++)
-               {
-                       GL_BindVBO(0);
-                       qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
-               }
                CHECKGLERROR
                break;
        }
@@ -2021,6 +2008,8 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *
 void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
 {
        gltextureunit_t *unit = gl_state.units + unitnum;
+       if (unitnum >= MAX_TEXTUREUNITS)
+               Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
        // update array settings
        // note: there is no need to check bufferobject here because all cases
        // that involve a valid bufferobject also supply a texcoord array
@@ -2068,8 +2057,8 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si
 int R_Mesh_TexBound(unsigned int unitnum, int id)
 {
        gltextureunit_t *unit = gl_state.units + unitnum;
-       if (unitnum >= vid.teximageunits)
-               return 0;
+       if (unitnum >= MAX_TEXTUREUNITS)
+               Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
        if (id == GL_TEXTURE_2D)
                return unit->t2d;
        if (id == GL_TEXTURE_3D)
@@ -2096,16 +2085,12 @@ void R_Mesh_ClearBindingsForTexture(int texnum)
 {
        gltextureunit_t *unit;
        unsigned int unitnum;
-       // this doesn't really unbind the texture, but it does prevent a mistaken "do nothing" behavior on the next time this same texnum is bound on the same unit as the same type (this mainly affects r_shadow_bouncegrid because 3D textures are so rarely used)
-       for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
+       // unbind the texture from any units it is bound on - this prevents accidental reuse of certain textures whose bindings can linger far too long otherwise (e.g. bouncegrid which is a 3D texture) and confuse the driver later.
+       for (unitnum = 0; unitnum < MAX_TEXTUREUNITS; unitnum++)
        {
                unit = gl_state.units + unitnum;
-               if (unit->t2d == texnum)
-                       unit->t2d = -1;
-               if (unit->t3d == texnum)
-                       unit->t3d = -1;
-               if (unit->tcubemap == texnum)
-                       unit->tcubemap = -1;
+               if (unit->texture && unit->texture->texnum == texnum)
+                       R_Mesh_TexBind(unitnum, NULL);
        }
 }
 
@@ -2113,8 +2098,8 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
 {
        gltextureunit_t *unit = gl_state.units + unitnum;
        int texnum;
-       if (unitnum >= vid.teximageunits)
-               return;
+       if (unitnum >= MAX_TEXTUREUNITS)
+               Sys_Error("R_Mesh_TexBind: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
        if (unit->texture == tex)
                return;
        switch(vid.renderpath)
@@ -2146,9 +2131,9 @@ void R_Mesh_ResetTextureState(void)
 
        BACKENDACTIVECHECK
 
-       for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
+       for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
                R_Mesh_TexBind(unitnum, NULL);
-       for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
+       for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
                R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
 }
 
index fa7a8e0..c61fa36 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -111,12 +111,12 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
                                // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
                                if ((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))
                                {
-                                       Con_DPrintf("Draw_CachePic(\"%s\"): reloading pic due to mismatch on flags\n", path);
+                                       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic due to mismatch on flags\n", path, draw_frame);
                                        goto reload;
                                }
                                if (!pic->skinframe || !pic->skinframe->base)
                                {
-                                       Con_DPrintf("Draw_CachePic(\"%s\"): reloading pic\n", path);
+                                       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic\n", path, draw_frame);
                                        goto reload;
                                }
                                if (!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
@@ -131,11 +131,11 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
 
        if (numcachepics == MAX_CACHED_PICS)
        {
-               Con_Printf ("Draw_CachePic(\"%s\"): numcachepics == MAX_CACHED_PICS\n", path);
+               Con_Printf ("Draw_CachePic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", path, draw_frame);
                // FIXME: support NULL in callers?
                return cachepics; // return the first one
        }
-       Con_DPrintf("Draw_CachePic(\"%s\"): loading pic\n", path);
+       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: loading pic%s\n", path, draw_frame, (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) ? " notpersist" : "");
        pic = cachepics + (numcachepics++);
        memset(pic, 0, sizeof(*pic));
        strlcpy (pic->name, path, sizeof(pic->name));
@@ -207,7 +207,10 @@ qboolean Draw_IsPicLoaded(cachepic_t *pic)
        if (pic == NULL)
                return false;
        if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+       {
+               Con_DPrintf("Draw_IsPicLoaded(\"%s\"): Loading external skin\n", pic->name);
                pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+       }
        // skinframe will only be NULL if the pic was created with CACHEPICFLAG_FAILONMISSING and not found
        return pic->skinframe != NULL && pic->skinframe->base != NULL;
 }
@@ -217,7 +220,10 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
        if (pic == NULL)
                return NULL;
        if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+       {
+               Con_DPrintf("Draw_GetPicTexture(\"%s\"): Loading external skin\n", pic->name);
                pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+       }
        pic->lastusedframe = draw_frame;
        return pic->skinframe ? pic->skinframe->base : NULL;
 }
@@ -231,8 +237,13 @@ void Draw_Frame(void)
                return;
        nextpurgetime = realtime + 0.05;
        for (i = 0, pic = cachepics;i < numcachepics;i++, pic++)
+       {
                if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame - 3)
+               {
+                       Con_DPrintf("Draw_Frame(%i): Unloading \"%s\"\n", draw_frame, pic->name);
                        R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+               }
+       }
        draw_frame++;
 }
 
@@ -251,20 +262,23 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned cha
        {
                if (pic->flags & CACHEPICFLAG_NEWPIC && pic->skinframe && pic->skinframe->base && pic->width == width && pic->height == height)
                {
+                       Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: updating texture\n", picname, draw_frame);
                        R_UpdateTexture(pic->skinframe->base, pixels_bgra, 0, 0, 0, width, height, 1);
                        R_SkinFrame_MarkUsed(pic->skinframe);
                        pic->lastusedframe = draw_frame;
                        return pic;
                }
+               Con_Printf("Draw_NewPic(\"%s\"): frame %i: reloading pic because flags/size changed\n", picname, draw_frame);
        }
        else
        {
                if (numcachepics == MAX_CACHED_PICS)
                {
-                       Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+                       Con_Printf ("Draw_NewPic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", picname, draw_frame);
                        // FIXME: support NULL in callers?
                        return cachepics; // return the first one
                }
+               Con_Printf("Draw_NewPic(\"%s\"): frame %i: creating new cachepic\n", picname, draw_frame);
                pic = cachepics + (numcachepics++);
                memset(pic, 0, sizeof(*pic));
                strlcpy (pic->name, picname, sizeof(pic->name));
@@ -298,9 +312,8 @@ void Draw_FreePic(const char *picname)
        {
                if (!strcmp (picname, pic->name) && pic->skinframe)
                {
+                       Con_DPrintf("Draw_FreePic(\"%s\"): frame %i: freeing pic\n", picname, draw_frame);
                        R_SkinFrame_PurgeSkinFrame(pic->skinframe);
-                       pic->width = 0;
-                       pic->height = 0;
                        return;
                }
        }
index 9edd9c0..abb360d 100644 (file)
@@ -3034,7 +3034,7 @@ static void gl_main_start(void)
        {
        case RENDERPATH_GL32:
        case RENDERPATH_GLES2:
-               Cvar_SetValueQuick(&r_textureunits, vid.texunits);
+               Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS);
                Cvar_SetValueQuick(&gl_combine, 1);
                Cvar_SetValueQuick(&r_glsl, 1);
                r_loadnormalmap = true;
diff --git a/vid.h b/vid.h
index c281f7d..e1b14ef 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 extern int cl_available;
 
-#define MAX_TEXTUREUNITS 16
+#define MAX_TEXTUREUNITS 32
 
 typedef enum renderpath_e
 {
@@ -94,9 +94,6 @@ typedef struct viddef_s
        renderpath_t renderpath;
        qboolean allowalphatocoverage; // indicates the GL_AlphaToCoverage function works on this renderpath and framebuffer
 
-       unsigned int texunits;
-       unsigned int teximageunits;
-       unsigned int texarrayunits;
        unsigned int drawrangeelements_maxvertices;
        unsigned int drawrangeelements_maxindices;
 
index e7a32b1..f01a4e8 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -1768,13 +1768,6 @@ void GLES_Init(void)
                Con_Printf("GL_OES_texture_3d reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n");
        }
 
-       vid.texunits = 4;
-       vid.teximageunits = 8;
-       vid.texarrayunits = 5;
-       qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&vid.teximageunits);CHECKGLERROR
-       vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
-       vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
-       vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
        Con_DPrint("Using GLES2 rendering path\n");
        vid.renderpath = RENDERPATH_GLES2;
        vid.sRGBcapable2D = false;
index 8d92adb..f29eea2 100644 (file)
@@ -773,9 +773,6 @@ void VID_ClearExtensions(void)
        vid.maxtexturesize_2d = 0;
        vid.maxtexturesize_3d = 0;
        vid.maxtexturesize_cubemap = 0;
-       vid.texunits = 1;
-       vid.teximageunits = 1;
-       vid.texarrayunits = 1;
        vid.max_anisotropy = 1;
        vid.maxdrawbuffers = 1;
 
@@ -867,9 +864,6 @@ void VID_CheckExtensions(void)
        qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
        qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
 
-       vid.texunits = 4;
-       vid.teximageunits = 32;
-       vid.texarrayunits = 10;
        vid.renderpath = RENDERPATH_GL32;
        vid.sRGBcapable2D = false;
        vid.sRGBcapable3D = true;