Browse Source

Fixed lost vertex/index buffer data not being correctly reported.
Update vertex/index buffer shadow data first, but return failure if updating the actual GPU buffer fails.

Lasse Öörni 13 years ago
parent
commit
a4a31dd3eb

+ 7 - 13
Engine/Graphics/BillboardSet.cpp

@@ -53,6 +53,8 @@ OBJECTTYPESTATIC(BillboardSet);
 BillboardSet::BillboardSet(Context* context) :
 BillboardSet::BillboardSet(Context* context) :
     Drawable(context),
     Drawable(context),
     geometry_(new Geometry(context)),
     geometry_(new Geometry(context)),
+    vertexBuffer_(new VertexBuffer(context_)),
+    indexBuffer_(new IndexBuffer(context_)),
     animationLodBias_(1.0f),
     animationLodBias_(1.0f),
     animationLodTimer_(0.0f),
     animationLodTimer_(0.0f),
     relative_(true),
     relative_(true),
@@ -66,8 +68,6 @@ BillboardSet::BillboardSet(Context* context) :
 {
 {
     drawableFlags_ = DRAWABLE_GEOMETRY;
     drawableFlags_ = DRAWABLE_GEOMETRY;
     
     
-    vertexBuffer_ = new VertexBuffer(context_);
-    indexBuffer_ = new IndexBuffer(context_);
     geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1 | MASK_TEXCOORD2);
     geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1 | MASK_TEXCOORD2);
     geometry_->SetIndexBuffer(indexBuffer_);
     geometry_->SetIndexBuffer(indexBuffer_);
     
     
@@ -136,18 +136,8 @@ void BillboardSet::UpdateBatches(const FrameInfo& frame)
 
 
 void BillboardSet::UpdateGeometry(const FrameInfo& frame)
 void BillboardSet::UpdateGeometry(const FrameInfo& frame)
 {
 {
-    if (vertexBuffer_->IsDataLost() || indexBuffer_->IsDataLost())
-    {
-        vertexBuffer_->ClearDataLost();
-        indexBuffer_->ClearDataLost();
-        bufferSizeDirty_ = true;
-    }
-    
-    if (bufferSizeDirty_)
-    {
+    if (bufferSizeDirty_ || vertexBuffer_->IsDataLost() || indexBuffer_->IsDataLost())
         UpdateBufferSize();
         UpdateBufferSize();
-        forceUpdate_ = true;
-    }
     
     
     if (bufferDirty_)
     if (bufferDirty_)
         UpdateVertexBuffer(frame);
         UpdateVertexBuffer(frame);
@@ -347,6 +337,8 @@ void BillboardSet::UpdateBufferSize()
     
     
     bufferSizeDirty_ = false;
     bufferSizeDirty_ = false;
     bufferDirty_ = true;
     bufferDirty_ = true;
+    forceUpdate_ = true;
+    
     if (!numBillboards)
     if (!numBillboards)
         return;
         return;
     
     
@@ -365,6 +357,7 @@ void BillboardSet::UpdateBufferSize()
     }
     }
     
     
     indexBuffer_->Unlock();
     indexBuffer_->Unlock();
+    indexBuffer_->ClearDataLost();
 }
 }
 
 
 void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
 void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
@@ -467,6 +460,7 @@ void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
     }
     }
     
     
     vertexBuffer_->Unlock();
     vertexBuffer_->Unlock();
+    vertexBuffer_->ClearDataLost();
 }
 }
 
 
 void BillboardSet::MarkPositionsDirty()
 void BillboardSet::MarkPositionsDirty()

+ 0 - 2
Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -782,7 +782,6 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
         return false;
         return false;
     }
     }
     
     
-    // Build vertex declaration hash code out of the buffers & masks
     unsigned long long hash = 0;
     unsigned long long hash = 0;
     for (unsigned i = 0; i < buffers.Size(); ++i)
     for (unsigned i = 0; i < buffers.Size(); ++i)
     {
     {
@@ -794,7 +793,6 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
     
     
     if (hash)
     if (hash)
     {
     {
-        // If no previous vertex declaration for that hash, create new
         if (!vertexDeclarations_.Contains(hash))
         if (!vertexDeclarations_.Contains(hash))
         {
         {
             SharedPtr<VertexDeclaration> newDeclaration(new VertexDeclaration(this, buffers, elementMasks));
             SharedPtr<VertexDeclaration> newDeclaration(new VertexDeclaration(this, buffers, elementMasks));

+ 12 - 7
Engine/Graphics/Direct3D9/D3D9IndexBuffer.cpp

@@ -145,6 +145,9 @@ bool IndexBuffer::SetData(const void* data)
         return false;
         return false;
     }
     }
     
     
+    if (shadowData_ && data != shadowData_.Get())
+        memcpy(shadowData_.Get(), data, indexCount_ * indexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         void* hwData = MapBuffer(0, indexCount_, true);
         void* hwData = MapBuffer(0, indexCount_, true);
@@ -153,11 +156,11 @@ bool IndexBuffer::SetData(const void* data)
             memcpy(hwData, data, indexCount_ * indexSize_);
             memcpy(hwData, data, indexCount_ * indexSize_);
             UnmapBuffer();
             UnmapBuffer();
         }
         }
+        else
+            return false;
     }
     }
     
     
-    if (shadowData_ && data != shadowData_.Get())
-        memcpy(shadowData_.Get(), data, indexCount_ * indexSize_);
-    
+    dataLost_ = false;
     return true;
     return true;
 }
 }
 
 
