]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
some cleanup of glDelete calls to guard against bugs caused by GL
[xonotic/darkplaces.git] / gl_backend.c
index 8415c146e22d8d5895574f5ccb5c709d96ea6a27..0847eb6075a29d01c6f8e1a6e77b6d38ce16d75e 100644 (file)
@@ -235,6 +235,7 @@ typedef struct gl_state_s
        int lockrange_count;
        int vertexbufferobject;
        int elementbufferobject;
+       int uniformbufferobject;
        int framebufferobject;
        int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
        qboolean pointer_color_enabled;
@@ -467,8 +468,6 @@ static void gl_backend_shutdown(void)
 
        if (gl_state.preparevertices_tempdata)
                Mem_Free(gl_state.preparevertices_tempdata);
-       if (gl_state.preparevertices_dynamicvertexbuffer)
-               R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
 
        Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
 
@@ -1247,6 +1246,16 @@ static void GL_BindEBO(int bufferobject)
        }
 }
 
+static void GL_BindUBO(int bufferobject)
+{
+       if (gl_state.uniformbufferobject != bufferobject)
+       {
+               gl_state.uniformbufferobject = bufferobject;
+               CHECKGLERROR
+               qglBindBufferARB(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR
+       }
+}
+
 static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
 {
@@ -1311,6 +1320,7 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte
                        if (status != GL_FRAMEBUFFER_COMPLETE)
                        {
                                Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
+                               gl_state.framebufferobject = 0; // GL unbinds it for us
                                qglDeleteFramebuffers(1, (GLuint*)&temp);
                                temp = 0;
                        }
@@ -1365,6 +1375,7 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte
                        if (status != GL_FRAMEBUFFER_COMPLETE)
                        {
                                Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
+                               gl_state.framebufferobject = 0; // GL unbinds it for us
                                qglDeleteFramebuffers(1, (GLuint*)&temp);
                                temp = 0;
                        }
@@ -1391,7 +1402,12 @@ void R_Mesh_DestroyFramebufferObject(int fbo)
        case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                if (fbo)
+               {
+                       // GL clears the binding if we delete something bound
+                       if (gl_state.framebufferobject == fbo)
+                               gl_state.framebufferobject = 0;
                        qglDeleteFramebuffers(1, (GLuint*)&fbo);
+               }
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -2742,9 +2758,10 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        if (!gl_mesh_prefer_short_elements.integer)
        {
                if (element3i)
+               {
                        element3s = NULL;
-               if (element3i_indexbuffer)
-                       element3i_indexbuffer = NULL;
+                       element3s_indexbuffer = NULL;
+               }
        }
        // adjust the pointers for firsttriangle
        if (element3i)
@@ -2782,9 +2799,9 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
                {
                        if (gl_state.draw_dynamicindexbuffer)
-                               R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
+                               R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s), false, 0);
                        else
-                               gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
+                               gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, false, true, true);
                        element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
                        element3s_bufferoffset = 0;
                }
@@ -2794,9 +2811,9 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
                {
                        if (gl_state.draw_dynamicindexbuffer)
-                               R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
+                               R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i), false, 0);
                        else
-                               gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
+                               gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, false, true, false);
                        element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
                        element3i_bufferoffset = 0;
                }
@@ -2805,9 +2822,9 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        bufferoffset3i = element3i_bufferoffset;
        bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
        bufferoffset3s = element3s_bufferoffset;
-       r_refdef.stats.draws++;
-       r_refdef.stats.draws_vertices += numvertices;
-       r_refdef.stats.draws_elements += numelements;
+       r_refdef.stats[r_stat_draws]++;
+       r_refdef.stats[r_stat_draws_vertices] += numvertices;
+       r_refdef.stats[r_stat_draws_elements] += numelements;
        if (gl_paranoid.integer)
        {
                unsigned int i;
@@ -3276,38 +3293,51 @@ void R_Mesh_Finish(void)
        R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
 }
 
