Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
299
libs/drape/batcher.cpp
Normal file
299
libs/drape/batcher.cpp
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
#include "drape/batcher.hpp"
|
||||
#include "drape/batcher_helpers.hpp"
|
||||
#include "drape/cpu_buffer.hpp"
|
||||
#include "drape/index_storage.hpp"
|
||||
#include "drape/vertex_array_buffer.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace dp
|
||||
{
|
||||
class Batcher::CallbacksWrapper : public BatchCallbacks
|
||||
{
|
||||
public:
|
||||
CallbacksWrapper(RenderState const & state, ref_ptr<OverlayHandle> overlay, ref_ptr<Batcher> batcher)
|
||||
: m_state(state)
|
||||
, m_overlay(overlay)
|
||||
, m_batcher(batcher)
|
||||
{}
|
||||
|
||||
void SetVAO(ref_ptr<VertexArrayBuffer> buffer)
|
||||
{
|
||||
// Invocation with non-null VAO will cause to invalid range of indices.
|
||||
// It means that VAO has been changed during batching.
|
||||
if (m_buffer != nullptr)
|
||||
m_vaoChanged = true;
|
||||
|
||||
m_buffer = buffer;
|
||||
m_indicesRange.m_idxStart = m_buffer->GetIndexCount();
|
||||
}
|
||||
|
||||
void FlushData(ref_ptr<GraphicsContext> context, BindingInfo const & info, void const * data, uint32_t count) override
|
||||
{
|
||||
if (m_overlay != nullptr && info.IsDynamic())
|
||||
{
|
||||
uint32_t offset = m_buffer->GetDynamicBufferOffset(info);
|
||||
m_overlay->AddDynamicAttribute(info, offset, count);
|
||||
}
|
||||
m_buffer->UploadData(context, info, data, count);
|
||||
}
|
||||
|
||||
void * GetIndexStorage(uint32_t size, uint32_t & startIndex) override
|
||||
{
|
||||
startIndex = m_buffer->GetStartIndexValue();
|
||||
if (m_overlay == nullptr || !m_overlay->IndexesRequired())
|
||||
{
|
||||
m_indexStorage.Resize(size);
|
||||
return m_indexStorage.GetRaw();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_overlay->IndexStorage(size);
|
||||
}
|
||||
}
|
||||
|
||||
void SubmitIndices(ref_ptr<GraphicsContext> context) override
|
||||
{
|
||||
if (m_overlay == nullptr || !m_overlay->IndexesRequired())
|
||||
m_buffer->UploadIndices(context, m_indexStorage.GetRawConst(), m_indexStorage.Size());
|
||||
}
|
||||
|
||||
uint32_t GetAvailableVertexCount() const override { return m_buffer->GetAvailableVertexCount(); }
|
||||
|
||||
uint32_t GetAvailableIndexCount() const override { return m_buffer->GetAvailableIndexCount(); }
|
||||
|
||||
void ChangeBuffer(ref_ptr<GraphicsContext> context) override { m_batcher->ChangeBuffer(context, make_ref(this)); }
|
||||
|
||||
RenderState const & GetState() const { return m_state; }
|
||||
|
||||
IndicesRange const & Finish()
|
||||
{
|
||||
if (!m_vaoChanged)
|
||||
m_indicesRange.m_idxCount = m_buffer->GetIndexCount() - m_indicesRange.m_idxStart;
|
||||
else
|
||||
m_indicesRange = IndicesRange();
|
||||
|
||||
return m_indicesRange;
|
||||
}
|
||||
|
||||
private:
|
||||
RenderState const & m_state;
|
||||
ref_ptr<OverlayHandle> m_overlay;
|
||||
ref_ptr<Batcher> m_batcher;
|
||||
ref_ptr<VertexArrayBuffer> m_buffer;
|
||||
IndexStorage m_indexStorage;
|
||||
IndicesRange m_indicesRange;
|
||||
bool m_vaoChanged = false;
|
||||
};
|
||||
|
||||
Batcher::Batcher(uint32_t indexBufferSize, uint32_t vertexBufferSize)
|
||||
: m_indexBufferSize(indexBufferSize)
|
||||
, m_vertexBufferSize(vertexBufferSize)
|
||||
{}
|
||||
|
||||
Batcher::~Batcher()
|
||||
{
|
||||
m_buckets.clear();
|
||||
}
|
||||
|
||||
void Batcher::InsertTriangleList(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params)
|
||||
{
|
||||
InsertTriangleList(context, state, params, nullptr);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertTriangleList(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && handle)
|
||||
{
|
||||
return InsertPrimitives<TriangleListBatch>(context, state, params, std::move(handle), 0 /* vertexStride */);
|
||||
}
|
||||
|
||||
void Batcher::InsertTriangleStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params)
|
||||
{
|
||||
InsertTriangleStrip(context, state, params, nullptr);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertTriangleStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && handle)
|
||||
{
|
||||
return InsertPrimitives<TriangleStripBatch>(context, state, params, std::move(handle), 0 /* vertexStride */);
|
||||
}
|
||||
|
||||
void Batcher::InsertTriangleFan(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params)
|
||||
{
|
||||
InsertTriangleFan(context, state, params, nullptr);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertTriangleFan(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && handle)
|
||||
{
|
||||
return InsertPrimitives<TriangleFanBatch>(context, state, params, std::move(handle), 0 /* vertexStride */);
|
||||
}
|
||||
|
||||
void Batcher::InsertListOfStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, uint8_t vertexStride)
|
||||
{
|
||||
InsertListOfStrip(context, state, params, nullptr, vertexStride);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertListOfStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && handle,
|
||||
uint8_t vertexStride)
|
||||
{
|
||||
return InsertPrimitives<TriangleListOfStripBatch>(context, state, params, std::move(handle), vertexStride);
|
||||
}
|
||||
|
||||
void Batcher::InsertLineStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params)
|
||||
{
|
||||
InsertLineStrip(context, state, params, nullptr);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertLineStrip(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && handle)
|
||||
{
|
||||
return InsertPrimitives<LineStripBatch>(context, state, params, std::move(handle), 0 /* vertexStride */);
|
||||
}
|
||||
|
||||
void Batcher::InsertLineRaw(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, std::vector<int> const & indices)
|
||||
{
|
||||
InsertLineRaw(context, state, params, indices, nullptr);
|
||||
}
|
||||
|
||||
IndicesRange Batcher::InsertLineRaw(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, std::vector<int> const & indices,
|
||||
drape_ptr<OverlayHandle> && handle)
|
||||
{
|
||||
return InsertPrimitives<LineRawBatch>(context, state, params, std::move(handle), 0 /* vertexStride */, indices);
|
||||
}
|
||||
|
||||
void Batcher::StartSession(TFlushFn && flusher)
|
||||
{
|
||||
m_flushInterface = std::move(flusher);
|
||||
}
|
||||
|
||||
void Batcher::EndSession(ref_ptr<GraphicsContext> context)
|
||||
{
|
||||
Flush(context);
|
||||
m_flushInterface = TFlushFn();
|
||||
}
|
||||
|
||||
void Batcher::ResetSession()
|
||||
{
|
||||
m_flushInterface = TFlushFn();
|
||||
m_buckets.clear();
|
||||
}
|
||||
|
||||
void Batcher::SetFeatureMinZoom(int minZoom)
|
||||
{
|
||||
m_featureMinZoom = minZoom;
|
||||
|
||||
for (auto const & bucket : m_buckets)
|
||||
bucket.second->SetFeatureMinZoom(m_featureMinZoom);
|
||||
}
|
||||
|
||||
void Batcher::SetBatcherHash(uint64_t batcherHash)
|
||||
{
|
||||
m_batcherHash = batcherHash;
|
||||
}
|
||||
|
||||
void Batcher::ChangeBuffer(ref_ptr<GraphicsContext> context, ref_ptr<CallbacksWrapper> wrapper)
|
||||
{
|
||||
RenderState const & state = wrapper->GetState();
|
||||
FinalizeBucket(context, state);
|
||||
|
||||
CHECK(m_buckets.find(state) == m_buckets.end(), ());
|
||||
ref_ptr<RenderBucket> bucket = GetBucket(state);
|
||||
wrapper->SetVAO(bucket->GetBuffer());
|
||||
}
|
||||
|
||||
ref_ptr<RenderBucket> Batcher::GetBucket(RenderState const & state)
|
||||
{
|
||||
auto res = m_buckets.insert({state, nullptr});
|
||||
if (res.second)
|
||||
{
|
||||
drape_ptr<VertexArrayBuffer> vao =
|
||||
make_unique_dp<VertexArrayBuffer>(m_indexBufferSize, m_vertexBufferSize, m_batcherHash);
|
||||
drape_ptr<RenderBucket> buffer = make_unique_dp<RenderBucket>(std::move(vao));
|
||||
buffer->SetFeatureMinZoom(m_featureMinZoom);
|
||||
res.first->second = std::move(buffer);
|
||||
}
|
||||
|
||||
return make_ref(res.first->second);
|
||||
}
|
||||
|
||||
void Batcher::FinalizeBucket(ref_ptr<GraphicsContext> context, RenderState const & state)
|
||||
{
|
||||
auto const it = m_buckets.find(state);
|
||||
CHECK(it != m_buckets.end(), ("Have no bucket for finalize with given state"));
|
||||
drape_ptr<RenderBucket> bucket = std::move(it->second);
|
||||
m_buckets.erase(it);
|
||||
|
||||
bucket->GetBuffer()->Preflush(context);
|
||||
m_flushInterface(state, std::move(bucket));
|
||||
}
|
||||
|
||||
void Batcher::Flush(ref_ptr<GraphicsContext> context)
|
||||
{
|
||||
ASSERT(m_flushInterface != NULL, ());
|
||||
std::for_each(m_buckets.begin(), m_buckets.end(), [this, context](TBuckets::value_type & bucket)
|
||||
{
|
||||
ASSERT(bucket.second != nullptr, ());
|
||||
bucket.second->GetBuffer()->Preflush(context);
|
||||
m_flushInterface(bucket.first, std::move(bucket.second));
|
||||
});
|
||||
|
||||
m_buckets.clear();
|
||||
}
|
||||
|
||||
template <typename TBatcher, typename... TArgs>
|
||||
IndicesRange Batcher::InsertPrimitives(ref_ptr<GraphicsContext> context, RenderState const & state,
|
||||
ref_ptr<AttributeProvider> params, drape_ptr<OverlayHandle> && transferHandle,
|
||||
uint8_t vertexStride, TArgs... batcherArgs)
|
||||
{
|
||||
ref_ptr<VertexArrayBuffer> vao = GetBucket(state)->GetBuffer();
|
||||
IndicesRange range;
|
||||
|
||||
drape_ptr<OverlayHandle> handle = std::move(transferHandle);
|
||||
|
||||
{
|
||||
Batcher::CallbacksWrapper wrapper(state, make_ref(handle), make_ref(this));
|
||||
wrapper.SetVAO(vao);
|
||||
|
||||
TBatcher batch(wrapper, batcherArgs...);
|
||||
batch.SetCanDivideStreams(handle == nullptr);
|
||||
batch.SetVertexStride(vertexStride);
|
||||
batch.BatchData(context, params);
|
||||
|
||||
range = wrapper.Finish();
|
||||
}
|
||||
|
||||
if (handle != nullptr)
|
||||
GetBucket(state)->AddOverlayHandle(std::move(handle));
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
Batcher * BatcherFactory::GetNew() const
|
||||
{
|
||||
return new Batcher(m_indexBufferSize, m_vertexBufferSize);
|
||||
}
|
||||
|
||||
SessionGuard::SessionGuard(ref_ptr<GraphicsContext> context, Batcher & batcher, Batcher::TFlushFn && flusher)
|
||||
: m_context(context)
|
||||
, m_batcher(batcher)
|
||||
{
|
||||
m_batcher.StartSession(std::move(flusher));
|
||||
}
|
||||
|
||||
SessionGuard::~SessionGuard()
|
||||
{
|
||||
m_batcher.EndSession(m_context);
|
||||
}
|
||||
} // namespace dp
|
||||
Loading…
Add table
Add a link
Reference in a new issue