From b25a3c6e4d1af0767559a030cbd12e5f942e08a7 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Wed, 5 Jun 2024 21:34:36 -0500 Subject: [PATCH] OpenGL2: Add run-time support for unsigned short indexes OpenGL ES 2 is only required to support unsigned short for indexes. --- code/renderergl2/tr_extensions.c | 24 ++++++++++++ code/renderergl2/tr_local.h | 10 ++++- code/renderergl2/tr_shade.c | 11 +++++- code/renderergl2/tr_vbo.c | 67 ++++++++++++++++++++++---------- 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/code/renderergl2/tr_extensions.c b/code/renderergl2/tr_extensions.c index f0ea7d0a..8603794b 100644 --- a/code/renderergl2/tr_extensions.c +++ b/code/renderergl2/tr_extensions.c @@ -45,6 +45,17 @@ void GLimp_InitExtraExtensions(void) if (strstr((char *)qglGetString(GL_RENDERER), "Intel")) glRefConfig.intelGraphics = qtrue; + if (qglesMajorVersion) + { + glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_SHORT; + glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned short); + } + else + { + glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_INT; + glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned int); + } + // set DSA fallbacks #define GLE(ret, name, ...) qgl##name = GLDSA_##name; QGL_EXT_direct_state_access_PROCS; @@ -124,6 +135,19 @@ void GLimp_InitExtraExtensions(void) ri.Printf(PRINT_ALL, result[2], extension); } + // GL_OES_element_index_uint + extension = "GL_OES_element_index_uint"; + if (SDL_GL_ExtensionSupported(extension)) + { + glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_INT; + glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned int); + ri.Printf(PRINT_ALL, result[1], extension); + } + else + { + ri.Printf(PRINT_ALL, result[2], extension); + } + goto done; } diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index bdc6e477..eab069e1 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -49,8 +49,10 @@ QGL_ARB_vertex_array_object_PROCS; QGL_EXT_direct_state_access_PROCS; #undef GLE -#define GL_INDEX_TYPE GL_UNSIGNED_INT -typedef unsigned int glIndex_t; +#define GL_INDEX_TYPE GL_UNSIGNED_SHORT +typedef unsigned short glIndex_t; + +typedef unsigned int vaoCacheGlIndex_t; #define BUFFER_OFFSET(i) ((char *)NULL + (i)) @@ -1431,6 +1433,9 @@ typedef struct { qboolean vertexArrayObject; qboolean directStateAccess; + GLenum vaoCacheGlIndexType; // GL_UNSIGNED_INT or GL_UNSIGNED_SHORT + size_t vaoCacheGlIndexSize; // must be <= sizeof( vaoCacheGlIndex_t ) + // OpenGL ES extensions qboolean readDepth; qboolean readStencil; @@ -2220,6 +2225,7 @@ void R_VaoList_f(void); void RB_UpdateTessVao(unsigned int attribBits); void VaoCache_Commit(void); +void VaoCache_DrawElements(int numIndexes, int firstIndex); void VaoCache_Init(void); void VaoCache_BindVao(void); void VaoCache_CheckAdd(qboolean *endSurface, qboolean *recycleVertexBuffer, qboolean *recycleIndexBuffer, int numVerts, int numIndexes); diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 21f9543a..dec35e52 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -40,7 +40,14 @@ R_DrawElements void R_DrawElements( int numIndexes, int firstIndex ) { - qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t))); + if (tess.useCacheVao) + { + VaoCache_DrawElements(numIndexes, firstIndex); + } + else + { + qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t))); + } } @@ -1720,6 +1727,8 @@ void RB_EndSurface( void ) { tess.numIndexes = 0; tess.numVertexes = 0; tess.firstIndex = 0; + tess.useCacheVao = qfalse; + tess.useInternalVao = qfalse; GLimp_LogComment( "----------\n" ); } diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c index df64f8bc..5094df18 100644 --- a/code/renderergl2/tr_vbo.c +++ b/code/renderergl2/tr_vbo.c @@ -676,7 +676,7 @@ static struct srfVert_t vertexes[VAOCACHE_QUEUE_MAX_VERTEXES]; int vertexCommitSize; - glIndex_t indexes[VAOCACHE_QUEUE_MAX_INDEXES]; + vaoCacheGlIndex_t indexes[VAOCACHE_QUEUE_MAX_INDEXES]; int indexCommitSize; } vcq; @@ -687,18 +687,13 @@ vcq; // srfVert_t is 60 bytes // assuming each vert is referenced 4 times, need 16 bytes (4 glIndex_t) per vert // -> need about 4/15ths the space for indexes as vertexes -#if GL_INDEX_TYPE == GL_UNSIGNED_SHORT -#define VAOCACHE_VERTEX_BUFFER_SIZE (sizeof(srfVert_t) * USHRT_MAX) -#define VAOCACHE_INDEX_BUFFER_SIZE (sizeof(glIndex_t) * USHRT_MAX * 4) -#else // GL_UNSIGNED_INT #define VAOCACHE_VERTEX_BUFFER_SIZE (16 * 1024 * 1024) #define VAOCACHE_INDEX_BUFFER_SIZE (5 * 1024 * 1024) -#endif typedef struct buffered_s { - void *data; - int size; + glIndex_t *indexes; + int numIndexes; int bufferOffset; } buffered_t; @@ -736,7 +731,7 @@ void VaoCache_Commit(void) buffered_t *indexSet2 = indexSet; for (surf = vcq.surfaces; surf < end; surf++, indexSet2++) { - if (surf->indexes != indexSet2->data || (surf->numIndexes * sizeof(glIndex_t)) != indexSet2->size) + if (surf->indexes != indexSet2->indexes || surf->numIndexes != indexSet2->numIndexes) break; } @@ -750,7 +745,7 @@ void VaoCache_Commit(void) // If found, use it if (indexSet < vc.surfaceIndexSets + vc.numSurfaces) { - tess.firstIndex = indexSet->bufferOffset / sizeof(glIndex_t); + tess.firstIndex = indexSet->bufferOffset / glRefConfig.vaoCacheGlIndexSize; //ri.Printf(PRINT_ALL, "firstIndex %d numIndexes %d as %d\n", tess.firstIndex, tess.numIndexes, (int)(batchLength - vc.batchLengths)); //ri.Printf(PRINT_ALL, "vc.numSurfaces %d vc.numBatches %d\n", vc.numSurfaces, vc.numBatches); } @@ -759,20 +754,21 @@ void VaoCache_Commit(void) else { srfVert_t *dstVertex = vcq.vertexes; - glIndex_t *dstIndex = vcq.indexes; + vaoCacheGlIndex_t *dstIndex = vcq.indexes; + unsigned short *dstIndexUshort = (unsigned short *)vcq.indexes; batchLength = vc.batchLengths + vc.numBatches; *batchLength = vcq.numSurfaces; vc.numBatches++; - tess.firstIndex = vc.indexOffset / sizeof(glIndex_t); + tess.firstIndex = vc.indexOffset / glRefConfig.vaoCacheGlIndexSize; vcq.vertexCommitSize = 0; vcq.indexCommitSize = 0; for (surf = vcq.surfaces; surf < end; surf++) { glIndex_t *srcIndex = surf->indexes; int vertexesSize = surf->numVerts * sizeof(srfVert_t); - int indexesSize = surf->numIndexes * sizeof(glIndex_t); + int indexesSize = surf->numIndexes * glRefConfig.vaoCacheGlIndexSize; int i, indexOffset = (vc.vertexOffset + vcq.vertexCommitSize) / sizeof(srfVert_t); Com_Memcpy(dstVertex, surf->vertexes, vertexesSize); @@ -781,13 +777,21 @@ void VaoCache_Commit(void) vcq.vertexCommitSize += vertexesSize; indexSet = vc.surfaceIndexSets + vc.numSurfaces; - indexSet->data = surf->indexes; - indexSet->size = indexesSize; + indexSet->indexes = surf->indexes; + indexSet->numIndexes = surf->numIndexes; indexSet->bufferOffset = vc.indexOffset + vcq.indexCommitSize; vc.numSurfaces++; - for (i = 0; i < surf->numIndexes; i++) - *dstIndex++ = *srcIndex++ + indexOffset; + if (glRefConfig.vaoCacheGlIndexType == GL_UNSIGNED_SHORT) + { + for (i = 0; i < surf->numIndexes; i++) + *dstIndexUshort++ = *srcIndex++ + indexOffset; + } + else + { + for (i = 0; i < surf->numIndexes; i++) + *dstIndex++ = *srcIndex++ + indexOffset; + } vcq.indexCommitSize += indexesSize; } @@ -810,9 +814,30 @@ void VaoCache_Commit(void) } } +void VaoCache_DrawElements(int numIndexes, int firstIndex) +{ + assert( glState.currentVao == vc.vao ); + + qglDrawElements(GL_TRIANGLES, numIndexes, glRefConfig.vaoCacheGlIndexType, BUFFER_OFFSET(firstIndex * glRefConfig.vaoCacheGlIndexSize)); +} + void VaoCache_Init(void) { - vc.vao = R_CreateVao("VaoCache", NULL, VAOCACHE_VERTEX_BUFFER_SIZE, NULL, VAOCACHE_INDEX_BUFFER_SIZE, VAO_USAGE_DYNAMIC); + int vertexBufferSize; + int indexBufferSize; + + if (glRefConfig.vaoCacheGlIndexType == GL_UNSIGNED_SHORT) + { + vertexBufferSize = sizeof(srfVert_t) * USHRT_MAX; + indexBufferSize = sizeof(unsigned short) * USHRT_MAX * 4; + } + else + { + vertexBufferSize = VAOCACHE_VERTEX_BUFFER_SIZE; + indexBufferSize = VAOCACHE_INDEX_BUFFER_SIZE; + } + + vc.vao = R_CreateVao("VaoCache", NULL, vertexBufferSize, NULL, indexBufferSize, VAO_USAGE_DYNAMIC); vc.vao->attribs[ATTR_INDEX_POSITION].enabled = 1; vc.vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1; @@ -881,7 +906,7 @@ void VaoCache_BindVao(void) void VaoCache_CheckAdd(qboolean *endSurface, qboolean *recycleVertexBuffer, qboolean *recycleIndexBuffer, int numVerts, int numIndexes) { int vertexesSize = sizeof(srfVert_t) * numVerts; - int indexesSize = sizeof(glIndex_t) * numIndexes; + int indexesSize = glRefConfig.vaoCacheGlIndexSize * numIndexes; if (vc.vao->vertexesSize < vc.vertexOffset + vcq.vertexCommitSize + vertexesSize) { @@ -924,7 +949,7 @@ void VaoCache_CheckAdd(qboolean *endSurface, qboolean *recycleVertexBuffer, qboo *endSurface = qtrue; } - if (VAOCACHE_QUEUE_MAX_INDEXES * sizeof(glIndex_t) < vcq.indexCommitSize + indexesSize) + if (VAOCACHE_QUEUE_MAX_INDEXES * glRefConfig.vaoCacheGlIndexSize < vcq.indexCommitSize + indexesSize) { //ri.Printf(PRINT_ALL, "out of queued indexes\n"); *endSurface = qtrue; @@ -964,5 +989,5 @@ void VaoCache_AddSurface(srfVert_t *verts, int numVerts, glIndex_t *indexes, int vcq.numSurfaces++; vcq.vertexCommitSize += sizeof(srfVert_t) * numVerts; - vcq.indexCommitSize += sizeof(glIndex_t) * numIndexes; + vcq.indexCommitSize += glRefConfig.vaoCacheGlIndexSize * numIndexes; }