Skip to content

Commit

Permalink
#5943: More optimisations to reduce the amount of data that is marked…
Browse files Browse the repository at this point in the history
… as modified and copied around.
  • Loading branch information
codereader committed Apr 22, 2022
1 parent 36f4977 commit c6ca4aa
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 50 deletions.
39 changes: 15 additions & 24 deletions libs/render/ContinuousBuffer.h
Expand Up @@ -14,15 +14,9 @@ namespace detail

struct BufferTransaction
{
enum class Type
{
Allocate,
Deallocate,
Update,
};

IGeometryStore::Slot slot;
Type type;
std::size_t offset;
std::size_t numChangedElements;
};

}
Expand Down Expand Up @@ -183,7 +177,8 @@ class ContinuousBuffer
_unsyncedSlots.insert(handle);
}

void resizeData(Handle handle, std::size_t elementCount)
// Returns true if the size of this size actually changed
bool resizeData(Handle handle, std::size_t elementCount)
{
auto& slot = _slots[handle];

Expand All @@ -192,9 +187,11 @@ class ContinuousBuffer
throw std::logic_error("Cannot resize to a large amount than allocated in GeometryStore::Buffer::resizeData");
}

slot.Used = elementCount;
if (slot.Used == elementCount) return false; // no size change

slot.Used = elementCount;
_unsyncedSlots.insert(handle);
return true;
}

void deallocate(Handle handle)
Expand Down Expand Up @@ -245,11 +242,7 @@ class ContinuousBuffer
{
for (const auto& transaction : transactions)
{
// Only the updated slots will actually have altered any data
if (transaction.type == detail::BufferTransaction::Type::Update)
{
_unsyncedSlots.insert(getHandle(transaction.slot));
}
_unsyncedSlots.insert(getHandle(transaction.slot));
}

return;
Expand All @@ -265,17 +258,15 @@ class ContinuousBuffer

for (const auto& transaction : transactions)
{
// Only the updated slots will actually have altered any data
if (transaction.type == detail::BufferTransaction::Type::Update)
{
auto handle = getHandle(transaction.slot);
auto& otherSlot = other._slots[handle];
auto handle = getHandle(transaction.slot);
auto& otherSlot = other._slots[handle];

memcpy(_buffer.data() + otherSlot.Offset, other._buffer.data() + otherSlot.Offset, otherSlot.Size * sizeof(ElementType));
memcpy(_buffer.data() + otherSlot.Offset + transaction.offset,
other._buffer.data() + otherSlot.Offset + transaction.offset,
transaction.numChangedElements * sizeof(ElementType));

// Remember this slot to be synced to the GPU
_unsyncedSlots.insert(handle);
}
// Remember this slot to be synced to the GPU
_unsyncedSlots.insert(handle);
}

// Replicate the slot allocation data
Expand Down
57 changes: 33 additions & 24 deletions libs/render/GeometryStore.h
Expand Up @@ -36,12 +36,13 @@ class GeometryStore final :
IBufferObject::Ptr indexBufferObject;

// Keep track of modified slots as long as this buffer is in use
std::vector<detail::BufferTransaction> transactionLog;
std::vector<detail::BufferTransaction> vertexTransactionLog;
std::vector<detail::BufferTransaction> indexTransactionLog;

void applyTransactions(const FrameBuffer& other)
{
vertices.applyTransactions(other.transactionLog, other.vertices, GetVertexSlot);
indices.applyTransactions(other.transactionLog, other.indices, GetIndexSlot);
vertices.applyTransactions(other.vertexTransactionLog, other.vertices, GetVertexSlot);
indices.applyTransactions(other.indexTransactionLog, other.indices, GetIndexSlot);
}

void syncToBufferObjects()
Expand All @@ -50,9 +51,20 @@ class GeometryStore final :
indices.syncModificationsToBufferObject(indexBufferObject);
}

void recordTransaction(Slot slot, detail::BufferTransaction::Type type)
void recordVertexTransaction(Slot slot, std::size_t offset, std::size_t numChangedElements)
{
transactionLog.emplace_back(detail::BufferTransaction{ slot, type });
vertexTransactionLog.emplace_back(detail::BufferTransaction
{
slot, offset, numChangedElements
});
}

void recordIndexTransaction(Slot slot, std::size_t offset, std::size_t numChangedElements)
{
indexTransactionLog.emplace_back(detail::BufferTransaction
{
slot, offset, numChangedElements
});
}
};

