From 5b3af77450f61020a1cc32073a1dd2df6e7fabbe Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Fri, 7 Jul 2023 15:03:39 -0700 Subject: [PATCH] shared vertex buffers (#1310) Co-authored-by: Stefan Karschti --- include/mbgl/gfx/drawable.hpp | 9 +- include/mbgl/gfx/drawable_builder.hpp | 4 +- include/mbgl/gfx/vertex_attribute.hpp | 54 +++++- include/mbgl/gl/drawable_gl.hpp | 2 +- include/mbgl/gl/drawable_gl_builder.hpp | 7 - include/mbgl/gl/vertex_attribute_gl.hpp | 9 +- src/mbgl/gfx/drawable_builder.cpp | 38 ++-- src/mbgl/gfx/upload_pass.hpp | 6 +- src/mbgl/gfx/vertex_attribute.cpp | 7 + src/mbgl/gfx/vertex_vector.hpp | 69 +++++++- src/mbgl/gl/drawable_gl.cpp | 8 +- src/mbgl/gl/drawable_gl_impl.hpp | 2 +- src/mbgl/gl/upload_pass.cpp | 97 ++++++++-- src/mbgl/gl/upload_pass.hpp | 6 +- src/mbgl/gl/value.cpp | 2 +- src/mbgl/gl/vertex_attribute_gl.cpp | 33 ++-- src/mbgl/layout/symbol_layout.cpp | 95 +++++----- src/mbgl/renderer/buckets/circle_bucket.cpp | 6 +- src/mbgl/renderer/buckets/circle_bucket.hpp | 7 +- src/mbgl/renderer/buckets/debug_bucket.cpp | 2 + src/mbgl/renderer/buckets/fill_bucket.cpp | 6 +- src/mbgl/renderer/buckets/fill_bucket.hpp | 7 +- .../buckets/fill_extrusion_bucket.cpp | 6 +- .../buckets/fill_extrusion_bucket.hpp | 7 +- src/mbgl/renderer/buckets/heatmap_bucket.cpp | 6 +- src/mbgl/renderer/buckets/heatmap_bucket.hpp | 7 +- .../renderer/buckets/hillshade_bucket.cpp | 5 + .../renderer/buckets/hillshade_bucket.hpp | 2 + src/mbgl/renderer/buckets/line_bucket.cpp | 6 +- src/mbgl/renderer/buckets/line_bucket.hpp | 7 +- src/mbgl/renderer/buckets/raster_bucket.cpp | 5 + src/mbgl/renderer/buckets/raster_bucket.hpp | 2 + src/mbgl/renderer/buckets/symbol_bucket.cpp | 22 +-- src/mbgl/renderer/buckets/symbol_bucket.hpp | 38 +++- .../renderer/layers/render_circle_layer.cpp | 54 +++--- .../renderer/layers/render_circle_layer.hpp | 1 + .../layers/render_fill_extrusion_layer.cpp | 27 +-- .../renderer/layers/render_fill_layer.cpp | 76 ++++---- .../renderer/layers/render_fill_layer.hpp | 1 + .../renderer/layers/render_heatmap_layer.cpp | 84 +++++---- .../renderer/layers/render_heatmap_layer.hpp | 4 + .../renderer/layers/render_line_layer.cpp | 77 ++++---- .../renderer/layers/render_symbol_layer.cpp | 166 +++++------------- src/mbgl/renderer/paint_property_binder.hpp | 6 + src/mbgl/renderer/render_static_data.cpp | 5 +- src/mbgl/text/placement.cpp | 36 ++-- 46 files changed, 647 insertions(+), 479 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index c143691c0..80c56ebd2 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -143,11 +143,10 @@ public: const gfx::ColorMode& getColorMode() const; void setColorMode(const gfx::ColorMode&); - /// Get the number of vertexes - std::size_t getVertexCount() const { return getVertexAttributes().getMaxCount(); } - /// Get the vertex attributes that override default values in the shader program virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + virtual gfx::VertexAttributeArray& mutableVertexAttributes() = 0; + virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0; virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0; @@ -171,8 +170,8 @@ public: static_cast(components[3])}; } - virtual const UniqueDrawableData& getData() const { return drawableData; } - virtual void setData(UniqueDrawableData&& value) { drawableData = std::move(value); } + const UniqueDrawableData& getData() const { return drawableData; } + void setData(UniqueDrawableData&& value) { drawableData = std::move(value); } protected: bool enabled = true; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 20e55c49b..fedfb40d6 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -100,7 +100,7 @@ public: void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } /// Get the vertex attributes that override default values in the shader program - virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + const gfx::VertexAttributeArray& getVertexAttributes() const { return vertexAttrs; } /// Set the name given to new drawables void setDrawableName(std::string value) { drawableName = std::move(value); } @@ -125,7 +125,7 @@ public: void addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1); /// A set of attribute values to be added for each vertex - void setVertexAttributes(const VertexAttributeArray&); + void setVertexAttributes(const VertexAttributeArray& value); void setVertexAttributes(VertexAttributeArray&&); /// Add some vertex elements, returns the index of the first one added diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 71069c55a..4cc209b3f 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -21,6 +21,7 @@ using mat4 = std::array; namespace gfx { class ShaderProgramBase; +class VertexVectorBase; class VertexAttribute { public: @@ -43,11 +44,26 @@ public: stride((int)stride_), dataType(dataType_), items(count_) {} - VertexAttribute(const VertexAttribute&) = default; + VertexAttribute(const VertexAttribute& other) + : index(other.index), + dataType(other.dataType), + items(other.items), + sharedRawData(other.sharedRawData), + sharedType(other.sharedType), + sharedOffset(other.sharedOffset), + sharedVertexOffset(other.sharedVertexOffset), + sharedStride(other.sharedStride) + {} VertexAttribute(VertexAttribute&& other) : index(other.index), dataType(other.dataType), - items(std::move(other.items)) {} + items(std::move(other.items)), + sharedRawData(std::move(other.sharedRawData)), + sharedType(other.sharedType), + sharedOffset(other.sharedOffset), + sharedVertexOffset(other.sharedVertexOffset), + sharedStride(other.sharedStride) + {} public: virtual ~VertexAttribute() = default; @@ -57,7 +73,7 @@ public: std::size_t getStride() const { return stride; } - std::size_t getCount() const { return items.size(); } + std::size_t getCount() const; AttributeDataType getDataType() const { return dataType; } const ElementType& get(std::size_t i) const { return items[i]; } @@ -99,10 +115,7 @@ public: } bool isDirty() const { return dirty; } - void setDirty() { - dirty = true; - rawData.clear(); - } + void setDirty(bool value = true) { dirty = value; } template inline typename std::enable_if::type set(std::size_t, std::tuple, std::size_t) {} @@ -117,6 +130,23 @@ public: } } + std::vector& getRawData() { return rawData; } + const std::vector& getRawData() const { return rawData; } + + const std::shared_ptr& getSharedRawData() const { return sharedRawData; } + AttributeDataType getSharedType() const { return sharedType; } + uint32_t getSharedOffset() const { return sharedOffset; } + uint32_t getSharedVertexOffset() const { return sharedVertexOffset; } + uint32_t getSharedStride() const { return sharedStride; } + void setSharedRawData(std::shared_ptr data, uint32_t offset, uint32_t vertexOffset, uint32_t stride_, AttributeDataType type) { + sharedRawData = std::move(data); + sharedType = type; + sharedOffset = offset; + sharedVertexOffset = vertexOffset; + sharedStride = stride_; + } + void resetSharedRawData() { sharedRawData.reset(); } + protected: VertexAttribute& operator=(const VertexAttribute&) = default; VertexAttribute& operator=(VertexAttribute&& other) { @@ -135,7 +165,15 @@ protected: AttributeDataType dataType; std::vector items; + + // Cache of attribute data mutable std::vector rawData; + + std::shared_ptr sharedRawData; + AttributeDataType sharedType = AttributeDataType::Invalid; + uint32_t sharedOffset = 0; + uint32_t sharedVertexOffset = 0; + uint32_t sharedStride = 0; }; /// Stores a collection of vertex attributes by name @@ -215,7 +253,7 @@ public: } using ResolveDelegate = - std::function&)>; + std::function&)>; /// Call the provided delegate with each value, providing the override if one exists. void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const; diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 07be116ba..ab2142fd2 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -44,7 +44,7 @@ public: void setVertexAttributes(const gfx::VertexAttributeArray& value) override; void setVertexAttributes(gfx::VertexAttributeArray&& value) override; - gfx::VertexAttributeArray& mutableVertexAttributes(); + gfx::VertexAttributeArray& mutableVertexAttributes() override; const gfx::UniformBufferArray& getUniformBuffers() const override; gfx::UniformBufferArray& mutableUniformBuffers() override; diff --git a/include/mbgl/gl/drawable_gl_builder.hpp b/include/mbgl/gl/drawable_gl_builder.hpp index 32361a23a..089b67a22 100644 --- a/include/mbgl/gl/drawable_gl_builder.hpp +++ b/include/mbgl/gl/drawable_gl_builder.hpp @@ -15,10 +15,6 @@ public: : gfx::DrawableBuilder(std::move(name_)) {} ~DrawableGLBuilder() override = default; - const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } - void setVertexAttributes(const VertexAttributeArrayGL& value) { vertexAttributes = value; } - void setVertexAttributes(VertexAttributeArrayGL&& value) { vertexAttributes = std::move(value); } - protected: gfx::UniqueDrawable createDrawable() const override; @@ -27,9 +23,6 @@ protected: /// Setup the SDK-specific aspects after all the values are present void init() override; - -private: - VertexAttributeArrayGL vertexAttributes; }; } // namespace gl diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index d2a476485..581e6e2cb 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -1,13 +1,18 @@ #pragma once +#include #include #include #include namespace mbgl { +namespace gfx { +class VertexBufferResource; +} // namespace gfx namespace gl { class VertexAttributeArrayGL; +class UploadPass; class VertexAttributeGL final : public gfx::VertexAttribute { // Can only be created by VertexAttributeArrayGL @@ -25,7 +30,6 @@ private: public: ~VertexAttributeGL() override = default; -public: platform::GLenum getGLType() const { return glType; } void setGLType(platform::GLenum value); @@ -34,7 +38,7 @@ public: std::size_t getStride() const; - const std::vector& getRaw(platform::GLenum) const; + static const std::vector& getRaw(gfx::VertexAttribute& attr, platform::GLenum); private: static int getSize(platform::GLenum glType); @@ -43,7 +47,6 @@ private: private: platform::GLenum glType = 0; - mutable platform::GLenum rawType = 0; bool normalized = false; }; diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 109ae3c5e..128ba4cbb 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -38,8 +38,8 @@ UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) { } void DrawableBuilder::flush() { - const auto vertexCount = curVertexCount(); - if (vertexCount) { + if (curVertexCount()) + { const auto& draw = getCurrentDrawable(/*createIfNone=*/true); draw->setEnabled(enabled); draw->setLineWidth(static_cast(lineWidth)); @@ -56,25 +56,8 @@ void DrawableBuilder::flush() { draw->setTextures(textures); draw->setTweakers(tweakers); - if (auto drawAttrs = getVertexAttributes().clone()) { - vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) { - if (auto& drawAttr = drawAttrs->getOrAdd(iName)) { - if (iAttr.getCount() == 1) { - // Apply the value to all vertexes - for (std::size_t i = 0; i < vertexCount; ++i) { - drawAttr->setVariant(i, iAttr.get(0)); - } - } else if (iAttr.getCount() == vertexCount) { - for (std::size_t i = 0; i < vertexCount; ++i) { - drawAttr->setVariant(i, iAttr.get(i)); - } - } else { - // throw? - Log::Warning(Event::General, "Invalid attribute count"); - } - } - }); - + const auto& builderAttrs = getVertexAttributes(); + if (auto drawAttrs = builderAttrs.clone()) { draw->setVertexAttributes(std::move(*drawAttrs)); } @@ -147,7 +130,7 @@ void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) { } void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) { - vertexAttrs = attrs; + vertexAttrs = std::move(attrs); } std::size_t DrawableBuilder::addVertices(const std::vector>& vertices, @@ -169,7 +152,7 @@ void DrawableBuilder::setRawVertices(std::vector&& data, std::size_t co void DrawableBuilder::setSegments(gfx::DrawMode mode, std::vector indexes, const std::vector& segments) { - setSegments(mode, indexes, segments.data(), segments.size()); + setSegments(mode, std::move(indexes), segments.data(), segments.size()); } void DrawableBuilder::setSegments(gfx::DrawMode mode, @@ -185,10 +168,13 @@ void DrawableBuilder::setSegments(gfx::DrawMode mode, } else if (mode.type == DrawModeType::Lines) { assert(seg.indexLength % 2 == 0); } - assert(seg.vertexOffset + seg.vertexLength <= curVertexCount()); + const auto vertexCount = curVertexCount(); + assert(!vertexCount || seg.vertexOffset + seg.vertexLength <= curVertexCount()); assert(seg.indexOffset + seg.indexLength <= impl->indexes.size()); - for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) { - assert(impl->indexes[seg.indexOffset + j] < curVertexCount()); + if (vertexCount) { + for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) { + assert(impl->indexes[seg.indexOffset + j] < vertexCount); + } } #endif diff --git a/src/mbgl/gfx/upload_pass.hpp b/src/mbgl/gfx/upload_pass.hpp index a104da927..a5ec411a6 100644 --- a/src/mbgl/gfx/upload_pass.hpp +++ b/src/mbgl/gfx/upload_pass.hpp @@ -51,13 +51,13 @@ public: public: template - VertexBuffer createVertexBuffer(VertexVector&& v, + VertexBuffer createVertexBuffer(const VertexVector& v, const BufferUsageType usage = BufferUsageType::StaticDraw) { return {v.elements(), createVertexBufferResource(v.data(), v.bytes(), usage)}; } template - void updateVertexBuffer(VertexBuffer& buffer, VertexVector&& v) { + void updateVertexBuffer(VertexBuffer& buffer, const VertexVector& v) { assert(v.elements() == buffer.elements); updateVertexBufferResource(buffer.getResource(), v.data(), v.bytes()); } @@ -83,7 +83,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - /*out*/ std::unique_ptr& outBuffer) = 0; + /*out*/ std::vector>& outBuffers) = 0; #endif protected: diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index f20b2c1e4..0388b6e42 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -7,6 +9,11 @@ namespace mbgl { namespace gfx { +std::size_t VertexAttribute::getCount() const { + return sharedRawData ? sharedRawData->getRawCount() : items.size(); +} + + std::unique_ptr VertexAttributeArray::nullref = nullptr; VertexAttributeArray::VertexAttributeArray(int initCapacity) diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index 10c1afd9e..893439e3c 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -7,19 +7,67 @@ namespace mbgl { namespace gfx { +struct VertexBufferBase { + virtual ~VertexBufferBase() = default; +}; + +class VertexVectorBase { +public: + VertexVectorBase() = default; + VertexVectorBase(const VertexVectorBase&) {} // buffer is not copied + VertexVectorBase(VertexVectorBase&& other) : + buffer(std::move(other.buffer)), + dirty(other.dirty), + released(other.released) + {} + virtual ~VertexVectorBase() = default; + + virtual const void* getRawData() const = 0; + virtual std::size_t getRawSize() const = 0; + virtual std::size_t getRawCount() const = 0; + + VertexBufferBase* getBuffer() const { return buffer.get(); } + void setBuffer(std::unique_ptr&& value) { buffer = std::move(value); } + + bool getDirty() const { return dirty; } + void setDirty(bool value = true) { dirty = value; } + + bool isReleased() const { return released; } + +protected: + std::unique_ptr buffer; + bool dirty = true; + bool released = false; +}; +using VertexVectorBasePtr = std::shared_ptr; + template -class VertexVector { +class VertexVector final : public VertexVectorBase { public: using Vertex = V; + + VertexVector() = default; + VertexVector(const VertexVector& other) : + VertexVectorBase(other), + v(other.v) {} + VertexVector(VertexVector&& other) : + VertexVectorBase(std::move(other)), + v(std::move(other.v)) {} + ~VertexVector() override = default; + template void emplace_back(Arg&& vertex) { v.emplace_back(std::forward(vertex)); } - void extend(std::size_t n, const Vertex& val) { v.resize(v.size() + n, val); } + void extend(std::size_t n, const Vertex& val) { + v.resize(v.size() + n, val); + dirty = true; + } Vertex& at(std::size_t n) { assert(n < v.size()); + dirty = true; return v.at(n); } const Vertex& at(std::size_t n) const { @@ -33,12 +81,27 @@ public: bool empty() const { return v.empty(); } - void clear() { v.clear(); } + void clear() { + dirty = true; + v.clear(); + } + + void release() { + // If we've already created a buffer, we don't need the raw data any more. + if (buffer) { + clear(); + } + released = true; + } const Vertex* data() const { return v.data(); } const std::vector& vector() const { return v; } + const void* getRawData() const override { return v.data(); } + std::size_t getRawSize() const override { return sizeof(Vertex); } + std::size_t getRawCount() const override { return v.size(); } + private: std::vector v; }; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index a203e7e72..e172d54d8 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -18,7 +18,7 @@ DrawableGL::DrawableGL(std::string name_) DrawableGL::~DrawableGL() { impl->indexBuffer = {0, nullptr}; - impl->attributeBuffer.reset(); + impl->attributeBuffers.clear(); } void DrawableGL::draw(PaintParameters& parameters) const { @@ -159,7 +159,7 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { const auto& indexAttribute = defaults.get(impl->vertexAttrName); const auto vertexAttributeIndex = static_cast(indexAttribute ? indexAttribute->getIndex() : -1); - std::unique_ptr vertexBuffer; + std::vector> vertexBuffers; auto bindings = uploadPass.buildAttributeBindings(impl->vertexCount, impl->vertexType, vertexAttributeIndex, @@ -167,9 +167,9 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { defaults, overrides, usage, - vertexBuffer); + vertexBuffers); - impl->attributeBuffer = std::move(vertexBuffer); + impl->attributeBuffers = std::move(vertexBuffers); impl->indexBuffer = std::move(indexBuffer); // Create a VAO for each group of vertexes described by a segment diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index 9a55a97d5..bffaa4f2a 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -41,7 +41,7 @@ public: VertexAttributeArrayGL vertexAttributes; gfx::IndexBuffer indexBuffer = {0, nullptr}; - gfx::UniqueVertexBufferResource attributeBuffer; + std::vector attributeBuffers; UniformBufferArrayGL uniformBuffers; diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index c2229f973..323914798 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -1,4 +1,7 @@ #include + +#include +#include #include #include #include @@ -25,7 +28,7 @@ UploadPass::UploadPass(gl::CommandEncoder& commandEncoder_, const char* name) debugGroup(commandEncoder.createDebugGroup(name)) {} std::unique_ptr UploadPass::createVertexBufferResource(const void* data, - std::size_t size, + const std::size_t size, const gfx::BufferUsageType usage) { BufferID id = 0; MBGL_CHECK_ERROR(glGenBuffers(1, &id)); @@ -126,7 +129,44 @@ void UploadPass::updateTextureResourceSub(gfx::TextureResource& resource, data)); } +struct VertexBufferGL : public gfx::VertexBufferBase { + ~VertexBufferGL() override = default; + + std::unique_ptr resource; +}; + #if MLN_DRAWABLE_RENDERER +namespace { +const std::unique_ptr noBuffer; +} +const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec, const gfx::BufferUsageType usage) { + if (vec) { + const auto* rawBufPtr = vec->getRawData(); + const auto rawBufSize = static_cast(vec->getRawCount() * vec->getRawSize()); + + // If we already have a buffer... + if (auto* rawData = static_cast(vec->getBuffer()); rawData && rawData->resource) { + auto& resource = static_cast(*rawData->resource); + + // If it's changed, update it + if (rawBufSize <= resource.byteSize) { + if (vec->getDirty()) { + updateVertexBufferResource(resource, rawBufPtr, rawBufSize); + } + return rawData->resource; + } + } + // Otherwise, create a new one + if (rawBufSize > 0) { + auto buffer = std::make_unique(); + buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage); + vec->setBuffer(std::move(buffer)); + return static_cast(vec->getBuffer())->resource; + } + } + return noBuffer; +} + static std::size_t padSize(std::size_t size, std::size_t padding) { return (padding - (size % padding)) % padding; } @@ -145,7 +185,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, - /*out*/ std::unique_ptr& outBuffer) { + /*out*/ std::vector>& outBuffers) { AttributeBindingArray bindings; bindings.resize(defaults.size()); @@ -170,21 +210,35 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( } // For each attribute in the program, with the corresponding default and optional override... - const auto resolveAttr = [&](const std::string& name, const auto& defaultAttr, const auto& overrideAttr) -> void { - const auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr; - const auto& effectiveGL = static_cast(effectiveAttr); - const auto& defaultGL = static_cast(defaultAttr); + const auto resolveAttr = [&](const std::string& name, auto& defaultAttr, auto& overrideAttr) -> void { + auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr; + const auto& defaultGL = static_cast(defaultAttr); const auto stride = defaultAttr.getStride(); const auto offset = static_cast(allData.size()); const auto index = static_cast(defaultGL.getIndex()); + bindings.resize(std::max(bindings.size(), index + 1)); + + if (const auto& buffer = getBuffer(effectiveAttr.getSharedRawData(), usage)) { + bindings[index] = { + /*.attribute = */ {effectiveAttr.getSharedType(), effectiveAttr.getSharedOffset()}, + /*.vertexStride = */ effectiveAttr.getSharedStride(), + /*.vertexBufferResource = */ buffer.get(), + /*.vertexOffset = */ effectiveAttr.getSharedVertexOffset(), + }; + return; + } + if (index == vertexAttributeIndex) { // already handled return; } // Get the raw data for the values in the desired format - const auto& rawData = effectiveGL.getRaw(defaultGL.getGLType()); + const auto& rawData = VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType()); + if (rawData.empty()) { + VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType()); + } if (rawData.size() == stride * vertexCount) { // The override provided a value for each vertex, append it as-is @@ -204,7 +258,6 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( return; } - bindings.resize(std::max(bindings.size(), index + 1)); bindings[index] = { /*.attribute = */ {defaultAttr.getDataType(), offset}, /* vertexStride = */ static_cast(stride), @@ -221,19 +274,25 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( assert(vertexStride * vertexCount <= allData.size()); - if (auto vertBuf = createVertexBufferResource(allData.data(), allData.size(), usage)) { - // Fill in the buffer in each binding that was generated - std::for_each(bindings.begin(), bindings.end(), [&](auto& b) { - if (b) { - b->vertexBufferResource = vertBuf.get(); - } - }); - - outBuffer = std::move(vertBuf); - return bindings; + if (!allData.empty()) { + if (auto vertBuf = createVertexBufferResource(allData.data(), allData.size(), usage)) { + // Fill in the buffer in each binding that was generated without its own buffer + std::for_each(bindings.begin(), bindings.end(), [&](auto& b) { + if (b && !b->vertexBufferResource) { + b->vertexBufferResource = vertBuf.get(); + } + }); + + outBuffers.emplace_back(std::move(vertBuf)); + } else { + assert(false); + return {}; + } } - return {}; + assert(std::all_of(bindings.begin(), bindings.end(), [](const auto& b){ return !b || b->vertexBufferResource; })); + + return bindings; } #endif diff --git a/src/mbgl/gl/upload_pass.hpp b/src/mbgl/gl/upload_pass.hpp index 4cd1d4bd3..08dfcc3e6 100644 --- a/src/mbgl/gl/upload_pass.hpp +++ b/src/mbgl/gl/upload_pass.hpp @@ -7,6 +7,8 @@ namespace mbgl { namespace gfx { class CommandEncoder; +class VertexVectorBase; +using VertexVectorBasePtr = std::shared_ptr; } // namespace gfx @@ -41,6 +43,8 @@ public: void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override; #if MLN_DRAWABLE_RENDERER + const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, gfx::BufferUsageType); + gfx::AttributeBindingArray buildAttributeBindings( const std::size_t vertexCount, const gfx::AttributeDataType vertexType, @@ -49,7 +53,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - /*out*/ std::unique_ptr& outBuffer) override; + /*out*/ std::vector>& outBuffers) override; #endif public: diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index 6370ba38a..69d6053d1 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -483,7 +483,7 @@ GLint components(const gfx::AttributeDataType type) { #endif void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocation location) { - if (binding) { + if (binding && binding->vertexBufferResource) { context.vertexBuffer = reinterpret_cast(*binding->vertexBufferResource).buffer; MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index 1d86e78c1..4145af951 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -1,6 +1,9 @@ #include +#include #include +#include +#include #include #include @@ -112,7 +115,9 @@ bool VertexAttributeGL::get(const gfx::VertexAttribute::ElementType& element, GL case GL_FLOAT_MAT2: return gl::get(element, buffer) || gl::get(element, buffer, [](int4 x) { return float4{(float)x[0], (float)x[1], (float)x[2], (float)x[3]}; - }); + }) || gl::get(element, buffer, [](ushort8 x) { + return float4{(float)x[0], (float)x[1], (float)x[2], (float)x[3]}; + }); case GL_INT: return gl::get(element, buffer) || gl::get(element, buffer); case GL_UNSIGNED_INT: @@ -146,27 +151,29 @@ std::size_t VertexAttributeGL::getStride() const { return getStride(getGLType()); } -const std::vector& VertexAttributeGL::getRaw(platform::GLenum type) const { - if (dirty || rawType != type) { - const auto count = getCount(); - // const auto size_ = getSize(type); - const auto stride_ = getStride(type); - +namespace { +const std::vector noData; +} +const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, platform::GLenum type) { + const auto count = attr.getCount(); + const auto stride_ = getStride(type); + auto& rawData = attr.getRawData(); + if (attr.isDirty() || rawData.size() != count * stride_) { rawData.resize(stride_ * count); - std::fill(rawData.begin(), rawData.end(), 0); if (!rawData.empty()) { + std::fill(rawData.begin(), rawData.end(), 0); + std::uint8_t* outPtr = rawData.data(); for (std::size_t i = 0; i < count; ++i) { - if (!get(items[i], type, outPtr)) { - // throw? + if (!get(attr.get(i), type, outPtr)) { + // missing type conversion + assert(false); } outPtr += stride_; } } - - dirty = false; - rawType = type; + attr.setDirty(false); } return rawData; } diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 1d1597609..8ebb96e01 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -844,7 +844,7 @@ void SymbolLayout::createBucket(const ImagePositions&, for (auto& pair : bucket->paintProperties) { pair.second.iconBinders.populateVertexVectors( - feature, iconBuffer.vertices.elements(), symbolInstance.dataFeatureIndex, {}, {}, canonical); + feature, iconBuffer.vertices().elements(), symbolInstance.dataFeatureIndex, {}, {}, canonical); } } @@ -932,7 +932,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket, const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex)); for (auto& pair : bucket.paintProperties) { pair.second.textBinders.populateVertexVectors( - feature, bucket.text.vertices.elements(), feature.index, {}, {}, canonical, formattedSection); + feature, bucket.text.vertices().elements(), feature.index, {}, {}, canonical, formattedSection); } } @@ -1002,7 +1002,7 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer, if (buffer.segments.empty() || buffer.segments.back().vertexLength + vertexLength > std::numeric_limits::max() || std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits::epsilon()) { - buffer.segments.emplace_back(buffer.vertices.elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey); + buffer.segments.emplace_back(buffer.vertices().elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey); } // We're generating triangle fans, so we always start with the first @@ -1012,57 +1012,58 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer, auto index = static_cast(segment.vertexLength); // coordinates (2 triangles) - buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, - tl, - symbol.glyphOffset.y, - tex.x, - tex.y, - sizeData, - symbol.isSDF, - pixelOffsetTL, - minFontScale)); - buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, - tr, - symbol.glyphOffset.y, - tex.x + tex.w, - tex.y, - sizeData, - symbol.isSDF, - {pixelOffsetBR.x, pixelOffsetTL.y}, - minFontScale)); - buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, - bl, - symbol.glyphOffset.y, - tex.x, - tex.y + tex.h, - sizeData, - symbol.isSDF, - {pixelOffsetTL.x, pixelOffsetBR.y}, - minFontScale)); - buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, - br, - symbol.glyphOffset.y, - tex.x + tex.w, - tex.y + tex.h, - sizeData, - symbol.isSDF, - pixelOffsetBR, - minFontScale)); + auto& vertices = buffer.vertices(); + vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, + tl, + symbol.glyphOffset.y, + tex.x, + tex.y, + sizeData, + symbol.isSDF, + pixelOffsetTL, + minFontScale)); + vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, + tr, + symbol.glyphOffset.y, + tex.x + tex.w, + tex.y, + sizeData, + symbol.isSDF, + {pixelOffsetBR.x, pixelOffsetTL.y}, + minFontScale)); + vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, + bl, + symbol.glyphOffset.y, + tex.x, + tex.y + tex.h, + sizeData, + symbol.isSDF, + {pixelOffsetTL.x, pixelOffsetBR.y}, + minFontScale)); + vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point, + br, + symbol.glyphOffset.y, + tex.x + tex.w, + tex.y + tex.h, + sizeData, + symbol.isSDF, + pixelOffsetBR, + minFontScale)); // Dynamic/Opacity vertices are initialized so that the vertex count always // agrees with the layout vertex buffer, but they will always be updated // before rendering happens auto dynamicVertex = SymbolSDFIconProgram::dynamicLayoutVertex(labelAnchor.point, 0); - buffer.dynamicVertices.emplace_back(dynamicVertex); - buffer.dynamicVertices.emplace_back(dynamicVertex); - buffer.dynamicVertices.emplace_back(dynamicVertex); - buffer.dynamicVertices.emplace_back(dynamicVertex); + buffer.dynamicVertices().emplace_back(dynamicVertex); + buffer.dynamicVertices().emplace_back(dynamicVertex); + buffer.dynamicVertices().emplace_back(dynamicVertex); + buffer.dynamicVertices().emplace_back(dynamicVertex); auto opacityVertex = SymbolSDFIconProgram::opacityVertex(1.0, 1.0); - buffer.opacityVertices.emplace_back(opacityVertex); - buffer.opacityVertices.emplace_back(opacityVertex); - buffer.opacityVertices.emplace_back(opacityVertex); - buffer.opacityVertices.emplace_back(opacityVertex); + buffer.opacityVertices().emplace_back(opacityVertex); + buffer.opacityVertices().emplace_back(opacityVertex); + buffer.opacityVertices().emplace_back(opacityVertex); + buffer.opacityVertices().emplace_back(opacityVertex); // add the two triangles, referencing the four coordinates we just inserted. buffer.triangles.emplace_back(index + 0, index + 1, index + 2); diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index a246ebfc7..2935a7e1a 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -21,9 +21,12 @@ CircleBucket::CircleBucket(const std::maprelease(); +} void CircleBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER if (!uploaded) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); @@ -32,6 +35,7 @@ void CircleBucket::upload(gfx::UploadPass& uploadPass) { for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp index c1584ec5d..c81ad94da 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.hpp +++ b/src/mbgl/renderer/buckets/circle_bucket.hpp @@ -30,12 +30,17 @@ public: void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; - gfx::VertexVector vertices; + using VertexVector = gfx::VertexVector; + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + gfx::IndexVector triangles; SegmentVector segments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER std::map paintPropertyBinders; diff --git a/src/mbgl/renderer/buckets/debug_bucket.cpp b/src/mbgl/renderer/buckets/debug_bucket.cpp index 1df0f5614..064ee183f 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.cpp +++ b/src/mbgl/renderer/buckets/debug_bucket.cpp @@ -71,6 +71,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, } void DebugBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER if (!vertices.empty()) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); indexBuffer = uploadPass.createIndexBuffer(std::move(indices)); @@ -80,6 +81,7 @@ void DebugBucket::upload(gfx::UploadPass& uploadPass) { static const PremultipliedImage emptyImage{Size(1, 1), data.data(), data.size()}; texture = uploadPass.createTexture(emptyImage); } +#endif // MLN_LEGACY_RENDERER } } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index 02b0e12c4..26e05589e 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -49,7 +49,9 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties&, } } -FillBucket::~FillBucket() = default; +FillBucket::~FillBucket() { + sharedVertices->release(); +} void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, @@ -131,6 +133,7 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, } void FillBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER if (!uploaded) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines)); @@ -141,6 +144,7 @@ void FillBucket::upload(gfx::UploadPass& uploadPass) { for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp index b3014da76..53ee9e59d 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_bucket.hpp @@ -40,15 +40,20 @@ public: void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; - gfx::VertexVector vertices; + using VertexVector = gfx::VertexVector; + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + gfx::IndexVector lines; gfx::IndexVector triangles; SegmentVector lineSegments; SegmentVector triangleSegments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional lineIndexBuffer; std::optional triangleIndexBuffer; +#endif // MLN_LEGACY_RENDERER std::map paintPropertyBinders; }; diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index 6b3eb461e..3d9a57fe3 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -52,7 +52,9 @@ FillExtrusionBucket::FillExtrusionBucket( } } -FillExtrusionBucket::~FillExtrusionBucket() = default; +FillExtrusionBucket::~FillExtrusionBucket() { + sharedVertices->release(); +} void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, @@ -168,6 +170,7 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, } void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER if (!uploaded) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); @@ -176,6 +179,7 @@ void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) { for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp index 22770a9cb..1787d101b 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp @@ -39,12 +39,17 @@ public: void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; - gfx::VertexVector vertices; + using VertexVector = gfx::VertexVector; + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + gfx::IndexVector triangles; SegmentVector triangleSegments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER std::unordered_map paintPropertyBinders; }; diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp index c8f560fad..fbf568717 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp @@ -21,15 +21,19 @@ HeatmapBucket::HeatmapBucket(const BucketParameters& parameters, } } -HeatmapBucket::~HeatmapBucket() = default; +HeatmapBucket::~HeatmapBucket() { + sharedVertices->release(); +} void HeatmapBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp index 33f99822a..58116fe59 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp @@ -30,12 +30,17 @@ public: float getQueryRadius(const RenderLayer&) const override; - gfx::VertexVector vertices; + using VertexVector = gfx::VertexVector; + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + gfx::IndexVector triangles; SegmentVector segments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER std::map paintPropertyBinders; diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.cpp b/src/mbgl/renderer/buckets/hillshade_bucket.cpp index 0796409bd..cf2159549 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.cpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.cpp @@ -29,6 +29,7 @@ void HillshadeBucket::upload(gfx::UploadPass& uploadPass) { return; } +#if MLN_LEGACY_RENDERER const PremultipliedImage* image = demdata.getImage(); dem = uploadPass.createTexture(*image); @@ -38,13 +39,17 @@ void HillshadeBucket::upload(gfx::UploadPass& uploadPass) { if (!indices.empty()) { indexBuffer = uploadPass.createIndexBuffer(std::move(indices)); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } void HillshadeBucket::clear() { +#if MLN_LEGACY_RENDERER vertexBuffer = {}; indexBuffer = {}; +#endif // MLN_LEGACY_RENDERER + segments.clear(); vertices.clear(); indices.clear(); diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.hpp b/src/mbgl/renderer/buckets/hillshade_bucket.hpp index a2098a93e..caf0632a7 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.hpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.hpp @@ -44,8 +44,10 @@ public: gfx::IndexVector indices; SegmentVector segments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER private: DEMData demdata; diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 952810cae..aeacdd9dd 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -25,7 +25,9 @@ LineBucket::LineBucket(LineBucket::PossiblyEvaluatedLayoutProperties layout_, } } -LineBucket::~LineBucket() = default; +LineBucket::~LineBucket() { + sharedVertices->release(); +} void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection, @@ -575,6 +577,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, } void LineBucket::upload(gfx::UploadPass& uploadPass) { +#if MLN_LEGACY_RENDERER if (!uploaded) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); @@ -583,6 +586,7 @@ void LineBucket::upload(gfx::UploadPass& uploadPass) { for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp index f98bed20a..afb4fd089 100644 --- a/src/mbgl/renderer/buckets/line_bucket.hpp +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -42,12 +42,17 @@ public: PossiblyEvaluatedLayoutProperties layout; - gfx::VertexVector vertices; + using VertexVector = gfx::VertexVector; + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + gfx::IndexVector triangles; SegmentVector segments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER std::map paintPropertyBinders; diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp index 2b0cf65c1..f2e6dadcf 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.cpp +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -19,6 +19,7 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) { if (!hasData()) { return; } +#if MLN_LEGACY_RENDERER if (!texture) { texture = uploadPass.createTexture(*image); } @@ -28,12 +29,16 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) { if (!indices.empty()) { indexBuffer = uploadPass.createIndexBuffer(std::move(indices)); } +#endif // MLN_LEGACY_RENDERER uploaded = true; } void RasterBucket::clear() { +#if MLN_LEGACY_RENDERER vertexBuffer = {}; indexBuffer = {}; +#endif // MLN_LEGACY_RENDERER + segments.clear(); vertices.clear(); indices.clear(); diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp index 76ee30c0d..8182f2a0d 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.hpp +++ b/src/mbgl/renderer/buckets/raster_bucket.hpp @@ -36,8 +36,10 @@ public: gfx::IndexVector indices; SegmentVector segments; +#if MLN_LEGACY_RENDERER std::optional> vertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER }; } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index eb6c25476..d9c218db2 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -63,12 +63,13 @@ SymbolBucket::SymbolBucket(Immutable #include +#include #include namespace mbgl { @@ -132,18 +133,41 @@ public: std::unique_ptr textSizeBinder; - struct Buffer { - gfx::VertexVector vertices; - gfx::VertexVector> dynamicVertices; - gfx::VertexVector> opacityVertices; + using VertexVector = gfx::VertexVector; + using VertexBuffer = gfx::VertexBuffer; + using DynamicVertexVector = gfx::VertexVector>; + using DynamicVertexBuffer = gfx::VertexBuffer>; + using OpacityVertexVector = gfx::VertexVector>; + using OpacityVertexBuffer = gfx::VertexBuffer>; + + struct Buffer final { + ~Buffer() { + sharedVertices->release(); + sharedDynamicVertices->release(); + sharedOpacityVertices->release(); + } + std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices() { return *sharedVertices; } + const VertexVector& vertices() const { return *sharedVertices; } + + std::shared_ptr sharedDynamicVertices = std::make_shared(); + DynamicVertexVector& dynamicVertices() { return *sharedDynamicVertices; } + const DynamicVertexVector& dynamicVertices() const { return *sharedDynamicVertices; } + + std::shared_ptr sharedOpacityVertices = std::make_shared(); + OpacityVertexVector& opacityVertices() { return *sharedOpacityVertices; } + const OpacityVertexVector& opacityVertices() const { return *sharedOpacityVertices; } + gfx::IndexVector triangles; SegmentVector segments; std::vector placedSymbols; - std::optional> vertexBuffer; - std::optional>> dynamicVertexBuffer; - std::optional>> opacityVertexBuffer; +#if MLN_LEGACY_RENDERER + std::optional vertexBuffer; + std::optional dynamicVertexBuffer; + std::optional opacityVertexBuffer; std::optional indexBuffer; +#endif // MLN_LEGACY_RENDERER } text; std::unique_ptr iconSizeBinder; diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 5f86ff132..c8b1993b8 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -60,6 +60,13 @@ RenderCircleLayer::RenderCircleLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} +void RenderCircleLayer::prepare(const LayerPrepareParameters& parameters) { + RenderLayer::prepare(parameters); +#if MLN_DRAWABLE_RENDERER + updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER +} + void RenderCircleLayer::transition(const TransitionParameters& parameters) { unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } @@ -256,6 +263,9 @@ bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryG } #if MLN_DRAWABLE_RENDERER +namespace { + + struct alignas(16) CircleInterpolateUBO { float color_t; float radius_t; @@ -268,8 +278,11 @@ struct alignas(16) CircleInterpolateUBO { }; static_assert(sizeof(CircleInterpolateUBO) % 16 == 0); -static const std::string CircleShaderGroupName = "CircleShader"; -static constexpr std::string_view CircleInterpolateUBOName = "CircleInterpolateUBO"; +constexpr auto CircleShaderGroupName = "CircleShader"; +constexpr auto CircleInterpolateUBOName = "CircleInterpolateUBO"; +constexpr auto VertexAttribName = "a_pos"; + +} // namespace void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, @@ -301,8 +314,6 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, } std::unique_ptr circleBuilder; - std::vector newTiles; - gfx::VertexAttributeArray circleVertexAttrs; constexpr auto renderPass = RenderPass::Translucent; if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { @@ -324,10 +335,11 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, continue; } - auto& bucket = static_cast(*renderData->bucket); + const auto& bucket = static_cast(*renderData->bucket); + const auto vertexCount = bucket.vertices.elements(); const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - float zoom = static_cast(state.getZoom()); + const float zoom = static_cast(state.getZoom()); const CircleInterpolateUBO interpolateUBO = { /* .color_t = */ std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /* .radius_t = */ std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -349,9 +361,8 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, continue; } - circleVertexAttrs.clear(); - - auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties( paintPropertyBinders, evaluated); - auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms); + const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!circleShader) { continue; } - std::vector> rawVerts; - const auto buildVertices = [&]() { - const std::vector>>::Vertex>& - verts = bucket.vertices.vector(); - if (rawVerts.size() < verts.size()) { - rawVerts.resize(verts.size()); - std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); - } - }; + if (const auto& attr = circleVertexAttrs.add(VertexAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(CircleLayoutVertex, a1), 0, sizeof(CircleLayoutVertex), gfx::AttributeDataType::Short2); + } circleBuilder = context.createDrawableBuilder("circle"); circleBuilder->setShader(std::static_pointer_cast(circleShader)); - circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly); + circleBuilder->setDepthType(gfx::DepthMaskType::ReadOnly); circleBuilder->setColorMode(gfx::ColorMode::alphaBlended()); circleBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); circleBuilder->setRenderPass(renderPass); - circleBuilder->setVertexAttributes(circleVertexAttrs); - - buildVertices(); - circleBuilder->addVertices(rawVerts, 0, rawVerts.size()); - + circleBuilder->setVertexAttributes(std::move(circleVertexAttrs)); + + circleBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); circleBuilder->setSegments( gfx::Triangles(), bucket.triangles.vector(), bucket.segments.data(), bucket.segments.size()); diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index bb7d03852..322d4804d 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -23,6 +23,7 @@ public: #endif private: + void prepare(const LayerPrepareParameters&) override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 374bc1c82..9ad6d33b5 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -39,6 +39,7 @@ namespace { constexpr std::string_view FillExtrusionShaderName = "FillExtrusionShader"; constexpr std::string_view FillExtrusionPatternShaderName = "FillExtrusionPatternShader"; +constexpr auto PosAttribName = "a_pos"; constexpr auto NormAttribName = "a_normal_ed"; constexpr auto IconTextureName = "u_image"; @@ -350,8 +351,6 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } const auto vertexCount = bucket.vertices.elements(); - constexpr auto vertexSize = sizeof(FillExtrusionLayoutVertex::a1); - const auto defPattern = mbgl::Faded{"", ""}; const auto fillPatternValue = evaluated.get().constantOr(defPattern); const auto patternPosA = tile.getPattern(fillPatternValue.from.id()); @@ -450,30 +449,22 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } } - if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) { - const auto count = bucket.vertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, util::cast(bucket.vertices.at(i).a2)); // int16_t x4 - } + if (const auto& attr = vertexAttrs.getOrAdd(PosAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a1), 0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short2); } - - std::vector rawVertices(vertexSize * vertexCount); - for (std::size_t i = 0; i < vertexCount; ++i) { - std::memcpy(&rawVertices[vertexSize * i], &bucket.vertices.at(i).a1, vertexSize); + if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a2), 0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short4); } colorBuilder->setEnableStencil(doDepthPass); if (doDepthPass) { - auto vertexCopy = rawVertices; - depthBuilder->setRawVertices(std::move(vertexCopy), vertexCount, gfx::AttributeDataType::Short2); + depthBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); } - colorBuilder->setRawVertices(std::move(rawVertices), vertexCount, gfx::AttributeDataType::Short2); + colorBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); if (doDepthPass) { - gfx::VertexAttributeArray attribCopy; - attribCopy.copy(vertexAttrs); - depthBuilder->setVertexAttributes(std::move(attribCopy)); + auto copy = vertexAttrs.clone(); + depthBuilder->setVertexAttributes(std::move(*copy)); } colorBuilder->setVertexAttributes(std::move(vertexAttrs)); diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index a9b0d2888..adeaec501 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -42,6 +42,7 @@ constexpr auto FillOutlineShaderName = "FillOutlineShader"; constexpr auto FillPatternShaderName = "FillPatternShader"; constexpr auto FillOutlinePatternShaderName = "FillOutlinePatternShader"; +constexpr auto PosAttribName = "a_pos"; constexpr auto IconTextureName = "u_image"; #endif // MLN_DRAWABLE_RENDERER @@ -58,6 +59,13 @@ RenderFillLayer::RenderFillLayer(Immutable _impl) RenderFillLayer::~RenderFillLayer() = default; +void RenderFillLayer::prepare(const LayerPrepareParameters& params) { + RenderLayer::prepare(params); +#if MLN_DRAWABLE_RENDERER + updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER +} + void RenderFillLayer::transition(const TransitionParameters& parameters) { unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } @@ -329,10 +337,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, std::unique_ptr outlineBuilder; std::unique_ptr patternBuilder; std::unique_ptr outlinePatternBuilder; - gfx::VertexAttributeArray fillVertexAttrs; - gfx::VertexAttributeArray outlineVertexAttrs; - gfx::VertexAttributeArray patternVertexAttrs; - gfx::VertexAttributeArray patternOutlineVertexAttrs; const auto layerPrefix = getID() + "/"; const auto renderPass = static_cast(evaluatedProperties->renderPasses); @@ -414,36 +418,27 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, continue; } - std::vector> rawVerts; - const auto buildVertices = [&]() { - const auto& verts = bucket.vertices.vector(); - if (rawVerts.size() < verts.size()) { - rawVerts.resize(verts.size()); - std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); - } - }; - - fillVertexAttrs.clear(); - outlineVertexAttrs.clear(); - // `Fill*Program` all use `style::FillPaintProperties` - const auto fillUniformProps = - fillVertexAttrs.readDataDrivenPaintProperties( - binders, evaluated); - const auto outlineUniformProps = - outlineVertexAttrs.readDataDrivenPaintProperties( + gfx::VertexAttributeArray vertexAttrs; + const auto uniformProps = + vertexAttrs.readDataDrivenPaintProperties( binders, evaluated); + const auto vertexCount = bucket.vertices.elements(); + if (const auto& attr = vertexAttrs.add(PosAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(FillLayoutVertex, a1), 0, sizeof(FillLayoutVertex), gfx::AttributeDataType::Short2); + } + if (unevaluated.get().isUndefined()) { // Fill will occur in opaque or translucent pass based on `opaquePassCutoff`. // Outline always occurs in translucent pass, defaults to fill color const auto doOutline = evaluated.get(); const auto fillShader = std::static_pointer_cast( - fillShaderGroup->getOrCreateShader(context, fillUniformProps)); + fillShaderGroup->getOrCreateShader(context, uniformProps)); const auto outlineShader = doOutline ? std::static_pointer_cast( - outlineShaderGroup->getOrCreateShader(context, outlineUniformProps)) + outlineShaderGroup->getOrCreateShader(context, uniformProps)) : nullptr; if (!fillBuilder && fillShader) { @@ -471,10 +466,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } if (fillBuilder) { - buildVertices(); fillBuilder->setShader(fillShader); - fillBuilder->setVertexAttributes(fillVertexAttrs); - fillBuilder->addVertices(rawVerts, 0, rawVerts.size()); + if (outlineBuilder) { + fillBuilder->setVertexAttributes(vertexAttrs); + } else { + fillBuilder->setVertexAttributes(std::move(vertexAttrs)); + } + fillBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); fillBuilder->setSegments(gfx::Triangles(), bucket.triangles.vector(), bucket.triangleSegments.data(), @@ -482,10 +480,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, finish(*fillBuilder, tileID, interpolateUBO, tileProps); } if (outlineBuilder) { - buildVertices(); outlineBuilder->setShader(outlineShader); - outlineBuilder->setVertexAttributes(outlineVertexAttrs); - outlineBuilder->addVertices(rawVerts, 0, rawVerts.size()); + outlineBuilder->setVertexAttributes(std::move(vertexAttrs)); + outlineBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); outlineBuilder->setSegments( gfx::Lines(2), bucket.lines.vector(), bucket.lineSegments.data(), bucket.lineSegments.size()); finish(*outlineBuilder, tileID, interpolateUBO, tileProps); @@ -499,10 +496,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, const auto doOutline = evaluated.get() && unevaluated.get().isUndefined(); const auto fillShader = std::static_pointer_cast( - patternShaderGroup->getOrCreateShader(context, fillUniformProps)); + patternShaderGroup->getOrCreateShader(context, uniformProps)); const auto outlineShader = doOutline ? std::static_pointer_cast( outlinePatternShaderGroup->getOrCreateShader( - context, outlineUniformProps)) + context, uniformProps)) : nullptr; if (!patternBuilder) { @@ -527,14 +524,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } } - gfx::DrawableTweakerPtr tweaker; if (patternBuilder) { patternBuilder->clearTweakers(); } if (outlinePatternBuilder) { outlinePatternBuilder->clearTweakers(); } - if ((patternBuilder || outlinePatternBuilder) && !tweaker) { + if (patternBuilder || outlinePatternBuilder) { if (const auto& atlases = tile.getAtlasTextures()) { auto tweaker = std::make_shared(atlases, /*glyphName=*/std::string(), @@ -550,11 +546,14 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } if (patternBuilder) { - buildVertices(); patternBuilder->setShader(fillShader); patternBuilder->setRenderPass(renderPass); - patternBuilder->setVertexAttributes(fillVertexAttrs); - patternBuilder->addVertices(rawVerts, 0, rawVerts.size()); + if (outlinePatternBuilder) { + patternBuilder->setVertexAttributes(vertexAttrs); + } else { + patternBuilder->setVertexAttributes(std::move(vertexAttrs)); + } + patternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); patternBuilder->setSegments(gfx::Triangles(), bucket.triangles.vector(), bucket.triangleSegments.data(), @@ -563,11 +562,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, finish(*patternBuilder, tileID, interpolateUBO, tileProps); } if (outlinePatternBuilder) { - buildVertices(); outlinePatternBuilder->setShader(outlineShader); outlinePatternBuilder->setRenderPass(renderPass); - outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs); - outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size()); + outlinePatternBuilder->setVertexAttributes(std::move(vertexAttrs)); + outlinePatternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); outlinePatternBuilder->setSegments( gfx::Lines(2), bucket.lines.vector(), bucket.lineSegments.data(), bucket.lineSegments.size()); diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index fdf54f89f..5e253122c 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -30,6 +30,7 @@ public: #endif private: + void prepare(const LayerPrepareParameters&) override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 9d345478c..037d0b701 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -45,6 +45,13 @@ RenderHeatmapLayer::RenderHeatmapLayer(Immutable _impl) RenderHeatmapLayer::~RenderHeatmapLayer() = default; +void RenderHeatmapLayer::prepare(const LayerPrepareParameters& parameters) { + RenderLayer::prepare(parameters); +#if MLN_DRAWABLE_RENDERER + updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER +} + void RenderHeatmapLayer::transition(const TransitionParameters& parameters) { unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); updateColorRamp(); @@ -260,6 +267,8 @@ void RenderHeatmapLayer::removeAllDrawables() { } } +namespace { + struct alignas(16) HeatmapInterpolateUBO { float weight_t; float radius_t; @@ -267,9 +276,12 @@ struct alignas(16) HeatmapInterpolateUBO { }; static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0); -static const std::string HeatmapShaderGroupName = "HeatmapShader"; -static const std::string HeatmapTextureShaderGroupName = "HeatmapTextureShader"; -static constexpr std::string_view HeatmapInterpolateUBOName = "HeatmapInterpolateUBO"; +constexpr auto HeatmapShaderGroupName = "HeatmapShader"; +constexpr auto HeatmapTextureShaderGroupName = "HeatmapTextureShader"; +constexpr auto HeatmapInterpolateUBOName = "HeatmapInterpolateUBO"; +constexpr auto VertexAttribName = "a_pos"; + +} void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, @@ -318,9 +330,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } std::unique_ptr heatmapBuilder; - std::vector newTiles; - gfx::VertexAttributeArray heatmapVertexAttrs; - auto renderPass = RenderPass::Translucent; + constexpr auto renderPass = RenderPass::Translucent; if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { return; @@ -341,10 +351,11 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, continue; } - auto& bucket = static_cast(*renderData->bucket); + const auto& bucket = static_cast(*renderData->bucket); + const auto vertexCount = bucket.vertices.elements(); const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - float zoom = static_cast(state.getZoom()); + const float zoom = static_cast(state.getZoom()); const HeatmapInterpolateUBO interpolateUBO = { /* .weight_t = */ std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /* .radius_t = */ std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -358,25 +369,19 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, continue; } - heatmapVertexAttrs.clear(); + gfx::VertexAttributeArray heatmapVertexAttrs; - auto propertiesAsUniforms = heatmapVertexAttrs.readDataDrivenPaintProperties( + const auto propertiesAsUniforms = heatmapVertexAttrs.readDataDrivenPaintProperties( paintPropertyBinders, evaluated); - auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms); + const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!heatmapShader) { continue; } - std::vector> rawVerts; - const auto buildVertices = [&]() { - const std::vector>>::Vertex>& - verts = bucket.vertices.vector(); - if (rawVerts.size() < verts.size()) { - rawVerts.resize(verts.size()); - std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); - } - }; + if (const auto& attr = heatmapVertexAttrs.add(VertexAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(HeatmapLayoutVertex, a1), 0, sizeof(HeatmapLayoutVertex), gfx::AttributeDataType::Short2); + } heatmapBuilder = context.createDrawableBuilder("heatmap"); heatmapBuilder->setShader(std::static_pointer_cast(heatmapShader)); @@ -384,13 +389,9 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, : gfx::DepthMaskType::ReadOnly); heatmapBuilder->setColorMode(gfx::ColorMode::additive()); heatmapBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - heatmapBuilder->setRenderPass(renderPass); - heatmapBuilder->setVertexAttributes(heatmapVertexAttrs); - - buildVertices(); - heatmapBuilder->addVertices(rawVerts, 0, rawVerts.size()); - + heatmapBuilder->setVertexAttributes(std::move(heatmapVertexAttrs)); + heatmapBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); heatmapBuilder->setSegments( gfx::Triangles(), bucket.triangles.vector(), bucket.segments.data(), bucket.segments.size()); @@ -415,8 +416,6 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, setLayerGroup(std::move(layerGroup_), changes); } - auto* textureLayerGroup = static_cast(layerGroup.get()); - if (!heatmapTextureShader) { heatmapTextureShader = context.getGenericShader(shaders, HeatmapTextureShaderGroupName); } @@ -425,19 +424,20 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return; } + auto* textureLayerGroup = static_cast(layerGroup.get()); textureLayerGroup->clearDrawables(); std::unique_ptr heatmapTextureBuilder; - std::vector> textureRawVerts; - const auto buildTextureVertices = [&]() { - const std::vector>>::Vertex> verts = - RenderStaticData::heatmapTextureVertices().vector(); - if (textureRawVerts.size() < verts.size()) { - textureRawVerts.resize(verts.size()); - std::transform(verts.begin(), verts.end(), textureRawVerts.begin(), [](const auto& x) { return x.a1; }); - } - }; + if (!sharedTextureVertices) { + sharedTextureVertices = std::make_shared(RenderStaticData::heatmapTextureVertices()); + } + const auto textureVertexCount = sharedTextureVertices->elements(); + + gfx::VertexAttributeArray textureVertexAttrs; + if (const auto& attr = textureVertexAttrs.add(VertexAttribName)) { + attr->setSharedRawData(sharedTextureVertices, offsetof(HeatmapLayoutVertex, a1), 0, sizeof(HeatmapLayoutVertex), gfx::AttributeDataType::Short2); + } heatmapTextureBuilder = context.createDrawableBuilder("heatmapTexture"); heatmapTextureBuilder->setShader(heatmapTextureShader); @@ -445,16 +445,12 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, : gfx::DepthMaskType::ReadOnly); heatmapTextureBuilder->setColorMode(gfx::ColorMode::alphaBlended()); heatmapTextureBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - heatmapTextureBuilder->setRenderPass(renderPass); - - buildTextureVertices(); - heatmapTextureBuilder->addVertices(textureRawVerts, 0, textureRawVerts.size()); - + heatmapTextureBuilder->setVertexAttributes(std::move(textureVertexAttrs)); + heatmapTextureBuilder->setRawVertices({}, textureVertexCount, gfx::AttributeDataType::Short2); if (segments.empty()) { segments = RenderStaticData::heatmapTextureSegments(); } - heatmapTextureBuilder->setSegments( gfx::Triangles(), RenderStaticData::quadTriangleIndices().vector(), segments.data(), segments.size()); @@ -468,7 +464,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, texture->setImage(colorRamp); texture->setSamplerConfiguration( {gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - heatmapTextureBuilder->setTexture(texture, colorRampLocation.value()); + heatmapTextureBuilder->setTexture(std::move(texture), colorRampLocation.value()); } heatmapTextureBuilder->flush(); diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index ead422eb9..40f05774b 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -28,6 +28,7 @@ public: #endif private: + void prepare(const LayerPrepareParameters&) override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; @@ -72,6 +73,9 @@ private: gfx::ShaderGroupPtr heatmapShaderGroup; gfx::ShaderProgramBasePtr heatmapTextureShader; RenderTargetPtr renderTarget; + + using TextureVertexVector = gfx::VertexVector; + std::shared_ptr sharedTextureVertices; #endif }; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index a7276f019..2cc4f7520 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -38,6 +38,13 @@ inline const LineLayer::Impl& impl_cast(const Immutable& imp return static_cast(*impl); } +#if MLN_DRAWABLE_RENDERER + +constexpr auto VertexAttribName = "a_pos_normal"; +constexpr auto DataAttribName = "a_data"; + +#endif // MLN_DRAWABLE_RENDERER + } // namespace RenderLineLayer::RenderLineLayer(Immutable _impl) @@ -97,6 +104,10 @@ void RenderLineLayer::prepare(const LayerPrepareParameters& params) { params.lineAtlas.getDashPatternTexture( evaluated.get().from, evaluated.get().to, cap); } + +#if MLN_DRAWABLE_RENDERER + updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER } void RenderLineLayer::upload(gfx::UploadPass& uploadPass) { @@ -461,31 +472,27 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, : gfx::ColorMode::unblended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setEnableStencil(true); - builder->setVertexAttrName("a_pos_normal"); + builder->setVertexAttrName(VertexAttribName); return builder; }; - auto addVertices = [&](std::unique_ptr& builder, const LineBucket& bucket) { - std::vector> vertices; - vertices.resize(bucket.vertices.vector().size()); - std::transform( - bucket.vertices.vector().begin(), bucket.vertices.vector().end(), vertices.begin(), [](const auto& x) { - return x.a1; - }); - builder->addVertices(vertices, 0, vertices.size()); - }; - - auto addAttributes = [&](std::unique_ptr& builder, + auto addAttributes = [&](gfx::DrawableBuilder& builder, const LineBucket& bucket, - gfx::VertexAttributeArray& vertexAttrs) { - if (auto& attr = vertexAttrs.getOrAdd("a_data")) { - size_t index{0}; - for (const auto& vert : bucket.vertices.vector()) { - attr->set(index++, gfx::VertexAttribute::int4{vert.a2[0], vert.a2[1], vert.a2[2], vert.a2[3]}); - } + gfx::VertexAttributeArray&& vertexAttrs) { + + const auto vertexCount = bucket.vertices.elements(); + builder.setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); + + if (const auto& attr = vertexAttrs.add(VertexAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a1), 0, sizeof(LineLayoutVertex), gfx::AttributeDataType::Short2); } - builder->setVertexAttributes(std::move(vertexAttrs)); + + if (const auto& attr = vertexAttrs.add(DataAttribName)) { + attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a2), 0, sizeof(LineLayoutVertex), gfx::AttributeDataType::UByte4); + } + + builder.setVertexAttributes(std::move(vertexAttrs)); }; auto setSegments = [&](std::unique_ptr& builder, const LineBucket& bucket) { @@ -508,8 +515,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, const auto& crossfade = getCrossfade(renderData->layerProperties); // interpolation UBOs - float zoom = static_cast(state.getZoom()); - LineInterpolationUBO lineInterpolationUBO{ + const float zoom = static_cast(state.getZoom()); + const LineInterpolationUBO lineInterpolationUBO{ /*color_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*blur_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*opacity_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -518,7 +525,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, /*width_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), 0, 0}; - LineGradientInterpolationUBO lineGradientInterpolationUBO{ + const LineGradientInterpolationUBO lineGradientInterpolationUBO{ /*blur_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*opacity_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*gapwidth_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -526,7 +533,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, /*width_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), 0, {0, 0}}; - LinePatternInterpolationUBO linePatternInterpolationUBO{ + const LinePatternInterpolationUBO linePatternInterpolationUBO{ /*blur_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*opacity_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*offset_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -535,7 +542,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, /*pattern_from_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*pattern_to_t =*/std::get<1>(paintPropertyBinders.get()->interpolationFactor(zoom)), 0}; - LineSDFInterpolationUBO lineSDFInterpolationUBO{ + const LineSDFInterpolationUBO lineSDFInterpolationUBO{ /*color_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*blur_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /*opacity_t =*/std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), @@ -547,9 +554,9 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // tile dependent properties UBOs: const auto& linePatternValue = evaluated.get().constantOr(Faded{"", ""}); - std::optional patternPosA = tile.getPattern(linePatternValue.from.id()); - std::optional patternPosB = tile.getPattern(linePatternValue.to.id()); - LinePatternTilePropertiesUBO linePatternTilePropertiesUBO{ + const std::optional patternPosA = tile.getPattern(linePatternValue.from.id()); + const std::optional patternPosB = tile.getPattern(linePatternValue.to.id()); + const LinePatternTilePropertiesUBO linePatternTilePropertiesUBO{ /*pattern_from =*/patternPosA ? util::cast(patternPosA->tlbr()) : std::array{0}, /*pattern_to =*/patternPosB ? util::cast(patternPosB->tlbr()) : std::array{0}}; @@ -586,7 +593,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, if (!evaluated.get().from.empty()) { // dash array line (SDF) gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintPropertiesgetOrCreateShader(context, propertiesAsUniforms)); // vertices, attributes and segments - addVertices(builder, bucket); - addAttributes(builder, bucket, vertexAttrs); + addAttributes(*builder, bucket, std::move(vertexAttrs)); setSegments(builder, bucket); // finish @@ -630,8 +636,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); // vertices and attributes - addVertices(builder, bucket); - addAttributes(builder, bucket, vertexAttrs); + addAttributes(*builder, bucket, std::move(vertexAttrs)); // texture if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) { @@ -667,8 +672,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); // vertices and attributes - addVertices(builder, bucket); - addAttributes(builder, bucket, vertexAttrs); + addAttributes(*builder, bucket, std::move(vertexAttrs)); // texture if (const auto samplerLocation = builder->getShader()->getSamplerLocation("u_image")) { @@ -702,7 +706,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } else { // simple line gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintPropertiesgetOrCreateShader(context, propertiesAsUniforms)); // vertices, attributes and segments - addVertices(builder, bucket); - addAttributes(builder, bucket, vertexAttrs); + addAttributes(*builder, bucket, std::move(vertexAttrs)); setSegments(builder, bucket); // finish diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 451f16f01..e5bf420e5 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -756,44 +756,34 @@ void updateTileDrawable(gfx::Drawable& drawable, if (!drawable.getData()) { return; } - + auto& drawData = static_cast(*drawable.getData()); const auto isText = (drawData.symbolType == SymbolType::Text); const auto currentZoom = static_cast(state.getZoom()); - + // This property can be set after the initial appearance of the tile, as part of the layout process. drawData.bucketVariablePlacement = bucket.hasVariablePlacement; - + const auto tileUBO = buildTileUBO(bucket, drawData, currentZoom); const auto interpolateUBO = buildInterpUBO(paintProps, isText, currentZoom); - + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableTilePropsUBOName, &tileUBO, context); uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableInterpolateUBOName, &interpolateUBO, context); - + // TODO: detect whether anything has actually changed // See `Placement::updateBucketDynamicVertices` - if (const auto newAttribs = drawable.getVertexAttributes().clone()) { - const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF); - const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon); + const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF); + const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon); - if (auto& attr = newAttribs->getOrAdd(projPosAttribName)) { - const auto count = buffer.dynamicVertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, util::cast(buffer.dynamicVertices.at(i).a1)); - } - } - - if (auto& attr = newAttribs->getOrAdd(fadeOpacityAttribName)) { - const auto count = buffer.opacityVertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, buffer.opacityVertices.at(i).a1[0]); - } - } - - drawable.setVertexAttributes(std::move(*newAttribs)); + auto& attribs = drawable.mutableVertexAttributes(); + if (const auto& attr = attribs.get(projPosAttribName)) { + using Vertex = gfx::Vertex; + attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3); + } + if (const auto& attr = attribs.get(fadeOpacityAttribName)) { + using Vertex = gfx::Vertex; + attr->setSharedRawData(buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float); } } @@ -884,7 +874,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const SymbolType type) mutable { for (const auto& segment : buffer.segments) { const auto key = sortFeaturesByKey ? segment.sortKey : (serialKey += 1.0); - assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices.elements()); + assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices().elements()); it = renderableSegments.emplace_hint( it, std::ref(segment), tile, renderData, bucketPaintProperties, key, type, tileID.overscaledZ); } @@ -927,46 +917,25 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, auto& tileInfo = tileCache[tile.id]; - const auto buildVertices = [&](const SymbolBucket::Buffer& buffer_, RawVertexVec& dest) -> auto& { - const std::vector& src = buffer_.vertices.vector(); - const auto vertSize = sizeof(SymbolLayoutVertex::a1); - if (dest.size() != vertSize * src.size()) { - dest.resize(vertSize * src.size()); - for (std::size_t i = 0; i < src.size(); ++i) { - std::memcpy(&dest[vertSize * i], &src[i].a1, vertSize); - } - } - return dest; - }; gfx::VertexAttributeArray attrs; - if (const auto& attr = attrs.getOrAdd(dataAttibName)) { - const auto count = buffer.vertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, util::cast(buffer.vertices.at(i).a2)); - } + const auto vertexCount = buffer.vertices().elements(); + if (const auto& attr = attrs.add(posOffsetAttribName)) { + attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a1), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::Short4); } - if (const auto& attr = attrs.getOrAdd(pixOffsetAttribName)) { - const auto count = buffer.vertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, util::cast(buffer.vertices.at(i).a3)); - } + if (const auto& attr = attrs.add(dataAttibName)) { + attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a2), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::UShort4); } - if (const auto& attr = attrs.getOrAdd(projPosAttribName)) { - const auto count = buffer.dynamicVertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, util::cast(buffer.dynamicVertices.at(i).a1)); - } + if (const auto& attr = attrs.add(pixOffsetAttribName)) { + attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a3), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::Short4); } - if (const auto& attr = attrs.getOrAdd(fadeOpacityAttribName)) { - const auto count = buffer.opacityVertices.elements(); - attr->reserve(count); - for (auto i = 0ULL; i < count; ++i) { - attr->set(i, buffer.opacityVertices.at(i).a1[0]); - } + if (const auto& attr = attrs.add(projPosAttribName)) { + using Vertex = gfx::Vertex; + attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3); + } + if (const auto& attr = attrs.add(fadeOpacityAttribName)) { + using Vertex = gfx::Vertex; + attr->setSharedRawData(buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float); } const auto uniformProps = isText ? attrs.readDataDrivenPaintProperties& segment, - const gfx::IndexVector& indices, - const RawVertexVec& vertices, - const std::size_t vertexCount, const bool isHalo, const std::string_view suffix) { if (!shaderGroup) { @@ -1031,9 +996,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, builder->clearTweakers(); builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker); - + builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); builder->setDrawableName(layerPrefix + std::string(suffix)); - builder->setVertexAttributes(std::move(attrs)); + builder->setVertexAttributes(attrs); const auto shader = std::static_pointer_cast( shaderGroup->getOrCreateShader(context, uniformProps, posOffsetAttribName)); @@ -1047,9 +1012,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // !partiallyEvaluatedTextSize.isZoomConstant; const auto filterType = linear ? // gfx::TextureFilterType::Linear : gfx::TextureFilterType::Nearest; - auto raw = vertices; - builder->setRawVertices(std::move(raw), vertexCount, gfx::AttributeDataType::Short4); - builder->setSegments(gfx::Triangles(), indices.vector(), &segment, 1); + auto indexes = buffer.triangles.vector(); + builder->setSegments(gfx::Triangles(), std::move(indexes), &renderable.segment.get(), 1); builder->flush(); @@ -1078,82 +1042,34 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, }; if (isText) { - const auto& vertices = buildVertices(buffer, tileInfo.textVertices); - const auto vertexCount = buffer.vertices.elements(); - const auto& indices = buffer.triangles; if (bucket.iconsInText) { if (textHalo) { - draw(symbolTextAndIconGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ true, - "halo"); + draw(symbolTextAndIconGroup, /* isHalo = */ true, "halo"); } if (textFill) { - draw(symbolTextAndIconGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ false, - "fill"); + draw(symbolTextAndIconGroup, /* isHalo = */ false, "fill"); } } else { if (textHalo) { - draw(symbolSDFTextGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ true, - "halo"); + draw(symbolSDFTextGroup, /* isHalo = */ true, "halo"); } if (textFill) { - draw(symbolSDFTextGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ false, - "fill"); + draw(symbolSDFTextGroup, /* isHalo = */ false, "fill"); } } } else { // icons - const auto& vertices = buildVertices(buffer, tileInfo.iconVertices); - const auto vertexCount = buffer.vertices.elements(); - const auto& indices = buffer.triangles; if (sdfIcons) { if (iconHalo) { - draw(symbolSDFIconGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ true, - "halo"); + draw(symbolSDFIconGroup, /* isHalo = */ true, "halo"); } if (iconFill) { - draw(symbolSDFIconGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ false, - "fill"); + draw(symbolSDFIconGroup, /* isHalo = */ false, "fill"); } } else { - draw(symbolIconGroup, - renderable.segment, - indices, - vertices, - vertexCount, - /* isHalo = */ false, - "icon"); + draw(symbolIconGroup, /* isHalo = */ false, "icon"); } } } diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 7bacca46c..9a7235de7 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -303,7 +303,9 @@ public: } void upload(gfx::UploadPass& uploadPass) override { +#if MLN_LEGACY_RENDERER vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector)); +#endif // MLN_LEGACY_RENDERER } std::tuple> attributeBinding( @@ -424,7 +426,9 @@ public: } void upload(gfx::UploadPass& uploadPass) override { +#if MLN_LEGACY_RENDERER vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector)); +#endif // MLN_LEGACY_RENDERER } std::tuple> attributeBinding( @@ -533,9 +537,11 @@ public: if (!patternToVertexVector.empty()) { assert(!zoomInVertexVector.empty()); assert(!zoomOutVertexVector.empty()); +#if MLN_LEGACY_RENDERER patternToVertexBuffer = uploadPass.createVertexBuffer(std::move(patternToVertexVector)); zoomInVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomInVertexVector)); zoomOutVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomOutVertexVector)); +#endif // MLN_LEGACY_RENDERER } } diff --git a/src/mbgl/renderer/render_static_data.cpp b/src/mbgl/renderer/render_static_data.cpp index 6e0eec20d..13e6239d4 100644 --- a/src/mbgl/renderer/render_static_data.cpp +++ b/src/mbgl/renderer/render_static_data.cpp @@ -86,11 +86,14 @@ SegmentVector RenderStaticData::heatmapTextureSegments void RenderStaticData::upload(gfx::UploadPass& uploadPass) { if (!uploaded) { + // these are still used by stencil buffer rendering tileVertexBuffer = uploadPass.createVertexBuffer(tileVertices()); + quadTriangleIndexBuffer = uploadPass.createIndexBuffer(quadTriangleIndices()); +#if MLN_LEGACY_RENDERER rasterVertexBuffer = uploadPass.createVertexBuffer(rasterVertices()); heatmapTextureVertexBuffer = uploadPass.createVertexBuffer(heatmapTextureVertices()); - quadTriangleIndexBuffer = uploadPass.createIndexBuffer(quadTriangleIndices()); tileBorderIndexBuffer = uploadPass.createIndexBuffer(tileLineStripIndices()); +#endif // MLN_LEGACY_RENDERER uploaded = true; } } diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 39e9d8b62..4e576e193 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -777,7 +777,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const bool pitchWithMap = layout.get() == style::AlignmentType::Map; const bool keepUpright = layout.get(); if (bucket.hasSdfIconData()) { - reprojectLineLabels(bucket.sdfIcon.dynamicVertices, + reprojectLineLabels(bucket.sdfIcon.dynamicVertices(), bucket.sdfIcon.placedSymbols, tile.matrix, pitchWithMap, @@ -789,7 +789,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, result = true; } if (bucket.hasIconData()) { - reprojectLineLabels(bucket.icon.dynamicVertices, + reprojectLineLabels(bucket.icon.dynamicVertices(), bucket.icon.placedSymbols, tile.matrix, pitchWithMap, @@ -805,7 +805,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, if (bucket.hasTextData() && layout.get() == AlignmentType::Map) { const bool pitchWithMap = layout.get() == style::AlignmentType::Map; const bool keepUpright = layout.get(); - reprojectLineLabels(bucket.text.dynamicVertices, + reprojectLineLabels(bucket.text.dynamicVertices(), bucket.text.placedSymbols, tile.matrix, pitchWithMap, @@ -817,7 +817,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, result = true; } } else if (hasVariableAnchors) { - bucket.text.dynamicVertices.clear(); + bucket.text.sharedDynamicVertices->clear(); bucket.hasVariablePlacement = false; const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(static_cast(state.getZoom())); @@ -846,7 +846,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, // These symbols are from a justification that is not being // used, or a label that wasn't placed so we don't need to do // the extra math to figure out what incremental shift to apply. - hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices); + hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices()); } else { const Point tileAnchor = symbol.anchorPoint; const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix); @@ -889,25 +889,25 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, } for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) { - addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices); + addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices()); } } } if (updateTextFitIcon && bucket.hasVariablePlacement) { auto updateIcon = [&](SymbolBucket::Buffer& iconBuffer) { - iconBuffer.dynamicVertices.clear(); + iconBuffer.sharedDynamicVertices->clear(); for (std::size_t i = 0; i < iconBuffer.placedSymbols.size(); ++i) { const PlacedSymbol& placedIcon = iconBuffer.placedSymbols[i]; if (placedIcon.hidden || (!placedIcon.placedOrientation && bucket.allowVerticalPlacement)) { - hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices); + hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices()); } else { const auto& pair = placedTextShifts.find(i); if (pair == placedTextShifts.end()) { - hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices); + hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices()); } else { for (std::size_t j = 0; j < placedIcon.glyphOffsets.size(); ++j) { - addDynamicAttributes(pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices); + addDynamicAttributes(pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices()); } } } @@ -920,13 +920,13 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, result = true; } else if (bucket.allowVerticalPlacement && bucket.hasTextData()) { const auto updateDynamicVertices = [](SymbolBucket::Buffer& buffer) { - buffer.dynamicVertices.clear(); + buffer.sharedDynamicVertices->clear(); for (const PlacedSymbol& symbol : buffer.placedSymbols) { if (symbol.hidden || !symbol.placedOrientation) { - hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices); + hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices()); } else { for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) { - addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices); + addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices()); } } } @@ -948,9 +948,9 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState& state, std::set& seenCrossTileIDs) const { - if (bucket.hasTextData()) bucket.text.opacityVertices.clear(); - if (bucket.hasIconData()) bucket.icon.opacityVertices.clear(); - if (bucket.hasSdfIconData()) bucket.sdfIcon.opacityVertices.clear(); + if (bucket.hasTextData()) bucket.text.sharedOpacityVertices->clear(); + if (bucket.hasIconData()) bucket.icon.sharedOpacityVertices->clear(); + if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityVertices->clear(); if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices.clear(); if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices.clear(); if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices.clear(); @@ -1015,7 +1015,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden(); } - bucket.text.opacityVertices.extend(textOpacityVerticesSize, opacityVertex); + bucket.text.opacityVertices().extend(textOpacityVerticesSize, opacityVertex); style::TextWritingModeType previousOrientation = style::TextWritingModeType::Horizontal; if (bucket.allowVerticalPlacement) { @@ -1047,7 +1047,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, iconBuffer.placedSymbols[*symbolInstance.placedVerticalIconIndex].hidden = opacityState.isHidden(); } - iconBuffer.opacityVertices.extend(iconOpacityVerticesSize, opacityVertex); + iconBuffer.opacityVertices().extend(iconOpacityVerticesSize, opacityVertex); } auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point& shift) {