Regenerating uniform maps fix 69/221469/5
authoradam.b <adam.b@samsung.com>
Thu, 2 Jan 2020 16:45:08 +0000 (16:45 +0000)
committeradam.b <adam.b@samsung.com>
Fri, 3 Jan 2020 15:40:45 +0000 (15:40 +0000)
The problem:
Crash when uniform maps changed on the update side but not on the render side.
The crash is caused if "keep rendering".

The fix:
When new shader is set, the message is sent to Render::Renderer which will be
executed when object becomes visible (renderable). The message sets the flag
indicating whether the shader changed so next time the renderer sets uniforms
first the maps will be regenerated.

Change-Id: I06d872945f1db6c8fe180d347a5674e8931761b7

automated-tests/src/dali/utc-Dali-Renderer.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h

index 0410a52..3a12e96 100644 (file)
@@ -3009,3 +3009,51 @@ int UtcDaliRendererRenderingBehavior(void)
 
   END_TEST;
 }
+
+int UtcDaliRendererRegenerateUniformMap(void)
+{
+  TestApplication application;
+
+  tet_infoline( "Test regenerating uniform map when attaching renderer to the node" );
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc" );
+  Renderer renderer = Renderer::New( geometry, shader );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer( renderer );
+  actor.SetSize( 400, 400 );
+  actor.SetColor( Vector4( 1.0f, 0.0f, 1.0f, 1.0f ) );
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  actor.RemoveRenderer( renderer );
+  shader = Shader::New( "vertexSrc", "fragmentSrc" );
+  shader.RegisterProperty( "opacity", 0.5f );
+  renderer.SetShader( shader );
+
+  Stage::GetCurrent().KeepRendering( 1.0f );
+
+  // Update for several frames
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // Add Renderer
+  actor.AddRenderer( renderer );
+  application.SendNotification();
+  application.Render();
+
+  // Nothing to test here, the test must not crash
+  auto updateStatus = application.GetUpdateStatus();
+  DALI_TEST_CHECK( updateStatus & Integration::KeepUpdating::STAGE_KEEP_RENDERING );
+
+  END_TEST;
+}
index 74c4959..9324d86 100644 (file)
@@ -145,7 +145,8 @@ Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
   mDepthWriteMode( depthWriteMode ),
   mDepthTestMode( depthTestMode ),
   mUpdateAttributesLocation( true ),
-  mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
+  mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
+  mShaderChanged( false )
 {
   if( blendingBitmask != 0u )
   {
@@ -216,8 +217,12 @@ void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataP
 
   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
       node.GetUniformMapChanged(bufferIndex) ||
-      mUniformIndexMap.Count() == 0)
+      mUniformIndexMap.Count() == 0 ||
+      mShaderChanged )
   {
+    // Reset shader pointer
+    mShaderChanged = false;
+
     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
 
@@ -586,6 +591,11 @@ void Renderer::SetSortAttributes( BufferIndex bufferIndex,
   sortAttributes.geometry = mGeometry;
 }
 
+void Renderer::SetShaderChanged( bool value )
+{
+  mShaderChanged = value;
+}
+
 } // namespace SceneGraph
 
 } // namespace Internal
index 9157d72..406dff4 100755 (executable)
@@ -371,6 +371,13 @@ public:
    */
   void SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const;
 
+  /**
+   * Sets the flag indicating whether shader changed.
+   *
+   * @param[in] value True if shader changed
+   */
+  void SetShaderChanged( bool value );
+
 private:
 
   struct UniformIndexMap;
@@ -444,6 +451,8 @@ private:
   DepthTestMode::Type          mDepthTestMode:3;            ///< The depth test mode
   bool                         mUpdateAttributesLocation:1; ///< Indicates attribute locations have changed
   bool                         mPremultipledAlphaEnabled:1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
+  bool                         mShaderChanged:1;            ///< Flag indicating the shader changed and uniform maps have to be updated
+
 
 };
 
index 169be5c..ad0974b 100644 (file)
@@ -112,7 +112,8 @@ enum Flags
   RESEND_STENCIL_OPERATION_ON_FAIL   = 1 << 15,
   RESEND_STENCIL_OPERATION_ON_Z_FAIL = 1 << 16,
   RESEND_STENCIL_OPERATION_ON_Z_PASS = 1 << 17,
-  RESEND_WRITE_TO_COLOR_BUFFER       = 1 << 18
+  RESEND_WRITE_TO_COLOR_BUFFER       = 1 << 18,
+  RESEND_SHADER                      = 1 << 19,
 };
 
 } // Anonymous namespace
@@ -341,6 +342,13 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex )
       new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilOperationOnZPass, mStencilParameters.stencilOperationOnZPass );
     }
 
+    if( mResendFlag & RESEND_SHADER )
+    {
+      typedef MessageValue1< Render::Renderer, bool > DerivedType;
+      uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+      new (slot) DerivedType( mRenderer, &Render::Renderer::SetShaderChanged, true );
+    }
+
     mResendFlag = 0;
   }
 }
@@ -373,7 +381,7 @@ void Renderer::SetShader( Shader* shader )
   mShader = shader;
   mShader->AddConnectionObserver( *this );
   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
-  mResendFlag |= RESEND_GEOMETRY;
+  mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER;
 
   if( mRenderDataProvider )
   {
index 7051e44..508b4af 100755 (executable)
@@ -470,7 +470,6 @@ private:
   DepthWriteMode::Type         mDepthWriteMode:3;                 ///< Local copy of the depth write mode
   DepthTestMode::Type          mDepthTestMode:3;                  ///< Local copy of the depth test mode
   DevelRenderer::Rendering::Type mRenderingBehavior:2;            ///< The rendering behavior
-
   bool                         mUniformMapChanged[2];             ///< Records if the uniform map has been altered this frame
   bool                         mPremultipledAlphaEnabled:1;       ///< Flag indicating whether the Pre-multiplied Alpha Blending is required