@@ -187,6 +190,9 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
     if (!count)
     if (!count)
         return true;
         return true;
     
     
+    if (shadowData_ && shadowData_.Get() + start * indexSize_ != data)
+        memcpy(shadowData_.Get() + start * indexSize_, data, count * indexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         void* hwData = MapBuffer(start, count, discard);
         void* hwData = MapBuffer(start, count, discard);
@@ -195,11 +201,10 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
             memcpy(hwData, data, count * indexSize_);
             memcpy(hwData, data, count * indexSize_);
             UnmapBuffer();
             UnmapBuffer();
         }
         }
+        else
+            return false;
     }
     }
-    
-    if (shadowData_ && shadowData_.Get() + start * indexSize_ != data)
-        memcpy(shadowData_.Get() + start * indexSize_, data, count * indexSize_);
-    
+
     return true;
     return true;
 }
 }
 
 

+ 14 - 9
Engine/Graphics/Direct3D9/D3D9VertexBuffer.cpp

@@ -29,7 +29,7 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
-const unsigned VertexBuffer::elementSize[] = 
+const unsigned VertexBuffer::elementSize[] =
 {
 {
     3 * sizeof(float), // Position
     3 * sizeof(float), // Position
     3 * sizeof(float), // Normal
     3 * sizeof(float), // Normal
@@ -46,7 +46,7 @@ const unsigned VertexBuffer::elementSize[] =
     4 * sizeof(float) // Instancematrix3
     4 * sizeof(float) // Instancematrix3
 };
 };
 
 
-const String VertexBuffer::elementName[] = 
+const String VertexBuffer::elementName[] =
 {
 {
     "Position",
     "Position",
     "Normal",
     "Normal",
@@ -185,6 +185,9 @@ bool VertexBuffer::SetData(const void* data)
         return false;
         return false;
     }
     }
     
     
+    if (shadowData_ && data != shadowData_.Get())
+        memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         void* hwData = MapBuffer(0, vertexCount_, true);
         void* hwData = MapBuffer(0, vertexCount_, true);
@@ -193,11 +196,11 @@ bool VertexBuffer::SetData(const void* data)
             memcpy(hwData, data, vertexCount_ * vertexSize_);
             memcpy(hwData, data, vertexCount_ * vertexSize_);
             UnmapBuffer();
             UnmapBuffer();
         }
         }
+        else
+            return false;
     }
     }
     
     
-    if (shadowData_ && data != shadowData_.Get())
-        memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
-    
+    dataLost_ = false;
     return true;
     return true;
 }
 }
 
 
@@ -227,6 +230,9 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
     if (!count)
     if (!count)
         return true;
         return true;
     
     
+    if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
+        memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         void* hwData = MapBuffer(start, count, discard);
         void* hwData = MapBuffer(start, count, discard);
@@ -235,11 +241,10 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
             memcpy(hwData, data, count * vertexSize_);
             memcpy(hwData, data, count * vertexSize_);
             UnmapBuffer();
             UnmapBuffer();
         }
         }
+        else
+            return false;
     }
     }
-    
-    if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
-        memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
-    
+
     return true;
     return true;
 }
 }
 
 

+ 3 - 4
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -597,6 +597,8 @@ bool Graphics::SetVertexBuffers(const Vector<VertexBuffer*>& buffers, const PODV
         elementMasks_[i] = elementMask;
         elementMasks_[i] = elementMask;
         changed = true;
         changed = true;
         
         
+        // Beware buffers with missing OpenGL objects, as binding a zero buffer object means accessing CPU memory for vertex data,
+        // in which case the pointer will be invalid and cause a crash
         if (!buffer || !buffer->GetGPUObject())
         if (!buffer || !buffer->GetGPUObject())
             continue;
             continue;
         
         
@@ -676,7 +678,6 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
                 elementMask = buffer->GetElementMask() & elementMasks[i];
                 elementMask = buffer->GetElementMask() & elementMasks[i];
         }
         }
         
         
-        // If buffer and element mask have stayed the same, skip to the next buffer
         if (buffer == vertexBuffers_[i] && elementMask == elementMasks_[i] && !changed)
         if (buffer == vertexBuffers_[i] && elementMask == elementMasks_[i] && !changed)
             continue;
             continue;
         
         
