diff options
Diffstat (limited to 'src/renderergl2/tr_vbo.c')
-rw-r--r-- | src/renderergl2/tr_vbo.c | 928 |
1 files changed, 928 insertions, 0 deletions
diff --git a/src/renderergl2/tr_vbo.c b/src/renderergl2/tr_vbo.c new file mode 100644 index 00000000..483df2e3 --- /dev/null +++ b/src/renderergl2/tr_vbo.c @@ -0,0 +1,928 @@ +/* +=========================================================================== +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net> + +This file is part of XreaL source code. + +XreaL source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +XreaL source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with XreaL source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// tr_vbo.c +#include "tr_local.h" + +/* +============ +R_CreateVBO +============ +*/ +VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage) +{ + VBO_t *vbo; + int glUsage; + + switch (usage) + { + case VBO_USAGE_STATIC: + glUsage = GL_STATIC_DRAW_ARB; + break; + + case VBO_USAGE_DYNAMIC: + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + + default: + Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); + return NULL; + } + + if(strlen(name) >= MAX_QPATH) + { + ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long", name); + } + + if ( tr.numVBOs == MAX_VBOS ) { + ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit"); + } + + R_IssuePendingRenderCommands(); + + vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); + tr.numVBOs++; + + memset(vbo, 0, sizeof(*vbo)); + + Q_strncpyz(vbo->name, name, sizeof(vbo->name)); + + vbo->vertexesSize = vertexesSize; + + qglGenBuffersARB(1, &vbo->vertexesVBO); + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage); + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + + glState.currentVBO = NULL; + + GL_CheckErrors(); + + return vbo; +} + +/* +============ +R_CreateVBO2 +============ +*/ +VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage) +{ + VBO_t *vbo; + int i; + + byte *data; + int dataSize; + int dataOfs; + + int glUsage; + + switch (usage) + { + case VBO_USAGE_STATIC: + glUsage = GL_STATIC_DRAW_ARB; + break; + + case VBO_USAGE_DYNAMIC: + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + + default: + Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); + return NULL; + } + + if(!numVertexes) + return NULL; + + if(strlen(name) >= MAX_QPATH) + { + ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name); + } + + if ( tr.numVBOs == MAX_VBOS ) { + ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit"); + } + + R_IssuePendingRenderCommands(); + + vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); + tr.numVBOs++; + + memset(vbo, 0, sizeof(*vbo)); + + Q_strncpyz(vbo->name, name, sizeof(vbo->name)); + + if (usage == VBO_USAGE_STATIC) + { + // since these vertex attributes are never altered, interleave them + vbo->ofs_xyz = 0; + dataSize = sizeof(verts[0].xyz); + + if(stateBits & ATTR_NORMAL) + { + vbo->ofs_normal = dataSize; + dataSize += sizeof(verts[0].normal); + } + +#ifdef USE_VERT_TANGENT_SPACE + if(stateBits & ATTR_TANGENT) + { + vbo->ofs_tangent = dataSize; + dataSize += sizeof(verts[0].tangent); + } + + if(stateBits & ATTR_BITANGENT) + { + vbo->ofs_bitangent = dataSize; + dataSize += sizeof(verts[0].bitangent); + } +#endif + + if(stateBits & ATTR_TEXCOORD) + { + vbo->ofs_st = dataSize; + dataSize += sizeof(verts[0].st); + } + + if(stateBits & ATTR_LIGHTCOORD) + { + vbo->ofs_lightmap = dataSize; + dataSize += sizeof(verts[0].lightmap); + } + + if(stateBits & ATTR_COLOR) + { + vbo->ofs_vertexcolor = dataSize; + dataSize += sizeof(verts[0].vertexColors); + } + + if(stateBits & ATTR_LIGHTDIRECTION) + { + vbo->ofs_lightdir = dataSize; + dataSize += sizeof(verts[0].lightdir); + } + + vbo->stride_xyz = dataSize; + vbo->stride_normal = dataSize; +#ifdef USE_VERT_TANGENT_SPACE + vbo->stride_tangent = dataSize; + vbo->stride_bitangent = dataSize; +#endif + vbo->stride_st = dataSize; + vbo->stride_lightmap = dataSize; + vbo->stride_vertexcolor = dataSize; + vbo->stride_lightdir = dataSize; + + // create VBO + dataSize *= numVertexes; + data = ri.Hunk_AllocateTempMemory(dataSize); + dataOfs = 0; + + //ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, + //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); + + for (i = 0; i < numVertexes; i++) + { + // xyz + memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); + dataOfs += sizeof(verts[i].xyz); + + // normal + if(stateBits & ATTR_NORMAL) + { + memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal)); + dataOfs += sizeof(verts[i].normal); + } + +#ifdef USE_VERT_TANGENT_SPACE + // tangent + if(stateBits & ATTR_TANGENT) + { + memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent)); + dataOfs += sizeof(verts[i].tangent); + } + + // bitangent + if(stateBits & ATTR_BITANGENT) + { + memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent)); + dataOfs += sizeof(verts[i].bitangent); + } +#endif + + // vertex texcoords + if(stateBits & ATTR_TEXCOORD) + { + memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); + dataOfs += sizeof(verts[i].st); + } + + // feed vertex lightmap texcoords + if(stateBits & ATTR_LIGHTCOORD) + { + memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); + dataOfs += sizeof(verts[i].lightmap); + } + + // feed vertex colors + if(stateBits & ATTR_COLOR) + { + memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); + dataOfs += sizeof(verts[i].vertexColors); + } + + // feed vertex light directions + if(stateBits & ATTR_LIGHTDIRECTION) + { + memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); + dataOfs += sizeof(verts[i].lightdir); + } + } + } + else + { + // since these vertex attributes may be changed, put them in flat arrays + dataSize = sizeof(verts[0].xyz); + + if(stateBits & ATTR_NORMAL) + { + dataSize += sizeof(verts[0].normal); + } + +#ifdef USE_VERT_TANGENT_SPACE + if(stateBits & ATTR_TANGENT) + { + dataSize += sizeof(verts[0].tangent); + } + + if(stateBits & ATTR_BITANGENT) + { + dataSize += sizeof(verts[0].bitangent); + } +#endif + + if(stateBits & ATTR_TEXCOORD) + { + dataSize += sizeof(verts[0].st); + } + + if(stateBits & ATTR_LIGHTCOORD) + { + dataSize += sizeof(verts[0].lightmap); + } + + if(stateBits & ATTR_COLOR) + { + dataSize += sizeof(verts[0].vertexColors); + } + + if(stateBits & ATTR_LIGHTDIRECTION) + { + dataSize += sizeof(verts[0].lightdir); + } + + // create VBO + dataSize *= numVertexes; + data = ri.Hunk_AllocateTempMemory(dataSize); + dataOfs = 0; + + vbo->ofs_xyz = 0; + vbo->ofs_normal = 0; +#ifdef USE_VERT_TANGENT_SPACE + vbo->ofs_tangent = 0; + vbo->ofs_bitangent = 0; +#endif + vbo->ofs_st = 0; + vbo->ofs_lightmap = 0; + vbo->ofs_vertexcolor = 0; + vbo->ofs_lightdir = 0; + + vbo->stride_xyz = sizeof(verts[0].xyz); + vbo->stride_normal = sizeof(verts[0].normal); +#ifdef USE_VERT_TANGENT_SPACE + vbo->stride_tangent = sizeof(verts[0].tangent); + vbo->stride_bitangent = sizeof(verts[0].bitangent); +#endif + vbo->stride_vertexcolor = sizeof(verts[0].vertexColors); + vbo->stride_st = sizeof(verts[0].st); + vbo->stride_lightmap = sizeof(verts[0].lightmap); + vbo->stride_lightdir = sizeof(verts[0].lightdir); + + //ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, + //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); + + // xyz + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); + dataOfs += sizeof(verts[i].xyz); + } + + // normal + if(stateBits & ATTR_NORMAL) + { + vbo->ofs_normal = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal)); + dataOfs += sizeof(verts[i].normal); + } + } + +#ifdef USE_VERT_TANGENT_SPACE + // tangent + if(stateBits & ATTR_TANGENT) + { + vbo->ofs_tangent = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent)); + dataOfs += sizeof(verts[i].tangent); + } + } + + // bitangent + if(stateBits & ATTR_BITANGENT) + { + vbo->ofs_bitangent = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent)); + dataOfs += sizeof(verts[i].bitangent); + } + } +#endif + + // vertex texcoords + if(stateBits & ATTR_TEXCOORD) + { + vbo->ofs_st = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); + dataOfs += sizeof(verts[i].st); + } + } + + // feed vertex lightmap texcoords + if(stateBits & ATTR_LIGHTCOORD) + { + vbo->ofs_lightmap = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); + dataOfs += sizeof(verts[i].lightmap); + } + } + + // feed vertex colors + if(stateBits & ATTR_COLOR) + { + vbo->ofs_vertexcolor = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); + dataOfs += sizeof(verts[i].vertexColors); + } + } + + // feed vertex lightdirs + if(stateBits & ATTR_LIGHTDIRECTION) + { + vbo->ofs_lightdir = dataOfs; + for (i = 0; i < numVertexes; i++) + { + memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); + dataOfs += sizeof(verts[i].lightdir); + } + } + } + + + vbo->vertexesSize = dataSize; + + qglGenBuffersARB(1, &vbo->vertexesVBO); + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage); + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + + glState.currentVBO = NULL; + + GL_CheckErrors(); + + ri.Hunk_FreeTempMemory(data); + + return vbo; +} + + +/* +============ +R_CreateIBO +============ +*/ +IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage) +{ + IBO_t *ibo; + int glUsage; + + switch (usage) + { + case VBO_USAGE_STATIC: + glUsage = GL_STATIC_DRAW_ARB; + break; + + case VBO_USAGE_DYNAMIC: + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + + default: + Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); + return NULL; + } + + if(strlen(name) >= MAX_QPATH) + { + ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name); + } + + if ( tr.numIBOs == MAX_IBOS ) { + ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit"); + } + + R_IssuePendingRenderCommands(); + + ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); + tr.numIBOs++; + + Q_strncpyz(ibo->name, name, sizeof(ibo->name)); + + ibo->indexesSize = indexesSize; + + qglGenBuffersARB(1, &ibo->indexesVBO); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + + glState.currentIBO = NULL; + + GL_CheckErrors(); + + return ibo; +} + +/* +============ +R_CreateIBO2 +============ +*/ +IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage) +{ + IBO_t *ibo; + int i, j; + + byte *indexes; + int indexesSize; + int indexesOfs; + + srfTriangle_t *tri; + glIndex_t index; + int glUsage; + + switch (usage) + { + case VBO_USAGE_STATIC: + glUsage = GL_STATIC_DRAW_ARB; + break; + + case VBO_USAGE_DYNAMIC: + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + + default: + Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); + return NULL; + } + + if(!numTriangles) + return NULL; + + if(strlen(name) >= MAX_QPATH) + { + ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long", name); + } + + if ( tr.numIBOs == MAX_IBOS ) { + ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit"); + } + + R_IssuePendingRenderCommands(); + + ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); + tr.numIBOs++; + + Q_strncpyz(ibo->name, name, sizeof(ibo->name)); + + indexesSize = numTriangles * 3 * sizeof(int); + indexes = ri.Hunk_AllocateTempMemory(indexesSize); + indexesOfs = 0; + + for(i = 0, tri = triangles; i < numTriangles; i++, tri++) + { + for(j = 0; j < 3; j++) + { + index = tri->indexes[j]; + memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t)); + indexesOfs += sizeof(glIndex_t); + } + } + + ibo->indexesSize = indexesSize; + + qglGenBuffersARB(1, &ibo->indexesVBO); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + + glState.currentIBO = NULL; + + GL_CheckErrors(); + + ri.Hunk_FreeTempMemory(indexes); + + return ibo; +} + +/* +============ +R_BindVBO +============ +*/ +void R_BindVBO(VBO_t * vbo) +{ + if(!vbo) + { + //R_BindNullVBO(); + ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo"); + return; + } + + if(r_logFile->integer) + { + // don't just call LogComment, or we will get a call to va() every frame! + GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name)); + } + + if(glState.currentVBO != vbo) + { + glState.currentVBO = vbo; + glState.vertexAttribPointersSet = 0; + + glState.vertexAttribsInterpolation = 0; + glState.vertexAttribsOldFrame = 0; + glState.vertexAttribsNewFrame = 0; + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); + + backEnd.pc.c_vboVertexBuffers++; + } +} + +/* +============ +R_BindNullVBO +============ +*/ +void R_BindNullVBO(void) +{ + GLimp_LogComment("--- R_BindNullVBO ---\n"); + + if(glState.currentVBO) + { + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glState.currentVBO = NULL; + } + + GL_CheckErrors(); +} + +/* +============ +R_BindIBO +============ +*/ +void R_BindIBO(IBO_t * ibo) +{ + if(!ibo) + { + //R_BindNullIBO(); + ri.Error(ERR_DROP, "R_BindIBO: NULL ibo"); + return; + } + + if(r_logFile->integer) + { + // don't just call LogComment, or we will get a call to va() every frame! + GLimp_LogComment(va("--- R_BindIBO( %s ) ---\n", ibo->name)); + } + + if(glState.currentIBO != ibo) + { + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); + + glState.currentIBO = ibo; + + backEnd.pc.c_vboIndexBuffers++; + } +} + +/* +============ +R_BindNullIBO +============ +*/ +void R_BindNullIBO(void) +{ + GLimp_LogComment("--- R_BindNullIBO ---\n"); + + if(glState.currentIBO) + { + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + glState.currentIBO = NULL; + glState.vertexAttribPointersSet = 0; + } +} + +/* +============ +R_InitVBOs +============ +*/ +void R_InitVBOs(void) +{ + int dataSize; + int offset; + + ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n"); + + tr.numVBOs = 0; + tr.numIBOs = 0; + + dataSize = sizeof(tess.xyz[0]); + dataSize += sizeof(tess.normal[0]); +#ifdef USE_VERT_TANGENT_SPACE + dataSize += sizeof(tess.tangent[0]); + dataSize += sizeof(tess.bitangent[0]); +#endif + dataSize += sizeof(tess.vertexColors[0]); + dataSize += sizeof(tess.texCoords[0][0]) * 2; + dataSize += sizeof(tess.lightdir[0]); + dataSize *= SHADER_MAX_VERTEXES; + + tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC); + + offset = 0; + + tess.vbo->ofs_xyz = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; + tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; +#ifdef USE_VERT_TANGENT_SPACE + tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; + tess.vbo->ofs_bitangent = offset; offset += sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES; +#endif + // these next two are actually interleaved + tess.vbo->ofs_st = offset; + tess.vbo->ofs_lightmap = offset + sizeof(tess.texCoords[0][0]); + offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; + + tess.vbo->ofs_vertexcolor = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; + tess.vbo->ofs_lightdir = offset; + + tess.vbo->stride_xyz = sizeof(tess.xyz[0]); + tess.vbo->stride_normal = sizeof(tess.normal[0]); +#ifdef USE_VERT_TANGENT_SPACE + tess.vbo->stride_tangent = sizeof(tess.tangent[0]); + tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]); +#endif + tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]); + tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2; + tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2; + tess.vbo->stride_lightdir = sizeof(tess.lightdir[0]); + + dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES; + + tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC); + + R_BindNullVBO(); + R_BindNullIBO(); + + GL_CheckErrors(); +} + +/* +============ +R_ShutdownVBOs +============ +*/ +void R_ShutdownVBOs(void) +{ + int i; + VBO_t *vbo; + IBO_t *ibo; + + ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n"); + + R_BindNullVBO(); + R_BindNullIBO(); + + + for(i = 0; i < tr.numVBOs; i++) + { + vbo = tr.vbos[i]; + + if(vbo->vertexesVBO) + { + qglDeleteBuffersARB(1, &vbo->vertexesVBO); + } + + //ri.Free(vbo); + } + + for(i = 0; i < tr.numIBOs; i++) + { + ibo = tr.ibos[i]; + + if(ibo->indexesVBO) + { + qglDeleteBuffersARB(1, &ibo->indexesVBO); + } + + //ri.Free(ibo); + } + + tr.numVBOs = 0; + tr.numIBOs = 0; +} + +/* +============ +R_VBOList_f +============ +*/ +void R_VBOList_f(void) +{ + int i; + VBO_t *vbo; + IBO_t *ibo; + int vertexesSize = 0; + int indexesSize = 0; + + ri.Printf(PRINT_ALL, " size name\n"); + ri.Printf(PRINT_ALL, "----------------------------------------------------------\n"); + + for(i = 0; i < tr.numVBOs; i++) + { + vbo = tr.vbos[i]; + + ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024), + (vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name); + + vertexesSize += vbo->vertexesSize; + } + + for(i = 0; i < tr.numIBOs; i++) + { + ibo = tr.ibos[i]; + + ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024), + (ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name); + + indexesSize += ibo->indexesSize; + } + + ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs); + ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024), + (vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); + + ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs); + ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024), + (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); +} + + +/* +============== +RB_UpdateVBOs + +Adapted from Tess_UpdateVBOs from xreal + +Tr3B: update the default VBO to replace the client side vertex arrays +============== +*/ +void RB_UpdateVBOs(unsigned int attribBits) +{ + GLimp_LogComment("--- RB_UpdateVBOs ---\n"); + + backEnd.pc.c_dynamicVboDraws++; + + // update the default VBO + if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES) + { + R_BindVBO(tess.vbo); + + if(attribBits & ATTR_BITS) + { + if(attribBits & ATTR_POSITION) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); + } + + if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD) + { + // these are interleaved, so we update both if either need it + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); + } + + if(attribBits & ATTR_NORMAL) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); + } + +#ifdef USE_VERT_TANGENT_SPACE + if(attribBits & ATTR_TANGENT) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); + } + + if(attribBits & ATTR_BITANGENT) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent); + } +#endif + + if(attribBits & ATTR_COLOR) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); + } + + if(attribBits & ATTR_LIGHTDIRECTION) + { + //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0])); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); + } + } + else + { + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); +#ifdef USE_VERT_TANGENT_SPACE + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent); +#endif + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); + } + + } + + // update the default IBO + if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) + { + R_BindIBO(tess.ibo); + + qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); + } +} |