OpenGL2: Vertex array object support.

This commit is contained in:
SmileTheory 2014-10-14 01:50:44 -07:00
parent 873a02bd3c
commit 84206c8598
19 changed files with 582 additions and 666 deletions

View file

@ -726,6 +726,17 @@ extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F #define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
#endif #endif
// GL_ARB_vertex_array_object
extern void (APIENTRY * qglBindVertexArrayARB)(GLuint array);
extern void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays);
extern void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
#ifndef GL_ARB_vertex_array_object
#define GL_ARB_vertex_array_object
#define GL_VERTEX_ARRAY_BINDING_ARB 0x85B5
#endif
#if defined(WIN32) #if defined(WIN32)
// WGL_ARB_create_context // WGL_ARB_create_context
#ifndef WGL_ARB_create_context #ifndef WGL_ARB_create_context

View file

@ -412,7 +412,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
tess.xyz[baseVertex + j][1] = tempVert[1]; tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2]; tess.xyz[baseVertex + j][2] = tempVert[2];
tess.normal[baseVertex + j] = R_VboPackNormal(tempNormal); tess.normal[baseVertex + j] = R_VaoPackNormal(tempNormal);
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];

View file

@ -1844,10 +1844,10 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out)
/* /*
=============== ===============
R_CreateWorldVBOs R_CreateWorldVaos
=============== ===============
*/ */
static void R_CreateWorldVBOs(void) static void R_CreateWorldVaos(void)
{ {
int i, j, k; int i, j, k;
@ -1861,8 +1861,7 @@ static void R_CreateWorldVBOs(void)
msurface_t *surface, **firstSurf, **lastSurf, **currSurf; msurface_t *surface, **firstSurf, **lastSurf, **currSurf;
msurface_t **surfacesSorted; msurface_t **surfacesSorted;
VBO_t *vbo; vao_t *vao;
IBO_t *ibo;
int maxVboSize = 4 * 1024 * 1024; int maxVboSize = 4 * 1024 * 1024;
@ -1978,7 +1977,7 @@ static void R_CreateWorldVBOs(void)
{ {
int currVboSize; int currVboSize;
// Find range of surfaces to place in a vbo/ibo by: // Find range of surfaces to place in a VAO by:
// - Collecting a number of surfaces which fit under maxVboSize, or // - Collecting a number of surfaces which fit under maxVboSize, or
// - All the surfaces with a single shader which go over maxVboSize // - All the surfaces with a single shader which go over maxVboSize
currVboSize = 0; currVboSize = 0;
@ -2017,7 +2016,7 @@ static void R_CreateWorldVBOs(void)
numSurfaces++; numSurfaces++;
} }
ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numIndexes / 3); ri.Printf(PRINT_ALL, "...calculating world VAO %d ( %i verts %i tris )\n", k, numVerts, numIndexes / 3);
// create arrays // create arrays
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t)); verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
@ -2050,16 +2049,14 @@ static void R_CreateWorldVBOs(void)
} }
} }
vbo = R_CreateVBO2(va("staticBspModel%i_VBO", k), numVerts, verts); vao = R_CreateVao2(va("staticBspModel%i_VAO", k), numVerts, verts, numIndexes, indexes);
ibo = R_CreateIBO2(va("staticBspModel%i_IBO", k), numIndexes, indexes);
// point bsp surfaces to VBO // point bsp surfaces to VAO
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{ {
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
bspSurf->vbo = vbo; bspSurf->vao = vao;
bspSurf->ibo = ibo;
} }
ri.Hunk_FreeTempMemory(indexes); ri.Hunk_FreeTempMemory(indexes);
@ -2123,7 +2120,7 @@ static void R_CreateWorldVBOs(void)
mergedSurf = s_worldData.mergedSurfaces; mergedSurf = s_worldData.mergedSurfaces;
for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf) for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
{ {
srfBspSurface_t *bspSurf, *vboSurf; srfBspSurface_t *bspSurf, *vaoSurf;
for ( lastSurf++ ; lastSurf < surfacesSorted + numSortedSurfaces; lastSurf++) for ( lastSurf++ ; lastSurf < surfacesSorted + numSortedSurfaces; lastSurf++)
{ {
@ -2147,35 +2144,34 @@ static void R_CreateWorldVBOs(void)
bspSurf = (srfBspSurface_t *)(*firstSurf)->data; bspSurf = (srfBspSurface_t *)(*firstSurf)->data;
vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); vaoSurf = ri.Hunk_Alloc(sizeof(*vaoSurf), h_low);
memset(vboSurf, 0, sizeof(*vboSurf)); memset(vaoSurf, 0, sizeof(*vaoSurf));
vboSurf->surfaceType = SF_VBO_MESH; vaoSurf->surfaceType = SF_VAO_MESH;
vboSurf->vbo = bspSurf->vbo; vaoSurf->vao = bspSurf->vao;
vboSurf->ibo = bspSurf->ibo;
vboSurf->firstIndex = bspSurf->firstIndex; vaoSurf->firstIndex = bspSurf->firstIndex;
vboSurf->minIndex = bspSurf->minIndex; vaoSurf->minIndex = bspSurf->minIndex;
vboSurf->maxIndex = bspSurf->maxIndex; vaoSurf->maxIndex = bspSurf->maxIndex;
ClearBounds(vboSurf->cullBounds[0], vboSurf->cullBounds[1]); ClearBounds(vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{ {
srfBspSurface_t *currBspSurf = (srfBspSurface_t *)(*currSurf)->data; srfBspSurface_t *currBspSurf = (srfBspSurface_t *)(*currSurf)->data;
vboSurf->numVerts += currBspSurf->numVerts; vaoSurf->numVerts += currBspSurf->numVerts;
vboSurf->numIndexes += currBspSurf->numIndexes; vaoSurf->numIndexes += currBspSurf->numIndexes;
vboSurf->minIndex = MIN(vboSurf->minIndex, currBspSurf->minIndex); vaoSurf->minIndex = MIN(vaoSurf->minIndex, currBspSurf->minIndex);
vboSurf->maxIndex = MAX(vboSurf->maxIndex, currBspSurf->maxIndex); vaoSurf->maxIndex = MAX(vaoSurf->maxIndex, currBspSurf->maxIndex);
AddPointToBounds((*currSurf)->cullinfo.bounds[0], vboSurf->cullBounds[0], vboSurf->cullBounds[1]); AddPointToBounds((*currSurf)->cullinfo.bounds[0], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
AddPointToBounds((*currSurf)->cullinfo.bounds[1], vboSurf->cullBounds[0], vboSurf->cullBounds[1]); AddPointToBounds((*currSurf)->cullinfo.bounds[1], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
} }
VectorCopy(vboSurf->cullBounds[0], mergedSurf->cullinfo.bounds[0]); VectorCopy(vaoSurf->cullBounds[0], mergedSurf->cullinfo.bounds[0]);
VectorCopy(vboSurf->cullBounds[1], mergedSurf->cullinfo.bounds[1]); VectorCopy(vaoSurf->cullBounds[1], mergedSurf->cullinfo.bounds[1]);
mergedSurf->cullinfo.type = CULLINFO_BOX; mergedSurf->cullinfo.type = CULLINFO_BOX;
mergedSurf->data = (surfaceType_t *)vboSurf; mergedSurf->data = (surfaceType_t *)vaoSurf;
mergedSurf->fogIndex = (*firstSurf)->fogIndex; mergedSurf->fogIndex = (*firstSurf)->fogIndex;
mergedSurf->cubemapIndex = (*firstSurf)->cubemapIndex; mergedSurf->cubemapIndex = (*firstSurf)->cubemapIndex;
mergedSurf->shader = (*firstSurf)->shader; mergedSurf->shader = (*firstSurf)->shader;
@ -2206,7 +2202,7 @@ static void R_CreateWorldVBOs(void)
ri.Free(surfacesSorted); ri.Free(surfacesSorted);
endTime = ri.Milliseconds(); endTime = ri.Milliseconds();
ri.Printf(PRINT_ALL, "world VBOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); ri.Printf(PRINT_ALL, "world VAOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
} }
/* /*
@ -2270,7 +2266,7 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
// Two passes, allocate surfaces first, then load them full of data // Two passes, allocate surfaces first, then load them full of data
// This ensures surfaces are close together to reduce L2 cache misses when using VBOs, // This ensures surfaces are close together to reduce L2 cache misses when using VAOs,
// which don't actually use the verts and indexes // which don't actually use the verts and indexes
in = (void *)(fileBase + surfs->fileofs); in = (void *)(fileBase + surfs->fileofs);
out = s_worldData.surfaces; out = s_worldData.surfaces;
@ -2393,7 +2389,7 @@ static void R_LoadSubmodels( lump_t *l ) {
if(i == 0) if(i == 0)
{ {
// Add this for limiting VBO surface creation // Add this for limiting VAO surface creation
s_worldData.numWorldSurfaces = out->numSurfaces; s_worldData.numWorldSurfaces = out->numSurfaces;
} }
} }
@ -3402,17 +3398,16 @@ void RE_LoadWorldMap( const char *name ) {
} }
} }
// create static VBOS from the world // create static VAOS from the world
R_CreateWorldVBOs(); R_CreateWorldVaos();
s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker; s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker;
// only set tr.world now that we know the entire level has loaded properly // only set tr.world now that we know the entire level has loaded properly
tr.world = &s_worldData; tr.world = &s_worldData;
// make sure the VBO glState entries are safe // make sure the VAO glState entry is safe
R_BindNullVBO(); R_BindNullVao();
R_BindNullIBO();
// Render all cubemaps // Render all cubemaps
if (r_cubeMapping->integer && tr.numCubemaps) if (r_cubeMapping->integer && tr.numCubemaps)

View file

@ -66,8 +66,8 @@ void R_PerformanceCounters( void ) {
} }
else if (r_speeds->integer == 7 ) else if (r_speeds->integer == 7 )
{ {
ri.Printf( PRINT_ALL, "VBO draws: static %i dynamic %i\nMultidraws: %i merged %i\n", ri.Printf( PRINT_ALL, "VAO draws: static %i dynamic %i\nMultidraws: %i merged %i\n",
backEnd.pc.c_staticVboDraws, backEnd.pc.c_dynamicVboDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged ); backEnd.pc.c_staticVaoDraws, backEnd.pc.c_dynamicVaoDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged );
ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n", ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n",
backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws); backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws);
} }

View file

@ -178,6 +178,12 @@ void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei sa
// GL_ARB_draw_buffers // GL_ARB_draw_buffers
void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs); void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
// GL_ARB_vertex_array_object
void (APIENTRY * qglBindVertexArrayARB)(GLuint array);
void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays);
void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
static qboolean GLimp_HaveExtension(const char *ext) static qboolean GLimp_HaveExtension(const char *ext)
{ {
const char *ptr = Q_stristr( glConfig.extensions_string, ext ); const char *ptr = Q_stristr( glConfig.extensions_string, ext );
@ -682,4 +688,25 @@ void GLimp_InitExtraExtensions()
// use float lightmaps? // use float lightmaps?
glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer); glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer);
// GL_ARB_vertex_array_object
extension = "GL_ARB_vertex_array_object";
glRefConfig.vertexArrayObject = qfalse;
if( GLimp_HaveExtension( extension ) )
{
qglBindVertexArrayARB = (void *) SDL_GL_GetProcAddress("glBindVertexArray");
qglDeleteVertexArraysARB = (void *) SDL_GL_GetProcAddress("glDeleteVertexArrays");
qglGenVertexArraysARB = (void *) SDL_GL_GetProcAddress("glGenVertexArrays");
qglIsVertexArrayARB = (void *) SDL_GL_GetProcAddress("glIsVertexArray");
if (r_arb_vertex_array_object->integer)
glRefConfig.vertexArrayObject = qtrue;
ri.Printf(PRINT_ALL, result[glRefConfig.vertexArrayObject ? 1 : 0], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
} }

View file

@ -1487,50 +1487,40 @@ void GLSL_BindNullProgram(void)
void GLSL_VertexAttribsState(uint32_t stateBits) void GLSL_VertexAttribsState(uint32_t stateBits)
{ {
uint32_t diff = stateBits ^ glState.vertexAttribsState; int attribIndex;
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
if (diff)
{ {
int attribIndex; uint32_t attribBit = 1 << attribIndex;
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) if (stateBits & attribBit)
{ {
uint32_t attribBit = 1 << attribIndex; qglEnableVertexAttribArrayARB(attribIndex);
if(diff & attribBit) }
{ else
if (stateBits & attribBit) {
{ qglDisableVertexAttribArrayARB(attribIndex);
qglEnableVertexAttribArrayARB(attribIndex);
}
else
{
qglDisableVertexAttribArrayARB(attribIndex);
}
}
} }
} }
GLSL_VertexAttribPointers(stateBits); GLSL_VertexAttribPointers(stateBits);
glState.vertexAttribsState = stateBits;
} }
void GLSL_VertexAttribPointers(uint32_t attribBits) void GLSL_VertexAttribPointers(uint32_t attribBits)
{ {
int newFrame, oldFrame; int newFrame, oldFrame;
VBO_t *vbo = glState.currentVBO; vao_t *vao = glState.currentVao;
int attribIndex; int attribIndex;
uint32_t extraOffsets[ATTR_INDEX_COUNT]; uint32_t extraOffsets[ATTR_INDEX_COUNT];
if(!vbo) if(!vao)
{ {
ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound"); ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VAO bound");
return; return;
} }
// don't just call LogComment, or we will get a call to va() every frame! // don't just call LogComment, or we will get a call to va() every frame!
if(r_logFile->integer) if(r_logFile->integer)
{ {
GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", vbo->name)); GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", vao->name));
} }
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
@ -1541,13 +1531,18 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
newFrame = glState.vertexAttribsNewFrame; newFrame = glState.vertexAttribsNewFrame;
if (glState.vertexAnimation) if (glState.vertexAnimation)
{ {
glState.vertexAttribPointersSet &= ~(ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TANGENT | ATTR_TANGENT2); extraOffsets[ATTR_INDEX_POSITION] = newFrame * vao->size_xyz;
extraOffsets[ATTR_INDEX_POSITION] = newFrame * vbo->size_xyz; extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vao->size_xyz;
extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vbo->size_xyz; extraOffsets[ATTR_INDEX_NORMAL] = newFrame * vao->size_normal;
extraOffsets[ATTR_INDEX_NORMAL] = newFrame * vbo->size_normal; extraOffsets[ATTR_INDEX_NORMAL2] = oldFrame * vao->size_normal;
extraOffsets[ATTR_INDEX_NORMAL2] = oldFrame * vbo->size_normal; extraOffsets[ATTR_INDEX_TANGENT] = newFrame * vao->size_normal;
extraOffsets[ATTR_INDEX_TANGENT] = newFrame * vbo->size_normal; extraOffsets[ATTR_INDEX_TANGENT2] = oldFrame * vao->size_normal;
extraOffsets[ATTR_INDEX_TANGENT2] = oldFrame * vbo->size_normal; }
// this may not be bound if we're using VAOs
if (glRefConfig.vertexArrayObject)
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
} }
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
@ -1555,13 +1550,12 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
uint32_t attribBit = 1 << attribIndex; uint32_t attribBit = 1 << attribIndex;
vaoAttrib_t *vAtb; vaoAttrib_t *vAtb;
if (!(attribBits & attribBit) || (glState.vertexAttribPointersSet & attribBit)) if (!(attribBits & attribBit))
continue; continue;
vAtb = &vbo->attribs[attribIndex]; vAtb = &vao->attribs[attribIndex];
qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + extraOffsets[attribIndex])); qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + extraOffsets[attribIndex]));
glState.vertexAttribPointersSet |= attribBit;
} }
} }

View file

@ -104,6 +104,7 @@ cvar_t *r_arb_half_float_pixel;
cvar_t *r_ext_framebuffer_multisample; cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map; cvar_t *r_arb_seamless_cube_map;
cvar_t *r_arb_vertex_type_2_10_10_10_rev; cvar_t *r_arb_vertex_type_2_10_10_10_rev;
cvar_t *r_arb_vertex_array_object;
cvar_t *r_mergeMultidraws; cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces; cvar_t *r_mergeLeafSurfaces;
@ -944,15 +945,12 @@ void GL_SetDefaultState( void )
// //
glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
glState.vertexAttribsState = 0;
glState.vertexAttribPointersSet = 0;
glState.currentProgram = 0; glState.currentProgram = 0;
qglUseProgramObjectARB(0); qglUseProgramObjectARB(0);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL; glState.currentVao = NULL;
glState.currentIBO = NULL;
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
qglDepthMask( GL_TRUE ); qglDepthMask( GL_TRUE );
@ -1136,6 +1134,7 @@ void R_Register( void )
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH); r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH); r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
"0", CVAR_ARCHIVE | CVAR_LATCH ); "0", CVAR_ARCHIVE | CVAR_LATCH );
@ -1442,7 +1441,7 @@ void R_Init( void ) {
GLSL_InitGPUShaders(); GLSL_InitGPUShaders();
R_InitVBOs(); R_InitVaos();
R_InitShaders(); R_InitShaders();
@ -1492,7 +1491,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
FBO_Shutdown(); FBO_Shutdown();
R_DeleteTextures(); R_DeleteTextures();
R_ShutdownVBOs(); R_ShutdownVaos();
GLSL_ShutdownGPUShaders(); GLSL_ShutdownGPUShaders();
} }

View file

@ -99,7 +99,7 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
case SF_FACE: case SF_FACE:
case SF_GRID: case SF_GRID:
case SF_TRIANGLES: case SF_TRIANGLES:
case SF_VBO_MESH: case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = mask; ((srfBspSurface_t *)surf->data)->dlightBits = mask;
break; break;

View file

@ -49,8 +49,7 @@ typedef unsigned int glIndex_t;
#define MAX_FBOS 64 #define MAX_FBOS 64
#define MAX_VISCOUNTS 5 #define MAX_VISCOUNTS 5
#define MAX_VBOS 4096 #define MAX_VAOS 4096
#define MAX_IBOS 4096
#define MAX_CALC_PSHADOWS 64 #define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces #define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
@ -101,9 +100,9 @@ typedef struct {
typedef enum typedef enum
{ {
VBO_USAGE_STATIC, VAO_USAGE_STATIC,
VBO_USAGE_DYNAMIC VAO_USAGE_DYNAMIC
} vboUsage_t; } vaoUsage_t;
typedef struct vaoAttrib_s typedef struct vaoAttrib_s
{ {
@ -116,26 +115,22 @@ typedef struct vaoAttrib_s
} }
vaoAttrib_t; vaoAttrib_t;
typedef struct VBO_s typedef struct vao_s
{ {
char name[MAX_QPATH]; char name[MAX_QPATH];
uint32_t vao;
uint32_t vertexesVBO; uint32_t vertexesVBO;
int vertexesSize; // amount of memory data allocated for all vertices in bytes int vertexesSize; // amount of memory data allocated for all vertices in bytes
vaoAttrib_t attribs[VAO_MAX_ATTRIBS]; vaoAttrib_t attribs[VAO_MAX_ATTRIBS];
uint32_t size_xyz; uint32_t size_xyz;
uint32_t size_normal; uint32_t size_normal;
} VBO_t;
typedef struct IBO_s uint32_t indexesIBO;
{
char name[MAX_QPATH];
uint32_t indexesVBO;
int indexesSize; // amount of memory data allocated for all triangles in bytes int indexesSize; // amount of memory data allocated for all triangles in bytes
// uint32_t ofsIndexes; } vao_t;
} IBO_t;
//=============================================================================== //===============================================================================
@ -859,8 +854,8 @@ typedef enum {
SF_FLARE, SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_DISPLAY_LIST, SF_DISPLAY_LIST,
SF_VBO_MESH, SF_VAO_MESH,
SF_VBO_MDVMESH, SF_VAO_MDVMESH,
SF_NUM_SURFACE_TYPES, SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int ) SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
@ -923,7 +918,7 @@ typedef struct
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}} #define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#endif #endif
// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH // srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VAO_MESH
typedef struct srfBspSurface_s typedef struct srfBspSurface_s
{ {
surfaceType_t surfaceType; surfaceType_t surfaceType;
@ -953,8 +948,7 @@ typedef struct srfBspSurface_s
glIndex_t maxIndex; glIndex_t maxIndex;
// static render data // static render data
VBO_t *vbo; vao_t *vao;
IBO_t *ibo;
// SF_GRID specific variables after here // SF_GRID specific variables after here
@ -1016,7 +1010,7 @@ typedef struct srfIQModel_s {
int first_triangle, num_triangles; int first_triangle, num_triangles;
} srfIQModel_t; } srfIQModel_t;
typedef struct srfVBOMDVMesh_s typedef struct srfVaoMdvMesh_s
{ {
surfaceType_t surfaceType; surfaceType_t surfaceType;
@ -1030,9 +1024,8 @@ typedef struct srfVBOMDVMesh_s
glIndex_t maxIndex; glIndex_t maxIndex;
// static render data // static render data
VBO_t *vbo; vao_t *vao;
IBO_t *ibo; } srfVaoMdvMesh_t;
} srfVBOMDVMesh_t;
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *); extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
@ -1256,8 +1249,8 @@ typedef struct mdvModel_s
int numSurfaces; int numSurfaces;
mdvSurface_t *surfaces; mdvSurface_t *surfaces;
int numVBOSurfaces; int numVaoSurfaces;
srfVBOMDVMesh_t *vboSurfaces; srfVaoMdvMesh_t *vaoSurfaces;
int numSkins; int numSkins;
} mdvModel_t; } mdvModel_t;
@ -1370,16 +1363,13 @@ typedef struct {
int texEnv[2]; int texEnv[2];
int faceCulling; int faceCulling;
unsigned long glStateBits; unsigned long glStateBits;
uint32_t vertexAttribsState;
uint32_t vertexAttribPointersSet;
uint32_t vertexAttribsNewFrame; uint32_t vertexAttribsNewFrame;
uint32_t vertexAttribsOldFrame; uint32_t vertexAttribsOldFrame;
float vertexAttribsInterpolation; float vertexAttribsInterpolation;
qboolean vertexAnimation; qboolean vertexAnimation;
shaderProgram_t *currentProgram; shaderProgram_t *currentProgram;
FBO_t *currentFBO; FBO_t *currentFBO;
VBO_t *currentVBO; vao_t *currentVao;
IBO_t *currentIBO;
mat4_t modelview; mat4_t modelview;
mat4_t projection; mat4_t projection;
mat4_t modelviewProjection; mat4_t modelviewProjection;
@ -1428,6 +1418,7 @@ typedef struct {
GLenum packedNormalDataType; GLenum packedNormalDataType;
qboolean floatLightmap; qboolean floatLightmap;
qboolean vertexArrayObject;
} glRefConfig_t; } glRefConfig_t;
@ -1436,13 +1427,12 @@ typedef struct {
int c_surfBatches; int c_surfBatches;
float c_overDraw; float c_overDraw;
int c_vboVertexBuffers; int c_vaoBinds;
int c_vboIndexBuffers; int c_vaoVertexes;
int c_vboVertexes; int c_vaoIndexes;
int c_vboIndexes;
int c_staticVboDraws; int c_staticVaoDraws;
int c_dynamicVboDraws; int c_dynamicVaoDraws;
int c_multidraws; int c_multidraws;
int c_multidrawsMerged; int c_multidrawsMerged;
@ -1643,11 +1633,8 @@ typedef struct {
int numFBOs; int numFBOs;
FBO_t *fbos[MAX_FBOS]; FBO_t *fbos[MAX_FBOS];
int numVBOs; int numVaos;
VBO_t *vbos[MAX_VBOS]; vao_t *vaos[MAX_VAOS];
int numIBOs;
IBO_t *ibos[MAX_IBOS];
// shader indexes from other modules will be looked up in tr.shaders[] // shader indexes from other modules will be looked up in tr.shaders[]
// shader indexes from drawsurfs will be looked up in sortedShaders[] // shader indexes from drawsurfs will be looked up in sortedShaders[]
@ -1729,6 +1716,7 @@ extern cvar_t *r_arb_half_float_pixel;
extern cvar_t *r_ext_framebuffer_multisample; extern cvar_t *r_ext_framebuffer_multisample;
extern cvar_t *r_arb_seamless_cube_map; extern cvar_t *r_arb_seamless_cube_map;
extern cvar_t *r_arb_vertex_type_2_10_10_10_rev; extern cvar_t *r_arb_vertex_type_2_10_10_10_rev;
extern cvar_t *r_arb_vertex_array_object;
extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_nobind; // turns off binding to appropriate textures
extern cvar_t *r_singleShader; // make most world faces use default shader extern cvar_t *r_singleShader; // make most world faces use default shader
@ -2032,9 +2020,8 @@ typedef struct shaderCommands_s
//int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16); //int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);
void *attribPointers[ATTR_INDEX_COUNT]; void *attribPointers[ATTR_INDEX_COUNT];
VBO_t *vbo; vao_t *vao;
IBO_t *ibo; qboolean useInternalVao;
qboolean useInternalVBO;
stageVars_t svars QALIGN(16); stageVars_t svars QALIGN(16);
@ -2074,7 +2061,7 @@ void RB_EndSurface(void);
void RB_CheckOverflow( int verts, int indexes ); void RB_CheckOverflow( int verts, int indexes );
#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);} #define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);}
void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ); void R_DrawElementsVao( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex );
void RB_StageIteratorGeneric( void ); void RB_StageIteratorGeneric( void );
void RB_StageIteratorSky( void ); void RB_StageIteratorSky( void );
void RB_StageIteratorVertexLitTexture( void ); void RB_StageIteratorVertexLitTexture( void );
@ -2194,28 +2181,24 @@ VERTEX BUFFER OBJECTS
============================================================ ============================================================
*/ */
uint32_t R_VboPackTangent(vec4_t v); uint32_t R_VaoPackTangent(vec4_t v);
uint32_t R_VboPackNormal(vec3_t v); uint32_t R_VaoPackNormal(vec3_t v);
void R_VboUnpackTangent(vec4_t v, uint32_t b); void R_VaoUnpackTangent(vec4_t v, uint32_t b);
void R_VboUnpackNormal(vec3_t v, uint32_t b); void R_VaoUnpackNormal(vec3_t v, uint32_t b);
VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage); vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage);
VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes); vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *inIndexes);
IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage); void R_BindVao(vao_t *vao);
IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes); void R_BindNullVao(void);
void R_BindVBO(VBO_t * vbo); void Vao_SetVertexPointers(vao_t *vao);
void R_BindNullVBO(void);
void R_BindIBO(IBO_t * ibo); void R_InitVaos(void);
void R_BindNullIBO(void); void R_ShutdownVaos(void);
void R_VaoList_f(void);
void R_InitVBOs(void); void RB_UpdateTessVao(unsigned int attribBits);
void R_ShutdownVBOs(void);
void R_VBOList_f(void);
void RB_UpdateTessVbo(unsigned int attribBits);
/* /*

View file

@ -1575,7 +1575,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
shortest = len; shortest = len;
} }
R_VboUnpackNormal(tNormal, tess.normal[tess.indexes[i]]); R_VaoUnpackNormal(tNormal, tess.normal[tess.indexes[i]]);
if ( DotProduct( normal, tNormal ) >= 0 ) if ( DotProduct( normal, tNormal ) >= 0 )
{ {

View file

@ -388,9 +388,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
// don't add third_person objects if not viewing through a portal // don't add third_person objects if not viewing through a portal
if(!personalModel) if(!personalModel)
{ {
srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i]; srfVaoMdvMesh_t *vaoSurface = &model->vaoSurfaces[i];
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse, cubemapIndex ); R_AddDrawSurf((void *)vaoSurface, shader, fogNum, qfalse, qfalse, cubemapIndex );
} }
surface++; surface++;

View file

@ -656,14 +656,14 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
} }
{ {
srfVBOMDVMesh_t *vboSurf; srfVaoMdvMesh_t *vaoSurf;
mdvModel->numVBOSurfaces = mdvModel->numSurfaces; mdvModel->numVaoSurfaces = mdvModel->numSurfaces;
mdvModel->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low); mdvModel->vaoSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vaoSurfaces) * mdvModel->numSurfaces, h_low);
vboSurf = mdvModel->vboSurfaces; vaoSurf = mdvModel->vaoSurfaces;
surf = mdvModel->surfaces; surf = mdvModel->surfaces;
for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++) for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++)
{ {
vec3_t *verts; vec3_t *verts;
vec2_t *texcoords; vec2_t *texcoords;
@ -713,13 +713,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
VectorCopy(v->xyz, verts[j]); VectorCopy(v->xyz, verts[j]);
normals[j] = R_VboPackNormal(v->normal); normals[j] = R_VaoPackNormal(v->normal);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
CrossProduct(v->normal, v->tangent, nxt); CrossProduct(v->normal, v->tangent, nxt);
VectorCopy(v->tangent, tangent); VectorCopy(v->tangent, tangent);
tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f; tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
tangents[j] = R_VboPackTangent(tangent); tangents[j] = R_VaoPackTangent(tangent);
#endif #endif
} }
@ -729,76 +729,76 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
texcoords[j][1] = st->st[1]; texcoords[j][1] = st->st[1];
} }
vboSurf->surfaceType = SF_VBO_MDVMESH; vaoSurf->surfaceType = SF_VAO_MDVMESH;
vboSurf->mdvModel = mdvModel; vaoSurf->mdvModel = mdvModel;
vboSurf->mdvSurface = surf; vaoSurf->mdvSurface = surf;
vboSurf->numIndexes = surf->numIndexes; vaoSurf->numIndexes = surf->numIndexes;
vboSurf->numVerts = surf->numVerts; vaoSurf->numVerts = surf->numVerts;
vboSurf->minIndex = 0; vaoSurf->minIndex = 0;
vboSurf->maxIndex = surf->numVerts; vaoSurf->maxIndex = surf->numVerts;
vboSurf->vbo = R_CreateVBO(va("staticMD3Mesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); vaoSurf->vao = R_CreateVao(va("staticMD3Mesh_VAO '%s'", surf->name), data, dataSize, (byte *)surf->indexes, surf->numIndexes * sizeof(*surf->indexes), VAO_USAGE_STATIC);
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].enabled = 1;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].enabled = 1;
#endif #endif
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].count = 3; vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].count = 3;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].count = 3; vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].count = 3;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].count = 4; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].count = 4; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].count = 4;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].count = 4; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].count = 4; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].count = 4;
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2; vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].type = GL_FLOAT; vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].type = GL_FLOAT;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].type = glRefConfig.packedNormalDataType; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].type = glRefConfig.packedNormalDataType;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].type = glRefConfig.packedNormalDataType; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].type = glRefConfig.packedNormalDataType;
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT; vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].normalized = GL_FALSE; vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].normalized = GL_FALSE;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].normalized = GL_TRUE; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].normalized = GL_TRUE;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].normalized = GL_TRUE; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].normalized = GL_TRUE;
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].offset = ofs_xyz; vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].offset = ofs_xyz;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].stride = sizeof(*verts); vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(*verts);
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].offset = ofs_xyz; vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].offset = ofs_xyz;
vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].stride = sizeof(*verts); vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].stride = sizeof(*verts);
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].offset = ofs_normal; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].offset = ofs_normal;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(*normals); vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(*normals);
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].offset = ofs_normal; vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].offset = ofs_normal;
vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].stride = sizeof(*normals); vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].stride = sizeof(*normals);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].offset = ofs_tangent; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = ofs_tangent;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(*tangents); vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(*tangents);
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].offset = ofs_tangent; vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].offset = ofs_tangent;
vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].stride = sizeof(*tangents); vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].stride = sizeof(*tangents);
#endif #endif
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = ofs_st; vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].offset = ofs_st;
vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(*st); vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(*st);
vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts; vaoSurf->vao->size_xyz = sizeof(*verts) * surf->numVerts;
vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts; vaoSurf->vao->size_normal = sizeof(*normals) * surf->numVerts;
Vao_SetVertexPointers(vaoSurf->vao);
ri.Free(data); ri.Free(data);
vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numIndexes, surf->indexes);
} }
} }

View file

@ -1130,7 +1130,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]); normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]);
normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]); normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]);
*outNormal = R_VboPackNormal(normal); *outNormal = R_VaoPackNormal(normal);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]); tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
@ -1138,7 +1138,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]); tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
tangent[3] = data->tangents[4*vtx+3]; tangent[3] = data->tangents[4*vtx+3];
*outTangent++ = R_VboPackTangent(tangent); *outTangent++ = R_VaoPackTangent(tangent);
#endif #endif
} }

View file

@ -41,7 +41,7 @@ R_DrawElements
================== ==================
*/ */
void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ) void R_DrawElementsVao( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex )
{ {
if (glRefConfig.drawRangeElements) if (glRefConfig.drawRangeElements)
qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t))); qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
@ -51,7 +51,7 @@ void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex
} }
static void R_DrawMultiElementsVBO( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex, static void R_DrawMultiElementsVao( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex,
GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex) GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex)
{ {
if (glRefConfig.multiDrawArrays) if (glRefConfig.multiDrawArrays)
@ -154,11 +154,11 @@ static void DrawTris (shaderCommands_t *input) {
if (input->multiDrawPrimitives) if (input->multiDrawPrimitives)
{ {
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
} }
} }
@ -202,7 +202,7 @@ void RB_BeginSurface( shader_t *shader, int fogNum, int cubemapIndex ) {
tess.xstages = state->stages; tess.xstages = state->stages;
tess.numPasses = state->numUnfoggedPasses; tess.numPasses = state->numUnfoggedPasses;
tess.currentStageIteratorFunc = state->optimalStageIteratorFunc; tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
tess.useInternalVBO = qtrue; tess.useInternalVao = qtrue;
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) { if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
@ -429,11 +429,11 @@ static void ProjectDlightTexture( void ) {
if (tess.multiDrawPrimitives) if (tess.multiDrawPrimitives)
{ {
shaderCommands_t *input = &tess; shaderCommands_t *input = &tess;
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
} }
backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_totalIndexes += tess.numIndexes;
@ -873,11 +873,11 @@ static void ForwardDlight( void ) {
if (input->multiDrawPrimitives) if (input->multiDrawPrimitives)
{ {
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
} }
backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_totalIndexes += tess.numIndexes;
@ -949,11 +949,11 @@ static void ProjectPshadowVBOGLSL( void ) {
if (input->multiDrawPrimitives) if (input->multiDrawPrimitives)
{ {
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
} }
backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_totalIndexes += tess.numIndexes;
@ -1032,11 +1032,11 @@ static void RB_FogPass( void ) {
if (tess.multiDrawPrimitives) if (tess.multiDrawPrimitives)
{ {
shaderCommands_t *input = &tess; shaderCommands_t *input = &tess;
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
} }
} }
@ -1398,11 +1398,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
// //
if (input->multiDrawPrimitives) if (input->multiDrawPrimitives)
{ {
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
} }
// allow skipping out to show just lightmaps during development // allow skipping out to show just lightmaps during development
@ -1462,11 +1462,11 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
if (input->multiDrawPrimitives) if (input->multiDrawPrimitives)
{ {
R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
} }
else else
{ {
R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
} }
} }
} }
@ -1489,20 +1489,20 @@ void RB_StageIteratorGeneric( void )
return; return;
} }
if (tess.useInternalVBO) if (tess.useInternalVao)
{ {
RB_DeformTessGeometry(); RB_DeformTessGeometry();
} }
vertexAttribs = RB_CalcShaderVertexAttribs( input ); vertexAttribs = RB_CalcShaderVertexAttribs( input );
if (tess.useInternalVBO) if (tess.useInternalVao)
{ {
RB_UpdateTessVbo(vertexAttribs); RB_UpdateTessVao(vertexAttribs);
} }
else else
{ {
backEnd.pc.c_staticVboDraws++; backEnd.pc.c_staticVaoDraws++;
} }
// //
@ -1543,7 +1543,10 @@ void RB_StageIteratorGeneric( void )
// //
// Set vertex attribs and pointers // Set vertex attribs and pointers
// //
GLSL_VertexAttribsState(vertexAttribs); if (tess.useInternalVao)
GLSL_VertexAttribsState(vertexAttribs);
else if (glState.vertexAnimation)
GLSL_VertexAttribPointers(vertexAttribs & (ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TANGENT | ATTR_TANGENT2));
// //
// render depth if in depthfill mode // render depth if in depthfill mode

