Ensuring GL Sync is only used for RefreshOnce render tasks 59/58259/6
authorDavid Steele <david.steele@samsung.com>
Thu, 28 Jan 2016 14:37:21 +0000 (14:37 +0000)
committerDavid Steele <david.steele@samsung.com>
Thu, 4 Feb 2016 15:03:00 +0000 (07:03 -0800)
GL Sync is currently used when a framebuffer is backed with a native
image.  It is tracked using a RenderTracker, which is created in
SceneGraph::RenderTask::PrepareRenderInstruction.  In
RenderManager::DoRender, if the render tracker is available, then this
creates a sync object.  Consequently, if the render task is a
RefreshAlways task, then a sync object is created each frame.

This change ensures that a render tracker is only created for a
RefreshOnce render tracker, and that the sync object is created only
once, rather than every frame.

Change-Id: I93f5c2649c58cc3100b4ddc8546cf023cd728e5a
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali/dali-test-suite-utils/test-application.h
automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp
automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h
automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/render/common/render-manager.cpp
dali/internal/update/manager/process-render-tasks.cpp
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h

index 995e117..5fb6e11 100644 (file)
@@ -59,6 +59,9 @@ TestApplication::TestApplication( bool   initialize,
 
 void TestApplication::Initialize()
 {
+  // We always need the first update!
+  mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING;
+
   mCore = Dali::Integration::Core::New(
     mRenderController,
     mPlatformAbstraction,
@@ -153,11 +156,20 @@ void TestApplication::SetSurfaceWidth( unsigned int width, unsigned height )
 
 void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
 {
+  if( GetUpdateStatus() == 0 &&
+      mRenderStatus.NeedsUpdate() == false &&
+      ! GetRenderController().WasCalled(TestRenderController::RequestUpdateFunc) )
+  {
+    fprintf(stderr, "WARNING - Update not required\n");
+  }
+
   unsigned int nextVSyncTime = mLastVSyncTime + intervalMilliseconds;
   float elapsedSeconds = intervalMilliseconds / 1e3f;
 
   mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus );
 
+  GetRenderController().Initialize();
+
   mLastVSyncTime = nextVSyncTime;
 }
 
@@ -182,6 +194,15 @@ bool TestApplication::UpdateOnly( unsigned int intervalMilliseconds  )
   return mStatus.KeepUpdating();
 }
 
+bool TestApplication::GetRenderNeedsUpdate()
+{
+  return mRenderStatus.NeedsUpdate();
+}
+bool TestApplication::GetRenderHasRendered()
+{
+  return mRenderStatus.HasRendered();
+}
+
 bool TestApplication::RenderOnly( )
 {
   // Update Time values
index 3f61b93..cb5a92c 100644 (file)
@@ -78,6 +78,8 @@ public:
   bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
   bool RenderOnly( );
   void ResetContext();
+  bool GetRenderNeedsUpdate();
+  bool GetRenderHasRendered();
 
 private:
   void DoUpdate( unsigned int intervalMilliseconds );
index 533355c..65a884e 100644 (file)
@@ -132,5 +132,10 @@ void TestGlSyncAbstraction::ResetTrace() { mTrace.Reset(); }
  */
 TraceCallStack& TestGlSyncAbstraction::GetTrace() { return mTrace; }
 
+int TestGlSyncAbstraction::GetNumberOfSyncObjects()
+{
+  return mSyncObjects.size();
+}
+
 
 } // Dali
index e233176..278bcd7 100644 (file)
@@ -100,6 +100,13 @@ public: // TEST FUNCTIONS
    */
   TraceCallStack& GetTrace();
 
+  /**
+   * Get the number of sync objects
+   *
+   * @return the number of sync objects
+   */
+  int GetNumberOfSyncObjects();
+
 private:
   typedef std::vector<TestSyncObject*>   SyncContainer;
   typedef SyncContainer::iterator SyncIter;
index 69339c6..a18e05f 100644 (file)
@@ -28,6 +28,7 @@
 
 #define BOOLSTR(x) ((x)?"T":"F")
 
+//& set: DaliRenderTask
 
 using namespace Dali;
 
@@ -261,6 +262,9 @@ bool UpdateRender(TestApplication& application, TraceCallStack& callStack, bool
 {
   finishedSig = false;
   callStack.Reset();
+
+  tet_printf("TestApplication::UpdateRender().\n");
+
   application.Render(16);
   application.SendNotification();
 
@@ -1795,9 +1799,7 @@ int UtcDaliRenderTaskSignalFinished(void)
   DALI_TEST_CHECK( finished );
   finished = false;
 
-  application.Render(); // Double check no more finished signal
-  application.SendNotification();
-  DALI_TEST_CHECK( ! finished );
+  DALI_TEST_EQUALS( application.GetUpdateStatus(), 0, TEST_LOCATION );
   END_TEST;
 }
 
@@ -2475,6 +2477,7 @@ int UtcDaliRenderTaskOnce08(void)
   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
   TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
   TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  sync.GetTrace().Enable(true);
   drawTrace.Enable(true);
 
   Actor rootActor = Actor::New();
@@ -2492,7 +2495,7 @@ int UtcDaliRenderTaskOnce08(void)
 
   Stage::GetCurrent().Add(secondRootActor);
 
-  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, /*GL-SYNC*/ true);
   bool finished = false;
 
   ConnectionTracker connectionTracker;
@@ -2504,6 +2507,9 @@ int UtcDaliRenderTaskOnce08(void)
   // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false, __LINE__ ) );
   Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+  DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 0, TEST_LOCATION );
