//----------------------------------------------------------------------- void GLSLLinkProgram::updateUniformBlocks(GpuProgramParametersSharedPtr params, uint16 mask, GpuProgramType fromProgType) { // Iterate through the list of uniform buffers and update them as needed GLUniformBufferIterator currentBuffer = mGLUniformBufferReferences.begin(); GLUniformBufferIterator endBuffer = mGLUniformBufferReferences.end(); const GpuProgramParameters::GpuSharedParamUsageList& sharedParams = params->getSharedParameters(); GpuProgramParameters::GpuSharedParamUsageList::const_iterator it, end = sharedParams.end(); for (it = sharedParams.begin(); it != end; ++it) { for (;currentBuffer != endBuffer; ++currentBuffer) { GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(currentBuffer->get()); GpuSharedParametersPtr paramsPtr = it->getSharedParams(); // Block name is stored in mSharedParams->mName of GpuSharedParamUsageList items GLint UniformTransform; OGRE_CHECK_GL_ERROR(UniformTransform = glGetUniformBlockIndex(mGLProgramHandle, it->getName().c_str())); OGRE_CHECK_GL_ERROR(glUniformBlockBinding(mGLProgramHandle, UniformTransform, hwGlBuffer->getGLBufferBinding())); hwGlBuffer->writeData(0, hwGlBuffer->getSizeInBytes(), ¶msPtr->getFloatConstantList().front()); } } }
void GLSLSeparableProgram::updateUniformBlocks(GpuProgramParametersSharedPtr params, uint16 mask, GpuProgramType fromProgType) { //TODO Support uniform block arrays - need to figure how to do this via material. // Iterate through the list of uniform blocks and update them as needed. SharedParamsBufferMap::const_iterator currentPair = mSharedParamsBufferMap.begin(); SharedParamsBufferMap::const_iterator endPair = mSharedParamsBufferMap.end(); // const GpuProgramParameters::GpuSharedParamUsageList& sharedParams = params->getSharedParameters(); // const GpuProgramParameters::GpuSharedParamUsageList& sharedParams = params->getSharedParameters(); // GpuProgramParameters::GpuSharedParamUsageList::const_iterator it, end = sharedParams.end(); for (; currentPair != endPair; ++currentPair) { GpuSharedParametersPtr paramsPtr = currentPair->first; //FIXME Possible buffer does not exist if no associated uniform block. GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(currentPair->second.get()); if (!paramsPtr->isDirty()) continue; //FIXME does not check if current progrtype, or if shared param is active GpuConstantDefinitionIterator parami = paramsPtr->getConstantDefinitionIterator(); for (int i = 0; parami.current() != parami.end(); parami.moveNext(), i++) { //String name = parami->; //GpuConstantDefinition * param = GpuConstantConstantDefinition(name); //const String* name = ¶mi.current()->first; const GpuConstantDefinition* param = ¶mi.current()->second; BaseConstantType baseType = GpuConstantDefinition::getBaseType(param->constType); void* dataPtr; size_t index = param->physicalIndex; //TODO Maybe move to GpuSharedParams? Otherwise create bool buffer. switch (baseType) { case BCT_FLOAT: dataPtr = paramsPtr->getFloatPointer(index); break; case BCT_INT: dataPtr = paramsPtr->getIntPointer(index); break; case BCT_DOUBLE: dataPtr = paramsPtr->getDoublePointer(index); break; case BCT_UINT: case BCT_BOOL: dataPtr = paramsPtr->getUnsignedIntPointer(index); break; case BCT_SAMPLER: case BCT_SUBROUTINE: //TODO implement me! default: //TODO error handling continue; } // in bytes size_t length = param->arraySize * param->elementSize * 4; size_t offset = hwGlBuffer->mBufferParamsLayout.offsets[i]; hwGlBuffer->writeData(offset, length, dataPtr); } paramsPtr->_markClean(); } }
//--------------------------------------------------------------------- void GLSLProgramManagerCommon::extractUniforms(GLuint programObject, const GpuConstantDefinitionMap* vertexConstantDefs, const GpuConstantDefinitionMap* geometryConstantDefs, const GpuConstantDefinitionMap* fragmentConstantDefs, const GpuConstantDefinitionMap* hullConstantDefs, const GpuConstantDefinitionMap* domainConstantDefs, const GpuConstantDefinitionMap* computeConstantDefs, GLUniformReferenceList& list, GLUniformBufferList& sharedList) { // Scan through the active uniforms and add them to the reference list GLint uniformCount = 0; #define uniformLength 200 // GLint uniformLength = 0; // glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformLength); char uniformName[uniformLength]; GLUniformReference newGLUniformReference; // Get the number of active uniforms OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORMS, &uniformCount)); // Loop over each of the active uniforms, and add them to the reference container // only do this for user defined uniforms, ignore built in gl state uniforms for (int index = 0; index < uniformCount; index++) { GLint arraySize; GLenum glType; OGRE_CHECK_GL_ERROR(glGetActiveUniform(programObject, index, uniformLength, NULL, &arraySize, &glType, uniformName)); // Don't add built in uniforms OGRE_CHECK_GL_ERROR(newGLUniformReference.mLocation = glGetUniformLocation(programObject, uniformName)); if (newGLUniformReference.mLocation >= 0) { // User defined uniform found, add it to the reference list String paramName = String( uniformName ); // Current ATI drivers (Catalyst 7.2 and earlier) and older NVidia drivers will include all array elements as uniforms but we only want the root array name and location // Also note that ATI Catalyst 6.8 to 7.2 there is a bug with glUniform that does not allow you to update a uniform array past the first uniform array element // ie you can't start updating an array starting at element 1, must always be element 0. // If the uniform name has a "[" in it then its an array element uniform. String::size_type arrayStart = paramName.find("["); if (arrayStart != String::npos) { // if not the first array element then skip it and continue to the next uniform if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0) continue; paramName = paramName.substr(0, arrayStart); } // Find out which params object this comes from bool foundSource = completeParamSource(paramName, vertexConstantDefs, geometryConstantDefs, fragmentConstantDefs, hullConstantDefs, domainConstantDefs, computeConstantDefs, newGLUniformReference); // Only add this parameter if we found the source if (foundSource) { assert(size_t (arraySize) == newGLUniformReference.mConstantDef->arraySize && "GL doesn't agree with our array size!"); list.push_back(newGLUniformReference); } // Don't bother adding individual array params, they will be // picked up in the 'parent' parameter can copied all at once // anyway, individual indexes are only needed for lookup from // user params } // end if } // end for // Now deal with uniform blocks GLint blockCount = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount)); for (int index = 0; index < blockCount; index++) { OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockName(programObject, index, uniformLength, NULL, uniformName)); GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName); GLint blockSize, blockBinding; OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize)); OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_BINDING, &blockBinding)); HardwareUniformBufferSharedPtr newUniformBuffer = HardwareBufferManager::getSingleton().createUniformBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false, uniformName); GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(newUniformBuffer.get()); hwGlBuffer->setGLBufferBinding(blockBinding); sharedList.push_back(newUniformBuffer); } }