Browse Source

Update buffering for Direct3D9 GPU objects.

Lasse Öörni 13 years ago
parent
commit
4bf0bd7f3f

+ 2 - 1
Engine/Graphics/Direct3D9/D3D9GPUObject.cpp

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

+ 4 - 0
Engine/Graphics/Direct3D9/D3D9GPUObject.h

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

+ 28 - 2
Engine/Graphics/Direct3D9/D3D9IndexBuffer.cpp

@@ -63,11 +63,15 @@ void IndexBuffer::OnDeviceLost()
 
 void IndexBuffer::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (pool_ == D3DPOOL_DEFAULT || !object_)
     {
         Create();
         dataLost_ = !UpdateToGPU();
     }
+    else if (dataPending_)
+        dataLost_ = !UpdateToGPU();
+    
+    dataPending_ = false;
 }
 
 void IndexBuffer::Release()
@@ -149,6 +153,14 @@ bool IndexBuffer::SetData(const void* data)
     
     if (object_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Index buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+            return false;
+        }
+        
         void* hwData = MapBuffer(0, indexCount_, true);
         if (hwData)
         {
@@ -194,6 +206,14 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
     
     if (object_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Index buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+            return false;
+        }
+        
         void* hwData = MapBuffer(start, count, discard);
         if (hwData)
         {
@@ -234,7 +254,7 @@ void* IndexBuffer::Lock(unsigned start, unsigned count, bool discard)
     lockCount_ = count;
     
     // Because shadow data must be kept in sync, can only lock hardware buffer if not shadowed
-    if (object_ && !shadowData_)
+    if (object_ && !shadowData_ && !graphics_->IsDeviceLost())
         return MapBuffer(start, count, discard);
     else if (shadowData_)
     {
@@ -334,6 +354,12 @@ bool IndexBuffer::Create()
     
     if (graphics_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Index buffer creation while device is lost");
+            return false;
+        }
+        
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         if (!device || FAILED(device->CreateIndexBuffer(
             indexCount_ * indexSize_,

+ 35 - 3
Engine/Graphics/Direct3D9/D3D9Texture2D.cpp

@@ -80,7 +80,7 @@ void Texture2D::OnDeviceLost()
 
 void Texture2D::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (pool_ == D3DPOOL_DEFAULT || !object_)
     {
         // If has a file name, reload through the resource cache. Otherwise just recreate.
         if (!GetName().Trimmed().Empty())
@@ -91,6 +91,15 @@ void Texture2D::OnDeviceReset()
             dataLost_ = true;
         }
     }
+    else if (dataPending_)
+    {
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+            dataLost_ = true;
+    }
+    
+    dataPending_ = false;
 }
 
 void Texture2D::Release()
@@ -174,6 +183,13 @@ bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, con
         return false;
     }
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture data assignment while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     if (IsCompressed())
     {
         x &= ~3;
@@ -270,6 +286,13 @@ bool Texture2D::Load(SharedPtr<Image> image, bool useAlpha)
         return false;
     }
     
+    if (graphics_ && graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture load while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     unsigned memoryUse = sizeof(Texture2D);
     
     int quality = QUALITY_HIGH;
@@ -379,6 +402,12 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
     }
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Getting texture data while device is lost");
+        return false;
+    }
+    
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
     
@@ -450,11 +479,14 @@ bool Texture2D::Create()
 {
     Release();
     
-    if (!graphics_)
+    if (!graphics_ || !width_ || !height_)
         return false;
     
-    if (!width_ || !height_)
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture creation while device is lost");
         return false;
+    }
     
     IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
     // If creating a depth-stencil texture, and it is not supported, create a depth-stencil surface instead

+ 35 - 3
Engine/Graphics/Direct3D9/D3D9TextureCube.cpp

@@ -67,7 +67,7 @@ void TextureCube::OnDeviceLost()
 
 void TextureCube::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (pool_ == D3DPOOL_DEFAULT || !object_)
     {
         // If has a file name, reload through the resource cache. Otherwise just recreate.
         if (!GetName().Trimmed().Empty())
@@ -78,6 +78,15 @@ void TextureCube::OnDeviceReset()
             dataLost_ = true;
         }
     }
+    else if (dataPending_)
+    {
+        if (!GetName().Trimmed().Empty())
+            dataLost_ = !GetSubsystem<ResourceCache>()->ReloadResource(this);
+        else
+            dataLost_ = true;
+    }
+    
+    dataPending_ = false;
 }
 
 void TextureCube::Release()
@@ -175,6 +184,13 @@ bool TextureCube::SetData(CubeMapFace face, unsigned level, int x, int y, int wi
         return false;
     }
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture data assignment while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     if (IsCompressed())
     {
         x &= ~3;
@@ -329,6 +345,13 @@ bool TextureCube::Load(CubeMapFace face, SharedPtr<Image> image, bool useAlpha)
         return false;
     }
     
+    if (graphics_ && graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture load while device is lost");
+        dataPending_ = true;
+        return false;
+    }
+    
     unsigned memoryUse = 0;
     
     int quality = QUALITY_HIGH;
@@ -486,6 +509,12 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
     }
     
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Getting texture data while device is lost");
+        return false;
+    }
+    
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
     
@@ -557,11 +586,14 @@ bool TextureCube::Create()
 {
     Release();
     
-    if (!graphics_)
+    if (!graphics_ || !width_ || !height_)
         return false;
     
-    if (!width_ || !height_)
+    if (graphics_->IsDeviceLost())
+    {
+        LOGWARNING("Texture creation while device is lost");
         return false;
+    }
     
     IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
     if (!device || FAILED(device->CreateCubeTexture(

+ 28 - 2
Engine/Graphics/Direct3D9/D3D9VertexBuffer.cpp

@@ -98,11 +98,15 @@ void VertexBuffer::OnDeviceLost()
 
 void VertexBuffer::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (pool_ == D3DPOOL_DEFAULT || !object_)
     {
         Create();
         dataLost_ = !UpdateToGPU();
     }
+    else if (dataPending_)
+        dataLost_ = !UpdateToGPU();
+    
+    dataPending_ = false;
 }
 
 void VertexBuffer::Release()
@@ -189,6 +193,14 @@ bool VertexBuffer::SetData(const void* data)
     
     if (object_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Vertex buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+            return false;
+        }
+        
         void* hwData = MapBuffer(0, vertexCount_, true);
         if (hwData)
         {
@@ -234,6 +246,14 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
     
     if (object_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Vertex buffer data assignment while device is lost");
+            if (shadowData_)
+                dataPending_ = true;
+            return false;
+        }
+        
         void* hwData = MapBuffer(start, count, discard);
         if (hwData)
         {
@@ -274,7 +294,7 @@ void* VertexBuffer::Lock(unsigned start, unsigned count, bool discard)
     lockCount_ = count;
     
     // Because shadow data must be kept in sync, can only lock hardware buffer if not shadowed
-    if (object_ && !shadowData_)
+    if (object_ && !shadowData_ && !graphics_->IsDeviceLost())
         return MapBuffer(start, count, discard);
     else if (shadowData_)
     {
@@ -372,6 +392,12 @@ bool VertexBuffer::Create()
     
     if (graphics_)
     {
+        if (graphics_->IsDeviceLost())
+        {
+            LOGWARNING("Vertex buffer creation while device is lost");
+            return false;
+        }
+        
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         if (!device || FAILED(device->CreateVertexBuffer(
             vertexCount_ * vertexSize_,