]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
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 3857e98e303f53a4f188079d6be0474ff1b8a943..5e023da8ad617ed7ac22bdf9de497127a4ceef21 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 fcaeeb2d1d6f5fd7f4e6c5088f8cf8003997a2a6..60487161c7ec195b77051e1d8c8b8879056d8382 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 fa7a8e06f90956392895cefcc85f943f64481830..c61fa3669f8b64745e8e8b789296c61cd38fa4c9 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 9edd9c0d8246edad12d075a3cb3872a59d295525..abb360d4e51f22af72326544c107e3a56df77eda 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 c281f7dc1fa082d43074e696bd02f736dbd8e5b6..e1b14ef1b9956438a8c5e56831ee4a3a5199638b 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 e7a32b1293049ca2631e1ac28d4a5f2b090762b2..f01a4e85da2caa9ebcc8e239898ccbd6b6fc8906 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 8d92adb0ab3d5bd2427ad3d7429353257d0e9a80..f29eea2a12bb03ffd6525fbfbfc4712402ee84c1 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;