Browse Source

Refactor rendertarget update handling, to ensure both always-update and manual-update respect the order of backbuffer views rendering first. Closes #1171.

Lasse Öörni 10 years ago
parent
commit
6b775d7537

+ 5 - 28
Source/Urho3D/Graphics/Direct3D11/D3D11RenderSurface.cpp

@@ -80,30 +80,12 @@ void RenderSurface::SetLinkedDepthStencil(RenderSurface* depthStencil)
 
 
 void RenderSurface::QueueUpdate()
 void RenderSurface::QueueUpdate()
 {
 {
-    if (!updateQueued_)
-    {
-        bool hasValidView = false;
-
-        // Verify that there is at least 1 non-null viewport, as otherwise Renderer will not accept the surface and the update flag
-        // will be left on
-        for (unsigned i = 0; i < viewports_.Size(); ++i)
-        {
-            if (viewports_[i])
-            {
-                hasValidView = true;
-                break;
-            }
-        }
-
-        if (hasValidView)
-        {
-            Renderer* renderer = parentTexture_->GetSubsystem<Renderer>();
-            if (renderer)
-                renderer->QueueRenderSurface(this);
+    updateQueued_ = true;
+}
 
 
-            updateQueued_ = true;
-        }
-    }
+void RenderSurface::ResetUpdateQueued()
+{
+    updateQueued_ = false;
 }
 }
 
 
 void RenderSurface::Release()
 void RenderSurface::Release()
@@ -145,9 +127,4 @@ Viewport* RenderSurface::GetViewport(unsigned index) const
     return index < viewports_.Size() ? viewports_[index] : (Viewport*)0;
     return index < viewports_.Size() ? viewports_[index] : (Viewport*)0;
 }
 }
 
 
-void RenderSurface::WasUpdated()
-{
-    updateQueued_ = false;
-}
-
 }
 }

+ 4 - 2
Source/Urho3D/Graphics/Direct3D11/D3D11RenderSurface.h

@@ -88,8 +88,10 @@ public:
     /// Return linked depth-stencil surface.
     /// Return linked depth-stencil surface.
     RenderSurface* GetLinkedDepthStencil() const { return linkedDepthStencil_; }
     RenderSurface* GetLinkedDepthStencil() const { return linkedDepthStencil_; }
 
 
-    /// Clear update flag. Called by Renderer.
-    void WasUpdated();
+    /// Return whether manual update queued. Called internally.
+    bool IsUpdateQueued() const { return updateQueued_; }
+    /// Reset update queued flag. Called internally.
+    void ResetUpdateQueued();
 
 
 private:
 private:
     /// Parent texture.
     /// Parent texture.

+ 7 - 2
Source/Urho3D/Graphics/Direct3D11/D3D11Texture2D.cpp

@@ -537,8 +537,13 @@ bool Texture2D::Create()
 
 
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
-    if (renderSurface_ && renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-        renderSurface_->QueueUpdate();
+    if (renderSurface_ && (renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurface_->IsUpdateQueued()))
+    {
+        Renderer* renderer = GetSubsystem<Renderer>();
+        if (renderer)
+            renderer->QueueRenderSurface(renderSurface_);
+        renderSurface_->ResetUpdateQueued();
+    }
 }
 }
 
 
 }
 }

+ 8 - 2
Source/Urho3D/Graphics/Direct3D11/D3D11TextureCube.cpp

@@ -739,10 +739,16 @@ bool TextureCube::Create()
 
 
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
+    Renderer* renderer = GetSubsystem<Renderer>();
+
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     {
     {
-        if (renderSurfaces_[i] && renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-            renderSurfaces_[i]->QueueUpdate();
+        if (renderSurfaces_[i] && (renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurfaces_[i]->IsUpdateQueued()))
+        {
+            if (renderer)
+                renderer->QueueRenderSurface(renderSurfaces_[i]);
+            renderSurfaces_[i]->ResetUpdateQueued();
+        }
     }
     }
 }
 }
 
 

+ 5 - 28
Source/Urho3D/Graphics/Direct3D9/D3D9RenderSurface.cpp

