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);
  }

}
Пример #2
0
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;
    }
  }

}