+
 
   // CHANGE TO RENDER ONCE,
   newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
@@ -2511,10 +2517,20 @@ int UtcDaliRenderTaskOnce08(void)
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true, __LINE__ ) );
   lastSyncObj = sync.GetLastSyncObject();
   DALI_TEST_CHECK( lastSyncObj != NULL );
+  DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
 
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true, __LINE__ ) );
+
+
+  DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
+
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true, __LINE__ ) );
 
+  DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
+
   sync.SetObjectSynced( lastSyncObj, true );
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true, __LINE__ ) );
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false, __LINE__ ) );
@@ -2834,15 +2850,26 @@ int UtcDaliRenderTaskOnceNoSync04(void)
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true, __LINE__ ) );
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true, __LINE__ ) );
 
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+
   // FINISH RESOURCE LOADING
   CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false, __LINE__ ) );
   application.GetPlatform().ClearReadyResources();
 
+  lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+
   newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
   application.SendNotification(); //         Input,    Expected  Input,    Expected
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true, __LINE__ ) );
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false, __LINE__ ) );
+
+  lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+
   END_TEST;
 }
 
@@ -2877,6 +2904,10 @@ int UtcDaliRenderTaskOnceNoSync05(void)
   newTask.FinishedSignal().Connect( &application, renderTaskFinished );
   application.SendNotification();
 
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+
   // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true, __LINE__ ) );
   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true, __LINE__ ) );
@@ -3325,7 +3356,7 @@ int UtcDaliRenderTaskFinishInvisibleSourceActor(void)
 {
   TestApplication application;
 
-  tet_infoline("Testing RenderTask::SignalFinished()");
+  tet_infoline("Testing RenderTask::FinishInvisibleSourceActor()");
 
   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
   TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
@@ -3461,7 +3492,6 @@ int UtcDaliRenderTaskWorldToViewport(void)
 
   Stage::GetCurrent().Add(actor);
 
-  application.Render();
   application.SendNotification();
   application.Render();
   application.SendNotification();
@@ -3491,7 +3521,6 @@ int UtcDaliRenderTaskWorldToViewport(void)
   actor2.Add(actor);
   actor.SetParentOrigin( Vector3(0,0,0) );
 
-  application.Render();
   application.SendNotification();
   application.Render();
   application.SendNotification();
@@ -3521,6 +3550,8 @@ int UtcDaliRenderTaskViewportToLocal(void)
   // flush the queue and render once
   application.SendNotification();
   application.Render();
+  application.SendNotification();
+  application.Render();
 
   float localX;
   float localY;
index 082d601..ce16412 100644 (file)
@@ -612,6 +612,9 @@ void RenderManager::DoRender( RenderInstruction& instruction, Shader& defaultSha
 
   if( instruction.mRenderTracker && offscreen != NULL )
   {
+    // This will create a sync object every frame this render tracker
+    // is alive (though it should be now be created only for
+    // render-once render tasks)
     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
     instruction.mRenderTracker = NULL; // Only create once.
   }
index 81107f7..bcaf5fa 100644 (file)
@@ -252,6 +252,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
                                                  renderTask,
                                                  sourceNode->GetDrawMode() );
 
+      renderTask.SetResourcesFinished( resourcesFinished );
       PrepareRenderInstruction( updateBufferIndex,
                                 sortedLayers,
                                 renderTask,
@@ -259,8 +260,10 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
                                 renderTask.GetCullMode(),
                                 instructions );
     }
-
-    renderTask.SetResourcesFinished( resourcesFinished );
+    else
+    {
+      renderTask.SetResourcesFinished( resourcesFinished );
+    }
   }
 
   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n");
index 95b9015..5c06a12 100644 (file)
@@ -417,10 +417,11 @@ void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, Buffe
                      viewportSet ? &viewport : NULL,
                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
 
-  // if using native framebuffer, add a tracker
-  if( mTargetIsNativeFramebuffer )
+  if( mTargetIsNativeFramebuffer &&
+      mRefreshRate == Dali::RenderTask::REFRESH_ONCE &&
+      mResourcesFinished )
   {
-    // create tracker if not yet exists. if we switch to on-screen fbo, we still keep the tracker in case we need it again
+    // create tracker if one doesn't yet exist.
     if( !mRenderSyncTracker )
     {
       mRenderSyncTracker = new Render::RenderTracker();
index 3ccbbc2..698abe6 100644 (file)
@@ -313,6 +313,11 @@ public:
 
   /**
    * Prepares the render-instruction buffer to be populated with instructions.
+   *
+   * If the render task is a render-once framebuffer backed by a native image,
+   * then this method will ensure that a GL sync object is created to track
+   * when the rendering has finished.
+   *
    * @param[out] instruction to prepare
    * @param[in] updateBufferIndex The current update buffer index.
    */