void GLIDebugVariableGrid::SetUniformData(const UniformDataArray &newData) { //Clear existing array uniformDataArray.clear(); //Loop for all values for(uint i=0; i<newData.size(); i++) { UniformRowData newUniformRowData; //Assign the uniform data newUniformRowData.name = newData[i].name; newUniformRowData.type = newData[i].type; newUniformRowData.numTypeElements = newData[i].numTypeElements; newUniformRowData.isFloatType = newData[i].isFloatType; newUniformRowData.intUniformData = newData[i].intUniformData; newUniformRowData.floatUniformData = newData[i].floatUniformData; //Calculate the array size if(newUniformRowData.isFloatType) { //Ensure the array values are correct if(newUniformRowData.floatUniformData.size() % newUniformRowData.numTypeElements != 0) { newUniformRowData.arrayCount = 0; } else { newUniformRowData.arrayCount = newUniformRowData.floatUniformData.size() / newUniformRowData.numTypeElements; } } else { //Ensure the array values are correct if(newUniformRowData.intUniformData.size() % newUniformRowData.numTypeElements != 0) { newUniformRowData.arrayCount = 0; } else { newUniformRowData.arrayCount = newUniformRowData.intUniformData.size() / newUniformRowData.numTypeElements; } } //Add to the array uniformDataArray.push_back(newUniformRowData); } }
bool ShaderUtilsGLSL::GetUniformData(GLuint programHandle, UniformDataArray &retData) const { //Empty the return array retData.clear(); //Get if OpenGL calls can be made if(!gliCallBacks->GetGLInternalCallState()) { return false; } //Get the number of uniforms for the program GLint numUniforms = 0; iglGetProgramiv(programHandle, GL_ACTIVE_UNIFORMS, &numUniforms); if(numUniforms <= 0) { return true; } //Get the max uniform string size GLint maxUniformSize = 0; iglGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); if(maxUniformSize <= 0) { return false; } //Allocate the array to get the uniform strings GLchar * readUniformName = new GLchar[maxUniformSize+1]; //Loop for the number of uniforms in the program for(uint i=0;i<(uint)numUniforms;i++) { GLint typeSize=0; GLenum type; GLsizei lengthWritten=0; string newUniformName; //Call GetActiveUniform to get the name,type and size of the type iglGetActiveUniform(programHandle,i,maxUniformSize,&lengthWritten,&typeSize,&type,readUniformName); if(lengthWritten > 0) { //Convert to a string newUniformName = (char*)readUniformName; //Nvidia/ATI Hack ====================================== // Nvidia (in 69.xx drivers) and ATI Cat 5.9 return a uniform for every element of arrays. // Only take note of the first one and ignore the rest bool ignoreUniform = false; if(newUniformName.length() > 3 && newUniformName[newUniformName.length()-1] == ']') { //If the characters end with "[0]" if(newUniformName[newUniformName.length()-2] == '0' && newUniformName[newUniformName.length()-3] == '[') { //Erase the last three characters newUniformName.erase(newUniformName.length()-3, 3); LOGERR(("Nvidia/ATI uniform array workaround for %s",newUniformName.c_str())); } else { //Don't process this uniform ignoreUniform = true; } } //End Hack ====================================== //Ignore built in gl types if(newUniformName.find("gl_") != 0 && !ignoreUniform) { //Loop for the array size for the type vector<uint> indexDataArray; for(GLint s=0; s<typeSize; s++) { string testUniformName = newUniformName; if(s > 0) { //If it is an array type, get the index of each component string strBuffer; StringPrintF(strBuffer, "[%u]",s); testUniformName += strBuffer; } //Get the location of the uniform GLint uniLocation = iglGetUniformLocation(programHandle,(const GLchar*)testUniformName.c_str()); if(uniLocation < 0) { LOGERR(("GetUniformData - Uniform %s does not exist?",testUniformName.c_str())); //Clean up the uniform name delete [] readUniformName; return false; } //Add to the index data array indexDataArray.push_back(uniLocation); } UniformData newData; newData.indexData = indexDataArray; newData.remapIndex = 0; newData.name = newUniformName; newData.size = typeSize; newData.type = type; //Check that the type is known if(!GetTypeData(newData.type, newData.numTypeElements, newData.baseFormat)) { LOGERR(("GetUniformData - %s - Uniform is not a known type: 0x%x\n", newData.name.c_str(), newData.type)); //Clean up the uniform name delete [] readUniformName; return false; } //Add the new data to the return array retData.push_back(newData); } } } //Clean up the uniform name delete [] readUniformName; return true; }
void SubstituteShaderGLSL::GenerateUniformRemapArray(string &initLog) { uint i; string bufferStr; //Get the uniforms of the old program UniformDataArray oldUniformData; if(!shaderUtils.GetUniformData(oldProgramID, oldUniformData)) { initLog += "Unble to get old program unform data\n"; return; } //Get the uniforms of the new program UniformDataArray newUniformData; if(!shaderUtils.GetUniformData(programID, newUniformData)) { initLog += "Unble to get new program unform data\n"; return; } //Clear the mapping array remapUniformArray.clear(); //Loop for all values in the old array for(i=0; i<oldUniformData.size(); i++) { bool foundFlag = false; const UniformData & oldData = oldUniformData[i]; //Loop for all new values for(uint i2=0; i2<newUniformData.size(); i2++) { const UniformData & newData = newUniformData[i2]; //Check for a name match if(oldData.name == newData.name) { foundFlag = true; //Check the types and abort if not equal if(oldData.type != newData.type) { StringPrintF(bufferStr," %s - Uniforms types are different\n",oldData.name.c_str()); initLog += bufferStr; break; } //Check the sizes uint addDataTypeSize = oldData.size; if(oldData.size != newData.size) { StringPrintF(bufferStr," %s - Uniform sizes are different (%u != %u)\n", oldData.name.c_str(),oldData.size,newData.size); initLog += bufferStr; //Take the minimum of the two sizes if(newData.size < addDataTypeSize) { addDataTypeSize = newData.size; } } //Check the type size if(addDataTypeSize == 0) { StringPrintF(bufferStr," %s - Uniform size is zero?\n", oldData.name.c_str()); initLog += bufferStr; break; } //Create a new entry in the mapping array UniformData addData; addData.indexData = oldData.indexData; addData.remapIndex = newData.indexData[0]; addData.name = newData.name; addData.size = addDataTypeSize; addData.type = newData.type; //Get the data about the type if(!shaderUtils.GetTypeData(addData.type, addData.numTypeElements, addData.baseFormat)) { StringPrintF(bufferStr," %s - Uniform is not a known type: 0x%x\n", addData.name.c_str(),addData.type); initLog += bufferStr; break; } //Test if the data can be copied without OpenGL errors (ATI bug) if(TestUniformDataCopy(addData, initLog)) { //Add the data to the array remapUniformArray.push_back(addData); } #ifdef GLI_ATI_UNIFORM_GLSL_BUG //If it is just a single variable (hopefully a sampler), use the ATI override else if(addData.baseFormat == GL_INT && addData.numTypeElements == 1) { initLog += string("Using ATI uniform override on ") + addData.name + string("\n"); addData.isATIUniformOverride = true; remapUniformArray.push_back(addData); } #endif //GLI_ATI_UNIFORM_GLSL_BUG break; } } //If not found if(!foundFlag) { StringPrintF(bufferStr," %s - Uniform not found in new program\n", oldData.name.c_str()); initLog += bufferStr; } } //Log all the new uniforms not in the old program for(i=0; i<newUniformData.size(); i++) { bool foundFlag = false; const UniformData & newData = newUniformData[i]; //Loop for all old values for(uint i2=0; i2<oldUniformData.size(); i2++) { const UniformData & oldData = oldUniformData[i2]; //Check for a name match if(oldData.name == newData.name) { foundFlag = true; break; } } //If not found if(!foundFlag) { StringPrintF(bufferStr," %s - Uniform in new program -not in old program\n", newData.name.c_str()); initLog += bufferStr; } } }