Browse Source

Keep track of last bound VBO & UBO to avoid redundant binding.

Lasse Öörni 10 years ago
parent
commit
42963a7300

+ 3 - 2
Source/Urho3D/Graphics/OpenGL/OGLConstantBuffer.cpp

@@ -50,6 +50,7 @@ void ConstantBuffer::Release()
             return;
             return;
 
 
         #ifndef GL_ES_VERSION_2_0
         #ifndef GL_ES_VERSION_2_0
+        graphics_->SetUBO(0);
         glDeleteBuffers(1, &object_);
         glDeleteBuffers(1, &object_);
         #endif
         #endif
         object_ = 0;
         object_ = 0;
@@ -87,7 +88,7 @@ bool ConstantBuffer::SetSize(unsigned size)
         #ifndef GL_ES_VERSION_2_0
         #ifndef GL_ES_VERSION_2_0
         if (!object_)
         if (!object_)
             glGenBuffers(1, &object_);
             glGenBuffers(1, &object_);
-        glBindBuffer(GL_UNIFORM_BUFFER, object_);
+        graphics_->SetUBO(object_);
         glBufferData(GL_UNIFORM_BUFFER, size_, shadowData_.Get(), GL_DYNAMIC_DRAW);
         glBufferData(GL_UNIFORM_BUFFER, size_, shadowData_.Get(), GL_DYNAMIC_DRAW);
         #endif
         #endif
     }
     }
