|
|
@@ -26,10 +26,12 @@
|
|
|
#include "Drawable2D.h"
|
|
|
#include "DrawableProxy2D.h"
|
|
|
#include "Geometry.h"
|
|
|
+#include "GraphicsEvents.h"
|
|
|
#include "IndexBuffer.h"
|
|
|
#include "Log.h"
|
|
|
#include "Material.h"
|
|
|
#include "Node.h"
|
|
|
+#include "Profiler.h"
|
|
|
#include "Scene.h"
|
|
|
#include "VertexBuffer.h"
|
|
|
#include "Sort.h"
|
|
|
@@ -43,8 +45,11 @@ DrawableProxy2D::DrawableProxy2D(Context* context) :
|
|
|
Drawable(context, DRAWABLE_GEOMETRY),
|
|
|
indexBuffer_(new IndexBuffer(context_)),
|
|
|
vertexBuffer_(new VertexBuffer(context_)),
|
|
|
+ vertexCount_(0),
|
|
|
+ indexCount_(0),
|
|
|
orderDirty_(true)
|
|
|
{
|
|
|
+ SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(DrawableProxy2D, HandleBeginViewUpdate));
|
|
|
}
|
|
|
|
|
|
DrawableProxy2D::~DrawableProxy2D()
|
|
|
@@ -56,48 +61,117 @@ void DrawableProxy2D::RegisterObject(Context* context)
|
|
|
context->RegisterFactory<DrawableProxy2D>();
|
|
|
}
|
|
|
|
|
|
-void DrawableProxy2D::UpdateBatches(const FrameInfo& frame)
|
|
|
+void DrawableProxy2D::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventData)
|
|
|
{
|
|
|
+ using namespace BeginViewUpdate;
|
|
|
+
|
|
|
+ // Check that we are updating the correct scene
|
|
|
+ if (GetScene() != eventData[P_SCENE].GetPtr())
|
|
|
+ return;
|
|
|
+
|
|
|
+ PROFILE(UpdateDrawableProxy2D);
|
|
|
+
|
|
|
+ if (orderDirty_)
|
|
|
+ {
|
|
|
+ Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
|
|
|
+ orderDirty_ = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ vertexCount_ = 0;
|
|
|
+
|
|
|
+ if (drawablesVisible_.Size() != drawables_.Size())
|
|
|
+ drawablesVisible_.Resize(drawables_.Size());
|
|
|
+
|
|
|
+ /// \todo We could add frustum culling, but that would be problematic if we have several viewports. Right now all Drawable2D's
|
|
|
+ /// are always submitted for rendering
|
|
|
+ for (unsigned i = 0; i < drawables_.Size(); ++i)
|
|
|
+ {
|
|
|
+ Material* usedMaterial = drawables_[i]->GetUsedMaterial();
|
|
|
+ const Vector<Vertex2D>& vertices = drawables_[i]->GetVertices();
|
|
|
+ if (drawables_[i]->GetUsedMaterial() && vertices.Size())
|
|
|
+ {
|
|
|
+ drawablesVisible_[i] = true;
|
|
|
+ vertexCount_ += vertices.Size();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ drawablesVisible_[i] = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ indexCount_ = vertexCount_ / 4 * 6;
|
|
|
+
|
|
|
+ // Go through the drawables to form geometries & batches, but upload the actual vertex data later
|
|
|
+ materials_.Clear();
|
|
|
+
|
|
|
+ Material* material = 0;
|
|
|
+ unsigned iStart = 0;
|
|
|
+ unsigned iCount = 0;
|
|
|
+ unsigned vStart = 0;
|
|
|
+ unsigned vCount = 0;
|
|
|
+
|
|
|
+ for (unsigned d = 0; d < drawables_.Size(); ++d)
|
|
|
+ {
|
|
|
+ if (!drawablesVisible_[d])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ Material* usedMaterial = drawables_[d]->GetUsedMaterial();
|
|
|
+ const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
|
|
|
+
|
|
|
+ if (material != usedMaterial)
|
|
|
+ {
|
|
|
+ if (material)
|
|
|
+ {
|
|
|
+ AddBatch(material, iStart, iCount, vStart, vCount);
|
|
|
+ iStart += iCount;
|
|
|
+ iCount = 0;
|
|
|
+ vStart += vCount;
|
|
|
+ vCount = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ material = usedMaterial;
|
|
|
+ }
|
|
|
+
|
|
|
+ iCount += vertices.Size() / 4 * 6;
|
|
|
+ vCount += vertices.Size();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (material)
|
|
|
+ AddBatch(material, iStart, iCount, vStart, vCount);
|
|
|
+
|
|
|
+ // Now the amount of batches is known. Build the part of source batches that are sensitive to threading issues
|
|
|
+ // (material & geometry pointers)
|
|
|
unsigned count = materials_.Size();
|
|
|
batches_.Resize(count);
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i)
|
|
|
{
|
|
|
- batches_[i].distance_ = 10.0f + (count - i) * 0.001f;
|
|
|
batches_[i].material_ = materials_[i];
|
|
|
batches_[i].geometry_ = geometries_[i];
|
|
|
- batches_[i].worldTransform_ = &Matrix3x4::IDENTITY;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void DrawableProxy2D::UpdateGeometry(const FrameInfo& frame)
|
|
|
+void DrawableProxy2D::UpdateBatches(const FrameInfo& frame)
|
|
|
{
|
|
|
- materials_.Clear();
|
|
|
+ unsigned count = batches_.Size();
|
|
|
|
|
|
- if (orderDirty_)
|
|
|
+ // Update non-thread critical parts of the source batches
|
|
|
+ for (unsigned i = 0; i < count; ++i)
|
|
|
{
|
|
|
- Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
|
|
|
- orderDirty_ = false;
|
|
|
+ batches_[i].distance_ = 10.0f + (count - i) * 0.001f;
|
|
|
+ batches_[i].worldTransform_ = &Matrix3x4::IDENTITY;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- float timeStep = frame.timeStep_;
|
|
|
-
|
|
|
- unsigned vertexCount = 0;
|
|
|
- for (unsigned i = 0; i < drawables_.Size(); ++i)
|
|
|
- vertexCount += drawables_[i]->GetVertices().Size();
|
|
|
-
|
|
|
- if (vertexCount == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- unsigned indexCount = vertexCount / 4 * 6;
|
|
|
- if (indexBuffer_->GetIndexCount() < indexCount)
|
|
|
+void DrawableProxy2D::UpdateGeometry(const FrameInfo& frame)
|
|
|
+{
|
|
|
+ // Fill index buffer
|
|
|
+ if (indexBuffer_->GetIndexCount() < indexCount_)
|
|
|
{
|
|
|
- bool largeIndices = indexCount > 0xffff;
|
|
|
- indexBuffer_->SetSize(indexCount, largeIndices, true);
|
|
|
- void* buffer = indexBuffer_->Lock(0, indexCount, true);
|
|
|
+ bool largeIndices = indexCount_ > 0xffff;
|
|
|
+ indexBuffer_->SetSize(indexCount_, largeIndices, true);
|
|
|
+ void* buffer = indexBuffer_->Lock(0, indexCount_, true);
|
|
|
if (buffer)
|
|
|
{
|
|
|
- unsigned quadCount = indexCount / 6;
|
|
|
+ unsigned quadCount = indexCount_ / 6;
|
|
|
if (largeIndices)
|
|
|
{
|
|
|
unsigned* dest = reinterpret_cast<unsigned*>(buffer);
|
|
|
@@ -138,54 +212,36 @@ void DrawableProxy2D::UpdateGeometry(const FrameInfo& frame)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (vertexBuffer_->GetVertexCount() < vertexCount)
|
|
|
- vertexBuffer_->SetSize(vertexCount, MASK_VERTEX2D);
|
|
|
+ if (vertexBuffer_->GetVertexCount() < vertexCount_)
|
|
|
+ vertexBuffer_->SetSize(vertexCount_, MASK_VERTEX2D);
|
|
|
|
|
|
- Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer_->Lock(0, vertexCount, true));
|
|
|
- if (dest)
|
|
|
+ if (vertexCount_)
|
|
|
{
|
|
|
- Material* material = 0;
|
|
|
- unsigned iStart = 0;
|
|
|
- unsigned iCount = 0;
|
|
|
- unsigned vStart = 0;
|
|
|
- unsigned vCount = 0;
|
|
|
-
|
|
|
- for (unsigned d = 0; d < drawables_.Size(); ++d)
|
|
|
+ Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer_->Lock(0, vertexCount_, true));
|
|
|
+ if (dest)
|
|
|
{
|
|
|
- Material* usedMaterial = drawables_[d]->GetUsedMaterial();
|
|
|
- const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
|
|
|
- if (!usedMaterial || vertices.Empty())
|
|
|
- continue;
|
|
|
+ Material* material = 0;
|
|
|
+ unsigned iStart = 0;
|
|
|
+ unsigned iCount = 0;
|
|
|
+ unsigned vStart = 0;
|
|
|
+ unsigned vCount = 0;
|
|
|
|
|
|
- if (material != usedMaterial)
|
|
|
+ for (unsigned d = 0; d < drawables_.Size(); ++d)
|
|
|
{
|
|
|
- if (material)
|
|
|
- {
|
|
|
- AddBatch(material, iStart, iCount, vStart, vCount);
|
|
|
- iStart += iCount;
|
|
|
- iCount = 0;
|
|
|
- vStart += vCount;
|
|
|
- vCount = 0;
|
|
|
- }
|
|
|
-
|
|
|
- material = usedMaterial;
|
|
|
+ if (!drawablesVisible_[d])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
|
|
|
+ for (unsigned i = 0; i < vertices.Size(); ++i)
|
|
|
+ dest[i] = vertices[i];
|
|
|
+ dest += vertices.Size();
|
|
|
}
|
|
|
-
|
|
|
- for (unsigned i = 0; i < vertices.Size(); ++i)
|
|
|
- dest[i] = vertices[i];
|
|
|
- dest += vertices.Size();
|
|
|
-
|
|
|
- iCount += vertices.Size() / 4 * 6;
|
|
|
- vCount += vertices.Size();
|
|
|
+
|
|
|
+ vertexBuffer_->Unlock();
|
|
|
}
|
|
|
-
|
|
|
- if (material)
|
|
|
- AddBatch(material, iStart, iCount, vStart, vCount);
|
|
|
-
|
|
|
- vertexBuffer_->Unlock();
|
|
|
+ else
|
|
|
+ LOGERROR("Failed to lock vertex buffer");
|
|
|
}
|
|
|
- else
|
|
|
- LOGERROR("Failed to lock vertex buffer");
|
|
|
}
|
|
|
|
|
|
UpdateGeometryType DrawableProxy2D::GetUpdateGeometryType()
|
|
|
@@ -237,7 +293,7 @@ void DrawableProxy2D::AddBatch(Material* material, unsigned indexStart, unsigned
|
|
|
geometries_.Push(geometry);
|
|
|
}
|
|
|
|
|
|
- geometries_[batchSize - 1]->SetDrawRange(TRIANGLE_LIST, indexStart, indexCount, vertexStart, vertexCount);
|
|
|
+ geometries_[batchSize - 1]->SetDrawRange(TRIANGLE_LIST, indexStart, indexCount, vertexStart, vertexCount, false);
|
|
|
}
|
|
|
|
|
|
}
|