summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSmileTheory <SmileTheory@gmail.com>2014-10-14 01:50:44 -0700
committerTim Angus <tim@ngus.net>2015-03-17 11:38:53 +0000
commit263220b82eadc878900668d22d867122fc735968 (patch)
treeed4090d85c5dcee325b6c274ea2a643e7d646498
parent70b1f9dd1c8a530aa4b2a8510fb7f365331303d8 (diff)
OpenGL2: Vertex array object support.
-rw-r--r--src/renderercommon/qgl.h11
-rw-r--r--src/renderergl2/tr_animation.c2
-rw-r--r--src/renderergl2/tr_bsp.c71
-rw-r--r--src/renderergl2/tr_cmds.c4
-rw-r--r--src/renderergl2/tr_extensions.c27
-rw-r--r--src/renderergl2/tr_glsl.c60
-rw-r--r--src/renderergl2/tr_init.c11
-rw-r--r--src/renderergl2/tr_light.c2
-rw-r--r--src/renderergl2/tr_local.h105
-rw-r--r--src/renderergl2/tr_main.c2
-rw-r--r--src/renderergl2/tr_mesh.c4
-rw-r--r--src/renderergl2/tr_model.c132
-rw-r--r--src/renderergl2/tr_model_iqm.c4
-rw-r--r--src/renderergl2/tr_shade.c47
-rw-r--r--src/renderergl2/tr_shade_calc.c12
-rw-r--r--src/renderergl2/tr_sky.c4
-rw-r--r--src/renderergl2/tr_surface.c72
-rw-r--r--src/renderergl2/tr_vbo.c694
-rw-r--r--src/renderergl2/tr_world.c4
19 files changed, 592 insertions, 676 deletions
diff --git a/src/renderercommon/qgl.h b/src/renderercommon/qgl.h
index ba1f1428..559c4387 100644
--- a/src/renderercommon/qgl.h
+++ b/src/renderercommon/qgl.h
@@ -977,6 +977,17 @@ extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
#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)
// WGL_ARB_create_context
#ifndef WGL_ARB_create_context
diff --git a/src/renderergl2/tr_animation.c b/src/renderergl2/tr_animation.c
index 2f3db8f6..6e4e3fd1 100644
--- a/src/renderergl2/tr_animation.c
+++ b/src/renderergl2/tr_animation.c
@@ -413,7 +413,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
tess.xyz[baseVertex + j][1] = tempVert[1];
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][1] = v->texCoords[1];
diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c
index 424d29e1..beb07fe3 100644
--- a/src/renderergl2/tr_bsp.c
+++ b/src/renderergl2/tr_bsp.c
@@ -1845,10 +1845,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;
@@ -1862,8 +1862,7 @@ static void R_CreateWorldVBOs(void)
msurface_t *surface, **firstSurf, **lastSurf, **currSurf;
msurface_t **surfacesSorted;
- VBO_t *vbo;
- IBO_t *ibo;
+ vao_t *vao;
int maxVboSize = 4 * 1024 * 1024;
@@ -1979,7 +1978,7 @@ static void R_CreateWorldVBOs(void)
{
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
// - All the surfaces with a single shader which go over maxVboSize
currVboSize = 0;
@@ -2018,7 +2017,7 @@ static void R_CreateWorldVBOs(void)
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
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
@@ -2051,16 +2050,14 @@ static void R_CreateWorldVBOs(void)
}
}
- vbo = R_CreateVBO2(va("staticBspModel%i_VBO", k), numVerts, verts);
- ibo = R_CreateIBO2(va("staticBspModel%i_IBO", k), numIndexes, indexes);
+ vao = R_CreateVao2(va("staticBspModel%i_VAO", k), numVerts, verts, numIndexes, indexes);
- // point bsp surfaces to VBO
+ // point bsp surfaces to VAO
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
- bspSurf->vbo = vbo;
- bspSurf->ibo = ibo;
+ bspSurf->vao = vao;
}
ri.Hunk_FreeTempMemory(indexes);
@@ -2124,7 +2121,7 @@ static void R_CreateWorldVBOs(void)
mergedSurf = s_worldData.mergedSurfaces;
for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
{
- srfBspSurface_t *bspSurf, *vboSurf;
+ srfBspSurface_t *bspSurf, *vaoSurf;
for ( lastSurf++ ; lastSurf < surfacesSorted + numSortedSurfaces; lastSurf++)
{
@@ -2148,35 +2145,34 @@ static void R_CreateWorldVBOs(void)
bspSurf = (srfBspSurface_t *)(*firstSurf)->data;
- vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
- memset(vboSurf, 0, sizeof(*vboSurf));
- vboSurf->surfaceType = SF_VBO_MESH;
+ vaoSurf = ri.Hunk_Alloc(sizeof(*vaoSurf), h_low);
+ memset(vaoSurf, 0, sizeof(*vaoSurf));
+ vaoSurf->surfaceType = SF_VAO_MESH;
- vboSurf->vbo = bspSurf->vbo;
- vboSurf->ibo = bspSurf->ibo;
+ vaoSurf->vao = bspSurf->vao;
- vboSurf->firstIndex = bspSurf->firstIndex;
- vboSurf->minIndex = bspSurf->minIndex;
- vboSurf->maxIndex = bspSurf->maxIndex;
+ vaoSurf->firstIndex = bspSurf->firstIndex;
+ vaoSurf->minIndex = bspSurf->minIndex;
+ vaoSurf->maxIndex = bspSurf->maxIndex;
- ClearBounds(vboSurf->cullBounds[0], vboSurf->cullBounds[1]);
+ ClearBounds(vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfBspSurface_t *currBspSurf = (srfBspSurface_t *)(*currSurf)->data;
- vboSurf->numVerts += currBspSurf->numVerts;
- vboSurf->numIndexes += currBspSurf->numIndexes;
- vboSurf->minIndex = MIN(vboSurf->minIndex, currBspSurf->minIndex);
- vboSurf->maxIndex = MAX(vboSurf->maxIndex, currBspSurf->maxIndex);
- AddPointToBounds((*currSurf)->cullinfo.bounds[0], vboSurf->cullBounds[0], vboSurf->cullBounds[1]);
- AddPointToBounds((*currSurf)->cullinfo.bounds[1], vboSurf->cullBounds[0], vboSurf->cullBounds[1]);
+ vaoSurf->numVerts += currBspSurf->numVerts;
+ vaoSurf->numIndexes += currBspSurf->numIndexes;
+ vaoSurf->minIndex = MIN(vaoSurf->minIndex, currBspSurf->minIndex);
+ vaoSurf->maxIndex = MAX(vaoSurf->maxIndex, currBspSurf->maxIndex);
+ AddPointToBounds((*currSurf)->cullinfo.bounds[0], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
+ AddPointToBounds((*currSurf)->cullinfo.bounds[1], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]);
}
- VectorCopy(vboSurf->cullBounds[0], mergedSurf->cullinfo.bounds[0]);
- VectorCopy(vboSurf->cullBounds[1], mergedSurf->cullinfo.bounds[1]);
+ VectorCopy(vaoSurf->cullBounds[0], mergedSurf->cullinfo.bounds[0]);
+ VectorCopy(vaoSurf->cullBounds[1], mergedSurf->cullinfo.bounds[1]);
mergedSurf->cullinfo.type = CULLINFO_BOX;
- mergedSurf->data = (surfaceType_t *)vboSurf;
+ mergedSurf->data = (surfaceType_t *)vaoSurf;
mergedSurf->fogIndex = (*firstSurf)->fogIndex;
mergedSurf->cubemapIndex = (*firstSurf)->cubemapIndex;
mergedSurf->shader = (*firstSurf)->shader;
@@ -2207,7 +2203,7 @@ static void R_CreateWorldVBOs(void)
ri.Free(surfacesSorted);
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);
}
/*
@@ -2271,7 +2267,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
- // 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
in = (void *)(fileBase + surfs->fileofs);
out = s_worldData.surfaces;
@@ -2394,7 +2390,7 @@ static void R_LoadSubmodels( lump_t *l ) {
if(i == 0)
{
- // Add this for limiting VBO surface creation
+ // Add this for limiting VAO surface creation
s_worldData.numWorldSurfaces = out->numSurfaces;
}
}
@@ -3403,17 +3399,16 @@ void RE_LoadWorldMap( const char *name ) {
}
}
- // create static VBOS from the world
- R_CreateWorldVBOs();
+ // create static VAOS from the world
+ R_CreateWorldVaos();
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
tr.world = &s_worldData;
- // make sure the VBO glState entries are safe
- R_BindNullVBO();
- R_BindNullIBO();
+ // make sure the VAO glState entry is safe
+ R_BindNullVao();
// Render all cubemaps
if (r_cubeMapping->integer && tr.numCubemaps)
diff --git a/src/renderergl2/tr_cmds.c b/src/renderergl2/tr_cmds.c
index 540b2a1d..c3983e7d 100644
--- a/src/renderergl2/tr_cmds.c
+++ b/src/renderergl2/tr_cmds.c
@@ -67,8 +67,8 @@ void R_PerformanceCounters( void ) {
}
else if (r_speeds->integer == 7 )
{
- ri.Printf( PRINT_ALL, "VBO 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 );
+ ri.Printf( PRINT_ALL, "VAO draws: static %i dynamic %i\nMultidraws: %i merged %i\n",
+ 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",
backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws);
}
diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c
index e0f972a9..31c48a12 100644
--- a/src/renderergl2/tr_extensions.c
+++ b/src/renderergl2/tr_extensions.c
@@ -178,6 +178,12 @@ void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei sa
// GL_ARB_draw_buffers
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)
{
const char *ptr = Q_stristr( glConfig.extensions_string, ext );
@@ -682,4 +688,25 @@ void GLimp_InitExtraExtensions()
// use float lightmaps?
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);
+ }
+
}
diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c
index 6e8934ed..d41fb1ff 100644
--- a/src/renderergl2/tr_glsl.c
+++ b/src/renderergl2/tr_glsl.c
@@ -1487,50 +1487,40 @@ void GLSL_BindNullProgram(void)
void GLSL_VertexAttribsState(uint32_t stateBits)
{
- uint32_t diff = stateBits ^ glState.vertexAttribsState;
-
- if (diff)
+ int attribIndex;
+ for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
{
- int attribIndex;
- for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
+ uint32_t attribBit = 1 << attribIndex;
+ if (stateBits & attribBit)
{
- uint32_t attribBit = 1 << attribIndex;
- if(diff & attribBit)
- {
- if (stateBits & attribBit)
- {
- qglEnableVertexAttribArrayARB(attribIndex);
- }
- else
- {
- qglDisableVertexAttribArrayARB(attribIndex);
- }
- }
+ qglEnableVertexAttribArrayARB(attribIndex);
+ }
+ else
+ {
+ qglDisableVertexAttribArrayARB(attribIndex);
}
}
GLSL_VertexAttribPointers(stateBits);
-
- glState.vertexAttribsState = stateBits;
}
void GLSL_VertexAttribPointers(uint32_t attribBits)
{
int newFrame, oldFrame;
- VBO_t *vbo = glState.currentVBO;
+ vao_t *vao = glState.currentVao;
int attribIndex;
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;
}
// don't just call LogComment, or we will get a call to va() every frame!
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++)
@@ -1541,13 +1531,18 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
newFrame = glState.vertexAttribsNewFrame;
if (glState.vertexAnimation)
{
- glState.vertexAttribPointersSet &= ~(ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TANGENT | ATTR_TANGENT2);
- extraOffsets[ATTR_INDEX_POSITION] = newFrame * vbo->size_xyz;
- extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vbo->size_xyz;
- extraOffsets[ATTR_INDEX_NORMAL] = newFrame * vbo->size_normal;
- extraOffsets[ATTR_INDEX_NORMAL2] = oldFrame * vbo->size_normal;
- extraOffsets[ATTR_INDEX_TANGENT] = newFrame * vbo->size_normal;
- extraOffsets[ATTR_INDEX_TANGENT2] = oldFrame * vbo->size_normal;
+ extraOffsets[ATTR_INDEX_POSITION] = newFrame * vao->size_xyz;
+ extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vao->size_xyz;
+ extraOffsets[ATTR_INDEX_NORMAL] = newFrame * vao->size_normal;
+ extraOffsets[ATTR_INDEX_NORMAL2] = oldFrame * vao->size_normal;
+ extraOffsets[ATTR_INDEX_TANGENT] = newFrame * vao->size_normal;
+ extraOffsets[ATTR_INDEX_TANGENT2] = oldFrame * vao->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++)
@@ -1555,13 +1550,12 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
uint32_t attribBit = 1 << attribIndex;
vaoAttrib_t *vAtb;
- if (!(attribBits & attribBit) || (glState.vertexAttribPointersSet & attribBit))
+ if (!(attribBits & attribBit))
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]));
- glState.vertexAttribPointersSet |= attribBit;
}
}
diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c
index d5a0fc4a..3b55725d 100644
--- a/src/renderergl2/tr_init.c
+++ b/src/renderergl2/tr_init.c
@@ -103,6 +103,7 @@ cvar_t *r_arb_half_float_pixel;
cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map;
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_mergeLeafSurfaces;
@@ -872,15 +873,12 @@ void GL_SetDefaultState( void )
//
glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
- glState.vertexAttribsState = 0;
- glState.vertexAttribPointersSet = 0;
glState.currentProgram = 0;
qglUseProgramObjectARB(0);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glState.currentVBO = NULL;
- glState.currentIBO = NULL;
+ glState.currentVao = NULL;
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
qglDepthMask( GL_TRUE );
@@ -1064,6 +1062,7 @@ void R_Register( void )
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_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",
"0", CVAR_ARCHIVE | CVAR_LATCH );
@@ -1364,7 +1363,7 @@ void R_Init( void ) {
GLSL_InitGPUShaders();
- R_InitVBOs();
+ R_InitVaos();
R_InitShaders();
@@ -1413,7 +1412,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
if (glRefConfig.framebufferObject)
FBO_Shutdown();
R_DeleteTextures();
- R_ShutdownVBOs();
+ R_ShutdownVaos();
GLSL_ShutdownGPUShaders();
}
diff --git a/src/renderergl2/tr_light.c b/src/renderergl2/tr_light.c
index 4d54bff2..5993959e 100644
--- a/src/renderergl2/tr_light.c
+++ b/src/renderergl2/tr_light.c
@@ -100,7 +100,7 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
- case SF_VBO_MESH:
+ case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = mask;
break;
diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h
index 1c1dcff0..eac0c1eb 100644
--- a/src/renderergl2/tr_local.h
+++ b/src/renderergl2/tr_local.h
@@ -50,8 +50,7 @@ typedef unsigned int glIndex_t;
#define MAX_FBOS 64
#define MAX_VISCOUNTS 5
-#define MAX_VBOS 4096
-#define MAX_IBOS 4096
+#define MAX_VAOS 4096
#define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
@@ -102,9 +101,9 @@ typedef struct {
typedef enum
{
- VBO_USAGE_STATIC,
- VBO_USAGE_DYNAMIC
-} vboUsage_t;
+ VAO_USAGE_STATIC,
+ VAO_USAGE_DYNAMIC
+} vaoUsage_t;
typedef struct vaoAttrib_s
{
@@ -117,26 +116,22 @@ typedef struct vaoAttrib_s
}
vaoAttrib_t;
-typedef struct VBO_s
+typedef struct vao_s
{
char name[MAX_QPATH];
+ uint32_t vao;
+
uint32_t vertexesVBO;
int vertexesSize; // amount of memory data allocated for all vertices in bytes
vaoAttrib_t attribs[VAO_MAX_ATTRIBS];
uint32_t size_xyz;
uint32_t size_normal;
-} VBO_t;
-
-typedef struct IBO_s
-{
- char name[MAX_QPATH];
- uint32_t indexesVBO;
+ uint32_t indexesIBO;
int indexesSize; // amount of memory data allocated for all triangles in bytes
-// uint32_t ofsIndexes;
-} IBO_t;
+} vao_t;
//===============================================================================
@@ -860,8 +855,8 @@ typedef enum {
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_DISPLAY_LIST,
- SF_VBO_MESH,
- SF_VBO_MDVMESH,
+ SF_VAO_MESH,
+ SF_VAO_MDVMESH,
SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
@@ -924,7 +919,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}}
#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
{
surfaceType_t surfaceType;
@@ -954,8 +949,7 @@ typedef struct srfBspSurface_s
glIndex_t maxIndex;
// static render data
- VBO_t *vbo;
- IBO_t *ibo;
+ vao_t *vao;
// SF_GRID specific variables after here
@@ -1017,7 +1011,7 @@ typedef struct srfIQModel_s {
int first_triangle, num_triangles;
} srfIQModel_t;
-typedef struct srfVBOMDVMesh_s
+typedef struct srfVaoMdvMesh_s
{
surfaceType_t surfaceType;
@@ -1031,9 +1025,8 @@ typedef struct srfVBOMDVMesh_s
glIndex_t maxIndex;
// static render data
- VBO_t *vbo;
- IBO_t *ibo;
-} srfVBOMDVMesh_t;
+ vao_t *vao;
+} srfVaoMdvMesh_t;
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
@@ -1257,8 +1250,8 @@ typedef struct mdvModel_s
int numSurfaces;
mdvSurface_t *surfaces;
- int numVBOSurfaces;
- srfVBOMDVMesh_t *vboSurfaces;
+ int numVaoSurfaces;
+ srfVaoMdvMesh_t *vaoSurfaces;
int numSkins;
} mdvModel_t;
@@ -1371,16 +1364,13 @@ typedef struct {
int texEnv[2];
int faceCulling;
unsigned long glStateBits;
- uint32_t vertexAttribsState;
- uint32_t vertexAttribPointersSet;
uint32_t vertexAttribsNewFrame;
uint32_t vertexAttribsOldFrame;
float vertexAttribsInterpolation;
qboolean vertexAnimation;
shaderProgram_t *currentProgram;
FBO_t *currentFBO;
- VBO_t *currentVBO;
- IBO_t *currentIBO;
+ vao_t *currentVao;
mat4_t modelview;
mat4_t projection;
mat4_t modelviewProjection;
@@ -1429,6 +1419,7 @@ typedef struct {
GLenum packedNormalDataType;
qboolean floatLightmap;
+ qboolean vertexArrayObject;
} glRefConfig_t;
@@ -1437,13 +1428,12 @@ typedef struct {
int c_surfBatches;
float c_overDraw;
- int c_vboVertexBuffers;
- int c_vboIndexBuffers;
- int c_vboVertexes;
- int c_vboIndexes;
+ int c_vaoBinds;
+ int c_vaoVertexes;
+ int c_vaoIndexes;
- int c_staticVboDraws;
- int c_dynamicVboDraws;
+ int c_staticVaoDraws;
+ int c_dynamicVaoDraws;
int c_multidraws;
int c_multidrawsMerged;
@@ -1646,11 +1636,8 @@ typedef struct {
int numFBOs;
FBO_t *fbos[MAX_FBOS];
- int numVBOs;
- VBO_t *vbos[MAX_VBOS];
-
- int numIBOs;
- IBO_t *ibos[MAX_IBOS];
+ int numVaos;
+ vao_t *vaos[MAX_VAOS];
// shader indexes from other modules will be looked up in tr.shaders[]
// shader indexes from drawsurfs will be looked up in sortedShaders[]
@@ -1731,6 +1718,7 @@ extern cvar_t *r_arb_half_float_pixel;
extern cvar_t *r_ext_framebuffer_multisample;
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_array_object;
extern cvar_t *r_nobind; // turns off binding to appropriate textures
extern cvar_t *r_singleShader; // make most world faces use default shader
@@ -2034,9 +2022,8 @@ typedef struct shaderCommands_s
//int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);
void *attribPointers[ATTR_INDEX_COUNT];
- VBO_t *vbo;
- IBO_t *ibo;
- qboolean useInternalVBO;
+ vao_t *vao;
+ qboolean useInternalVao;
stageVars_t svars QALIGN(16);
@@ -2076,7 +2063,7 @@ void RB_EndSurface(void);
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);}
-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_StageIteratorSky( void );
void RB_StageIteratorVertexLitTexture( void );
@@ -2196,28 +2183,24 @@ VERTEX BUFFER OBJECTS
============================================================
*/
-uint32_t R_VboPackTangent(vec4_t v);
-uint32_t R_VboPackNormal(vec3_t v);
-void R_VboUnpackTangent(vec4_t v, uint32_t b);
-void R_VboUnpackNormal(vec3_t v, uint32_t b);
-
-VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage);
-VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes);
+uint32_t R_VaoPackTangent(vec4_t v);
+uint32_t R_VaoPackNormal(vec3_t v);
+void R_VaoUnpackTangent(vec4_t v, uint32_t b);
+void R_VaoUnpackNormal(vec3_t v, uint32_t b);
-IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage);
-IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes);
+vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage);
+vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *inIndexes);
-void R_BindVBO(VBO_t * vbo);
-void R_BindNullVBO(void);
+void R_BindVao(vao_t *vao);
+void R_BindNullVao(void);
-void R_BindIBO(IBO_t * ibo);
-void R_BindNullIBO(void);
+void Vao_SetVertexPointers(vao_t *vao);
-void R_InitVBOs(void);
-void R_ShutdownVBOs(void);
-void R_VBOList_f(void);
+void R_InitVaos(void);
+void R_ShutdownVaos(void);
+void R_VaoList_f(void);
-void RB_UpdateTessVbo(unsigned int attribBits);
+void RB_UpdateTessVao(unsigned int attribBits);
/*
diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c
index 85a56b10..132ef309 100644
--- a/src/renderergl2/tr_main.c
+++ b/src/renderergl2/tr_main.c
@@ -1576,7 +1576,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
shortest = len;
}
- R_VboUnpackNormal(tNormal, tess.normal[tess.indexes[i]]);
+ R_VaoUnpackNormal(tNormal, tess.normal[tess.indexes[i]]);
if ( DotProduct( normal, tNormal ) >= 0 )
{
diff --git a/src/renderergl2/tr_mesh.c b/src/renderergl2/tr_mesh.c
index 72078b75..790cb04d 100644
--- a/src/renderergl2/tr_mesh.c
+++ b/src/renderergl2/tr_mesh.c
@@ -389,9 +389,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
// don't add third_person objects if not viewing through a portal
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++;
diff --git a/src/renderergl2/tr_model.c b/src/renderergl2/tr_model.c
index 6a384648..c8c74e20 100644
--- a/src/renderergl2/tr_model.c
+++ b/src/renderergl2/tr_model.c
@@ -657,14 +657,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->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low);
+ mdvModel->numVaoSurfaces = mdvModel->numSurfaces;
+ mdvModel->vaoSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vaoSurfaces) * mdvModel->numSurfaces, h_low);
- vboSurf = mdvModel->vboSurfaces;
+ vaoSurf = mdvModel->vaoSurfaces;
surf = mdvModel->surfaces;
- for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++)
+ for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++)
{
vec3_t *verts;
vec2_t *texcoords;
@@ -714,13 +714,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
VectorCopy(v->xyz, verts[j]);
- normals[j] = R_VboPackNormal(v->normal);
+ normals[j] = R_VaoPackNormal(v->normal);
#ifdef USE_VERT_TANGENT_SPACE
CrossProduct(v->normal, v->tangent, nxt);
VectorCopy(v->tangent, tangent);
tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
- tangents[j] = R_VboPackTangent(tangent);
+ tangents[j] = R_VaoPackTangent(tangent);
#endif
}
@@ -730,76 +730,76 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
texcoords[j][1] = st->st[1];
}
- vboSurf->surfaceType = SF_VBO_MDVMESH;
- vboSurf->mdvModel = mdvModel;
- vboSurf->mdvSurface = surf;
- vboSurf->numIndexes = surf->numIndexes;
- vboSurf->numVerts = surf->numVerts;
+ vaoSurf->surfaceType = SF_VAO_MDVMESH;
+ vaoSurf->mdvModel = mdvModel;
+ vaoSurf->mdvSurface = surf;
+ vaoSurf->numIndexes = surf->numIndexes;
+ vaoSurf->numVerts = surf->numVerts;
- vboSurf->minIndex = 0;
- vboSurf->maxIndex = surf->numVerts;
+ vaoSurf->minIndex = 0;
+ 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;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].enabled = 1;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].enabled = 1;
#endif
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
-
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].count = 3;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].count = 3;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].count = 4;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].count = 4;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].count = 4;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].count = 4;
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
-
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].type = GL_FLOAT;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].type = glRefConfig.packedNormalDataType;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].type = glRefConfig.packedNormalDataType;
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
-
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].normalized = GL_FALSE;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].normalized = GL_TRUE;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].normalized = GL_TRUE;
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
-
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].offset = ofs_xyz;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION ].stride = sizeof(*verts);
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].offset = ofs_xyz;
- vboSurf->vbo->attribs[ATTR_INDEX_POSITION2 ].stride = sizeof(*verts);
-
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].offset = ofs_normal;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(*normals);
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].offset = ofs_normal;
- vboSurf->vbo->attribs[ATTR_INDEX_NORMAL2 ].stride = sizeof(*normals);
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
+
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].count = 3;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].count = 3;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].count = 4;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].count = 4;
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
+
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].type = GL_FLOAT;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].type = glRefConfig.packedNormalDataType;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].type = glRefConfig.packedNormalDataType;
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
+
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].normalized = GL_FALSE;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].normalized = GL_TRUE;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].normalized = GL_TRUE;
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
+
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].offset = ofs_xyz;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(*verts);
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].offset = ofs_xyz;
+ vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].stride = sizeof(*verts);
+
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].offset = ofs_normal;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(*normals);
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].offset = ofs_normal;
+ vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].stride = sizeof(*normals);
#ifdef USE_VERT_TANGENT_SPACE
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].offset = ofs_tangent;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(*tangents);
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].offset = ofs_tangent;
- vboSurf->vbo->attribs[ATTR_INDEX_TANGENT2 ].stride = sizeof(*tangents);
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = ofs_tangent;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(*tangents);
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].offset = ofs_tangent;
+ vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].stride = sizeof(*tangents);
#endif
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = ofs_st;
- vboSurf->vbo->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(*st);
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].offset = ofs_st;
+ vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(*st);
- vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts;
- vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts;
+ vaoSurf->vao->size_xyz = sizeof(*verts) * surf->numVerts;
+ vaoSurf->vao->size_normal = sizeof(*normals) * surf->numVerts;
- ri.Free(data);
+ Vao_SetVertexPointers(vaoSurf->vao);
- vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numIndexes, surf->indexes);
+ ri.Free(data);
}
}
diff --git a/src/renderergl2/tr_model_iqm.c b/src/renderergl2/tr_model_iqm.c
index febcf59b..4130bb10 100644
--- a/src/renderergl2/tr_model_iqm.c
+++ b/src/renderergl2/tr_model_iqm.c
@@ -1130,7 +1130,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
normal[1] = DotProduct(&nrmMat[3], &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
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[3] = data->tangents[4*vtx+3];
- *outTangent++ = R_VboPackTangent(tangent);
+ *outTangent++ = R_VaoPackTangent(tangent);
#endif
}
diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c
index e478e7a1..1ddfef69 100644
--- a/src/renderergl2/tr_shade.c
+++ b/src/renderergl2/tr_shade.c
@@ -42,7 +42,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)
qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
@@ -52,7 +52,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)
{
if (glRefConfig.multiDrawArrays)
@@ -155,11 +155,11 @@ static void DrawTris (shaderCommands_t *input) {
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
{
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
+ R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
}
}
@@ -203,7 +203,7 @@ void RB_BeginSurface( shader_t *shader, int fogNum, int cubemapIndex ) {
tess.xstages = state->stages;
tess.numPasses = state->numUnfoggedPasses;
tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
- tess.useInternalVBO = qtrue;
+ tess.useInternalVao = qtrue;
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
@@ -430,11 +430,11 @@ static void ProjectDlightTexture( void ) {
if (tess.multiDrawPrimitives)
{
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
{
- 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;
@@ -874,11 +874,11 @@ static void ForwardDlight( void ) {
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
{
- 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;
@@ -950,11 +950,11 @@ static void ProjectPshadowVBOGLSL( void ) {
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
{
- 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;
@@ -1033,11 +1033,11 @@ static void RB_FogPass( void ) {
if (tess.multiDrawPrimitives)
{
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
{
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
+ R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
}
}
@@ -1399,11 +1399,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
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
{
- 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
@@ -1463,11 +1463,11 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
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
{
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
+ R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
}
}
}
@@ -1490,20 +1490,20 @@ void RB_StageIteratorGeneric( void )
return;
}
- if (tess.useInternalVBO)
+ if (tess.useInternalVao)
{
RB_DeformTessGeometry();
}
vertexAttribs = RB_CalcShaderVertexAttribs( input );
- if (tess.useInternalVBO)
+ if (tess.useInternalVao)
{
- RB_UpdateTessVbo(vertexAttribs);
+ RB_UpdateTessVao(vertexAttribs);
}
else
{
- backEnd.pc.c_staticVboDraws++;
+ backEnd.pc.c_staticVaoDraws++;
}
//
@@ -1544,7 +1544,10 @@ void RB_StageIteratorGeneric( void )
//
// 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
diff --git a/src/renderergl2/tr_shade_calc.c b/src/renderergl2/tr_shade_calc.c
index b6a3e205..98ba62ad 100644
--- a/src/renderergl2/tr_shade_calc.c
+++ b/src/renderergl2/tr_shade_calc.c
@@ -126,7 +126,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
{
- R_VboUnpackNormal(offset, *normal);
+ R_VaoUnpackNormal(offset, *normal);
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
@@ -146,7 +146,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
ds->deformationWave.phase + off,
ds->deformationWave.frequency );
- R_VboUnpackNormal(offset, *normal);
+ R_VaoUnpackNormal(offset, *normal);
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
@@ -171,7 +171,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
vec3_t fNormal;
- R_VboUnpackNormal(fNormal, *normal);
+ R_VaoUnpackNormal(fNormal, *normal);
scale = 0.98f;
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
@@ -190,7 +190,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
VectorNormalizeFast( fNormal );
- *normal = R_VboPackNormal(fNormal);
+ *normal = R_VaoPackNormal(fNormal);
}
}
@@ -214,7 +214,7 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
float scale;
vec3_t fNormal;
- R_VboUnpackNormal(fNormal, *normal);
+ R_VaoUnpackNormal(fNormal, *normal);
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
@@ -278,7 +278,7 @@ void DeformText( const char *text ) {
height[1] = 0;
height[2] = -1;
- R_VboUnpackNormal(fNormal, tess.normal[0]);
+ R_VaoUnpackNormal(fNormal, tess.normal[0]);
CrossProduct( fNormal, height, width );
// find the midpoint of the box
diff --git a/src/renderergl2/tr_sky.c b/src/renderergl2/tr_sky.c
index 5a90f460..2a180da5 100644
--- a/src/renderergl2/tr_sky.c
+++ b/src/renderergl2/tr_sky.c
@@ -422,7 +422,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
tess.maxIndex = tess.numVertexes;
// 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;
@@ -467,7 +467,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
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)));
diff --git a/src/renderergl2/tr_surface.c b/src/renderergl2/tr_surface.c
index c1cd2b8f..1e4ab811 100644
--- a/src/renderergl2/tr_surface.c
+++ b/src/renderergl2/tr_surface.c
@@ -67,19 +67,18 @@ void RB_CheckOverflow( int verts, int indexes ) {
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_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex);
- R_BindVBO(vbo);
- R_BindIBO(ibo);
+ R_BindVao(vao);
}
- if (vbo != tess.vbo && ibo != tess.ibo)
- tess.useInternalVBO = qfalse;
+ if (vao != tess.vao)
+ tess.useInternalVao = qfalse;
}
@@ -128,7 +127,7 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4],
tess.normal[ndx] =
tess.normal[ndx+1] =
tess.normal[ndx+2] =
- tess.normal[ndx+3] = R_VboPackNormal(normal);
+ tess.normal[ndx+3] = R_VaoPackNormal(normal);
// standard square texture coordinates
VectorSet2(tess.texCoords[ndx ][0], s1, t1);
@@ -204,11 +203,11 @@ void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4])
tess.minIndex = 0;
tess.maxIndex = 3;
- RB_UpdateTessVbo(ATTR_POSITION | ATTR_TEXCOORD);
+ RB_UpdateTessVao(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.numVertexes = 0;
@@ -326,7 +325,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
glIndex_t *outIndex;
float *color;
- RB_CheckVBOandIBO(tess.vbo, tess.ibo);
+ RB_CheckVao(tess.vao);
RB_CHECKOVERFLOW( numVerts, numIndexes );
@@ -350,7 +349,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts;
normal = &tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
- *normal = R_VboPackNormal(dv->normal);
+ *normal = R_VaoPackNormal(dv->normal);
}
#ifdef USE_VERT_TANGENT_SPACE
@@ -359,7 +358,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts;
tangent = &tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
- *tangent = R_VboPackTangent(dv->tangent);
+ *tangent = R_VaoPackTangent(dv->tangent);
}
#endif
@@ -392,7 +391,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
dv = verts;
lightdir = &tess.lightdir[ tess.numVertexes ];
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
@@ -407,12 +406,12 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
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;
GLvoid *firstIndexOffset, *lastIndexOffset;
- if (!vbo || !ibo)
+ if (!vao)
{
return qfalse;
}
@@ -422,7 +421,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
return qfalse;
}
- RB_CheckVBOandIBO(vbo, ibo);
+ RB_CheckVao(vao);
tess.dlightBits |= dlightBits;
tess.pshadowBits |= pshadowBits;
@@ -516,7 +515,7 @@ RB_SurfaceTriangles
=============
*/
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 ) )
{
return;
@@ -602,7 +601,7 @@ static void RB_SurfaceBeam( void )
tess.maxIndex = tess.numVertexes;
// 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_BindProgram(sp);
@@ -611,7 +610,7 @@ static void RB_SurfaceBeam( void )
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.numVertexes = 0;
@@ -1151,7 +1150,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
VectorCopy(newVerts->xyz, outXyz);
VectorCopy(newVerts->normal, normal);
- *outNormal = R_VboPackNormal(normal);
+ *outNormal = R_VaoPackNormal(normal);
newVerts++;
outXyz += 4;
@@ -1176,7 +1175,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
VectorNormalize(normal);
- *outNormal = R_VboPackNormal(normal);
+ *outNormal = R_VaoPackNormal(normal);
newVerts++;
oldVerts++;
@@ -1251,7 +1250,7 @@ RB_SurfaceFace
==============
*/
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 ) )
{
return;
@@ -1321,7 +1320,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int pshadowBits;
//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 ) )
{
return;
@@ -1414,13 +1413,13 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{
- *normal++ = R_VboPackNormal(dv->normal);
+ *normal++ = R_VaoPackNormal(dv->normal);
}
#ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{
- *tangent++ = R_VboPackTangent(dv->tangent);
+ *tangent++ = R_VaoPackTangent(dv->tangent);
}
#endif
if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
@@ -1443,7 +1442,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{
- *lightdir++ = R_VboPackNormal(dv->lightdir);
+ *lightdir++ = R_VaoPackNormal(dv->lightdir);
}
//*vDlightBits++ = dlightBits;
@@ -1568,31 +1567,30 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
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 );
}
-void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
+void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
{
//mdvModel_t *mdvModel;
//mdvSurface_t *mdvSurface;
refEntity_t *refEnt;
- GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n");
+ GLimp_LogComment("--- RB_SurfaceVaoMdvMesh ---\n");
- if(!surface->vbo || !surface->ibo)
+ if(!surface->vao)
return;
- //RB_CheckVBOandIBO(surface->vbo, surface->ibo);
+ //RB_CheckVao(surface->vao);
RB_EndSurface();
RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex);
- R_BindVBO(surface->vbo);
- R_BindIBO(surface->ibo);
+ R_BindVao(surface->vao);
- tess.useInternalVBO = qfalse;
+ tess.useInternalVao = qfalse;
tess.numIndexes += surface->numIndexes;
tess.numVertexes += surface->numVerts;
@@ -1646,6 +1644,6 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST
- (void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH,
- (void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH
+ (void(*)(void*))RB_SurfaceVaoMesh, // SF_VAO_MESH,
+ (void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH
};
diff --git a/src/renderergl2/tr_vbo.c b/src/renderergl2/tr_vbo.c
index cb140921..31659f96 100644
--- a/src/renderergl2/tr_vbo.c
+++ b/src/renderergl2/tr_vbo.c
@@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#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)
{
@@ -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)
{
@@ -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)
{
@@ -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)
{
@@ -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;
switch (usage)
{
- case VBO_USAGE_STATIC:
+ case VAO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB;
break;
- case VBO_USAGE_DYNAMIC:
+ case VAO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB;
break;
default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
+ Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage);
return NULL;
}
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 ) {
- ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit");
+ if ( tr.numVaos == MAX_VAOS ) {
+ ri.Error( ERR_DROP, "R_CreateVao: MAX_VAOS hit");
}
R_IssuePendingRenderCommands();
- vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
- tr.numVBOs++;
+ vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
+ tr.numVaos++;
+
+ memset(vao, 0, sizeof(*vao));
+
+ Q_strncpyz(vao->name, name, sizeof(vao->name));
- memset(vbo, 0, sizeof(*vbo));
- Q_strncpyz(vbo->name, name, sizeof(vbo->name));
+ if (glRefConfig.vertexArrayObject)
+ {
+ qglGenVertexArraysARB(1, &vao->vao);
+ qglBindVertexArrayARB(vao->vao);
+ }
+
- vbo->vertexesSize = vertexesSize;
+ vao->vertexesSize = vertexesSize;
- 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, 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();
- 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;
byte *data;
@@ -166,79 +206,87 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
int glUsage = GL_STATIC_DRAW_ARB;
- if(!numVertexes)
+ if(!numVertexes || !numIndexes)
return NULL;
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 ) {
- ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit");
+ if ( tr.numVaos == MAX_VAOS ) {
+ ri.Error( ERR_DROP, "R_CreateVao2: MAX_VAOS hit");
}
R_IssuePendingRenderCommands();
- vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
- tr.numVBOs++;
+ vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
+ 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
- vbo->attribs[ATTR_INDEX_POSITION ].enabled = 1;
- vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
+ vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
+ vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE
- vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
+ vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
#endif
- vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
- vbo->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
- vbo->attribs[ATTR_INDEX_COLOR ].enabled = 1;
- vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
-
- vbo->attribs[ATTR_INDEX_POSITION ].count = 3;
- vbo->attribs[ATTR_INDEX_NORMAL ].count = 4;
- vbo->attribs[ATTR_INDEX_TANGENT ].count = 4;
- vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
- vbo->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
- vbo->attribs[ATTR_INDEX_COLOR ].count = 4;
- vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
-
- vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
- vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
- vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
- vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
- vbo->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
- vbo->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
- vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
-
- vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
- vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
- vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
- vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
- vbo->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
- vbo->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
- vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
-
- vbo->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_TEXCOORD ].enabled = 1;
+ vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
+ vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
+ vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
+
+ vao->attribs[ATTR_INDEX_POSITION ].count = 3;
+ vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
+ vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
+ vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
+ vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
+ vao->attribs[ATTR_INDEX_COLOR ].count = 4;
+ vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
+
+ vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
+ vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
+ vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
+ vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
+ vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
+ vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
+ vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
+
+ vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
+ vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
+ vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
+ vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
+ vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
+ vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
+ vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
+
+ vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz);
+ vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t);
#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
- vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += sizeof(verts[0].st);
- vbo->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
- vbo->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors);
- vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t);
-
- 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;
+ vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += sizeof(verts[0].st);
+ vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
+ vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors);
+ 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);
+ }
+
// create VBO
dataSize *= numVertexes;
@@ -255,13 +303,13 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// normal
p = (uint32_t *)(data + dataOfs);
- *p = R_VboPackNormal(verts[i].normal);
+ *p = R_VaoPackNormal(verts[i].normal);
dataOfs += sizeof(uint32_t);
#ifdef USE_VERT_TANGENT_SPACE
// tangent
p = (uint32_t *)(data + dataOfs);
- *p = R_VboPackTangent(verts[i].tangent);
+ *p = R_VaoPackTangent(verts[i].tangent);
dataOfs += sizeof(uint32_t);
#endif
@@ -279,334 +327,205 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// feed vertex light directions
p = (uint32_t *)(data + dataOfs);
- *p = R_VboPackNormal(verts[i].lightdir);
+ *p = R_VaoPackNormal(verts[i].lightdir);
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);
- qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage);
+ qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
+ 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);
- GL_CheckErrors();
+ qglGenBuffersARB(1, &vao->indexesIBO);
- ri.Hunk_FreeTempMemory(data);
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
+ qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesSize, indexes, glUsage);
- return vbo;
-}
+ Vao_SetVertexPointers(vao);
-/*
-============
-R_CreateIBO
-============
-*/
-IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage)
-{
- IBO_t *ibo;
- int glUsage;
- switch (usage)
- {
- case VBO_USAGE_STATIC:
- glUsage = GL_STATIC_DRAW_ARB;
- break;
-
- case VBO_USAGE_DYNAMIC:
- glUsage = GL_DYNAMIC_DRAW_ARB;
- break;
-
- default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
- return NULL;
- }
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name);
- }
-
- if ( tr.numIBOs == MAX_IBOS ) {
- ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit");
- }
-
- R_IssuePendingRenderCommands();
-
- ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
- tr.numIBOs++;
-
- Q_strncpyz(ibo->name, name, sizeof(ibo->name));
-
- ibo->indexesSize = indexesSize;
-
- qglGenBuffersARB(1, &ibo->indexesVBO);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
- qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-
- glState.currentIBO = NULL;
+ glState.currentVao = vao;
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);
+ ri.Hunk_FreeTempMemory(data);
- return ibo;
+ return vao;
}
+
/*
============
-R_BindVBO
+R_BindVao
============
*/
-void R_BindVBO(VBO_t * vbo)
+void R_BindVao(vao_t * vao)
{
- if(!vbo)
+ if(!vao)
{
- //R_BindNullVBO();
- ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo");
+ //R_BindNullVao();
+ ri.Error(ERR_DROP, "R_BindVao: NULL vao");
return;
}
if(r_logFile->integer)
{
// don't just call LogComment, or we will get a call to va() every frame!
- GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name));
+ GLimp_LogComment(va("--- R_BindVao( %s ) ---\n", vao->name));
}
- if(glState.currentVBO != vbo)
+ if(glState.currentVao != vao)
{
- glState.currentVBO = vbo;
- glState.vertexAttribPointersSet = 0;
+ glState.currentVao = vao;
glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0;
glState.vertexAnimation = qfalse;
+ backEnd.pc.c_vaoBinds++;
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
-
- backEnd.pc.c_vboVertexBuffers++;
- }
-}
+ if (glRefConfig.vertexArrayObject)
+ {
+ qglBindVertexArrayARB(vao->vao);
-/*
-============
-R_BindNullVBO
-============
-*/
-void R_BindNullVBO(void)
-{
- GLimp_LogComment("--- R_BindNullVBO ---\n");
+ // 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(glState.currentVBO)
- {
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- glState.currentVBO = NULL;
+ if (vao != tess.vao)
+ Vao_SetVertexPointers(vao);
+ }
}
-
- GL_CheckErrors();
}
/*
============
-R_BindIBO
+R_BindNullVao
============
*/
-void R_BindIBO(IBO_t * ibo)
+void R_BindNullVao(void)
{
- 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));
- }
+ GLimp_LogComment("--- R_BindNullVao ---\n");
- if(glState.currentIBO != ibo)
+ if(glState.currentVao)
{
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
-
- glState.currentIBO = ibo;
+ if (glRefConfig.vertexArrayObject)
+ {
+ qglBindVertexArrayARB(0);
- backEnd.pc.c_vboIndexBuffers++;
+ // 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;
}
-}
-
-/*
-============
-R_BindNullIBO
-============
-*/
-void R_BindNullIBO(void)
-{
- GLimp_LogComment("--- R_BindNullIBO ---\n");
- if(glState.currentIBO)
- {
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glState.currentIBO = NULL;
- glState.vertexAttribPointersSet = 0;
- }
+ GL_CheckErrors();
}
+
/*
============
-R_InitVBOs
+R_InitVaos
============
*/
-void R_InitVBOs(void)
+void R_InitVaos(void)
{
- int dataSize;
+ int vertexesSize, indexesSize;
int offset;
- ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n");
+ ri.Printf(PRINT_ALL, "------- R_InitVaos -------\n");
- tr.numVBOs = 0;
- tr.numIBOs = 0;
+ tr.numVaos = 0;
- dataSize = sizeof(tess.xyz[0]);
- dataSize += sizeof(tess.normal[0]);
+ vertexesSize = sizeof(tess.xyz[0]);
+ vertexesSize += sizeof(tess.normal[0]);
#ifdef USE_VERT_TANGENT_SPACE
- dataSize += sizeof(tess.tangent[0]);
+ vertexesSize += sizeof(tess.tangent[0]);
#endif
- dataSize += sizeof(tess.vertexColors[0]);
- dataSize += sizeof(tess.texCoords[0][0]) * 2;
- dataSize += sizeof(tess.lightdir[0]);
- dataSize *= SHADER_MAX_VERTEXES;
+ vertexesSize += sizeof(tess.vertexColors[0]);
+ vertexesSize += sizeof(tess.texCoords[0][0]) * 2;
+ vertexesSize += sizeof(tess.lightdir[0]);
+ 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;
- tess.vbo->attribs[ATTR_INDEX_POSITION ].enabled = 1;
- tess.vbo->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE
- tess.vbo->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
#endif
- tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
- tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
- tess.vbo->attribs[ATTR_INDEX_COLOR ].enabled = 1;
- tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
-
- tess.vbo->attribs[ATTR_INDEX_POSITION ].count = 3;
- tess.vbo->attribs[ATTR_INDEX_NORMAL ].count = 4;
- tess.vbo->attribs[ATTR_INDEX_TANGENT ].count = 4;
- tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
- tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
- tess.vbo->attribs[ATTR_INDEX_COLOR ].count = 4;
- tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
-
- tess.vbo->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
- tess.vbo->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
- tess.vbo->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
- tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
- tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
- tess.vbo->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
- tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
-
- tess.vbo->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
- tess.vbo->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
- tess.vbo->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
- tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
- tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
- tess.vbo->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
- tess.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
-
- tess.vbo->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_TEXCOORD ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
+
+ tess.vao->attribs[ATTR_INDEX_POSITION ].count = 3;
+ tess.vao->attribs[ATTR_INDEX_NORMAL ].count = 4;
+ tess.vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
+ tess.vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].count = 4;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
+
+ tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
+ tess.vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
+ tess.vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
+ tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
+
+ tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
+ tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
+ tess.vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
+ tess.vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
+
+ tess.vao->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[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
- 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
// these next two are actually interleaved
- tess.vbo->attribs[ATTR_INDEX_TEXCOORD ].offset = offset;
- tess.vbo->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]);
+ tess.vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]);
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.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset;
- tess.vbo->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_POSITION ].stride = sizeof(tess.xyz[0]);
+ tess.vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]);
#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
- tess.vbo->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]);
- tess.vbo->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.vbo->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]);
-
- dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES;
+ tess.vao->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]);
+ tess.vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
+ tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
+ tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]);
tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz;
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_LIGHTDIRECTION] = tess.lightdir;
- tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC);
+ Vao_SetVertexPointers(tess.vao);
- R_BindNullVBO();
- R_BindNullIBO();
+ R_BindNullVao();
GL_CheckErrors();
}
/*
============
-R_ShutdownVBOs
+R_ShutdownVaos
============
*/
-void R_ShutdownVBOs(void)
+void R_ShutdownVaos(void)
{
int i;
- VBO_t *vbo;
- IBO_t *ibo;
+ vao_t *vao;
- ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n");
+ ri.Printf(PRINT_ALL, "------- R_ShutdownVaos -------\n");
- R_BindNullVBO();
- R_BindNullIBO();
+ R_BindNullVao();
-
- for(i = 0; i < tr.numVBOs; i++)
+ for(i = 0; i < tr.numVaos; i++)
{
- vbo = tr.vbos[i];
+ vao = tr.vaos[i];
+
+ if(vao->vao)
+ qglDeleteVertexArraysARB(1, &vao->vao);
- if(vbo->vertexesVBO)
+ if(vao->vertexesVBO)
{
- qglDeleteBuffersARB(1, &vbo->vertexesVBO);
+ qglDeleteBuffersARB(1, &vao->vertexesVBO);
}
- //ri.Free(vbo);
- }
-
- for(i = 0; i < tr.numIBOs; i++)
- {
- ibo = tr.ibos[i];
-
- if(ibo->indexesVBO)
+ if(vao->indexesIBO)
{
- qglDeleteBuffersARB(1, &ibo->indexesVBO);
+ qglDeleteBuffersARB(1, &vao->indexesIBO);
}
-
- //ri.Free(ibo);
}
- tr.numVBOs = 0;
- tr.numIBOs = 0;
+ tr.numVaos = 0;
}
/*
============
-R_VBOList_f
+R_VaoList_f
============
*/
-void R_VBOList_f(void)
+void R_VaoList_f(void)
{
int i;
- VBO_t *vbo;
- IBO_t *ibo;
+ vao_t *vao;
int vertexesSize = 0;
int indexesSize = 0;
ri.Printf(PRINT_ALL, " size name\n");
ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
- for(i = 0; i < tr.numVBOs; i++)
+ 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),
- (vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name);
+ ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->vertexesSize / (1024 * 1024),
+ (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),
- (ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name);
+ ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->indexesSize / (1024 * 1024),
+ (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),
(vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
-
- ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs);
ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024),
(indexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
}
@@ -718,28 +623,35 @@ void R_VBOList_f(void)
/*
==============
-RB_UpdateTessVbo
+RB_UpdateTessVao
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
- if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES)
+ // update the default VAO
+ if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES && tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
{
int attribIndex;
- R_BindVBO(tess.vbo);
+ R_BindVao(tess.vao);
- // orphan old buffer so we don't stall on it
- qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
+ // these may not be bound if we're using VAOs
+ 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(!(attribBits & ATTR_BITS))
@@ -757,21 +669,15 @@ void RB_UpdateTessVbo(unsigned int attribBits)
{
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]);
}
}
- }
-
- // update the default IBO
- if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
- {
- 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);
+ // orphan old index buffer so we don't stall on it
+ qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
}
diff --git a/src/renderergl2/tr_world.c b/src/renderergl2/tr_world.c
index 9547c2e4..85f252dc 100644
--- a/src/renderergl2/tr_world.c
+++ b/src/renderergl2/tr_world.c
@@ -214,7 +214,7 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
- case SF_VBO_MESH:
+ case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
break;
@@ -300,7 +300,7 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
- case SF_VBO_MESH:
+ case SF_VAO_MESH:
((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
break;