diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index fd50734e..757bab38 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -1485,62 +1485,6 @@ void GLSL_BindNullProgram(void) } -void GLSL_VertexAttribPointers(uint32_t attribBits) -{ - int newFrame, oldFrame; - vao_t *vao = glState.currentVao; - int attribIndex; - uint32_t extraOffsets[ATTR_INDEX_COUNT]; - - if(!vao) - { - 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", vao->name)); - } - - for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) - extraOffsets[attribIndex] = 0; - - // position/normal/tangent are always set in case of animation - oldFrame = glState.vertexAttribsOldFrame; - newFrame = glState.vertexAttribsNewFrame; - if (glState.vertexAnimation) - { - extraOffsets[ATTR_INDEX_POSITION] = newFrame * vao->frameSize; - extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vao->frameSize; - extraOffsets[ATTR_INDEX_NORMAL] = newFrame * vao->frameSize; - extraOffsets[ATTR_INDEX_NORMAL2] = oldFrame * vao->frameSize; - extraOffsets[ATTR_INDEX_TANGENT] = newFrame * vao->frameSize; - extraOffsets[ATTR_INDEX_TANGENT2] = oldFrame * vao->frameSize; - } - - // 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++) - { - uint32_t attribBit = 1 << attribIndex; - vaoAttrib_t *vAtb; - - if (!(attribBits & attribBit)) - continue; - - vAtb = &vao->attribs[attribIndex]; - - qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + extraOffsets[attribIndex])); - } -} - - shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) { shaderStage_t *pStage = tess.xstages[stage]; diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index fba08e82..eb185305 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -949,9 +949,13 @@ void GL_SetDefaultState( void ) glState.currentProgram = 0; qglUseProgramObjectARB(0); + if (glRefConfig.vertexArrayObject) + qglBindVertexArrayARB(0); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glState.currentVao = NULL; + glState.vertexAttribsEnabled = 0; qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index e64b9e83..25517272 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1364,10 +1364,9 @@ typedef struct { int faceCullFront; uint32_t glStateBits; uint32_t storedGlState; - uint32_t vertexAttribsNewFrame; - uint32_t vertexAttribsOldFrame; float vertexAttribsInterpolation; qboolean vertexAnimation; + uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise shaderProgram_t *currentProgram; FBO_t *currentFBO; vao_t *currentVao; diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c index e167040d..fc201769 100644 --- a/code/renderergl2/tr_model.c +++ b/code/renderergl2/tr_model.c @@ -711,8 +711,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, { st = surf->st; for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { - memcpy(data + dataOfs, &st->st, sizeof(st->st)); - dataOfs += sizeof(st->st); + memcpy(data + dataOfs, &st->st, sizeof(vec2_t)); + dataOfs += sizeof(vec2_t); } v = surf->verts; @@ -725,8 +725,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, uint32_t *p; // xyz - memcpy(data + dataOfs, &v->xyz, sizeof(v->xyz)); - dataOfs += sizeof(v->xyz); + memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t)); + dataOfs += sizeof(vec3_t); // normal p = (uint32_t *)(data + dataOfs); @@ -758,11 +758,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, uint32_t *p; // xyz - memcpy(data + dataOfs, &v->xyz, sizeof(v->xyz)); + memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t)); dataOfs += sizeof(v->xyz); // st - memcpy(data + dataOfs, &st->st, sizeof(st->st)); + memcpy(data + dataOfs, &st->st, sizeof(vec2_t)); dataOfs += sizeof(st->st); // normal @@ -790,61 +790,50 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, vaoSurf->numVerts = surf->numVerts; vaoSurf->minIndex = 0; - vaoSurf->maxIndex = surf->numVerts; + vaoSurf->maxIndex = surf->numVerts - 1; vaoSurf->vao = R_CreateVao(va("staticMD3Mesh_VAO '%s'", surf->name), data, dataSize, (byte *)surf->indexes, surf->numIndexes * sizeof(*surf->indexes), VAO_USAGE_STATIC); - 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; + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].enabled = 1; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1; #ifdef USE_VERT_TANGENT_SPACE - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].enabled = 1; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; #endif - 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].count = 3; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].count = 2; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].count = 4; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4; - 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].type = GL_FLOAT; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = GL_FLOAT; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; - 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].normalized = GL_FALSE; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; - vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].offset = offset_xyz; - vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].offset = offset_xyz; - vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset_st; - vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].offset = offset_normal; - vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].offset = offset_normal; - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = offset_tangent; - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].offset = offset_tangent; + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].offset = offset_xyz; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].offset = offset_st; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].offset = offset_normal; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = offset_tangent; - vaoSurf->vao->attribs[ATTR_INDEX_POSITION ].stride = stride_xyz; - vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].stride = stride_xyz; - vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD ].stride = stride_st; - vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].stride = stride_normal; - vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ].stride = stride_normal; - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = stride_tangent; - vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ].stride = stride_tangent; + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].stride = stride_xyz; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].stride = stride_st; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].stride = stride_normal; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = stride_tangent; - vaoSurf->vao->frameSize = stride_xyz * surf->numVerts; + if (mdvModel->numFrames > 1) + { + vaoSurf->vao->attribs[ATTR_INDEX_POSITION2] = vaoSurf->vao->attribs[ATTR_INDEX_POSITION]; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ] = vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ]; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ] = vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ]; + + vaoSurf->vao->frameSize = stride_xyz * surf->numVerts; + } Vao_SetVertexPointers(vaoSurf->vao); diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 3f085a80..f70017e4 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -1538,12 +1538,6 @@ void RB_StageIteratorGeneric( void ) qglEnable( GL_POLYGON_OFFSET_FILL ); } - // - // Set vertex attribs and pointers - // - 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/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index 44ecacfd..d4617ec4 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -1589,8 +1589,8 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface) tess.useInternalVao = qfalse; - tess.numIndexes += surface->numIndexes; - tess.numVertexes += surface->numVerts; + tess.numIndexes = surface->numIndexes; + tess.numVertexes = surface->numVerts; tess.minIndex = surface->minIndex; tess.maxIndex = surface->maxIndex; @@ -1599,20 +1599,57 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface) refEnt = &backEnd.currentEntity->e; - if(refEnt->oldframe == refEnt->frame) - { - glState.vertexAttribsInterpolation = 0; - } - else - { - glState.vertexAttribsInterpolation = refEnt->backlerp; - } + glState.vertexAttribsInterpolation = (refEnt->oldframe == refEnt->frame) ? 0.0f : refEnt->backlerp; - glState.vertexAttribsOldFrame = refEnt->oldframe; - glState.vertexAttribsNewFrame = refEnt->frame; if (surface->mdvModel->numFrames > 1) + { + int frameOffset, attribIndex; + vaoAttrib_t *vAtb; + glState.vertexAnimation = qtrue; + if (glRefConfig.vertexArrayObject) + { + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, surface->vao->vertexesVBO); + } + + frameOffset = refEnt->frame * surface->vao->frameSize; + + attribIndex = ATTR_INDEX_POSITION; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_NORMAL; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_TANGENT; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + frameOffset = refEnt->oldframe * surface->vao->frameSize; + + attribIndex = ATTR_INDEX_POSITION2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_NORMAL2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_TANGENT2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + + if (!glRefConfig.vertexArrayObject) + { + attribIndex = ATTR_INDEX_TEXCOORD; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + } + } + RB_EndSurface(); // So we don't lerp surfaces that shouldn't be lerped diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c index 5c44b0e0..9734c5a7 100644 --- a/code/renderergl2/tr_vbo.c +++ b/code/renderergl2/tr_vbo.c @@ -94,24 +94,32 @@ void R_VaoUnpackNormal(vec3_t v, uint32_t b) void Vao_SetVertexPointers(vao_t *vao) { - int i; + int attribIndex; // set vertex pointers - for (i = 0; i < ATTR_INDEX_COUNT; i++) + for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) { - if (vao->attribs[i].enabled) + uint32_t attribBit = 1 << attribIndex; + vaoAttrib_t *vAtb = &vao->attribs[attribIndex]; + + if (vAtb->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); + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + if (glRefConfig.vertexArrayObject || !(glState.vertexAttribsEnabled & attribBit)) + qglEnableVertexAttribArrayARB(attribIndex); + + if (!glRefConfig.vertexArrayObject || vao == tess.vao) + glState.vertexAttribsEnabled |= attribBit; } else { - qglDisableVertexAttribArrayARB(i); + // don't disable vertex attribs when using vertex array objects + // Vao_SetVertexPointers is only called during init when using VAOs, and vertex attribs start disabled anyway + if (!glRefConfig.vertexArrayObject && (glState.vertexAttribsEnabled & attribBit)) + qglDisableVertexAttribArrayARB(attribIndex); + + if (!glRefConfig.vertexArrayObject || vao == tess.vao) + glState.vertexAttribsEnabled &= ~attribBit; } } } @@ -386,8 +394,6 @@ void R_BindVao(vao_t * vao) glState.currentVao = vao; glState.vertexAttribsInterpolation = 0; - glState.vertexAttribsOldFrame = 0; - glState.vertexAttribsNewFrame = 0; glState.vertexAnimation = qfalse; backEnd.pc.c_vaoBinds++; @@ -398,13 +404,19 @@ void R_BindVao(vao_t * vao) // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel? if (1) qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); + + // tess VAO always has buffers bound + if (vao == tess.vao) + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); } else { qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO); - Vao_SetVertexPointers(vao); + // tess VAO doesn't have vertex pointers set until data is uploaded + if (vao != tess.vao) + Vao_SetVertexPointers(vao); } } } @@ -642,13 +654,6 @@ void RB_UpdateTessVao(unsigned int attribBits) R_BindVao(tess.vao); - // 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); @@ -666,12 +671,31 @@ void RB_UpdateTessVao(unsigned int attribBits) for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) { - if (attribBits & (1 << attribIndex)) + uint32_t attribBit = 1 << attribIndex; + + if (attribBits & attribBit) { vaoAttrib_t *vAtb = &tess.vao->attribs[attribIndex]; // note: tess has a VBO where stride == size qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]); + + if (!glRefConfig.vertexArrayObject) + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + + if (!(glState.vertexAttribsEnabled & attribBit)) + { + qglEnableVertexAttribArrayARB(attribIndex); + glState.vertexAttribsEnabled |= attribBit; + } + } + else + { + if ((glState.vertexAttribsEnabled & attribBit)) + { + qglDisableVertexAttribArrayARB(attribIndex); + glState.vertexAttribsEnabled &= ~attribBit; + } } }