-r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
+r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isuniformbuffer, qboolean isdynamic, qboolean isindex16)
 {
        r_meshbuffer_t *buffer;
-       if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
-               return NULL;
+       if (isuniformbuffer)
+       {
+               if (!vid.support.arb_uniform_buffer_object)
+                       return NULL;
+       }
+       else
+       {
+               if (!vid.support.arb_vertex_buffer_object)
+                       return NULL;
+               if (!isdynamic && !(isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex))
+                       return NULL;
+       }
        buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
        memset(buffer, 0, sizeof(*buffer));
        buffer->bufferobject = 0;
        buffer->devicebuffer = NULL;
-       buffer->size = 0;
+       buffer->size = size;
        buffer->isindexbuffer = isindexbuffer;
+       buffer->isuniformbuffer = isuniformbuffer;
        buffer->isdynamic = isdynamic;
        buffer->isindex16 = isindex16;
        strlcpy(buffer->name, name, sizeof(buffer->name));
-       R_Mesh_UpdateMeshBuffer(buffer, data, size);
+       R_Mesh_UpdateMeshBuffer(buffer, data, size, false, 0);
        return buffer;
 }
 
-void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
+void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qboolean subdata, size_t offset)
 {
        if (!buffer)
                return;
        if (buffer->isindexbuffer)
        {
-               r_refdef.stats.indexbufferuploadcount++;
-               r_refdef.stats.indexbufferuploadsize += size;
+               r_refdef.stats[r_stat_indexbufferuploadcount]++;
+               r_refdef.stats[r_stat_indexbufferuploadsize] += size;
        }
        else
        {
-               r_refdef.stats.vertexbufferuploadcount++;
-               r_refdef.stats.vertexbufferuploadsize += size;
+               r_refdef.stats[r_stat_vertexbufferuploadcount]++;
+               r_refdef.stats[r_stat_vertexbufferuploadsize] += size;
        }
+       if (!subdata)
+               buffer->size = size;
        switch(vid.renderpath)
        {
        case RENDERPATH_GL11:
@@ -3317,11 +3347,18 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
        case RENDERPATH_GLES2:
                if (!buffer->bufferobject)
                        qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
-               if (buffer->isindexbuffer)
+               if (buffer->isuniformbuffer)
+                       GL_BindUBO(buffer->bufferobject);
+               else if (buffer->isindexbuffer)
                        GL_BindEBO(buffer->bufferobject);
                else
                        GL_BindVBO(buffer->bufferobject);
-               qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
+               if (subdata)
+                       qglBufferSubDataARB(buffer->isuniformbuffer ? GL_UNIFORM_BUFFER : (buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER), offset, size, data);
+               else
+                       qglBufferDataARB(buffer->isuniformbuffer ? GL_UNIFORM_BUFFER : (buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER), size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
+               if (buffer->isuniformbuffer)
+                       GL_BindUBO(0);
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -3331,17 +3368,17 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
                        if (buffer->isindexbuffer)
                        {
                                IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
-                               if (size > buffer->size || !buffer->devicebuffer)
+                               if (offset+size > buffer->size || !buffer->devicebuffer)
                                {
                                        if (buffer->devicebuffer)
                                                IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
                                        buffer->devicebuffer = NULL;
-                                       if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL)))
+                                       if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, offset+size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL)))
                                                Sys_Error("IDirect3DDevice9_CreateIndexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? (int)D3DFMT_INDEX16 : (int)D3DFMT_INDEX32, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9indexbuffer, (int)result);
                                        buffer->devicebuffer = (void *)d3d9indexbuffer;
-                                       buffer->size = size;
+                                       buffer->size = offset+size;
                                }