@@ -698,14 +699,12 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
             {
             {
                 newAttributes |= elementBit;
                 newAttributes |= elementBit;
                 
                 
-                // Enable attribute if not enabled yet
                 if ((impl_->enabledAttributes_ & elementBit) == 0)
                 if ((impl_->enabledAttributes_ & elementBit) == 0)
                 {
                 {
                     glEnableVertexAttribArray(j);
                     glEnableVertexAttribArray(j);
                     impl_->enabledAttributes_ |= elementBit;
                     impl_->enabledAttributes_ |= elementBit;
                 }
                 }
                 
                 
-                // Set the attribute pointer
                 glVertexAttribPointer(j, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
                 glVertexAttribPointer(j, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
                     VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
                     VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
             }
             }
@@ -715,7 +714,6 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
     if (!changed)
     if (!changed)
         return true;
         return true;
     
     
-    // Now check which vertex attributes should be disabled
     unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
     unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
     int disableIndex = 0;
     int disableIndex = 0;
     while (disableAttributes)
     while (disableAttributes)
@@ -2210,6 +2208,7 @@ void Graphics::ResetCachedState()
     
     
     impl_->activeTexture_ = 0;
     impl_->activeTexture_ = 0;
     impl_->enabledAttributes_ = 0;
     impl_->enabledAttributes_ = 0;
+    impl_->boundFbo_ = 0;
     
     
     // Set initial state to match Direct3D
     // Set initial state to match Direct3D
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_DEPTH_TEST);

+ 7 - 6
Engine/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -135,6 +135,9 @@ bool IndexBuffer::SetData(const void* data)
         return false;
         return false;
     }
     }
     
     
+    if (shadowData_ && data != shadowData_.Get())
+        memcpy(shadowData_.Get(), data, indexCount_ * indexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         graphics_->SetIndexBuffer(0);
         graphics_->SetIndexBuffer(0);
@@ -142,9 +145,7 @@ bool IndexBuffer::SetData(const void* data)
         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);
     }
     }
     
     
-    if (shadowData_ && data != shadowData_.Get())
-        memcpy(shadowData_.Get(), data, indexCount_ * indexSize_);
-    
+    dataLost_ = false;
     return true;
     return true;
 }
 }
 
 
@@ -174,6 +175,9 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
     if (!count)
     if (!count)
         return true;
         return true;
     
     
+    if (shadowData_ && shadowData_.Get() + start * indexSize_ != data)
+        memcpy(shadowData_.Get() + start * indexSize_, data, count * indexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         graphics_->SetIndexBuffer(0);
         graphics_->SetIndexBuffer(0);
@@ -184,9 +188,6 @@ bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count,
             glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
             glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }
     
     
-    if (shadowData_ && shadowData_.Get() + start * indexSize_ != data)
-        memcpy(shadowData_.Get() + start * indexSize_, data, count * indexSize_);
-    
     return true;
     return true;
 }
 }
 
 

+ 1 - 1
Engine/Graphics/OpenGL/OGLIndexBuffer.h

@@ -66,7 +66,7 @@ public:
     /// Return whether is dynamic.
     /// Return whether is dynamic.
     bool IsDynamic() const { return dynamic_; }
     bool IsDynamic() const { return dynamic_; }
     /// Return whether data is lost due to context loss.
     /// Return whether data is lost due to context loss.
-    bool IsDataLost() const { return false; }
+    bool IsDataLost() const { return dataLost_; }
     /// Return whether is currently locked.
     /// Return whether is currently locked.
     bool IsLocked() const { return lockState_ != LOCK_NONE; }
     bool IsLocked() const { return lockState_ != LOCK_NONE; }
     /// Return number of indices.
     /// Return number of indices.

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

@@ -226,15 +226,16 @@ bool VertexBuffer::SetData(const void* data)
         return false;
         return false;
     }
     }
     
     
+    if (shadowData_ && data != shadowData_.Get())
+        memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         glBindBuffer(GL_ARRAY_BUFFER, object_);
         glBindBuffer(GL_ARRAY_BUFFER, 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);
     }
     }
     
     
-    if (shadowData_ && data != shadowData_.Get())
-        memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
-    
+    dataLost_ = false;
     return true;
     return true;
 }
 }
 
 
@@ -264,6 +265,9 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
     if (!count)
     if (!count)
         return true;
         return true;
     
     
+    if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
+        memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
+    
     if (object_)
     if (object_)
     {
     {
         glBindBuffer(GL_ARRAY_BUFFER, object_);
         glBindBuffer(GL_ARRAY_BUFFER, object_);
@@ -273,9 +277,6 @@ bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count
             glBufferData(GL_ARRAY_BUFFER, count * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
             glBufferData(GL_ARRAY_BUFFER, count * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }
     
     
-    if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
-        memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
-    
     return true;
     return true;
 }
 }
 
 

+ 1 - 1
Engine/Graphics/OpenGL/OGLVertexBuffer.h

@@ -65,7 +65,7 @@ public:
     /// Return whether is dynamic.
     /// Return whether is dynamic.
     bool IsDynamic() const { return dynamic_; }
     bool IsDynamic() const { return dynamic_; }
     /// Return whether data is lost due to context loss.
     /// Return whether data is lost due to context loss.
-    bool IsDataLost() const { return false; }
+    bool IsDataLost() const { return dataLost_; }
     /// Return whether is currently locked.
     /// Return whether is currently locked.
     bool IsLocked() const { return lockState_ != LOCK_NONE; }
     bool IsLocked() const { return lockState_ != LOCK_NONE; }
     /// Return number of vertices.
     /// Return number of vertices.