//-----------------------------------------------------------------------
	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(), &paramsPtr->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 = &parami.current()->first;
                const GpuConstantDefinition* param = &parami.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);
        }
    }