Reduces almost 30% of matrix sets in dali-demo (from 75k to 53k once the demo is up and running)
Change-Id: I21b6985446fb2e9d832388c0c619b0bc60c13000
Signed-off-by: Adeel Kazmi <adeel.kazmi@samsung.com>
mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+ // reset the program matrices for all programs once per frame
+ // this ensures we will set view and projection matrix once per program per camera
+ // @todo move programs out of context onto a program controller and let that handle this
+ mImpl->context.ResetProgramMatrices();
+
size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
for ( size_t i = 0; i < count; ++i )
{
return "Unknown Open GLES error";
}
+void Context::ResetProgramMatrices()
+{
+ const ProgramContainer::iterator endp = mProgramCache.end();
+ for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
+ {
+ (*itp).second->SetProjectionMatrix( NULL );
+ (*itp).second->SetViewMatrix( NULL );
+ }
+}
+
Program* Context::GetCachedProgram( std::size_t hash ) const
{
std::map< std::size_t, Program* >::const_iterator iter = mProgramCache.find(hash);
void GlContextCreated();
/**
- * Called when the GL context is about to be destroyed.
+ * Called when the GL context has been destroyed.
*/
void GlContextDestroyed();
}
/**
+ * Reset the program matrices
+ */
+ void ResetProgramMatrices();
+
+ /**
* Get a cached program
* @param [in] hash value
* @return pointer to the program
namespace Internal
{
+namespace
+{
+/**
+ * Helper to set view and projection matrices once per program
+ */
+inline void SetMatrices( Program& program, const Matrix& projectionMatrix, const Matrix& viewMatrix )
+{
+ // set projection matrix if program has not yet received it this frame or if it is dirty
+ GLint loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
+ if( Program::UNIFORM_UNKNOWN != loc )
+ {
+ if( program.GetProjectionMatrix() != &projectionMatrix )
+ {
+ program.SetProjectionMatrix( &projectionMatrix );
+ program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
+ }
+ }
+ loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
+ if( Program::UNIFORM_UNKNOWN != loc )
+ {
+ if( program.GetViewMatrix() == &viewMatrix )
+ {
+ program.SetViewMatrix( &viewMatrix );
+ program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
+ }
+ }
+}
+}
+
namespace SceneGraph
{
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
float frametime,
- bool cull)
+ bool cull )
{
DALI_ASSERT_DEBUG( mContext && "Renderer::Render. Renderer not initialised!! (mContext == NULL)." );
DALI_ASSERT_DEBUG( mShader && "Renderer::Render. Shader not set!!" );
ShaderSubTypes subType=SHADER_DEFAULT;
GetGeometryTypes( bufferIndex, geometryType, subType );
Program& program = mShader->GetProgram( *mContext, geometryType, subType );
+ program.Use(); // apply the program so we can send uniforms to it
+
bool areVerticesFixed = program.AreVerticesFixed();
+ // set projection and view matrix if program has not yet received them yet this frame
+ SetMatrices( program, projectionMatrix, viewMatrix );
+
+ // subclass rendering
DoRender( bufferIndex, modelViewMatrix, modelMatrix, viewMatrix, projectionMatrix, color, cull && areVerticesFixed );
}
// check if uniform location fits the cache
if( location >= MAX_UNIFORM_CACHE_SIZE )
{
- // not cached, make the gl call through context
+ // not cached, make the gl call
LOG_GL( "Uniform1i(%d,%d)\n", location, value0 );
CHECK_GL( mContext, mGlAbstraction.Uniform1i( location, value0 ) );
}
// check if the value is different from what's already been set
if( value0 != mUniformCacheInt[ location ] )
{
- // make the gl call through context
+ // make the gl call
LOG_GL( "Uniform1i(%d,%d)\n", location, value0 );
CHECK_GL( mContext, mGlAbstraction.Uniform1i( location, value0 ) );
// update cache
// check if uniform location fits the cache
if( location >= MAX_UNIFORM_CACHE_SIZE )
{
- // not cached, make the gl call through context
+ // not cached, make the gl call
LOG_GL( "Uniform1f(%d,%f)\n", location, value0 );
CHECK_GL( mContext, mGlAbstraction.Uniform1f( location, value0 ) );
}
// check if the same value has already been set, reset if it is different
if( ( fabsf(value0 - mUniformCacheFloat[ location ]) >= Math::MACHINE_EPSILON_1 ) )
{
- // make the gl call through context
+ // make the gl call
LOG_GL( "Uniform1f(%d,%f)\n", location, value0 );
CHECK_GL( mContext, mGlAbstraction.Uniform1f( location, value0 ) );
// check if uniform location fits the cache
if( location >= MAX_UNIFORM_CACHE_SIZE )
{
- // not cached, make the gl call through context
+ // not cached, make the gl call
LOG_GL( "Uniform4f(%d,%f,%f,%f,%f)\n", location, value0, value1, value2, value3 );
CHECK_GL( mContext, mGlAbstraction.Uniform4f( location, value0, value1, value2, value3 ) );
}
( fabsf(value1 - mUniformCacheFloat4[ location ][ 1 ]) >= Math::MACHINE_EPSILON_1 )||
( fabsf(value2 - mUniformCacheFloat4[ location ][ 2 ]) >= Math::MACHINE_EPSILON_1 ) )
{
- // make the gl call through context
+ // make the gl call
LOG_GL( "Uniform4f(%d,%f,%f,%f,%f)\n", location, value0, value1, value2, value3 );
CHECK_GL( mContext, mGlAbstraction.Uniform4f( location, value0, value1, value2, value3 ) );
// update cache
return;
}
-
// Not caching these calls. Based on current analysis this is called very often
// but with different values (we're using this for MVP matrices)
- // NOTE! we never want GPU to transpose
+ // NOTE! we never want driver or GPU to transpose
LOG_GL( "UniformMatrix4fv(%d,%d,GL_FALSE,%x)\n", location, count, value );
CHECK_GL( mContext, mGlAbstraction.UniformMatrix4fv( location, count, GL_FALSE, value ) );
}
// Not caching these calls. Based on current analysis this is called very often
// but with different values (we're using this for MVP matrices)
- // NOTE! we never want GPU to transpose
+ // NOTE! we never want driver or GPU to transpose
LOG_GL( "UniformMatrix3fv(%d,%d,GL_FALSE,%x)\n", location, count, value );
CHECK_GL( mContext, mGlAbstraction.UniformMatrix3fv( location, count, GL_FALSE, value ) );
}
Program::Program(Integration::ShaderData* shaderData, Context& context, bool areVerticesFixed )
: mContext( context ),
mGlAbstraction( context.GetAbstraction() ),
+ mProjectionMatrix( NULL ),
+ mViewMatrix( NULL ),
mLinked( false ),
mVertexShaderId( 0 ),
mFragmentShaderId( 0 ),
Program::~Program()
{
- Unload(); // Resets gCurrentProgram
+ Unload();
}
void Program::Load()
/**
* Creates a new program, or returns a copy of an existing program in the program cache
- * maintained by Context
* @param [in] resourceId ResourceManager resourceId for the shader source and binary.
* Used as a lookup key in the program cache
* @param[in] shaderData A pointer to a data structure containing the program source
*/
bool AreVerticesFixed();
+ /**
+ * Set the projection matrix that has currently been sent
+ * @param matrix to set
+ */
+ void SetProjectionMatrix( const Matrix* matrix )
+ {
+ mProjectionMatrix = matrix;
+ }
+
+ /**
+ * Get the projection matrix that has currently been sent
+ * @return the matrix that is set
+ */
+ const Matrix* GetProjectionMatrix()
+ {
+ return mProjectionMatrix;
+ }
+
+ /**
+ * Set the projection matrix that has currently been sent
+ * @param matrix to set
+ */
+ void SetViewMatrix( const Matrix* matrix )
+ {
+ mViewMatrix = matrix;
+ }
+
+ /**
+ * Get the projection matrix that has currently been sent
+ * @return the matrix that is set
+ */
+ const Matrix* GetViewMatrix()
+ {
+ return mViewMatrix;
+ }
+
private: // Implementation
/**
Context& mContext; ///< The GL context state cache
Integration::GlAbstraction& mGlAbstraction; ///< The OpenGL Abstraction layer
+ const Matrix* mProjectionMatrix; ///< currently set projection matrix
+ const Matrix* mViewMatrix; ///< currently set view matrix
bool mLinked; ///< whether the program is linked
GLuint mVertexShaderId; ///< GL identifier for vertex shader
GLuint mFragmentShaderId; ///< GL identifier for fragment shader
DALI_ASSERT_DEBUG(NULL != mPrograms[ programType ][ subType ]);
Program& program = *(mPrograms[ programType ][ subType ]);
- program.Use();
// Ignore missing uniforms - custom shaders and flat color shaders don't have SAMPLER
program.SetUniformMatrix4fv( loc, 1, modelview.AsFloat() );
}
- loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
- if( Program::UNIFORM_UNKNOWN != loc )
- {
- DALI_PRINT_UNIFORM( debugStream, bufferIndex, "uProjection", projection );
- program.SetUniformMatrix4fv( loc, 1, projection.AsFloat() );
- }
-
loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
if( Program::UNIFORM_UNKNOWN != loc )
{
program.SetUniformMatrix4fv( loc, 1, model.AsFloat() );
}
- loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
- if( Program::UNIFORM_UNKNOWN != loc )
- {
- DALI_PRINT_UNIFORM( debugStream, bufferIndex, "uViewMatrix", view );
- program.SetUniformMatrix4fv( loc, 1, view.AsFloat() );
- }
-
// We should have one UniformMeta per uniform property
for ( unsigned int i = 0u; i < mUniformMetadata.Count(); ++i )
{