@@ -79,30 +79,12 @@ void RenderSurface::SetLinkedDepthStencil(RenderSurface* depthStencil)
 
 
 void RenderSurface::QueueUpdate()
 void RenderSurface::QueueUpdate()
 {
 {
-    if (!updateQueued_)
-    {
-        bool hasValidView = false;
-
-        // Verify that there is at least 1 non-null viewport, as otherwise Renderer will not accept the surface and the update flag
-        // will be left on
-        for (unsigned i = 0; i < viewports_.Size(); ++i)
-        {
-            if (viewports_[i])
-            {
-                hasValidView = true;
-                break;
-            }
-        }
-
-        if (hasValidView)
-        {
-            Renderer* renderer = parentTexture_->GetSubsystem<Renderer>();
-            if (renderer)
-                renderer->QueueRenderSurface(this);
+    updateQueued_ = true;
+}
 
 
-            updateQueued_ = true;
-        }
-    }
+void RenderSurface::ResetUpdateQueued()
+{
+    updateQueued_ = false;
 }
 }
 
 
 void RenderSurface::Release()
 void RenderSurface::Release()
@@ -143,9 +125,4 @@ Viewport* RenderSurface::GetViewport(unsigned index) const
     return index < viewports_.Size() ? viewports_[index] : (Viewport*)0;
     return index < viewports_.Size() ? viewports_[index] : (Viewport*)0;
 }
 }
 
 
-void RenderSurface::WasUpdated()
-{
-    updateQueued_ = false;
-}
-
 }
 }

+ 4 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9RenderSurface.h

@@ -85,8 +85,10 @@ public:
     /// Return linked depth-stencil surface.
     /// Return linked depth-stencil surface.
     RenderSurface* GetLinkedDepthStencil() const { return linkedDepthStencil_; }
     RenderSurface* GetLinkedDepthStencil() const { return linkedDepthStencil_; }
 
 
-    /// Clear update flag. Called by Renderer.
-    void WasUpdated();
+    /// Return whether manual update queued. Called internally.
+    bool IsUpdateQueued() const { return updateQueued_; }
+    /// Reset update queued flag. Called internally.
+    void ResetUpdateQueued();
 
 
 private:
 private:
     /// Parent texture.
     /// Parent texture.

+ 7 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.cpp

@@ -649,8 +649,13 @@ bool Texture2D::Create()
 
 
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
-    if (renderSurface_ && renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-        renderSurface_->QueueUpdate();
+    if (renderSurface_ && (renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurface_->IsUpdateQueued()))
+    {
+        Renderer* renderer = GetSubsystem<Renderer>();
+        if (renderer)
+            renderer->QueueRenderSurface(renderSurface_);
+        renderSurface_->ResetUpdateQueued();
+    }
 }
 }
 
 
 }
 }

+ 8 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.cpp

@@ -843,10 +843,16 @@ bool TextureCube::Create()
 
 
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
+    Renderer* renderer = GetSubsystem<Renderer>();
+
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     {
     {
-        if (renderSurfaces_[i] && renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-            renderSurfaces_[i]->QueueUpdate();
+        if (renderSurfaces_[i] && (renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurfaces_[i]->IsUpdateQueued()))
+        {
+            if (renderer)
+                renderer->QueueRenderSurface(renderSurfaces_[i]);
+            renderSurfaces_[i]->ResetUpdateQueued();
+        }
     }
     }
 }
 }
 
 

+ 1 - 1
Source/Urho3D/Graphics/GraphicsEvents.h

@@ -44,7 +44,7 @@ URHO3D_EVENT(E_WINDOWPOS, WindowPos)
     URHO3D_PARAM(P_Y, Y);                          // int
     URHO3D_PARAM(P_Y, Y);                          // int
 }
 }
 
 
-/// Request for queuing autoupdated rendersurfaces.
+/// Request for queuing rendersurfaces either in manual or always-update mode.
 URHO3D_EVENT(E_RENDERSURFACEUPDATE, RenderSurfaceUpdate)
 URHO3D_EVENT(E_RENDERSURFACEUPDATE, RenderSurfaceUpdate)
 {
 {
 }
 }

+ 5 - 28
Source/Urho3D/Graphics/OpenGL/OGLRenderSurface.cpp

@@ -88,30 +88,12 @@ void RenderSurface::SetLinkedDepthStencil(RenderSurface* depthStencil)
 
 
 void RenderSurface::QueueUpdate()
 void RenderSurface::QueueUpdate()
 {
 {
-    if (!updateQueued_)
-    {
-        bool hasValidView = false;
-
-        // Verify that there is at least 1 non-null viewport, as otherwise Renderer will not accept the surface and the update flag
-        // will be left on
-        for (unsigned i = 0; i < viewports_.Size(); ++i)
-        {
-            if (viewports_[i])
-            {
-                hasValidView = true;
-                break;
-            }
-        }
-
-        if (hasValidView)
-        {
-            Renderer* renderer = parentTexture_->GetSubsystem<Renderer>();
-            if (renderer)
-                renderer->QueueRenderSurface(this);
+    updateQueued_ = true;
+}
 
 
-            updateQueued_ = true;
-        }
-    }
+void RenderSurface::ResetUpdateQueued()
+{
+    updateQueued_ = false;
 }
 }
 
 
 bool RenderSurface::CreateRenderBuffer(unsigned width, unsigned height, unsigned format)
 bool RenderSurface::CreateRenderBuffer(unsigned width, unsigned height, unsigned format)
