Browse Source

Started work on buffering GPU resource updates while device lost.

Lasse Öörni 13 years ago
parent
commit
517030a2be

+ 2 - 1
Engine/Graphics/OpenGL/OGLGPUObject.cpp

@@ -30,7 +30,8 @@
 GPUObject::GPUObject(Graphics* graphics) :
 GPUObject::GPUObject(Graphics* graphics) :
     graphics_(graphics),
     graphics_(graphics),
     object_(0),
     object_(0),
-    dataLost_(false)
+    dataLost_(false),
+    dataPending_(false)
 {
 {
     if (graphics_)
     if (graphics_)
         graphics->AddGPUObject(this);
         graphics->AddGPUObject(this);

+ 4 - 0
Engine/Graphics/OpenGL/OGLGPUObject.h

@@ -52,6 +52,8 @@ public:
     unsigned GetGPUObject() const { return object_; }
     unsigned GetGPUObject() const { return object_; }
     /// Return whether data is lost due to context loss.
     /// Return whether data is lost due to context loss.
     bool IsDataLost() const { return dataLost_; }
     bool IsDataLost() const { return dataLost_; }
+    /// Return whether has pending data assigned while device was lost.
+    bool HasPendingData() const { return dataPending_; }
     
     
 protected:
 protected:
     /// Graphics subsystem.
     /// Graphics subsystem.
@@ -60,4 +62,6 @@ protected:
     unsigned object_;
     unsigned object_;
     /// Data lost flag.
     /// Data lost flag.
     bool dataLost_;
     bool dataLost_;
+    /// Data pending flag.
+    bool dataPending_;
 };
 };

+ 1 - 1
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -1793,7 +1793,7 @@ void Graphics::Restore()
 {
 {
     if (!impl_->window_)
     if (!impl_->window_)
         return;
         return;
-
+    
     // Ensure first that the context exists
     // Ensure first that the context exists
     if (!impl_->context_)
     if (!impl_->context_)
     {
     {

+ 37 - 9
Engine/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -68,6 +68,10 @@ void IndexBuffer::OnDeviceReset()
         Create();
         Create();
         dataLost_ = !UpdateToGPU();
         dataLost_ = !UpdateToGPU();
     }
     }
+    else if (dataPending_)
+        dataLost_ = !UpdateToGPU();
+    
+    dataPending_ = false;
 }
 }
 
 
 void IndexBuffer::Release()
 void IndexBuffer::Release()