View file

@ -125,7 +125,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
{ {
R_VboUnpackNormal(offset, *normal); R_VaoUnpackNormal(offset, *normal);
xyz[0] += offset[0] * scale; xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale; xyz[1] += offset[1] * scale;
@ -145,7 +145,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
ds->deformationWave.phase + off, ds->deformationWave.phase + off,
ds->deformationWave.frequency ); ds->deformationWave.frequency );
R_VboUnpackNormal(offset, *normal); R_VaoUnpackNormal(offset, *normal);
xyz[0] += offset[0] * scale; xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale; xyz[1] += offset[1] * scale;
@ -170,7 +170,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) { for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
vec3_t fNormal; vec3_t fNormal;
R_VboUnpackNormal(fNormal, *normal); R_VaoUnpackNormal(fNormal, *normal);
scale = 0.98f; scale = 0.98f;
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
@ -189,7 +189,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
VectorNormalizeFast( fNormal ); VectorNormalizeFast( fNormal );
*normal = R_VboPackNormal(fNormal); *normal = R_VaoPackNormal(fNormal);
} }
} }
@ -213,7 +213,7 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
float scale; float scale;
vec3_t fNormal; vec3_t fNormal;
R_VboUnpackNormal(fNormal, *normal); R_VaoUnpackNormal(fNormal, *normal);
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now ); off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
@ -277,7 +277,7 @@ void DeformText( const char *text ) {
height[1] = 0; height[1] = 0;
height[2] = -1; height[2] = -1;
R_VboUnpackNormal(fNormal, tess.normal[0]); R_VaoUnpackNormal(fNormal, tess.normal[0]);
CrossProduct( fNormal, height, width ); CrossProduct( fNormal, height, width );
// find the midpoint of the box // find the midpoint of the box

View file

@ -421,7 +421,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
tess.maxIndex = tess.numVertexes; tess.maxIndex = tess.numVertexes;
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
RB_UpdateTessVbo(ATTR_POSITION | ATTR_TEXCOORD); RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD);
/* /*
{ {
shaderProgram_t *sp = &tr.textureColorShader; shaderProgram_t *sp = &tr.textureColorShader;
@ -466,7 +466,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
} }
R_DrawElementsVBO(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex); R_DrawElementsVao(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex);
//qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t))); //qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t)));

View file

@ -66,19 +66,18 @@ void RB_CheckOverflow( int verts, int indexes ) {
RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex ); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex );
} }
void RB_CheckVBOandIBO(VBO_t *vbo, IBO_t *ibo) void RB_CheckVao(vao_t *vao)
{ {
if (!(vbo == glState.currentVBO && ibo == glState.currentIBO) || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES) if (vao != glState.currentVao || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES)
{ {
RB_EndSurface(); RB_EndSurface();
RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex);
R_BindVBO(vbo); R_BindVao(vao);
R_BindIBO(ibo);
} }
if (vbo != tess.vbo && ibo != tess.ibo) if (vao != tess.vao)
tess.useInternalVBO = qfalse; tess.useInternalVao = qfalse;
} }
@ -127,7 +126,7 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4],
tess.normal[ndx] = tess.normal[ndx] =
tess.normal[ndx+1] = tess.normal[ndx+1] =
tess.normal[ndx+2] = tess.normal[ndx+2] =
tess.normal[ndx+3] = R_VboPackNormal(normal); tess.normal[ndx+3] = R_VaoPackNormal(normal);
// standard square texture coordinates // standard square texture coordinates
VectorSet2(tess.texCoords[ndx ][0], s1, t1); VectorSet2(tess.texCoords[ndx ][0], s1, t1);
@ -203,11 +202,11 @@ void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4])
tess.minIndex = 0; tess.minIndex = 0;
tess.maxIndex = 3; tess.maxIndex = 3;
RB_UpdateTessVbo(ATTR_POSITION | ATTR_TEXCOORD); RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
tess.numIndexes = 0; tess.numIndexes = 0;
tess.numVertexes = 0; tess.numVertexes = 0;
@ -325,7 +324,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
glIndex_t *outIndex; glIndex_t *outIndex;
float *color; float *color;
RB_CheckVBOandIBO(tess.vbo, tess.ibo); RB_CheckVao(tess.vao);
RB_CHECKOVERFLOW( numVerts, numIndexes ); RB_CHECKOVERFLOW( numVerts, numIndexes );
@ -349,7 +348,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts; dv = verts;
normal = &tess.normal[ tess.numVertexes ]; normal = &tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal++ ) for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
*normal = R_VboPackNormal(dv->normal); *normal = R_VaoPackNormal(dv->normal);
} }
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
@ -358,7 +357,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts; dv = verts;
tangent = &tess.tangent[ tess.numVertexes ]; tangent = &tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ ) for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
*tangent = R_VboPackTangent(dv->tangent); *tangent = R_VaoPackTangent(dv->tangent);
} }
#endif #endif
@ -391,7 +390,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts; dv = verts;
lightdir = &tess.lightdir[ tess.numVertexes ]; lightdir = &tess.lightdir[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ ) for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
*lightdir = R_VboPackNormal(dv->lightdir); *lightdir = R_VaoPackNormal(dv->lightdir);
} }
#if 0 // nothing even uses vertex dlightbits #if 0 // nothing even uses vertex dlightbits
@ -406,12 +405,12 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
tess.numVertexes += numVerts; tess.numVertexes += numVerts;
} }
static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int minIndex, int maxIndex, int dlightBits, int pshadowBits, qboolean shaderCheck) static qboolean RB_SurfaceVao(vao_t *vao, int numVerts, int numIndexes, int firstIndex, int minIndex, int maxIndex, int dlightBits, int pshadowBits, qboolean shaderCheck)
{ {
int i, mergeForward, mergeBack; int i, mergeForward, mergeBack;
GLvoid *firstIndexOffset, *lastIndexOffset; GLvoid *firstIndexOffset, *lastIndexOffset;
if (!vbo || !ibo) if (!vao)
{ {
return qfalse; return qfalse;
} }
@ -421,7 +420,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
return qfalse; return qfalse;
} }
RB_CheckVBOandIBO(vbo, ibo); RB_CheckVao(vao);
tess.dlightBits |= dlightBits; tess.dlightBits |= dlightBits;
tess.pshadowBits |= pshadowBits; tess.pshadowBits |= pshadowBits;
@ -515,7 +514,7 @@ RB_SurfaceTriangles
============= =============
*/ */
static void RB_SurfaceTriangles( srfBspSurface_t *srf ) { static void RB_SurfaceTriangles( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{ {
return; return;
@ -601,7 +600,7 @@ static void RB_SurfaceBeam( void )
tess.maxIndex = tess.numVertexes; tess.maxIndex = tess.numVertexes;
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
RB_UpdateTessVbo(ATTR_POSITION); RB_UpdateTessVao(ATTR_POSITION);
GLSL_VertexAttribsState(ATTR_POSITION); GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp); GLSL_BindProgram(sp);
@ -610,7 +609,7 @@ static void RB_SurfaceBeam( void )
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed); GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed);
R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
tess.numIndexes = 0; tess.numIndexes = 0;
tess.numVertexes = 0; tess.numVertexes = 0;
@ -1150,7 +1149,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
VectorCopy(newVerts->xyz, outXyz); VectorCopy(newVerts->xyz, outXyz);
VectorCopy(newVerts->normal, normal); VectorCopy(newVerts->normal, normal);
*outNormal = R_VboPackNormal(normal); *outNormal = R_VaoPackNormal(normal);
newVerts++; newVerts++;
outXyz += 4; outXyz += 4;
@ -1175,7 +1174,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal); VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
VectorNormalize(normal); VectorNormalize(normal);
*outNormal = R_VboPackNormal(normal); *outNormal = R_VaoPackNormal(normal);
newVerts++; newVerts++;
oldVerts++; oldVerts++;
@ -1250,7 +1249,7 @@ RB_SurfaceFace
============== ==============
*/ */
static void RB_SurfaceFace( srfBspSurface_t *srf ) { static void RB_SurfaceFace( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{ {
return; return;
@ -1320,7 +1319,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int pshadowBits; int pshadowBits;
//int *vDlightBits; //int *vDlightBits;
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{ {
return; return;
@ -1413,13 +1412,13 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_NORMAL ) if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{ {
*normal++ = R_VboPackNormal(dv->normal); *normal++ = R_VaoPackNormal(dv->normal);
} }
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT ) if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{ {
*tangent++ = R_VboPackTangent(dv->tangent); *tangent++ = R_VaoPackTangent(dv->tangent);
} }
#endif #endif
if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
@ -1442,7 +1441,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{ {
*lightdir++ = R_VboPackNormal(dv->lightdir); *lightdir++ = R_VaoPackNormal(dv->lightdir);
} }
//*vDlightBits++ = dlightBits; //*vDlightBits++ = dlightBits;
@ -1567,31 +1566,30 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
} }
static void RB_SurfaceVBOMesh(srfBspSurface_t * srf) static void RB_SurfaceVaoMesh(srfBspSurface_t * srf)
{ {
RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes, srf->firstIndex,
srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse ); srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse );
} }
void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
{ {
//mdvModel_t *mdvModel; //mdvModel_t *mdvModel;
//mdvSurface_t *mdvSurface; //mdvSurface_t *mdvSurface;
refEntity_t *refEnt; refEntity_t *refEnt;
GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n"); GLimp_LogComment("--- RB_SurfaceVaoMdvMesh ---\n");
if(!surface->vbo || !surface->ibo) if(!surface->vao)
return; return;
//RB_CheckVBOandIBO(surface->vbo, surface->ibo); //RB_CheckVao(surface->vao);
RB_EndSurface(); RB_EndSurface();
RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex);
R_BindVBO(surface->vbo); R_BindVao(surface->vao);
R_BindIBO(surface->ibo);
tess.useInternalVBO = qfalse; tess.useInternalVao = qfalse;
tess.numIndexes += surface->numIndexes; tess.numIndexes += surface->numIndexes;
tess.numVertexes += surface->numVerts; tess.numVertexes += surface->numVerts;
@ -1645,6 +1643,6 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE, (void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST (void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST
(void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH, (void(*)(void*))RB_SurfaceVaoMesh, // SF_VAO_MESH,
(void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH (void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH
}; };

View file

@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h" #include "tr_local.h"
uint32_t R_VboPackTangent(vec4_t v) uint32_t R_VaoPackTangent(vec4_t v)
{ {
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{ {
@ -41,7 +41,7 @@ uint32_t R_VboPackTangent(vec4_t v)
} }
} }
uint32_t R_VboPackNormal(vec3_t v) uint32_t R_VaoPackNormal(vec3_t v)
{ {
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{ {
@ -57,7 +57,7 @@ uint32_t R_VboPackNormal(vec3_t v)
} }
} }
void R_VboUnpackTangent(vec4_t v, uint32_t b) void R_VaoUnpackTangent(vec4_t v, uint32_t b)
{ {
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{ {
@ -75,7 +75,7 @@ void R_VboUnpackTangent(vec4_t v, uint32_t b)
} }
} }
void R_VboUnpackNormal(vec3_t v, uint32_t b) void R_VaoUnpackNormal(vec3_t v, uint32_t b)
{ {
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{ {
@ -91,73 +91,113 @@ void R_VboUnpackNormal(vec3_t v, uint32_t b)
} }
} }
void Vao_SetVertexPointers(vao_t *vao)
{
int i;
// set vertex pointers
for (i = 0; i < ATTR_INDEX_COUNT; i++)
{
if (vao->attribs[i].enabled)
{
qglVertexAttribPointerARB((GLuint)i,
(GLint)vao->attribs[i].count,
(GLenum)vao->attribs[i].type,
(GLboolean)vao->attribs[i].normalized,
(GLsizei)vao->attribs[i].stride,
BUFFER_OFFSET(vao->attribs[i].offset));
qglEnableVertexAttribArrayARB(i);
}
else
{
qglDisableVertexAttribArrayARB(i);
}
}
}
/* /*
============ ============
R_CreateVBO R_CreateVao
============ ============
*/ */
VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage) vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage)
{ {
VBO_t *vbo; vao_t *vao;
int glUsage; int glUsage;
switch (usage) switch (usage)
{ {
case VBO_USAGE_STATIC: case VAO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB; glUsage = GL_STATIC_DRAW_ARB;
break; break;
case VBO_USAGE_DYNAMIC: case VAO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB; glUsage = GL_DYNAMIC_DRAW_ARB;
break; break;
default: default:
Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage);
return NULL; return NULL;
} }
if(strlen(name) >= MAX_QPATH) if(strlen(name) >= MAX_QPATH)
{ {
ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long", name); ri.Error(ERR_DROP, "R_CreateVao: \"%s\" is too long", name);
} }
if ( tr.numVBOs == MAX_VBOS ) { if ( tr.numVaos == MAX_VAOS ) {
ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit"); ri.Error( ERR_DROP, "R_CreateVao: MAX_VAOS hit");
} }
R_IssuePendingRenderCommands(); R_IssuePendingRenderCommands();
vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
tr.numVBOs++; tr.numVaos++;
memset(vbo, 0, sizeof(*vbo)); memset(vao, 0, sizeof(*vao));
Q_strncpyz(vbo->name, name, sizeof(vbo->name)); Q_strncpyz(vao->name, name, sizeof(vao->name));
vbo->vertexesSize = vertexesSize;
qglGenBuffersARB(1, &vbo->vertexesVBO); if (glRefConfig.vertexArrayObject)
{
qglGenVertexArraysARB(1, &vao->vao);
qglBindVertexArrayARB(vao->vao);
}
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
vao->vertexesSize = vertexesSize;
qglGenBuffersARB(1, &vao->vertexesVBO);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL; vao->indexesSize = indexesSize;
qglGenBuffersARB(1, &vao->indexesIBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
glState.currentVao = vao;
GL_CheckErrors(); GL_CheckErrors();
return vbo; return vao;
} }
/* /*
============ ============
R_CreateVBO2 R_CreateVao2
============ ============
*/ */
VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts) vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *indexes)
{ {
VBO_t *vbo; vao_t *vao;
int i; int i;
byte *data; byte *data;
@ -166,79 +206,87 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
int glUsage = GL_STATIC_DRAW_ARB; int glUsage = GL_STATIC_DRAW_ARB;
if(!numVertexes) if(!numVertexes || !numIndexes)
return NULL; return NULL;
if(strlen(name) >= MAX_QPATH) if(strlen(name) >= MAX_QPATH)
{ {
ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name); ri.Error(ERR_DROP, "R_CreateVao2: \"%s\" is too long", name);
} }
if ( tr.numVBOs == MAX_VBOS ) { if ( tr.numVaos == MAX_VAOS ) {
ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit"); ri.Error( ERR_DROP, "R_CreateVao2: MAX_VAOS hit");
} }
R_IssuePendingRenderCommands(); R_IssuePendingRenderCommands();
vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
tr.numVBOs++; tr.numVaos++;
memset(vbo, 0, sizeof(*vbo)); memset(vao, 0, sizeof(*vao));
Q_strncpyz(vbo->name, name, sizeof(vbo->name)); Q_strncpyz(vao->name, name, sizeof(vao->name));
// since these vertex attributes are never altered, interleave them // since these vertex attributes are never altered, interleave them
vbo->attribs[ATTR_INDEX_POSITION ].enabled = 1; vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1; vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1; vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
#endif #endif
vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1; vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
vbo->attribs[ATTR_INDEX_COLOR ].enabled = 1; vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
vbo->attribs[ATTR_INDEX_POSITION ].count = 3; vao->attribs[ATTR_INDEX_POSITION ].count = 3;
vbo->attribs[ATTR_INDEX_NORMAL ].count = 4; vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
vbo->attribs[ATTR_INDEX_TANGENT ].count = 4; vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2; vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2; vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
vbo->attribs[ATTR_INDEX_COLOR ].count = 4; vao->attribs[ATTR_INDEX_COLOR ].count = 4;
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT; vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT; vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
vbo->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT; vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
vbo->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
vbo->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz); vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz);
vbo->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t); vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
vbo->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t); vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t);
#endif #endif
vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += sizeof(verts[0].st); vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += sizeof(verts[0].st);
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += sizeof(verts[0].lightmap); vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
vbo->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors); vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors);
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t); vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t);
vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize;
vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize;
vao->attribs[ATTR_INDEX_TANGENT ].stride = dataSize;
vao->attribs[ATTR_INDEX_TEXCOORD ].stride = dataSize;
vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = dataSize;
vao->attribs[ATTR_INDEX_COLOR ].stride = dataSize;
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize;
if (glRefConfig.vertexArrayObject)
{
qglGenVertexArraysARB(1, &vao->vao);
qglBindVertexArrayARB(vao->vao);
}
vbo->attribs[ATTR_INDEX_POSITION ].stride = dataSize;
vbo->attribs[ATTR_INDEX_NORMAL ].stride = dataSize;
vbo->attribs[ATTR_INDEX_TANGENT ].stride = dataSize;
vbo->attribs[ATTR_INDEX_TEXCOORD ].stride = dataSize;
vbo->attribs[ATTR_INDEX_LIGHTCOORD ].stride = dataSize;
vbo->attribs[ATTR_INDEX_COLOR ].stride = dataSize;
vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize;
// create VBO // create VBO
dataSize *= numVertexes; dataSize *= numVertexes;
@ -255,13 +303,13 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// normal // normal
p = (uint32_t *)(data + dataOfs); p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].normal); *p = R_VaoPackNormal(verts[i].normal);
dataOfs += sizeof(uint32_t); dataOfs += sizeof(uint32_t);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
// tangent // tangent
p = (uint32_t *)(data + dataOfs); p = (uint32_t *)(data + dataOfs);
*p = R_VboPackTangent(verts[i].tangent); *p = R_VaoPackTangent(verts[i].tangent);
dataOfs += sizeof(uint32_t); dataOfs += sizeof(uint32_t);
#endif #endif
@ -279,334 +327,205 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// feed vertex light directions // feed vertex light directions
p = (uint32_t *)(data + dataOfs); p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].lightdir); *p = R_VaoPackNormal(verts[i].lightdir);
dataOfs += sizeof(uint32_t); dataOfs += sizeof(uint32_t);
} }
vbo->vertexesSize = dataSize; vao->vertexesSize = dataSize;
qglGenBuffersARB(1, &vbo->vertexesVBO); qglGenBuffersARB(1, &vao->vertexesVBO);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vao->vertexesSize, data, glUsage);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL; // create IBO
vao->indexesSize = numIndexes * sizeof(glIndex_t);
qglGenBuffersARB(1, &vao->indexesIBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesSize, indexes, glUsage);
Vao_SetVertexPointers(vao);
glState.currentVao = vao;
GL_CheckErrors(); GL_CheckErrors();
ri.Hunk_FreeTempMemory(data); ri.Hunk_FreeTempMemory(data);
return vbo; return vao;
} }
/* /*
============ ============
R_CreateIBO R_BindVao
============ ============
*/ */
IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage) void R_BindVao(vao_t * vao)
{ {
IBO_t *ibo; if(!vao)
int glUsage;
switch (usage)
{ {
case VBO_USAGE_STATIC: //R_BindNullVao();
glUsage = GL_STATIC_DRAW_ARB; ri.Error(ERR_DROP, "R_BindVao: NULL vao");
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 numIndexes, glIndex_t * inIndexes)
{
IBO_t *ibo;
int i;
glIndex_t *indexes;
int indexesSize;
int glUsage = GL_STATIC_DRAW_ARB;
if(!numIndexes)
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 = numIndexes * sizeof(glIndex_t);
indexes = ri.Hunk_AllocateTempMemory(indexesSize);
for(i = 0; i < numIndexes; i++)
{
indexes[i] = inIndexes[i];
}
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; return;
} }
if(r_logFile->integer) if(r_logFile->integer)
{ {
// don't just call LogComment, or we will get a call to va() every frame! // don't just call LogComment, or we will get a call to va() every frame!
GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name)); GLimp_LogComment(va("--- R_BindVao( %s ) ---\n", vao->name));
} }
if(glState.currentVBO != vbo) if(glState.currentVao != vao)
{ {
glState.currentVBO = vbo; glState.currentVao = vao;
glState.vertexAttribPointersSet = 0;
glState.vertexAttribsInterpolation = 0; glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0; glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0; glState.vertexAttribsNewFrame = 0;
glState.vertexAnimation = qfalse; glState.vertexAnimation = qfalse;
backEnd.pc.c_vaoBinds++;
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); if (glRefConfig.vertexArrayObject)
{
qglBindVertexArrayARB(vao->vao);
backEnd.pc.c_vboVertexBuffers++; // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel?
if (1)
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
}
else
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
if (vao != tess.vao)
Vao_SetVertexPointers(vao);
}
} }
} }
/* /*
============ ============
R_BindNullVBO R_BindNullVao
============ ============
*/ */
void R_BindNullVBO(void) void R_BindNullVao(void)
{ {
GLimp_LogComment("--- R_BindNullVBO ---\n"); GLimp_LogComment("--- R_BindNullVao ---\n");
if(glState.currentVBO) if(glState.currentVao)
{ {
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); if (glRefConfig.vertexArrayObject)
glState.currentVBO = NULL; {
qglBindVertexArrayARB(0);
// why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel?
if (1) qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
else
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
glState.currentVao = NULL;
} }
GL_CheckErrors(); 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 R_InitVaos
============ ============
*/ */
void R_BindNullIBO(void) void R_InitVaos(void)
{ {
GLimp_LogComment("--- R_BindNullIBO ---\n"); int vertexesSize, indexesSize;
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; int offset;
ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n"); ri.Printf(PRINT_ALL, "------- R_InitVaos -------\n");
tr.numVBOs = 0; tr.numVaos = 0;
tr.numIBOs = 0;
dataSize = sizeof(tess.xyz[0]); vertexesSize = sizeof(tess.xyz[0]);
dataSize += sizeof(tess.normal[0]); vertexesSize += sizeof(tess.normal[0]);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
dataSize += sizeof(tess.tangent[0]); vertexesSize += sizeof(tess.tangent[0]);
#endif #endif
dataSize += sizeof(tess.vertexColors[0]); vertexesSize += sizeof(tess.vertexColors[0]);
dataSize += sizeof(tess.texCoords[0][0]) * 2; vertexesSize += sizeof(tess.texCoords[0][0]) * 2;
dataSize += sizeof(tess.lightdir[0]); vertexesSize += sizeof(tess.lightdir[0]);
dataSize *= SHADER_MAX_VERTEXES; vertexesSize *= SHADER_MAX_VERTEXES;
tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC); indexesSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES;
tess.vao = R_CreateVao("tessVertexArray_VAO", NULL, vertexesSize, NULL, indexesSize, VAO_USAGE_DYNAMIC);
offset = 0; offset = 0;
tess.vbo->attribs[ATTR_INDEX_POSITION ].enabled = 1; tess.vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
tess.vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1; tess.vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
tess.vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1; tess.vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
#endif #endif
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1; tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
tess.vbo->attribs[ATTR_INDEX_COLOR ].enabled = 1; tess.vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1; tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
tess.vbo->attribs[ATTR_INDEX_POSITION ].count = 3; tess.vao->attribs[ATTR_INDEX_POSITION ].count = 3;
tess.vbo->attribs[ATTR_INDEX_NORMAL ].count = 4; tess.vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
tess.vbo->attribs[ATTR_INDEX_TANGENT ].count = 4; tess.vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2; tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
tess.vbo->attribs[ATTR_INDEX_COLOR ].count = 4; tess.vao->attribs[ATTR_INDEX_COLOR ].count = 4;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4; tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
tess.vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
tess.vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; tess.vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
tess.vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; tess.vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT; tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
tess.vbo->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT; tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType; tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
tess.vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
tess.vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
tess.vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; tess.vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE; tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
tess.vbo->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE; tess.vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE; tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
tess.vbo->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; tess.vao->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
tess.vbo->attribs[ATTR_INDEX_NORMAL ].offset = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; tess.vao->attribs[ATTR_INDEX_NORMAL ].offset = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
tess.vbo->attribs[ATTR_INDEX_TANGENT ].offset = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; tess.vao->attribs[ATTR_INDEX_TANGENT ].offset = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
#endif #endif
// these next two are actually interleaved // these next two are actually interleaved
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = offset; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]); tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]);
offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
tess.vbo->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; tess.vao->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset; tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset;
tess.vbo->attribs[ATTR_INDEX_POSITION ].stride = sizeof(tess.xyz[0]); tess.vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(tess.xyz[0]);
tess.vbo->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]); tess.vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]);
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
tess.vbo->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(tess.tangent[0]); tess.vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(tess.tangent[0]);
#endif #endif
tess.vbo->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]); tess.vao->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]);
tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2; tess.vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2; tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]); tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]);
dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES;
tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz; tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz;
tess.attribPointers[ATTR_INDEX_TEXCOORD] = tess.texCoords; tess.attribPointers[ATTR_INDEX_TEXCOORD] = tess.texCoords;
@ -617,100 +536,86 @@ void R_InitVBOs(void)
tess.attribPointers[ATTR_INDEX_COLOR] = tess.vertexColors; tess.attribPointers[ATTR_INDEX_COLOR] = tess.vertexColors;
tess.attribPointers[ATTR_INDEX_LIGHTDIRECTION] = tess.lightdir; tess.attribPointers[ATTR_INDEX_LIGHTDIRECTION] = tess.lightdir;
tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC); Vao_SetVertexPointers(tess.vao);
R_BindNullVBO(); R_BindNullVao();
R_BindNullIBO();
GL_CheckErrors(); GL_CheckErrors();
} }
/* /*
============ ============
R_ShutdownVBOs R_ShutdownVaos
============ ============
*/ */
void R_ShutdownVBOs(void) void R_ShutdownVaos(void)
{ {
int i; int i;
VBO_t *vbo; vao_t *vao;
IBO_t *ibo;
ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n"); ri.Printf(PRINT_ALL, "------- R_ShutdownVaos -------\n");
R_BindNullVBO(); R_BindNullVao();
R_BindNullIBO();
for(i = 0; i < tr.numVaos; i++)
for(i = 0; i < tr.numVBOs; i++)
{ {
vbo = tr.vbos[i]; vao = tr.vaos[i];
if(vbo->vertexesVBO) if(vao->vao)
qglDeleteVertexArraysARB(1, &vao->vao);
if(vao->vertexesVBO)
{ {
qglDeleteBuffersARB(1, &vbo->vertexesVBO); qglDeleteBuffersARB(1, &vao->vertexesVBO);
} }
//ri.Free(vbo); if(vao->indexesIBO)
}
for(i = 0; i < tr.numIBOs; i++)
{
ibo = tr.ibos[i];
if(ibo->indexesVBO)
{ {
qglDeleteBuffersARB(1, &ibo->indexesVBO); qglDeleteBuffersARB(1, &vao->indexesIBO);
} }
//ri.Free(ibo);
} }
tr.numVBOs = 0; tr.numVaos = 0;
tr.numIBOs = 0;
} }
/* /*
============ ============
R_VBOList_f R_VaoList_f
============ ============
*/ */
void R_VBOList_f(void) void R_VaoList_f(void)
{ {
int i; int i;
VBO_t *vbo; vao_t *vao;
IBO_t *ibo;
int vertexesSize = 0; int vertexesSize = 0;
int indexesSize = 0; int indexesSize = 0;
ri.Printf(PRINT_ALL, " size name\n"); ri.Printf(PRINT_ALL, " size name\n");
ri.Printf(PRINT_ALL, "----------------------------------------------------------\n"); ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
for(i = 0; i < tr.numVBOs; i++) for(i = 0; i < tr.numVaos; i++)
{ {
vbo = tr.vbos[i]; vao = tr.vaos[i];
ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024), ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->vertexesSize / (1024 * 1024),
(vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name); (vao->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vao->name);
vertexesSize += vbo->vertexesSize; vertexesSize += vao->vertexesSize;
} }
for(i = 0; i < tr.numIBOs; i++) for(i = 0; i < tr.numVaos; i++)
{ {
ibo = tr.ibos[i]; vao = tr.vaos[i];
ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024), ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->indexesSize / (1024 * 1024),
(ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name); (vao->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vao->name);
indexesSize += ibo->indexesSize; indexesSize += vao->indexesSize;
} }
ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs); ri.Printf(PRINT_ALL, " %i total VAOs\n", tr.numVaos);
ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024), ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024),
(vertexesSize % (1024 * 1024)) * 100 / (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), ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024),
(indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
} }
@ -718,28 +623,35 @@ void R_VBOList_f(void)
/* /*
============== ==============
RB_UpdateTessVbo RB_UpdateTessVao
Adapted from Tess_UpdateVBOs from xreal Adapted from Tess_UpdateVBOs from xreal
Update the default VBO to replace the client side vertex arrays Update the default VAO to replace the client side vertex arrays
============== ==============
*/ */
void RB_UpdateTessVbo(unsigned int attribBits) void RB_UpdateTessVao(unsigned int attribBits)
{ {
GLimp_LogComment("--- RB_UpdateTessVbo ---\n"); GLimp_LogComment("--- RB_UpdateTessVao ---\n");
backEnd.pc.c_dynamicVboDraws++; backEnd.pc.c_dynamicVaoDraws++;
// update the default VBO // update the default VAO
if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES) if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES && tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
{ {
int attribIndex; int attribIndex;
R_BindVBO(tess.vbo); R_BindVao(tess.vao);
// orphan old buffer so we don't stall on it // these may not be bound if we're using VAOs
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB); if (glRefConfig.vertexArrayObject)
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tess.vao->vertexesVBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.vao->indexesIBO);
}
// orphan old vertex buffer so we don't stall on it
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
// if nothing to set, set everything // if nothing to set, set everything
if(!(attribBits & ATTR_BITS)) if(!(attribBits & ATTR_BITS))
@ -757,21 +669,15 @@ void RB_UpdateTessVbo(unsigned int attribBits)
{ {
if (attribBits & (1 << attribIndex)) if (attribBits & (1 << attribIndex))
{ {
vaoAttrib_t *vAtb = &tess.vbo->attribs[attribIndex]; vaoAttrib_t *vAtb = &tess.vao->attribs[attribIndex];
// note: tess is a VBO where stride == size // note: tess has a VBO where stride == size
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]); qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]);
} }
} }
}
// update the default IBO // orphan old index buffer so we don't stall on it
if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
{
R_BindIBO(tess.ibo);
// orphan old buffer so we don't stall on it
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
} }

View file

@ -213,7 +213,7 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
case SF_FACE: case SF_FACE:
case SF_GRID: case SF_GRID:
case SF_TRIANGLES: case SF_TRIANGLES:
case SF_VBO_MESH: case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = dlightBits; ((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
break; break;
@ -299,7 +299,7 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
case SF_FACE: case SF_FACE:
case SF_GRID: case SF_GRID:
case SF_TRIANGLES: case SF_TRIANGLES:
case SF_VBO_MESH: case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits; ((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
break; break;