@@ -202,9 +184,4 @@ void RenderSurface::SetTarget(unsigned target)
     target_ = target;
     target_ = target;
 }
 }
 
 
-void RenderSurface::WasUpdated()
-{
-    updateQueued_ = false;
-}
-
 }
 }

+ 4 - 2
Source/Urho3D/Graphics/OpenGL/OGLRenderSurface.h

@@ -97,8 +97,10 @@ public:
     /// Return surface's OpenGL target.
     /// Return surface's OpenGL target.
     unsigned GetTarget() const { return target_; }
     unsigned GetTarget() const { return target_; }
 
 
-    /// Clear update flag. Called by Renderer.
-    void WasUpdated();
+    /// Return whether manual update queued. Called internally.
+    bool IsUpdateQueued() const { return updateQueued_; }
+    /// Reset update queued flag. Called internally.
+    void ResetUpdateQueued();
 
 
 private:
 private:
     /// Parent texture.
     /// Parent texture.

+ 7 - 2
Source/Urho3D/Graphics/OpenGL/OGLTexture2D.cpp

@@ -522,8 +522,13 @@ bool Texture2D::Create()
 
 
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void Texture2D::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
-    if (renderSurface_ && renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-        renderSurface_->QueueUpdate();
+    if (renderSurface_ && (renderSurface_->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurface_->IsUpdateQueued()))
+    {
+        Renderer* renderer = GetSubsystem<Renderer>();
+        if (renderer)
+            renderer->QueueRenderSurface(renderSurface_);
+        renderSurface_->ResetUpdateQueued();
+    }
 }
 }
 
 
 }
 }

+ 8 - 2
Source/Urho3D/Graphics/OpenGL/OGLTextureCube.cpp

@@ -727,10 +727,16 @@ bool TextureCube::Create()
 
 
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 void TextureCube::HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
+    Renderer* renderer = GetSubsystem<Renderer>();
+
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
     {
     {
-        if (renderSurfaces_[i] && renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS)
-            renderSurfaces_[i]->QueueUpdate();
+        if (renderSurfaces_[i] && (renderSurfaces_[i]->GetUpdateMode() == SURFACE_UPDATEALWAYS || renderSurfaces_[i]->IsUpdateQueued()))
+        {
+            if (renderer)
+                renderer->QueueRenderSurface(renderSurfaces_[i]);
+            renderSurfaces_[i]->ResetUpdateQueued();
+        }
     }
     }
 }
 }
 
 

+ 6 - 10
Source/Urho3D/Graphics/Renderer.cpp

@@ -680,14 +680,6 @@ void Renderer::Update(float timeStep)
         view->Update(frame_);
         view->Update(frame_);
     }
     }
 
 
-    // Reset update flag from queued render surfaces. At this point no new views can be added on this frame
-    for (unsigned i = 0; i < queuedViewports_.Size(); ++i)
-    {
-        WeakPtr<RenderSurface>& renderTarget = queuedViewports_[i].first_;
-        if (renderTarget)
-            renderTarget->WasUpdated();
-    }
-
     queuedViewports_.Clear();
     queuedViewports_.Clear();
     resetViews_ = false;
     resetViews_ = false;
 }
 }
@@ -814,8 +806,12 @@ void Renderer::QueueViewport(RenderSurface* renderTarget, Viewport* viewport)
 {
 {
     if (viewport)
     if (viewport)
     {
     {
-        queuedViewports_.Push(Pair<WeakPtr<RenderSurface>, WeakPtr<Viewport> >(WeakPtr<RenderSurface>(renderTarget),
-            WeakPtr<Viewport>(viewport)));
+        Pair<WeakPtr<RenderSurface>, WeakPtr<Viewport> > newView = 
+            MakePair(WeakPtr<RenderSurface>(renderTarget), WeakPtr<Viewport>(viewport));
+
+        // Prevent double add of the same rendertarget/viewport combination
+        if (!queuedViewports_.Contains(newView))
+            queuedViewports_.Push(newView);
     }
     }
 }
 }