@@ -76,7 +80,7 @@ void IndexBuffer::Release()
     
     
     if (object_)
     if (object_)
     {
     {
-        if (!graphics_)
+        if (!graphics_ || graphics_->IsDeviceLost())
             return;
             return;
         
         
         if (graphics_->GetIndexBuffer() == this)
         if (graphics_->GetIndexBuffer() == this)
@@ -139,9 +143,18 @@ bool IndexBuffer::SetData(const void* data)
     
     
     if (object_)
     if (object_)
     {
     {
-        graphics_->SetIndexBuffer(0);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        if (!graphics_->IsDeviceLost())
+        {
+            graphics_->SetIndexBuffer(0);
+            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
+            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        }
+        else
+        {
+            LOGWARNING("Index buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+        }
     }
     }
     
     
     dataLost_ = false;
     dataLost_ = false;
@@ -179,12 +192,21 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
     
     
     if (object_)
     if (object_)
     {
     {
-        graphics_->SetIndexBuffer(0);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
-        if (!discard || start != 0)
-            glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * indexSize_, count * indexSize_, data);
+        if (!graphics_->IsDeviceLost())
+        {
+            graphics_->SetIndexBuffer(0);
+            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
+            if (!discard || start != 0)
+                glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * indexSize_, count * indexSize_, data);
+            else
+                glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        }
         else
         else
-            glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        {
+            LOGWARNING("Index buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+        }
     }
     }
     
     
     return true;
     return true;
@@ -306,6 +328,12 @@ bool IndexBuffer::Create()
     
     
     if (graphics_)
     if (graphics_)
     {
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Index buffer creation while device is lost");
+            return false;
+        }
+        
         graphics_->SetIndexBuffer(0);
         graphics_->SetIndexBuffer(0);
         
         
         if (!object_)
         if (!object_)

+ 44 - 9
Engine/Graphics/OpenGL/OGLTexture2D.cpp

@@ -84,20 +84,32 @@ void Texture2D::OnDeviceLost()
 void Texture2D::OnDeviceReset()
 void Texture2D::OnDeviceReset()
 {
 {
     // If has a file name, reload through the resource cache. Otherwise just recreate.
     // If has a file name, reload through the resource cache. Otherwise just recreate.
-    if (!GetName().Trimmed().Empty())
-        dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
-    else
+    if (!object_)
     {
     {
-        Create();
-        dataLost_ = true;
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+        {
+            Create();
+            dataLost_ = true;
+        }
     }
     }
+    else if (dataPending_)
+    {
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+            dataLost_ = true;
+    }
+    
+    dataPending_ = false;
 }
 }
 
 
 void Texture2D::Release()
 void Texture2D::Release()
 {
 {
     if (object_)
     if (object_)
     {
     {
-        if (!graphics_)
+        if (!graphics_ || graphics_->IsDeviceLost())
             return;
             return;
         
         
         for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
         for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
@@ -167,6 +179,13 @@ bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, con
         return false;
         return false;
     }
     }
     
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture data assignment while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     if (IsCompressed())
     if (IsCompressed())
     {
     {
         x &= ~3;
         x &= ~3;
@@ -214,6 +233,13 @@ bool Texture2D::Load(SharedPtr<Image> image, bool useAlpha)
         return false;
         return false;
     }
     }
     
     
+    if (graphics_ && graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture load while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     unsigned memoryUse = sizeof(Texture2D);
     unsigned memoryUse = sizeof(Texture2D);
     
     
     int quality = QUALITY_HIGH;
     int quality = QUALITY_HIGH;
@@ -344,6 +370,12 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
         return false;
     }
     }
     
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Getting texture data while device is lost");
+        return false;
+    }
+    
     graphics_->SetTextureForUpdate(const_cast<Texture2D*>(this));
     graphics_->SetTextureForUpdate(const_cast<Texture2D*>(this));
     
     
     if (!IsCompressed())
     if (!IsCompressed())
@@ -354,7 +386,7 @@ bool Texture2D::GetData(unsigned level, void* dest) const
     graphics_->SetTexture(0, 0);
     graphics_->SetTexture(0, 0);
     return true;
     return true;
     #else
     #else
-    LOGERROR("Get texture data not supported");
+    LOGERROR("Getting texture data not supported");
     return false;
     return false;
     #endif
     #endif
 }
 }
@@ -363,11 +395,14 @@ bool Texture2D::Create()
 {
 {
     Release();
     Release();
     
     
-    if (!graphics_)
+    if (!graphics_ || !width_ || !height_)
         return false;
         return false;
     
     
-    if (!width_ || !height_)
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture creation while device is lost");
         return false;
         return false;
+    }
     
     
     unsigned externalFormat = GetExternalFormat(format_);
     unsigned externalFormat = GetExternalFormat(format_);
     unsigned dataType = GetDataType(format_);
     unsigned dataType = GetDataType(format_);

+ 45 - 10
Engine/Graphics/OpenGL/OGLTextureCube.cpp

@@ -74,20 +74,32 @@ void TextureCube::OnDeviceLost()
 void TextureCube::OnDeviceReset()
 void TextureCube::OnDeviceReset()
 {
 {
     // If has a file name, reload through the resource cache. Otherwise just recreate.
     // If has a file name, reload through the resource cache. Otherwise just recreate.
-    if (!GetName().Trimmed().Empty())
-        dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
-    else
+    if (!object_)
+    {
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+        {
+            Create();
+            dataLost_ = true;
+        }
+    }
+    else if (dataPending_)
     {
     {
-        Create();
-        dataLost_ = true;
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+            dataLost_ = true;
     }
     }
+    
+    dataPending_ = false;
 }
 }
 
 
 void TextureCube::Release()
 void TextureCube::Release()
 {
 {
     if (object_)
     if (object_)
     {
     {
-        if (!graphics_)
+        if (!graphics_ || graphics_->IsDeviceLost())
             return;
             return;
         
         
         for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
         for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
@@ -172,6 +184,13 @@ bool TextureCube::SetData(CubeMapFace face, unsigned level, int x, int y, int wi
         return false;
         return false;
     }
     }
     
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture data assignment while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     if (IsCompressed())
     if (IsCompressed())
     {
     {
         x &= ~3;
         x &= ~3;
@@ -225,7 +244,7 @@ bool TextureCube::Load(Deserializer& source)
     Graphics* graphics = GetSubsystem<Graphics>();
     Graphics* graphics = GetSubsystem<Graphics>();
     if (!graphics)
     if (!graphics)
         return true;
         return true;
-
+    
     // If over the texture budget, see if materials can be freed to allow textures to be freed
     // If over the texture budget, see if materials can be freed to allow textures to be freed
     CheckTextureBudget(GetTypeStatic());
     CheckTextureBudget(GetTypeStatic());
     
     
@@ -280,6 +299,13 @@ bool TextureCube::Load(CubeMapFace face, SharedPtr<Image> image, bool useAlpha)
         return false;
         return false;
     }
     }
     
     
+    if (graphics_ && graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture load while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     unsigned memoryUse = 0;
     unsigned memoryUse = 0;
     
     
     int quality = QUALITY_HIGH;
     int quality = QUALITY_HIGH;
@@ -455,6 +481,12 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
         return false;
     }
     }
     
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Getting texture data while device is lost");
+        return false;
+    }
+    
     graphics_->SetTextureForUpdate(const_cast<TextureCube*>(this));
     graphics_->SetTextureForUpdate(const_cast<TextureCube*>(this));
     
     
     if (!IsCompressed())
     if (!IsCompressed())
@@ -465,7 +497,7 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
     graphics_->SetTexture(0, 0);
     graphics_->SetTexture(0, 0);
     return true;
     return true;
     #else
     #else
-    LOGERROR("Get texture data not supported");
+    LOGERROR("Getting texture data not supported");
     return false;
     return false;
     #endif
     #endif
 }
 }
@@ -474,11 +506,14 @@ bool TextureCube::Create()
 {
 {
     Release();
     Release();
     
     
-    if (!graphics_)
+    if (!graphics_ || !width_ || !height_)
         return false;
         return false;
     
     
-    if (!width_ || !height_)
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture creation while device is lost");
         return false;
         return false;
+    }
     
     
     glGenTextures(1, &object_);
     glGenTextures(1, &object_);
     
     

+ 35 - 7
Engine/Graphics/OpenGL/OGLVertexBuffer.cpp

@@ -154,6 +154,10 @@ void VertexBuffer::OnDeviceReset()
         Create();
         Create();
         dataLost_ = !UpdateToGPU();
         dataLost_ = !UpdateToGPU();
     }
     }
+    else if (dataPending_)
+        dataLost_ = !UpdateToGPU();
+    
+    dataPending_ = false;
 }
 }
 
 
 void VertexBuffer::Release()
 void VertexBuffer::Release()