-                               if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
+                               if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, (unsigned int)offset, (unsigned int)size, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
                                {
                                        if (data)
                                                memcpy(datapointer, data, size);
@@ -3353,17 +3390,17 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
                        else
                        {
                                IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
-                               if (size > buffer->size || !buffer->devicebuffer)
+                               if (offset+size > buffer->size || !buffer->devicebuffer)
                                {
                                        if (buffer->devicebuffer)
                                                IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
                                        buffer->devicebuffer = NULL;
-                                       if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
+                                       if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, offset+size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
                                                Sys_Error("IDirect3DDevice9_CreateVertexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9vertexbuffer, (int)result);
                                        buffer->devicebuffer = (void *)d3d9vertexbuffer;
-                                       buffer->size = size;
+                                       buffer->size = offset+size;
                                }
-                               if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
+                               if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, (unsigned int)offset, (unsigned int)size, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
                                {
                                        if (data)
                                                memcpy(datapointer, data, size);
@@ -3397,6 +3434,13 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
        case RENDERPATH_GL20:
        case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
+               // GL clears the binding if we delete something bound
+               if (gl_state.uniformbufferobject == buffer->bufferobject)
+                       gl_state.uniformbufferobject = 0;
+               if (gl_state.vertexbufferobject == buffer->bufferobject)
+                       gl_state.vertexbufferobject = 0;
+               if (gl_state.elementbufferobject == buffer->bufferobject)
+                       gl_state.elementbufferobject = 0;
                qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
                break;
        case RENDERPATH_D3D9:
@@ -3425,22 +3469,51 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
        Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
 }
 
+static const char *buffertypename[R_BUFFERDATA_COUNT] = {"vertex", "index16", "index32", "uniform"};
 void GL_Mesh_ListVBOs(qboolean printeach)
 {
        int i, endindex;
-       size_t ebocount = 0, ebomemory = 0;
-       size_t vbocount = 0, vbomemory = 0;
+       int type;
+       int isdynamic;
+       int index16count, index16mem;
+       int index32count, index32mem;
+       int vertexcount, vertexmem;
+       int uniformcount, uniformmem;
+       int totalcount, totalmem;
+       size_t bufferstat[R_BUFFERDATA_COUNT][2][2];
        r_meshbuffer_t *buffer;
+       memset(bufferstat, 0, sizeof(bufferstat));
        endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
        for (i = 0;i < endindex;i++)
        {
                buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
                if (!buffer)
                        continue;
-               if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
-               else                       {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
+               if (buffer->isuniformbuffer)
+                       type = R_BUFFERDATA_UNIFORM;
+               else if (buffer->isindexbuffer && buffer->isindex16)
+                       type = R_BUFFERDATA_INDEX16;
+               else if (buffer->isindexbuffer)
+                       type = R_BUFFERDATA_INDEX32;
+               else
+                       type = R_BUFFERDATA_VERTEX;
+               isdynamic = buffer->isdynamic;
+               bufferstat[type][isdynamic][0]++;
+               bufferstat[type][isdynamic][1] += buffer->size;
+               if (printeach)
+                       Con_Printf("buffer #%i %s = %i bytes (%s %s)\n", i, buffer->name, (int)buffer->size, isdynamic ? "dynamic" : "static", buffertypename[type]);
        }
-       Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
+       index16count   = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][0] + bufferstat[R_BUFFERDATA_INDEX16][1][0]);
+       index16mem     = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][1] + bufferstat[R_BUFFERDATA_INDEX16][1][1]);
+       index32count   = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][0] + bufferstat[R_BUFFERDATA_INDEX32][1][0]);
+       index32mem     = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][1] + bufferstat[R_BUFFERDATA_INDEX32][1][1]);
+       vertexcount  = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][0] + bufferstat[R_BUFFERDATA_VERTEX ][1][0]);
+       vertexmem    = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][1] + bufferstat[R_BUFFERDATA_VERTEX ][1][1]);
+       uniformcount = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][0] + bufferstat[R_BUFFERDATA_UNIFORM][1][0]);
+       uniformmem   = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][1] + bufferstat[R_BUFFERDATA_UNIFORM][1][1]);
+       totalcount = index16count + index32count + vertexcount + uniformcount;
+       totalmem = index16mem + index32mem + vertexmem + uniformmem;
+       Con_Printf("%i 16bit indexbuffers totalling %i bytes (%.3f MB)\n%i 32bit indexbuffers totalling %i bytes (%.3f MB)\n%i vertexbuffers totalling %i bytes (%.3f MB)\n%i uniformbuffers totalling %i bytes (%.3f MB)\ncombined %i buffers totalling %i bytes (%.3fMB)\n", index16count, index16mem, index16mem / 10248576.0, index32count, index32mem, index32mem / 10248576.0, vertexcount, vertexmem, vertexmem / 10248576.0, uniformcount, uniformmem, uniformmem / 10248576.0, totalcount, totalmem, totalmem / 10248576.0);
 }
 
 