@@ -128,7 +129,7 @@ void ConstantBuffer::Apply()
     if (dirty_ && object_)
     if (dirty_ && object_)
     {
     {
         #ifndef GL_ES_VERSION_2_0
         #ifndef GL_ES_VERSION_2_0
-        glBindBuffer(GL_UNIFORM_BUFFER, object_);
+        graphics_->SetUBO(object_);
         glBufferData(GL_UNIFORM_BUFFER, size_, shadowData_.Get(), GL_DYNAMIC_DRAW);
         glBufferData(GL_UNIFORM_BUFFER, size_, shadowData_.Get(), GL_DYNAMIC_DRAW);
         #endif
         #endif
         dirty_ = false;
         dirty_ = false;

+ 47 - 20
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -590,7 +590,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     
     
     // Store the system FBO on IOS now
     // Store the system FBO on IOS now
     #ifdef IOS
     #ifdef IOS
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFbo_);
+    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
     #endif
     #endif
     
     
     fullscreen_ = fullscreen;
     fullscreen_ = fullscreen;
@@ -957,7 +957,7 @@ bool Graphics::SetVertexBuffers(const PODVector<VertexBuffer*>& buffers, const P
         if (!buffer || !buffer->GetGPUObject())
         if (!buffer || !buffer->GetGPUObject())
             continue;
             continue;
         
         
-        glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
+        SetVBO(buffer->GetGPUObject());
         unsigned vertexSize = buffer->GetVertexSize();
         unsigned vertexSize = buffer->GetVertexSize();
         
         
         for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
         for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
@@ -1055,7 +1055,7 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
         if (!buffer || !buffer->GetGPUObject())
         if (!buffer || !buffer->GetGPUObject())
             continue;
             continue;
         
         
-        glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
+        SetVBO(buffer->GetGPUObject());
         unsigned vertexSize = buffer->GetVertexSize();
         unsigned vertexSize = buffer->GetVertexSize();
         
         
         for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
         for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
@@ -1227,7 +1227,10 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
             ConstantBuffer* buffer = constantBuffers[i].Get();
             ConstantBuffer* buffer = constantBuffers[i].Get();
             if (buffer != currentConstantBuffers_[i])
             if (buffer != currentConstantBuffers_[i])
             {
             {
-                glBindBufferBase(GL_UNIFORM_BUFFER, i, buffer ? buffer->GetGPUObject() : 0);
+                unsigned object = buffer ? buffer->GetGPUObject() : 0;
+                glBindBufferBase(GL_UNIFORM_BUFFER, i, object);
+                // Calling glBindBufferBase also affects the generic buffer binding point
+                impl_->boundUBO_ = object;
                 shaderParameterSources_[i % MAX_SHADER_PARAMETER_GROUPS] = (const void*)M_MAX_UNSIGNED;
                 shaderParameterSources_[i % MAX_SHADER_PARAMETER_GROUPS] = (const void*)M_MAX_UNSIGNED;
                 currentConstantBuffers_[i] = buffer;
                 currentConstantBuffers_[i] = buffer;
             }
             }
@@ -2424,7 +2427,7 @@ void Graphics::CleanupRenderSurface(RenderSurface* surface)
     // Flush pending FBO changes first if any
     // Flush pending FBO changes first if any
     PrepareDraw();
     PrepareDraw();
 
 
-    unsigned currentFbo = impl_->boundFbo_;
+    unsigned currentFBO = impl_->boundFBO_;
 
 
     // Go through all FBOs and clean up the surface from them
     // Go through all FBOs and clean up the surface from them
     for (HashMap<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin();
     for (HashMap<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin();
@@ -2434,10 +2437,10 @@ void Graphics::CleanupRenderSurface(RenderSurface* surface)
         {
         {
             if (i->second_.colorAttachments_[j] == surface)
             if (i->second_.colorAttachments_[j] == surface)
             {
             {
-                if (currentFbo != i->second_.fbo_)
+                if (currentFBO != i->second_.fbo_)
                 {
                 {
                     BindFramebuffer(i->second_.fbo_);
                     BindFramebuffer(i->second_.fbo_);
-                    currentFbo = i->second_.fbo_;
+                    currentFBO = i->second_.fbo_;
                 }
                 }
                 BindColorAttachment(j, GL_TEXTURE_2D, 0);
                 BindColorAttachment(j, GL_TEXTURE_2D, 0);
                 i->second_.colorAttachments_[j] = 0;
                 i->second_.colorAttachments_[j] = 0;
@@ -2447,10 +2450,10 @@ void Graphics::CleanupRenderSurface(RenderSurface* surface)
         }
         }
         if (i->second_.depthAttachment_ == surface)
         if (i->second_.depthAttachment_ == surface)
         {
         {
-            if (currentFbo != i->second_.fbo_)
+            if (currentFBO != i->second_.fbo_)
             {
             {
                 BindFramebuffer(i->second_.fbo_);
                 BindFramebuffer(i->second_.fbo_);
-                currentFbo = i->second_.fbo_;
+                currentFBO = i->second_.fbo_;
             }
             }
             BindDepthAttachment(0, false);
             BindDepthAttachment(0, false);
             BindStencilAttachment(0, false);
             BindStencilAttachment(0, false);
@@ -2459,8 +2462,8 @@ void Graphics::CleanupRenderSurface(RenderSurface* surface)
     }
     }
 
 
     // Restore previously bound FBO now if needed
     // Restore previously bound FBO now if needed
-    if (currentFbo != impl_->boundFbo_)
-        BindFramebuffer(impl_->boundFbo_);
+    if (currentFBO != impl_->boundFBO_)
+        BindFramebuffer(impl_->boundFBO_);
 }
 }
 
 
 void Graphics::CleanupShaderPrograms(ShaderVariation* variation)
 void Graphics::CleanupShaderPrograms(ShaderVariation* variation)
@@ -2574,7 +2577,7 @@ void Graphics::Restore()
     {
     {
         impl_->context_ = SDL_GL_CreateContext(impl_->window_);
         impl_->context_ = SDL_GL_CreateContext(impl_->window_);
         #ifdef IOS
         #ifdef IOS
-        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFbo_);
+        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
         #endif
         #endif
         
         
         ResetCachedState();
         ResetCachedState();
@@ -2617,6 +2620,28 @@ void Graphics::MarkFBODirty()
     impl_->fboDirty_ = true;
     impl_->fboDirty_ = true;
 }
 }
 
 
+void Graphics::SetVBO(unsigned object)
+{
+    if (impl_->boundVBO_ != object)
+    {
+        if (object)
+            glBindBuffer(GL_ARRAY_BUFFER, object);
+        impl_->boundVBO_ = object;
+    }
+}
+
+void Graphics::SetUBO(unsigned object)
+{
+    #ifndef GL_ES_VERSION_2_0
+    if (impl_->boundUBO_ != object)
+    {
+        if (object)
+            glBindBuffer(GL_UNIFORM_BUFFER, object);
+        impl_->boundUBO_ = object;
+    }
+    #endif
+}
+
 unsigned Graphics::GetAlphaFormat()
 unsigned Graphics::GetAlphaFormat()
 {
 {
     #ifndef GL_ES_VERSION_2_0
     #ifndef GL_ES_VERSION_2_0
@@ -2905,10 +2930,10 @@ void Graphics::PrepareDraw()
     
     
         if (noFbo)
         if (noFbo)
         {
         {
-            if (impl_->boundFbo_ != impl_->systemFbo_)
+            if (impl_->boundFBO_ != impl_->systemFBO_)
             {
             {
-                BindFramebuffer(impl_->systemFbo_);
-                impl_->boundFbo_ = impl_->systemFbo_;
+                BindFramebuffer(impl_->systemFBO_);
+                impl_->boundFBO_ = impl_->systemFBO_;
             }
             }
         
         
             #ifndef GL_ES_VERSION_2_0
             #ifndef GL_ES_VERSION_2_0
@@ -2950,10 +2975,10 @@ void Graphics::PrepareDraw()
     
     
         i->second_.useTimer_.Reset();
         i->second_.useTimer_.Reset();
     
     
-        if (impl_->boundFbo_ != i->second_.fbo_)
+        if (impl_->boundFBO_ != i->second_.fbo_)
         {
         {
             BindFramebuffer(i->second_.fbo_);
             BindFramebuffer(i->second_.fbo_);
-            impl_->boundFbo_ = i->second_.fbo_;
+            impl_->boundFBO_ = i->second_.fbo_;
         }
         }
     
     
         #ifndef GL_ES_VERSION_2_0
         #ifndef GL_ES_VERSION_2_0
@@ -3101,7 +3126,7 @@ void Graphics::CleanupFramebuffers(bool force)
         for (HashMap<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin();
         for (HashMap<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin();
             i != impl_->frameBuffers_.End();)
             i != impl_->frameBuffers_.End();)
         {
         {
-            if (i->second_.fbo_ != impl_->boundFbo_ && (force || i->second_.useTimer_.GetMSec(false) >
+            if (i->second_.fbo_ != impl_->boundFBO_ && (force || i->second_.useTimer_.GetMSec(false) >
                 MAX_FRAMEBUFFER_AGE))
                 MAX_FRAMEBUFFER_AGE))
             {
             {
                 DeleteFramebuffer(i->second_.fbo_);
                 DeleteFramebuffer(i->second_.fbo_);
@@ -3113,7 +3138,7 @@ void Graphics::CleanupFramebuffers(bool force)
     }
     }
     else
     else
     {
     {
-        impl_->boundFbo_ = 0;
+        impl_->boundFBO_ = 0;
         impl_->frameBuffers_.Clear();
         impl_->frameBuffers_.Clear();
     }
     }
 }
 }
@@ -3164,7 +3189,9 @@ void Graphics::ResetCachedState()
     lastInstanceOffset_ = 0;
     lastInstanceOffset_ = 0;
     impl_->activeTexture_ = 0;
     impl_->activeTexture_ = 0;
     impl_->enabledAttributes_ = 0;
     impl_->enabledAttributes_ = 0;
-    impl_->boundFbo_ = impl_->systemFbo_;
+    impl_->boundFBO_ = impl_->systemFBO_;
+    impl_->boundVBO_ = 0;
+    impl_->boundUBO_ = 0;
     impl_->sRGBWrite_ = false;
     impl_->sRGBWrite_ = false;
     
     
     // Set initial state to match Direct3D
     // Set initial state to match Direct3D

+ 4 - 0
Source/Urho3D/Graphics/OpenGL/OGLGraphics.h

@@ -398,6 +398,10 @@ public:
     void Minimize();
     void Minimize();
     /// Mark the FBO needing an update.
     /// Mark the FBO needing an update.
     void MarkFBODirty();
     void MarkFBODirty();
+    /// Bind a VBO, avoiding redundant operation.
+    void SetVBO(unsigned object);
+    /// Bind a UBO, avoiding redundant operation.
+    void SetUBO(unsigned object);
     
     
     /// Return the API-specific alpha texture format.
     /// Return the API-specific alpha texture format.
     static unsigned GetAlphaFormat();
     static unsigned GetAlphaFormat();

+ 4 - 2
Source/Urho3D/Graphics/OpenGL/OGLGraphicsImpl.cpp

@@ -31,10 +31,12 @@ namespace Urho3D
 GraphicsImpl::GraphicsImpl() :
 GraphicsImpl::GraphicsImpl() :
     window_(0),
     window_(0),
     context_(0),
     context_(0),
-    systemFbo_(0),
+    systemFBO_(0),
     activeTexture_(0),
     activeTexture_(0),
     enabledAttributes_(0),
     enabledAttributes_(0),
-    boundFbo_(0),
+    boundFBO_(0),
+    boundVBO_(0),
+    boundUBO_(0),
     pixelFormat_(0),
     pixelFormat_(0),
     fboDirty_(false)
     fboDirty_(false)
 {
 {

+ 6 - 2
Source/Urho3D/Graphics/OpenGL/OGLGraphicsImpl.h

@@ -106,13 +106,17 @@ private:
     /// SDL OpenGL context.
     /// SDL OpenGL context.
     SDL_GLContext context_;
     SDL_GLContext context_;
     /// IOS system framebuffer handle.
     /// IOS system framebuffer handle.
-    unsigned systemFbo_;
+    unsigned systemFBO_;
     /// Active texture unit.
     /// Active texture unit.
     unsigned activeTexture_;
     unsigned activeTexture_;
     /// Vertex attributes in use.
     /// Vertex attributes in use.
     unsigned enabledAttributes_;
     unsigned enabledAttributes_;
     /// Currently bound frame buffer object.
     /// Currently bound frame buffer object.
-    unsigned boundFbo_;
+    unsigned boundFBO_;
+    /// Currently bound vertex buffer object.
+    unsigned boundVBO_;
+    /// Currently bound uniform buffer object.
+    unsigned boundUBO_;
     /// Current pixel format.
     /// Current pixel format.
     int pixelFormat_;
     int pixelFormat_;
     /// Map for FBO's per resolution and format.
     /// Map for FBO's per resolution and format.

+ 3 - 7
Source/Urho3D/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -143,8 +143,7 @@ bool IndexBuffer::SetData(const void* data)
     {
     {
         if (!graphics_->IsDeviceLost())
         if (!graphics_->IsDeviceLost())
         {
         {
-            graphics_->SetIndexBuffer(0);
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
+            graphics_->SetIndexBuffer(this);
             glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
             glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         }
         }
         else
         else
@@ -191,8 +190,7 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
     {
     {
         if (!graphics_->IsDeviceLost())
         if (!graphics_->IsDeviceLost())
         {
         {
-            graphics_->SetIndexBuffer(0);
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
+            graphics_->SetIndexBuffer(this);
             if (!discard || start != 0)
             if (!discard || start != 0)
                 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * indexSize_, count * indexSize_, data);
                 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * indexSize_, count * indexSize_, data);
             else
             else
@@ -333,8 +331,6 @@ bool IndexBuffer::Create()
             return true;
             return true;
         }
         }
         
         
-        graphics_->SetIndexBuffer(0);
-        
         if (!object_)
         if (!object_)
             glGenBuffers(1, &object_);
             glGenBuffers(1, &object_);
         if (!object_)
         if (!object_)
@@ -343,7 +339,7 @@ bool IndexBuffer::Create()
             return false;
             return false;
         }
         }
         
         
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
+        graphics_->SetIndexBuffer(this);
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }
     
     

+ 4 - 3
Source/Urho3D/Graphics/OpenGL/OGLVertexBuffer.cpp

@@ -154,6 +154,7 @@ void VertexBuffer::Release()
                     graphics_->SetVertexBuffer(0);
                     graphics_->SetVertexBuffer(0);
             }
             }
             
             
+            graphics_->SetVBO(0);
             glDeleteBuffers(1, &object_);
             glDeleteBuffers(1, &object_);
         }
         }
         
         
@@ -217,7 +218,7 @@ bool VertexBuffer::SetData(const void* data)
     {
     {
         if (!graphics_->IsDeviceLost())
         if (!graphics_->IsDeviceLost())
         {
         {
-            glBindBuffer(GL_ARRAY_BUFFER, object_);
+            graphics_->SetVBO(object_);
             glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
             glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         }
         }
         else
         else
@@ -264,7 +265,7 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
     {
     {
         if (!graphics_->IsDeviceLost())
         if (!graphics_->IsDeviceLost())
         {
         {
-            glBindBuffer(GL_ARRAY_BUFFER, object_);
+            graphics_->SetVBO(object_);
             if (!discard || start != 0)
             if (!discard || start != 0)
                 glBufferSubData(GL_ARRAY_BUFFER, start * vertexSize_, count * vertexSize_, data);
                 glBufferSubData(GL_ARRAY_BUFFER, start * vertexSize_, count * vertexSize_, data);
             else
             else
@@ -409,7 +410,7 @@ bool VertexBuffer::Create()
             return false;
             return false;
         }
         }
         
         
-        glBindBuffer(GL_ARRAY_BUFFER, object_);
+        graphics_->SetVBO(object_);
         glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }