CGLMQuery::CGLMQuery( GLMContext *ctx, GLMQueryParams *params ) { // make sure context is current // get the type of query requested // generate name(s) needed // set initial state appropriately ctx->MakeCurrent(); m_ctx = ctx; m_params = *params; m_name = 0; m_started = m_stopped = m_done = false; m_nullQuery = false; // assume value of convar at start time // does not change during individual query lifetime // started null = stays null // started live = stays live switch(m_params.m_type) { case EOcclusion: { //make an occlusion query (and a fence to go with it) glGenQueriesARB( 1, &m_name ); GLMPRINTF(("-A- CGLMQuery(OQ) created name %d", m_name)); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::CGLMQuery (OQ) saw %s error (%d) from glGenQueriesARB", decodedStr, errorcode ); m_name = 0; } } break; case EFence: //make a fence - no aux fence needed glGenFencesAPPLE(1, &m_name ); GLMPRINTF(("-A- CGLMQuery(fence) created name %d", m_name)); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::CGLMQuery (fence) saw %s error (%d) from glGenFencesAPPLE", decodedStr, errorcode ); m_name = 0; } break; } }
CGLMQuery::~CGLMQuery() { GLMPRINTF(("-A-> ~CGLMQuery")); // make sure query has completed (might not be necessary) // delete the name(s) m_ctx->MakeCurrent(); switch(m_params.m_type) { case EOcclusion: { // do a finish occlusion query ? GLMPRINTF(("-A- ~CGLMQuery(OQ) deleting name %d", m_name)); glDeleteQueries(1, &m_name ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::~CGLMQuery (OQ) saw %s error (%d) from glDeleteQueries", decodedStr, errorcode ); } } break; case EFence: { // do a finish fence ? GLMPRINTF(("-A- ~CGLMQuery(fence) deleting name %d", m_name)); glDeleteFencesAPPLE(1, &m_name ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::~CGLMQuery (fence) saw %s error (%d) from glDeleteFencesAPPLE", decodedStr, errorcode ); } } break; } m_name = 0; GLMPRINTF(("-A-< ~CGLMQuery")); }
// glUseProgram() will be called as a side effect! bool CGLMShaderPair::SetProgramPair( CGLMProgram *vp, CGLMProgram *fp ) { m_valid = false; // assume failure // true result means successful link and query bool vpgood = (vp!=NULL) && (vp->m_descs[ kGLMGLSL ].m_valid); bool fpgood = (fp!=NULL) && (fp->m_descs[ kGLMGLSL ].m_valid); if ( !fpgood ) { // fragment side allowed to be "null". fp = m_ctx->m_pNullFragmentProgram; } if ( vpgood && fpgood ) { if ( vp->m_nCentroidMask != fp->m_nCentroidMask ) { Warning( "CGLMShaderPair::SetProgramPair: Centroid masks differ at link time of vertex shader %s and pixel shader %s!\n", vp->m_shaderName, fp->m_shaderName ); } // attempt link. but first, detach any previously attached programs if (m_vertexProg) { gGL->glDetachObjectARB(m_program, m_vertexProg->m_descs[kGLMGLSL].m_object.glsl); m_vertexProg = NULL; } if (m_fragmentProg) { gGL->glDetachObjectARB(m_program, m_fragmentProg->m_descs[kGLMGLSL].m_object.glsl); m_fragmentProg = NULL; } // now attach gGL->glAttachObjectARB( m_program, vp->m_descs[kGLMGLSL].m_object.glsl ); m_vertexProg = vp; gGL->glAttachObjectARB( m_program, fp->m_descs[kGLMGLSL].m_object.glsl ); m_fragmentProg = fp; // force the locations for input attributes v0-vN to be at locations 0-N // use the vertex attrib map to know which slots are live or not... oy! we don't have that map yet... but it's OK. // fallback - just force v0-v15 to land in locations 0-15 as a standard. if ( vp->m_descs[kGLMGLSL].m_valid ) { for( int i = 0; i < 16; i++ ) { char tmp[16]; sprintf(tmp, "v%d", i); // v0 v1 v2 ... et al gGL->glBindAttribLocationARB( m_program, i, tmp ); } } if (CommandLine()->CheckParm("-dumpallshaders")) { // Dump all shaders, for debugging. FILE* pFile = fopen("shaderdump.txt", "a+"); if (pFile) { fprintf(pFile, "--------------VP:%s\n%s\n", vp->m_shaderName, vp->m_text); fprintf(pFile, "--------------FP:%s\n%s\n", fp->m_shaderName, fp->m_text); fclose(pFile); } } // now link gGL->glLinkProgramARB( m_program ); // check for success GLint result = 0; gGL->glGetObjectParameterivARB(m_program,GL_OBJECT_LINK_STATUS_ARB,&result); // want GL_TRUE if (result == GL_TRUE) { // success m_valid = true; m_revision++; } else { GLint length = 0; GLint laux = 0; // do some digging gGL->glGetObjectParameterivARB(m_program,GL_OBJECT_INFO_LOG_LENGTH_ARB,&length); GLcharARB *logString = (GLcharARB *)malloc(length * sizeof(GLcharARB)); gGL->glGetInfoLogARB(m_program, length, &laux, logString); char *vtemp = strdup(vp->m_text); vtemp[ vp->m_descs[kGLMGLSL].m_textOffset + vp->m_descs[kGLMGLSL].m_textLength ] = 0; char *ftemp = strdup(fp->m_text); ftemp[ fp->m_descs[kGLMGLSL].m_textOffset + fp->m_descs[kGLMGLSL].m_textLength ] = 0; GLMPRINTF(("-D- ----- GLSL link failed: \n %s ",logString )); GLMPRINTF(("-D- ----- GLSL vertex program selected: %08x (handle %08x)", vp, vp->m_descs[kGLMGLSL].m_object.glsl )); GLMPRINTTEXT(( vtemp + vp->m_descs[kGLMGLSL].m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- ----- GLSL fragment program selected: %08x (handle %08x)", fp, vp->m_descs[kGLMGLSL].m_object.glsl )); GLMPRINTTEXT(( ftemp + fp->m_descs[kGLMGLSL].m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- -----end-----" )); free( ftemp ); free( vtemp ); free( logString ); } } else { // fail Assert(!"Can't link these programs"); } if (m_valid) { gGL->glUseProgram( m_program ); m_ctx->NewLinkedProgram(); m_locVertexParams = gGL->glGetUniformLocationARB( m_program, "vc"); m_locVertexBoneParams = gGL->glGetUniformLocationARB( m_program, "vcbones"); m_locVertexScreenParams = gGL->glGetUniformLocationARB( m_program, "vcscreen"); m_nScreenWidthHeight = 0xFFFFFFFF; m_locVertexInteger0 = gGL->glGetUniformLocationARB( m_program, "i0"); m_bHasBoolOrIntUniforms = false; if ( m_locVertexInteger0 >= 0 ) m_bHasBoolOrIntUniforms = true; for ( uint i = 0; i < cMaxVertexShaderBoolUniforms; i++ ) { char buf[256]; V_snprintf( buf, sizeof(buf), "b%d", i ); m_locVertexBool[i] = gGL->glGetUniformLocationARB( m_program, buf ); if ( m_locVertexBool[i] != - 1 ) m_bHasBoolOrIntUniforms = true; } for ( uint i = 0; i < cMaxFragmentShaderBoolUniforms; i++ ) { char buf[256]; V_snprintf( buf, sizeof(buf), "fb%d", i ); m_locFragmentBool[i] = gGL->glGetUniformLocationARB( m_program, buf ); if ( m_locFragmentBool[i] != - 1 ) m_bHasBoolOrIntUniforms = true; } m_locFragmentParams = gGL->glGetUniformLocationARB( m_program, "pc"); for (uint i = 0; i < kGLMNumProgramTypes; i++) { m_NumUniformBufferParams[i] = 0; if (i == kGLMVertexProgram) { if (m_locVertexParams < 0) continue; } else if (m_locFragmentParams < 0) continue; const uint nNum = (i == kGLMVertexProgram) ? m_vertexProg->m_descs[kGLMGLSL].m_highWater : m_fragmentProg->m_descs[kGLMGLSL].m_highWater; uint j; for (j = 0; j < nNum; j++) { char buf[256]; V_snprintf(buf, sizeof(buf), "%cc[%i]", "vp"[i], j); // Grab the handle of each array element, so we can more efficiently update array elements in the middle. int l = m_UniformBufferParams[i][j] = gGL->glGetUniformLocationARB( m_program, buf ); if ( l < 0 ) break; } m_NumUniformBufferParams[i] = j; } m_locFragmentFakeSRGBEnable = gGL->glGetUniformLocationARB( m_program, "flSRGBWrite"); m_fakeSRGBEnableValue = -1.0f; for( int sampler=0; sampler<16; sampler++) { char tmp[16]; sprintf(tmp, "sampler%d", sampler); // sampler0 .. sampler1.. etc GLint nLoc = gGL->glGetUniformLocationARB( m_program, tmp ); m_locSamplers[sampler] = nLoc; if ( nLoc >= 0 ) { gGL->glUniform1iARB( nLoc, sampler ); } } } else { m_locVertexParams = -1; m_locVertexBoneParams = -1; m_locVertexScreenParams = -1; m_nScreenWidthHeight = 0xFFFFFFFF; m_locVertexInteger0 = -1; memset( m_locVertexBool, 0xFF, sizeof( m_locVertexBool ) ); memset( m_locFragmentBool, 0xFF, sizeof( m_locFragmentBool ) ); m_bHasBoolOrIntUniforms = false; m_locFragmentParams = -1; m_locFragmentFakeSRGBEnable = -1; m_fakeSRGBEnableValue = -999; memset( m_locSamplers, 0xFF, sizeof( m_locSamplers ) ); m_revision = 0; } return m_valid; }
bool CGLMProgram::CheckValidity( EGLMProgramLang lang ) { static char *targnames[] = { "vertex", "fragment" }; switch(lang) { case kGLMARB: { GLMShaderDesc *arbDesc; arbDesc = &m_descs[ kGLMARB ]; GLenum arbTarget = GLMProgTypeToARBEnum( m_type ); Assert( arbDesc->m_compiled ); arbDesc->m_valid = true; // assume success til we see otherwise // assume program is bound. is there anything wrong with it ? GLint isNative=0; gGL->glGetProgramivARB( arbTarget, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative ); // If the program is over the hardware's limits, print out some information if (isNative!=1) { arbDesc->m_valid = false; // check everything we can check char checkmask = (1<<m_type); // 1 for VP, 2 for FP for( GLMShaderLimitDesc *desc = g_glmShaderLimitDescs; desc->m_valueEnum !=0; desc++ ) { if ( desc->m_flags & checkmask ) { // test it GLint value = 0; GLint limit = 0; gGL->glGetProgramivARB(arbTarget, desc->m_valueEnum, &value); gGL->glGetProgramivARB(arbTarget, desc->m_limitEnum, &limit); if (value > limit) { GLMPRINTF(("-D- Invalid %s program: program has %d %s; limit is %d", targnames[ m_type ], value, desc->m_debugName, limit )); } } } } // syntax error check GLint errorLine; gGL->glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errorLine ); if ( errorLine!=-1 ) { const GLubyte* errorString = gGL->glGetString(GL_PROGRAM_ERROR_STRING_ARB); errorString; GLMPRINTF(( "-D- Syntax error in ARB %s program: %s",targnames[ m_type ], errorString )); arbDesc->m_valid = false; } if (!arbDesc->m_valid) { char *temp = strdup(m_text); temp[ arbDesc->m_textOffset + arbDesc->m_textLength ] = 0; GLMPRINTF(("-D- ----- ARB compile failed; bad source follows -----" )); GLMPRINTTEXT(( temp + arbDesc->m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- -----end-----" )); free( temp ); } return arbDesc->m_valid; } break; case kGLMGLSL: { GLMShaderDesc *glslDesc; GLcharARB *logString = NULL; glslDesc = &m_descs[ kGLMGLSL ]; GLenum glslStage = GLMProgTypeToGLSLEnum( m_type ); glslStage; Assert( glslDesc->m_compiled ); glslDesc->m_valid = true; // assume success til we see otherwise // GLSL error check int compiled = 0, length = 0, laux = 0; gGL->glGetObjectParameterivARB( (GLhandleARB)glslDesc->m_object.glsl, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); gGL->glGetObjectParameterivARB( (GLhandleARB)glslDesc->m_object.glsl, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); if ( length > 0 ) { logString = (GLcharARB *)malloc(length * sizeof(GLcharARB)); gGL->glGetInfoLogARB((GLhandleARB)glslDesc->m_object.glsl, length, &laux, logString); } // we may not be able to check "native limits" stuff until link time. meh if (!compiled) { glslDesc->m_valid = false; } if (!glslDesc->m_valid) { char *temp = strdup(m_text); temp[ glslDesc->m_textOffset + glslDesc->m_textLength ] = 0; GLMPRINTF(("-D- ----- GLSL compile failed: \n %s \n",logString )); GLMPRINTTEXT(( temp + glslDesc->m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- -----end-----" )); free( temp ); } if ( logString ) free( logString ); return glslDesc->m_valid; } break; } return false; }
bool CGLMProgram::Compile( EGLMProgramLang lang ) { bool result = true; // indicating validity.. bool noisy = false; noisy; int loglevel = gl_shaderpair_cachelog.GetInt(); switch( lang ) { case kGLMARB: { GLMShaderDesc *arbDesc; arbDesc = &m_descs[ kGLMARB ]; // make sure no GLSL program is set up gGL->glUseProgram(0); // bind our program container to context GLenum arbTarget = GLMProgTypeToARBEnum( m_type ); glSetEnable( arbTarget, true ); // unclear if I need this to compile or just to draw... gGL->glBindProgramARB( arbTarget, arbDesc->m_object.arb ); // object created or just re-bound char *section = m_text + arbDesc->m_textOffset; char *lastCharOfSection = section + arbDesc->m_textLength; // actually it's one past the last textual character lastCharOfSection; #if GLMDEBUG if(noisy) { GLMPRINTF((">-D- CGLMProgram::Compile submitting following text for ARB %s program (name %d) ---------------------", arbTarget == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex", arbDesc->m_object.arb )); // we don't have a "print this many chars" call yet // just temporarily null terminate the text we want to print char saveChar = *lastCharOfSection; *lastCharOfSection= 0; GLMPRINTTEXT(( section, eDebugDump )); *lastCharOfSection= saveChar; GLMPRINTF(("<-D- CGLMProgram::Compile ARB EOT--" )); } #endif gGL->glProgramStringARB( arbTarget, GL_PROGRAM_FORMAT_ASCII_ARB, arbDesc->m_textLength, section ); arbDesc->m_compiled = true; // compiled but not necessarily valid CheckValidity( lang ); // leave it bound n enabled, don't care (draw will sort it all out) result = arbDesc->m_valid; } break; case kGLMGLSL: { GLMShaderDesc *glslDesc; glslDesc = &m_descs[ kGLMGLSL ]; GLenum glslStage = GLMProgTypeToGLSLEnum( m_type ); glslStage; // there's no binding to do for GLSL. but make sure no ARB stuff is bound for tidiness. glSetEnable( GL_VERTEX_PROGRAM_ARB, false ); glSetEnable( GL_FRAGMENT_PROGRAM_ARB, false ); // add check errors on these gGL->glBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 ); gGL->glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, 0 ); // no GLSL program either gGL->glUseProgram(0); // pump text into GLSL shader object char *section = m_text + glslDesc->m_textOffset; char *lastCharOfSection = section + glslDesc->m_textLength; // actually it's one past the last textual character lastCharOfSection; #if GLMDEBUG if(noisy) { GLMPRINTF((">-D- CGLMProgram::Compile submitting following text for GLSL %s program (name %d) ---------------------", glslStage == GL_FRAGMENT_SHADER_ARB ? "fragment" : "vertex", glslDesc->m_object.glsl )); // we don't have a "print this many chars" call yet // just temporarily null terminate the text we want to print char saveChar = *lastCharOfSection; *lastCharOfSection= 0; GLMPRINTTEXT(( section, eDebugDump )); *lastCharOfSection= saveChar; GLMPRINTF(("<-D- CGLMProgram::Compile GLSL EOT--" )); } #endif gGL->glShaderSourceARB( glslDesc->m_object.glsl, 1, (const GLchar **)§ion, &glslDesc->m_textLength); // compile gGL->glCompileShaderARB( glslDesc->m_object.glsl ); glslDesc->m_compiled = true; // compiled but not necessarily valid CheckValidity( lang ); if (loglevel>=2) { char tempname[128]; //int tempindex = -1; //int tempcombo = -1; //GetLabelIndexCombo( tempname, sizeof(tempname), &tempindex, &tempcombo ); //printf("\ncompile: - [ %s/%d/%d ] on GL name %d ", tempname, tempindex, tempcombo, glslDesc->m_object.glsl ); GetComboIndexNameString( tempname, sizeof(tempname) ); printf("\ncompile: %s on GL name %d ", tempname, glslDesc->m_object.glsl ); } result = glslDesc->m_valid; } break; } return result; }
bool CGLMShaderPair::SetProgramPair ( CGLMProgram *vp, CGLMProgram *fp ) { m_valid = false; // assume failure // true result means successful link and query bool vpgood = (vp!=NULL) && (vp->m_descs[ kGLMGLSL ].m_valid); bool fpgood = (fp!=NULL) && (fp->m_descs[ kGLMGLSL ].m_valid); if (!fpgood) { // fragment side allowed to be "null". fp = m_ctx->m_nullFragmentProgram; } if (vpgood && fpgood) { // attempt link. but first, detach any previously attached programs if (m_vertexProg) { glDetachObjectARB(m_program, m_vertexProg->m_descs[kGLMGLSL].m_object.glsl); GLMCheckError(); m_vertexProg = NULL; } if (m_fragmentProg) { glDetachObjectARB(m_program, m_fragmentProg->m_descs[kGLMGLSL].m_object.glsl); GLMCheckError(); m_fragmentProg = NULL; } // now attach glAttachObjectARB(m_program, vp->m_descs[kGLMGLSL].m_object.glsl); m_vertexProg = vp; GLMCheckError(); glAttachObjectARB(m_program, fp->m_descs[kGLMGLSL].m_object.glsl); m_fragmentProg = fp; GLMCheckError(); // force the locations for input attributes v0-vN to be at locations 0-N // use the vertex attrib map to know which slots are live or not... oy! we don't have that map yet... but it's OK. // fallback - just force v0-v15 to land in locations 0-15 as a standard. if (vp->m_descs[kGLMGLSL].m_valid) { for( int i=0; i < 16; i++) { char tmp[16]; sprintf(tmp, "v%d", i); // v0 v1 v2 ... et al glBindAttribLocationARB( m_program, i, tmp ); GLMCheckError(); } } // now link glLinkProgramARB( m_program ); GLMCheckError(); // check for success GLint result = 0; glGetObjectParameterivARB(m_program,GL_OBJECT_LINK_STATUS_ARB,&result); // want GL_TRUE if (result == GL_TRUE) { // success m_valid = true; m_revision++; } else { GLint length = 0; GLint laux = 0; // do some digging glGetObjectParameterivARB(m_program,GL_OBJECT_INFO_LOG_LENGTH_ARB,&length); GLcharARB *logString = (GLcharARB *)malloc(length * sizeof(GLcharARB)); glGetInfoLogARB(m_program, length, &laux, logString); char *vtemp = strdup(vp->m_text); vtemp[ vp->m_descs[kGLMGLSL].m_textOffset + vp->m_descs[kGLMGLSL].m_textLength ] = 0; char *ftemp = strdup(fp->m_text); ftemp[ fp->m_descs[kGLMGLSL].m_textOffset + fp->m_descs[kGLMGLSL].m_textLength ] = 0; GLMPRINTF(("-D- ----- GLSL link failed: \n %s ",logString )); GLMPRINTF(("-D- ----- GLSL vertex program selected: %08x (handle %08x)", vp, vp->m_descs[kGLMGLSL].m_object.glsl )); GLMPRINTTEXT(( vtemp + vp->m_descs[kGLMGLSL].m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- ----- GLSL fragment program selected: %08x (handle %08x)", fp, vp->m_descs[kGLMGLSL].m_object.glsl )); GLMPRINTTEXT(( ftemp + fp->m_descs[kGLMGLSL].m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES )); GLMPRINTF(("-D- -----end-----" )); free( ftemp ); free( vtemp ); free( logString ); } } else { // fail Assert(!"Can't link these programs"); } if (m_valid) { m_locVertexParams = glGetUniformLocationARB( m_program, "vc"); GLMCheckError(); m_locVertexInteger0 = glGetUniformLocationARB( m_program, "i0"); GLMCheckError(); m_locVertexBool0 = glGetUniformLocationARB( m_program, "b0"); GLMCheckError(); m_locVertexBool1 = glGetUniformLocationARB( m_program, "b1"); GLMCheckError(); m_locVertexBool2 = glGetUniformLocationARB( m_program, "b2"); GLMCheckError(); m_locVertexBool3 = glGetUniformLocationARB( m_program, "b3"); GLMCheckError(); m_locFragmentParams = glGetUniformLocationARB( m_program, "pc"); GLMCheckError(); m_locFragmentFakeSRGBEnable = glGetUniformLocationARB( m_program, "flSRGBWrite"); GLMCheckError(); m_fakeSRGBEnableValue = -1.0f; for( int sampler=0; sampler<16; sampler++) { char tmp[16]; sprintf(tmp, "sampler%d", sampler); // sampler0 .. sampler1.. etc m_locSamplers[sampler] = glGetUniformLocationARB( m_program, tmp ); GLMCheckError(); } } else { m_locVertexParams = -1; m_locVertexInteger0 = -1; m_locVertexBool0 = -1; m_locVertexBool1 = -1; m_locVertexBool2 = -1; m_locVertexBool3 = -1; m_locFragmentParams = -1; m_locFragmentFakeSRGBEnable = -1; m_fakeSRGBEnableValue = -999; memset( m_locSamplers, 0xFF, sizeof( m_locSamplers ) ); m_revision = 0; } return m_valid; }