@@ -162,7 +166,7 @@ void VertexBuffer::Release()
     
     
     if (object_)
     if (object_)
     {
     {
-        if (!graphics_)
+        if (!graphics_ || graphics_->IsDeviceLost())
             return;
             return;
         
         
         for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
         for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
@@ -230,8 +234,17 @@ bool VertexBuffer::SetData(const void* data)
     
     
     if (object_)
     if (object_)
     {
     {
-        glBindBuffer(GL_ARRAY_BUFFER, object_);
-        glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        if (!graphics_->IsDeviceLost())
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, object_);
+            glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        }
+        else
+        {
+            LOGWARNING("Vertex buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+        }
     }
     }
     
     
     dataLost_ = false;
     dataLost_ = false;
@@ -269,11 +282,20 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
     
     
     if (object_)
     if (object_)
     {
     {
-        glBindBuffer(GL_ARRAY_BUFFER, object_);
-        if (!discard || start != 0)
-            glBufferSubData(GL_ARRAY_BUFFER, start * vertexSize_, count * vertexSize_, data);
+        if (!graphics_->IsDeviceLost())
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, object_);
+            if (!discard || start != 0)
+                glBufferSubData(GL_ARRAY_BUFFER, start * vertexSize_, count * vertexSize_, data);
+            else
+                glBufferData(GL_ARRAY_BUFFER, count * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        }
         else
         else
-            glBufferData(GL_ARRAY_BUFFER, count * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        {
+            LOGWARNING("Vertex buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+        }
     }
     }
     
     
     return true;
     return true;
@@ -378,6 +400,12 @@ bool VertexBuffer::Create()
     
     
     if (graphics_)
     if (graphics_)
     {
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Vertex buffer creation while device is lost");
+            return false;
+        }
+        
         if (!object_)
         if (!object_)
             glGenBuffers(1, &object_);
             glGenBuffers(1, &object_);
         if (!object_)
         if (!object_)