Expand Down Expand Up @@ -100,7 +112,8 @@ class GeometryStore final :
}

// This buffer is in sync now, we can clear its log
current.transactionLog.clear();
current.vertexTransactionLog.clear();
current.indexTransactionLog.clear();
}

std::pair<IBufferObject::Ptr, IBufferObject::Ptr> getBufferObjects() override
Expand Down Expand Up @@ -132,11 +145,7 @@ class GeometryStore final :
auto vertexSlot = current.vertices.allocate(numVertices);
auto indexSlot = current.indices.allocate(numIndices);

auto slot = GetSlot(SlotType::Regular, vertexSlot, indexSlot);

current.recordTransaction(slot, detail::BufferTransaction::Type::Allocate);

return slot;
return GetSlot(SlotType::Regular, vertexSlot, indexSlot);
}

Slot allocateIndexSlot(Slot slotContainingVertexData, std::size_t numIndices) override
Expand All @@ -154,11 +163,7 @@ class GeometryStore final :
auto indexSlot = current.indices.allocate(numIndices);

// In an IndexRemap slot, the vertex slot ID refers to the one containing the vertices
auto slot = GetSlot(SlotType::IndexRemap, GetVertexSlot(slotContainingVertexData), indexSlot);

current.recordTransaction(slot, detail::BufferTransaction::Type::Allocate);

return slot;
return GetSlot(SlotType::IndexRemap, GetVertexSlot(slotContainingVertexData), indexSlot);
}

void updateData(Slot slot, const std::vector<RenderVertex>& vertices,
Expand All @@ -179,7 +184,8 @@ class GeometryStore final :
assert(!indices.empty());
current.indices.setData(GetIndexSlot(slot), indices);

current.recordTransaction(slot, detail::BufferTransaction::Type::Update);
current.recordVertexTransaction(slot, 0, vertices.size());
current.recordIndexTransaction(slot, 0, indices.size());
}

void updateSubData(Slot slot, std::size_t vertexOffset, const std::vector<RenderVertex>& vertices,
Expand All @@ -200,7 +206,8 @@ class GeometryStore final :
assert(!indices.empty());
current.indices.setSubData(GetIndexSlot(slot), indexOffset, indices);

current.recordTransaction(slot, detail::BufferTransaction::Type::Update);
current.recordVertexTransaction(slot, vertexOffset, vertices.size());
current.recordIndexTransaction(slot, indexOffset, indices.size());
}

void resizeData(Slot slot, std::size_t vertexSize, std::size_t indexSize) override
Expand All @@ -209,16 +216,20 @@ class GeometryStore final :

if (GetSlotType(slot) == SlotType::Regular)
{
current.vertices.resizeData(GetVertexSlot(slot), vertexSize);
if (current.vertices.resizeData(GetVertexSlot(slot), vertexSize))
{
current.recordVertexTransaction(slot, 0, vertexSize);
}
}
else if (vertexSize > 0)
{
throw std::logic_error("This is an index remap slot, cannot resize vertex data");
}

current.indices.resizeData(GetIndexSlot(slot), indexSize);

current.recordTransaction(slot, detail::BufferTransaction::Type::Update);
if (current.indices.resizeData(GetIndexSlot(slot), indexSize))
{
current.recordIndexTransaction(slot, 0, indexSize);
}
}

void deallocateSlot(Slot slot) override
Expand All @@ -233,8 +244,6 @@ class GeometryStore final :
}

current.indices.deallocate(GetIndexSlot(slot));

current.recordTransaction(slot, detail::BufferTransaction::Type::Deallocate);
}

RenderParameters getRenderParameters(Slot slot) override
Expand Down
4 changes: 2 additions & 2 deletions test/ContinuousBuffer.cpp
Expand Up @@ -545,13 +545,13 @@ TEST(ContinuousBufferTest, SyncToBufferAfterApplyingTransaction)

// Copy this to a second buffer and change some data there
auto buffer2 = buffer;
auto modificationOffset = 3;
std::size_t modificationOffset = 3;
buffer2.setSubData(handle2, modificationOffset, four);

// Define the transaction
std::vector<render::detail::BufferTransaction> transactionLog;
transactionLog.emplace_back(render::detail::BufferTransaction{
handle2, render::detail::BufferTransaction::Type::Update
handle2, modificationOffset, four.size()
});

// Apply this transaction to the first buffer
Expand Down

0 comments on commit c6ca4aa

Please sign in to comment.