avoid sending view and projection matrices multiple times per frame to gl programs 96/24096/1
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Mon, 30 Jun 2014 17:05:05 +0000 (18:05 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 8 Jul 2014 13:19:39 +0000 (14:19 +0100)
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>
dali/internal/render/common/render-manager.cpp
dali/internal/render/gl-resources/context.cpp
dali/internal/render/gl-resources/context.h
dali/internal/render/renderers/scene-graph-renderer.cpp
dali/internal/render/shaders/program.cpp
dali/internal/render/shaders/program.h
dali/internal/render/shaders/shader.cpp

index db84631..d5a4058 100644 (file)
@@ -383,6 +383,11 @@ bool RenderManager::Render( Integration::RenderStatus& status )
     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 )
     {
index 6dc4384..f664268 100644 (file)
@@ -155,6 +155,16 @@ const char* Context::ErrorToString( GLenum errorCode )
   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);
index 369545a..b5d17d3 100644 (file)
@@ -83,7 +83,7 @@ public:
   void GlContextCreated();
 
   /**
-   * Called when the GL context is about to be destroyed.
+   * Called when the GL context has been destroyed.
    */
   void GlContextDestroyed();
 
@@ -1647,6 +1647,11 @@ public:
   }
 
   /**
+   * Reset the program matrices
+   */
+  void ResetProgramMatrices();
+
+  /**
    * Get a cached program
    * @param [in] hash value
    * @return pointer to the program
index 57a5b55..9fcd0db 100644 (file)
@@ -32,6 +32,35 @@ namespace Dali
 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
 {
 
@@ -76,7 +105,7 @@ void Renderer::Render( BufferIndex bufferIndex,
                        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!!" );
@@ -132,8 +161,14 @@ void Renderer::Render( BufferIndex bufferIndex,
   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 );
 }
 
index 79932d0..9fdc1a3 100644 (file)
@@ -228,7 +228,7 @@ void Program::SetUniform1i( GLint location, GLint 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( "Uniform1i(%d,%d)\n", location, value0 );
     CHECK_GL( mContext, mGlAbstraction.Uniform1i( location, value0 ) );
   }
@@ -237,7 +237,7 @@ void Program::SetUniform1i( GLint location, GLint 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
@@ -278,7 +278,7 @@ void Program::SetUniform1f( GLint location, GLfloat 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( "Uniform1f(%d,%f)\n", location, value0 );
     CHECK_GL( mContext, mGlAbstraction.Uniform1f( location, value0 ) );
   }
@@ -287,7 +287,7 @@ void Program::SetUniform1f( GLint location, GLfloat 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 ) );
 
@@ -346,7 +346,7 @@ void Program::SetUniform4f( GLint location, GLfloat value0, GLfloat value1, GLfl
   // 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 ) );
   }
@@ -359,7 +359,7 @@ void Program::SetUniform4f( GLint location, GLfloat value0, GLfloat value1, GLfl
         ( 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
@@ -383,10 +383,9 @@ void Program::SetUniformMatrix4fv( GLint location, GLsizei count, const GLfloat*
     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 ) );
 }
@@ -406,7 +405,7 @@ void Program::SetUniformMatrix3fv( GLint location, GLsizei count, const GLfloat*
 
   // 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 ) );
 }
@@ -439,6 +438,8 @@ bool Program::AreVerticesFixed()
 Program::Program(Integration::ShaderData* shaderData, Context& context, bool areVerticesFixed )
 : mContext( context ),
   mGlAbstraction( context.GetAbstraction() ),
+  mProjectionMatrix( NULL ),
+  mViewMatrix( NULL ),
   mLinked( false ),
   mVertexShaderId( 0 ),
   mFragmentShaderId( 0 ),
@@ -459,7 +460,7 @@ Program::Program(Integration::ShaderData* shaderData, Context& context, bool are
 
 Program::~Program()
 {
-  Unload(); // Resets gCurrentProgram
+  Unload();
 }
 
 void Program::Load()
index b2633f1..5878e7c 100644 (file)
@@ -130,7 +130,6 @@ public:
 
   /**
    * 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
@@ -257,6 +256,42 @@ public:
    */
   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
 
   /**
@@ -319,6 +354,8 @@ private:  // Data
 
   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
index 70a6c1b..4822dd1 100644 (file)
@@ -323,7 +323,6 @@ Program& Shader::Apply( Context& context,
   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
 
@@ -360,13 +359,6 @@ Program& Shader::Apply( Context& context,
     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 )
   {
@@ -398,13 +390,6 @@ Program& Shader::Apply( Context& context,
     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 )
   {