CGLMProgram::CGLMProgram( GLMContext *ctx, EGLMProgramType type ) { m_ctx = ctx; m_ctx->CheckCurrent(); m_type = type; m_serial = g_shader_serial++; m_text = NULL; // no text yet #if GLMDEBUG m_editable = NULL; #endif memset( &m_descs, 0, sizeof( m_descs ) ); m_samplerMask = 0; // dxabstract sets this field later // create an ARB vp/fp program object name. No need to bind it yet. GLMShaderDesc *arbDesc = &m_descs[ kGLMARB ]; glGenProgramsARB( 1, &arbDesc->m_object.arb ); // create a GLSL shader object. GLMShaderDesc *glslDesc = &m_descs[ kGLMGLSL ]; GLenum glslStage = GLMProgTypeToGLSLEnum( m_type ); glslDesc->m_object.glsl = glCreateShaderObjectARB( glslStage );; // no text has arrived yet. That's done in SetProgramText. }
CGLMProgram::CGLMProgram( GLMContext *ctx, EGLMProgramType type ) { m_ctx = ctx; m_ctx->CheckCurrent(); m_type = type; m_nHashTag = rand() ^ ( rand() << 15 ); m_text = NULL; // no text yet #if GLMDEBUG m_editable = NULL; #endif memset( &m_descs, 0, sizeof( m_descs ) ); m_samplerMask = 0; // dxabstract sets this field later m_samplerTypes = 0; m_fragDataMask = 0; m_numDrawBuffers = 0; memset( &m_drawBuffers, 0, sizeof( m_drawBuffers ) ); m_maxSamplers = GLM_SAMPLER_COUNT; m_nNumUsedSamplers = GLM_SAMPLER_COUNT; m_maxVertexAttrs = kGLMVertexAttributeIndexMax; // create an ARB vp/fp program object name. No need to bind it yet. GLMShaderDesc *arbDesc = &m_descs[ kGLMARB ]; Assert(gGL); gGL->glGenProgramsARB( 1, &arbDesc->m_object.arb ); // create a GLSL shader object. GLMShaderDesc *glslDesc = &m_descs[ kGLMGLSL ]; GLenum glslStage = GLMProgTypeToGLSLEnum( m_type ); glslDesc->m_object.glsl = gGL->glCreateShaderObjectARB( glslStage );; m_shaderName[0] = '\0'; m_bTranslatedProgram = false; m_nCentroidMask = 0; m_nShadowDepthSamplerMask = 0; // no text has arrived yet. That's done in SetProgramText. }
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; }