const char* gStdAttribs[ Program::ATTRIB_TYPE_LAST ] =
{
"aPosition", // ATTRIB_POSITION
- "aNormal", // ATTRIB_NORMAL
"aTexCoord", // ATTRIB_TEXCOORD
- "aColor", // ATTRIB_COLOR
- "aBoneWeights", // ATTRIB_BONE_WEIGHTS
- "aBoneIndices" // ATTRIB_BONE_INDICES
};
const char* gStdUniforms[ Program::UNIFORM_TYPE_LAST ] =
"uViewMatrix", // UNIFORM_VIEW_MATRIX,
"uNormalMatrix", // UNIFORM_NORMAL_MATRIX
"uColor", // UNIFORM_COLOR
- "uCustomTextureCoords", // UNIFORM_CUSTOM_TEXTURE_COORDS
"sTexture", // UNIFORM_SAMPLER
"sTextureRect", // UNIFORM_SAMPLER_RECT
"sEffect", // UNIFORM_EFFECT_SAMPLER
- "sEffectRect", // UNIFORM_EFFECT_SAMPLER_RECT
- "uTimeDelta", // UNIFORM_TIME_DELTA
- "sOpacityTexture", // UNIFORM_SAMPLER_OPACITY
- "sNormalMapTexture", // UNIFORM_SAMPLER_NORMAL_MAP
"uSize" // UNIFORM_SIZE
};
program = new Program( cache, shaderData, modifiesGeometry );
// we want to lazy load programs so dont do a Load yet, it gets done in Use()
-
cache.AddProgram( shaderHash, program );
}
return location;
}
+namespace
+{
+/**
+ * This struct is used to record the position of a uniform declaration
+ * within the fragment shader source code.
+ */
+struct LocationPosition
+{
+ GLint uniformLocation; ///< The location of the uniform (used as an identifier)
+ int characterPosition; ///< the position of the uniform declaration
+ LocationPosition( GLint uniformLocation, int characterPosition )
+ : uniformLocation(uniformLocation), characterPosition(characterPosition)
+ {
+ }
+};
+
+bool sortByPosition( LocationPosition a, LocationPosition b )
+{
+ return a.characterPosition < b.characterPosition;
+}
+}
+
+void Program::GetActiveSamplerUniforms()
+{
+ GLint numberOfActiveUniforms = -1;
+ GLint uniformMaxNameLength=-1;
+
+ mGlAbstraction.GetProgramiv( mProgramId, GL_ACTIVE_UNIFORMS, &numberOfActiveUniforms );
+ mGlAbstraction.GetProgramiv( mProgramId, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxNameLength );
+
+ std::vector<std::string> samplerNames;
+ char name[uniformMaxNameLength+1]; // Allow for null terminator
+ std::vector< LocationPosition > samplerUniformLocations;
+
+ {
+ int nameLength = -1;
+ int number = -1;
+ GLenum type = GL_ZERO;
+
+ for( int i=0; i<numberOfActiveUniforms; ++i )
+ {
+ mGlAbstraction.GetActiveUniform( mProgramId, (GLuint)i, uniformMaxNameLength,
+ &nameLength, &number, &type, name );
+
+ if( type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES )
+ {
+ GLuint location = mGlAbstraction.GetUniformLocation( mProgramId, name );
+ samplerNames.push_back(name);
+ samplerUniformLocations.push_back(LocationPosition(location, 0u));
+ }
+ }
+ }
+
+ if( samplerUniformLocations.size() > 1 )
+ {
+ // Now, re-order according to declaration order in the fragment source.
+ std::string fragShader( mProgramData->GetFragmentShader() );
+ for( unsigned int i=0; i<samplerUniformLocations.size(); ++i )
+ {
+ // Better to write own search algorithm that searches for all of
+ // the sampler names simultaneously, ensuring only one iteration
+ // over fragShader.
+ size_t characterPosition = fragShader.find( samplerNames[i] );
+ samplerUniformLocations[i].characterPosition = characterPosition;
+ }
+ std::sort( samplerUniformLocations.begin(), samplerUniformLocations.end(), sortByPosition);
+ }
+
+ for( unsigned int i=0; i<samplerUniformLocations.size(); ++i )
+ {
+ mSamplerUniformLocations.push_back( samplerUniformLocations[i].uniformLocation );
+ }
+}
+
+bool Program::GetSamplerUniformLocation( unsigned int index, GLint& location )
+{
+ bool result = false;
+ if( index < mSamplerUniformLocations.size() )
+ {
+ location = mSamplerUniformLocations[index];
+ result = true;
+ }
+ return result;
+}
+
void Program::SetUniform1i( GLint location, GLint value0 )
{
DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
return;
}
- // Not caching these as based on current analysis this is not called that often by our shaders
- LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 );
- CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) );
+ // check if uniform location fits the cache
+ if( location >= MAX_UNIFORM_CACHE_SIZE )
+ {
+ // not cached, make the gl call
+ LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 );
+ CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) );
+ }
+ else
+ {
+ // check if the same value has already been set, reset if it is different
+ if( ( fabsf(value0 - mUniformCacheFloat2[ location ][ 0 ]) >= Math::MACHINE_EPSILON_1 )||
+ ( fabsf(value1 - mUniformCacheFloat2[ location ][ 1 ]) >= Math::MACHINE_EPSILON_1 ) )
+ {
+ // make the gl call
+ LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 );
+ CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) );
+
+ // update cache
+ mUniformCacheFloat2[ location ][ 0 ] = value0;
+ mUniformCacheFloat2[ location ][ 1 ] = value1;
+ }
+ }
}
void Program::SetSizeUniform3f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2 )
{
RegisterUniform( gStdUniforms[ i ] );
}
+
// reset values
ResetAttribsUniformCache();
}
}
}
+ GetActiveSamplerUniforms();
+
// No longer needed
FreeShaders();
}
mUniformLocations[ i ].second = UNIFORM_NOT_QUERIED;
}
+ mSamplerUniformLocations.clear();
+
// reset uniform caches
mSizeUniformCache.x = mSizeUniformCache.y = mSizeUniformCache.z = 0.f;
// GL initializes uniforms to 0
mUniformCacheInt[ i ] = 0;
mUniformCacheFloat[ i ] = 0.0f;
+ mUniformCacheFloat2[ i ][ 0 ] = 0.0f;
+ mUniformCacheFloat2[ i ][ 1 ] = 0.0f;
mUniformCacheFloat4[ i ][ 0 ] = 0.0f;
mUniformCacheFloat4[ i ][ 1 ] = 0.0f;
mUniformCacheFloat4[ i ][ 2 ] = 0.0f;