@@ -4196,7 +4269,7 @@ static void R_Mesh_DestroyVertexDeclarations(void)
 #endif
 }
 
-void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
+void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
 {
        // upload temporary vertexbuffer for this rendering
        if (!gl_state.usevbo_staticvertex)
@@ -4204,9 +4277,9 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
        if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
        {
                if (gl_state.preparevertices_dynamicvertexbuffer)
-                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
+                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]), false, 0);
                else
-                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
+                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, false, true, false);
                vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
        }
        switch(vid.renderpath)
@@ -4215,7 +4288,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
        case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -4244,7 +4317,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
        case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -4260,7 +4333,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
        case RENDERPATH_GL11:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                }
@@ -4275,7 +4348,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
 #ifdef SUPPORTD3D
                IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
                if (vertexbuffer)
-                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
+                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(float[3]));
                else
                        IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
                gl_state.d3dvertexbuffer = (void *)vertexbuffer;
@@ -4319,7 +4392,7 @@ r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
 
 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
 {
-       R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
+       R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL, 0);
        gl_state.preparevertices_vertexgeneric = NULL;
        gl_state.preparevertices_numvertices = 0;
        return true;
@@ -4396,10 +4469,10 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
                for (i = 0;i < numvertices;i++)
                        Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
        R_Mesh_PrepareVertices_Generic_Unlock();
-       R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
+       R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL, 0);
 }
 
-void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
+void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
 {
        // upload temporary vertexbuffer for this rendering
        if (!gl_state.usevbo_staticvertex)
@@ -4407,9 +4480,9 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
        {
                if (gl_state.preparevertices_dynamicvertexbuffer)
-                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex), false, 0);
                else
-                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
+                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, false, true, false);
                vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
        }
        switch(vid.renderpath)
@@ -4418,9 +4491,9 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -4447,9 +4520,9 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                }
                else
@@ -4463,9 +4536,9 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        case RENDERPATH_GL11:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
                }
                else
                {
@@ -4478,7 +4551,7 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
 #ifdef SUPPORTD3D
                IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
                if (vertexbuffer)
-                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
+                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(*vertex));
                else
                        IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
                gl_state.d3dvertexbuffer = (void *)vertexbuffer;
@@ -4522,7 +4595,7 @@ r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
 
 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
 {
-       R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
+       R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL, 0);
        gl_state.preparevertices_vertexmesh = NULL;
        gl_state.preparevertices_numvertices = 0;
        return true;
@@ -4610,10 +4683,10 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
                for (i = 0;i < numvertices;i++)
                        Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
        R_Mesh_PrepareVertices_Mesh_Unlock();
-       R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
+       R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL, 0);
 }
 
-void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
+void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
 {
        // upload temporary vertexbuffer for this rendering
        if (!gl_state.usevbo_staticvertex)
@@ -4621,9 +4694,9 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
        {
                if (gl_state.preparevertices_dynamicvertexbuffer)
-                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex), false, 0);
                else
-                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
+                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, false, true, false);
                vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
        }
        switch(vid.renderpath)
@@ -4632,16 +4705,16 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , vertexbuffer, (int)((unsigned char *)vertex->svector3f          - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , vertexbuffer, (int)((unsigned char *)vertex->tvector3f          - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , vertexbuffer, (int)((unsigned char *)vertex->normal3f           - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->svector3f          - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->tvector3f          - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->normal3f           - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
                        R_Mesh_TexCoordPointer(5, 2, GL_FLOAT        , sizeof(*vertex), NULL, NULL, 0);
-                       R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub  , vertexbuffer, (int)((unsigned char *)vertex->skeletalindex4ub   - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , vertexbuffer, (int)((unsigned char *)vertex->skeletalweight4ub  - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub  , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalindex4ub   - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalweight4ub  - (unsigned char *)vertex));
                }
                else
                {
@@ -4661,10 +4734,10 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
                }
                else
                {
@@ -4677,9 +4750,9 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        case RENDERPATH_GL11:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
-                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
+                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
                }
                else
                {
@@ -4692,7 +4765,7 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
 #ifdef SUPPORTD3D
                IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
                if (vertexbuffer)
-                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
+                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(*vertex));
                else
                        IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
                gl_state.d3dvertexbuffer = (void *)vertexbuffer;