Beispiel #1
0
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;
	}
	
}
Beispiel #2
0
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"));
}
Beispiel #3
0
// 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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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 **)&section, &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;
}
Beispiel #6
0
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;
}