From fa9712cd8f9b1e9f427adb9fdf1b727e81bd7bf2 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 28 Nov 2023 18:57:51 -0800 Subject: [PATCH] Shared attributes (#1898) --- include/mbgl/gfx/drawable.hpp | 12 +-- include/mbgl/gfx/drawable_builder.hpp | 13 +-- include/mbgl/gfx/vertex_attribute.hpp | 14 +-- include/mbgl/gl/drawable_gl.hpp | 6 -- include/mbgl/gl/vertex_attribute_gl.hpp | 11 +-- include/mbgl/mtl/context.hpp | 9 +- include/mbgl/mtl/drawable.hpp | 6 -- include/mbgl/mtl/vertex_attribute.hpp | 23 +---- include/mbgl/shaders/gl/shader_program_gl.hpp | 2 - include/mbgl/shaders/mtl/shader_program.hpp | 1 - include/mbgl/shaders/shader_program_base.hpp | 6 -- src/mbgl/gfx/context.hpp | 31 +++--- src/mbgl/gfx/drawable_builder.cpp | 23 ++--- src/mbgl/gfx/drawable_builder_impl.cpp | 8 +- src/mbgl/gfx/drawable_builder_impl.hpp | 4 +- src/mbgl/gfx/index_vector.hpp | 3 + src/mbgl/gfx/vertex_attribute.cpp | 10 -- src/mbgl/gl/context.cpp | 5 + src/mbgl/gl/context.hpp | 2 + src/mbgl/gl/drawable_gl.cpp | 26 ++--- src/mbgl/gl/drawable_gl_impl.hpp | 2 - src/mbgl/mtl/context.cpp | 4 + src/mbgl/mtl/drawable.cpp | 31 +++--- src/mbgl/mtl/drawable_impl.hpp | 1 - .../layers/render_background_layer.cpp | 2 +- .../renderer/layers/render_circle_layer.cpp | 20 ++-- .../layers/render_fill_extrusion_layer.cpp | 26 +++-- .../renderer/layers/render_fill_layer.cpp | 23 +++-- .../renderer/layers/render_heatmap_layer.cpp | 59 ++++++++---- .../layers/render_hillshade_layer.cpp | 94 ++++++++++--------- .../renderer/layers/render_line_layer.cpp | 50 +++++----- .../renderer/layers/render_raster_layer.cpp | 61 ++++++------ .../renderer/layers/render_symbol_layer.cpp | 35 +++---- .../renderer/sources/render_tile_source.cpp | 4 +- .../style/layers/custom_drawable_layer.cpp | 9 +- 35 files changed, 290 insertions(+), 346 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 52090e96c..c84f4af3c 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -40,6 +40,7 @@ using DrawableTweakerPtr = std::shared_ptr; using IndexVectorBasePtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; using Texture2DPtr = std::shared_ptr; +using VertexAttributeArrayPtr = std::shared_ptr; class Drawable { public: @@ -188,16 +189,10 @@ public: virtual void setColorMode(const gfx::ColorMode&); /// Get the vertex attributes that override default values in the shader program - virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; - - /// Get the mutable vertex attribute array - virtual gfx::VertexAttributeArray& mutableVertexAttributes() = 0; + const gfx::VertexAttributeArrayPtr& getVertexAttributes() const noexcept { return vertexAttributes; } /// Set vertex attribute array - virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0; - - /// Set vertex attribute array - virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0; + void setVertexAttributes(gfx::VertexAttributeArrayPtr value) noexcept { vertexAttributes = std::move(value); } /// Provide raw data for vertices. Incompatible with adding primitives virtual void setVertices(std::vector&&, std::size_t, AttributeDataType) = 0; @@ -259,6 +254,7 @@ protected: int32_t subLayerIndex = 0; DepthMaskType depthType; // = DepthMaskType::ReadOnly; UniqueDrawableData drawableData{}; + gfx::VertexAttributeArrayPtr vertexAttributes; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 5013842ea..6ce94f852 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -42,7 +42,7 @@ public: UniqueDrawable& getCurrentDrawable(bool createIfNone); /// Close the current drawable, using a new one for any further work - void flush(); + void flush(gfx::Context& context); /// Get all the completed drawables const std::vector& getDrawables() const { return drawables; } @@ -134,9 +134,6 @@ public: /// Set the shader to be used void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } - /// Get the vertex attributes that override default values in the shader program - const gfx::VertexAttributeArray& getVertexAttributes() const; - /// Set the name given to new drawables void setDrawableName(std::string value) { drawableName = std::move(value); } @@ -157,9 +154,12 @@ public: /// Clear the tweaker collection void clearTweakers() { tweakers.clear(); } + /// Get the vertex attributes that override default values in the shader program + VertexAttributeArrayPtr& getVertexAttributes() { return vertexAttrs; } + const VertexAttributeArrayPtr& getVertexAttributes() const { return vertexAttrs; } + /// A set of attribute values to be added for each vertex - void setVertexAttributes(const VertexAttributeArray& value); - void setVertexAttributes(VertexAttributeArray&&); + void setVertexAttributes(VertexAttributeArrayPtr attrs) { vertexAttrs = std::move(attrs); } /// Add some vertex elements, returns the index of the first one added std::size_t addVertices(const std::vector>& vertices, @@ -232,6 +232,7 @@ protected: std::vector drawables; gfx::Drawable::Textures textures; std::vector tweakers; + gfx::VertexAttributeArrayPtr vertexAttrs; class Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 97dc4d8ff..14e19b7d7 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -366,23 +366,11 @@ public: } VertexAttributeArray& operator=(VertexAttributeArray&&); - VertexAttributeArray& operator=(const VertexAttributeArray&); + VertexAttributeArray& operator=(const VertexAttributeArray&) = delete; /// Clone the collection - virtual UniqueVertexAttributeArray clone() const { - auto newAttrs = std::make_unique(); - newAttrs->copy(*this); - return newAttrs; - } /// Copy another collection into this one - virtual void copy(const VertexAttributeArray& other) { - for (const auto& kv : other.attrs) { - if (kv.second) { - attrs.insert(std::make_pair(kv.first, copy(*kv.second))); - } - } - } /// Specialized DataDrivenPaintProperty reader /// @param binders Property binders for the target shader diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index fb90877bc..f7184a88b 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -41,12 +41,6 @@ public: void setVertices(std::vector&&, std::size_t, gfx::AttributeDataType) override; - const gfx::VertexAttributeArray& getVertexAttributes() const override; - void setVertexAttributes(const gfx::VertexAttributeArray& value) override; - void setVertexAttributes(gfx::VertexAttributeArray&& value) override; - - gfx::VertexAttributeArray& mutableVertexAttributes() override; - const gfx::UniformBufferArray& getUniformBuffers() const override; gfx::UniformBufferArray& mutableUniformBuffers() override; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index b1814a186..d57d5dbbc 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -61,16 +61,7 @@ public: VertexAttributeArray::operator=(std::move(other)); return *this; } - VertexAttributeArrayGL& operator=(const VertexAttributeArrayGL& other) { - VertexAttributeArray::operator=(other); - return *this; - } - - std::unique_ptr clone() const override { - auto newAttrs = std::make_unique(); - newAttrs->copy(*this); - return newAttrs; - } + VertexAttributeArrayGL& operator=(const VertexAttributeArrayGL&) = delete; /// Indicates whether any values have changed bool isDirty() const override; diff --git a/include/mbgl/mtl/context.hpp b/include/mbgl/mtl/context.hpp index 17cfd563b..97e1e4f5a 100644 --- a/include/mbgl/mtl/context.hpp +++ b/include/mbgl/mtl/context.hpp @@ -22,6 +22,11 @@ namespace mbgl { class ProgramParameters; class RenderStaticData; +namespace gfx { +class VertexAttributeArray; +using VertexAttributeArrayPtr = std::shared_ptr; +} // namespace gfx + namespace shaders { struct ClipUBO; } // namespace shaders @@ -85,8 +90,6 @@ public: RenderTargetPtr createRenderTarget(const Size size, const gfx::TextureChannelDataType type) override; - // UniqueFramebuffer createFramebuffer(const gfx::Texture2D& color); - void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) override; void setDirtyState() override; @@ -104,6 +107,8 @@ public: std::unique_ptr createDrawScopeResource() override; + gfx::VertexAttributeArrayPtr createVertexAttributeArray() const override; + #if !defined(NDEBUG) void visualizeStencilBuffer() override; void visualizeDepthBuffer(float depthRangeSize) override; diff --git a/include/mbgl/mtl/drawable.hpp b/include/mbgl/mtl/drawable.hpp index 8c001cf93..c4bb72519 100644 --- a/include/mbgl/mtl/drawable.hpp +++ b/include/mbgl/mtl/drawable.hpp @@ -40,12 +40,6 @@ public: void setVertices(std::vector&&, std::size_t, gfx::AttributeDataType) override; - const gfx::VertexAttributeArray& getVertexAttributes() const override; - void setVertexAttributes(const gfx::VertexAttributeArray& value) override; - void setVertexAttributes(gfx::VertexAttributeArray&& value) override; - - gfx::VertexAttributeArray& mutableVertexAttributes() override; - const gfx::UniformBufferArray& getUniformBuffers() const override; gfx::UniformBufferArray& mutableUniformBuffers() override; diff --git a/include/mbgl/mtl/vertex_attribute.hpp b/include/mbgl/mtl/vertex_attribute.hpp index 6ec027e5c..699e5bf64 100644 --- a/include/mbgl/mtl/vertex_attribute.hpp +++ b/include/mbgl/mtl/vertex_attribute.hpp @@ -18,17 +18,13 @@ private: friend VertexAttributeArray; VertexAttribute(int index_, gfx::AttributeDataType dataType_, std::size_t count_) : gfx::VertexAttribute(index_, dataType_, count_) {} - VertexAttribute(const VertexAttribute& other) - : gfx::VertexAttribute(other) {} + VertexAttribute(const VertexAttribute& other) = delete; VertexAttribute(VertexAttribute&& other) : gfx::VertexAttribute(std::move(other)) {} public: ~VertexAttribute() override = default; - /// Get the Metal buffer, creating it if necessary - // const gfx::UniqueVertexBufferResource& getBuffer(UploadPass&, const gfx::BufferUsageType); - static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&, UploadPass&, const gfx::BufferUsageType); @@ -45,16 +41,7 @@ public: gfx::VertexAttributeArray::operator=(std::move(other)); return *this; } - VertexAttributeArray& operator=(const VertexAttributeArray& other) { - gfx::VertexAttributeArray::operator=(other); - return *this; - } - - gfx::UniqueVertexAttributeArray clone() const override { - auto newAttrs = std::make_unique(); - newAttrs->copy(*this); - return newAttrs; - } + VertexAttributeArray& operator=(const VertexAttributeArray& other) = delete; /// Indicates whether any values have changed bool isDirty() const override; @@ -63,12 +50,6 @@ private: gfx::UniqueVertexAttribute create(int index, gfx::AttributeDataType dataType, std::size_t count) const override { return gfx::UniqueVertexAttribute(new VertexAttribute(index, dataType, count)); } - - using gfx::VertexAttributeArray::copy; - - gfx::UniqueVertexAttribute copy(const gfx::VertexAttribute& attr) const override { - return gfx::UniqueVertexAttribute(new VertexAttribute(static_cast(attr))); - } }; } // namespace mtl diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index fd7221a1d..9b6dc6bd6 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -48,8 +48,6 @@ public: protected: gfx::UniformBlockArray& mutableUniformBlocks() override { return uniformBlocks; } - gfx::VertexAttributeArray& mutableVertexAttributes() override { return vertexAttributes; } - protected: UniqueProgram glProgram; diff --git a/include/mbgl/shaders/mtl/shader_program.hpp b/include/mbgl/shaders/mtl/shader_program.hpp index 7e4a0260e..6e38a4451 100644 --- a/include/mbgl/shaders/mtl/shader_program.hpp +++ b/include/mbgl/shaders/mtl/shader_program.hpp @@ -62,7 +62,6 @@ public: std::optional getSamplerLocation(const StringIdentity id) const override; const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } - gfx::VertexAttributeArray& mutableVertexAttributes() override { return vertexAttributes; } const gfx::UniformBlockArray& getUniformBlocks() const override { return uniformBlocks; } gfx::UniformBlockArray& mutableUniformBlocks() override { return uniformBlocks; } diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp index ad7084a89..acdb80127 100644 --- a/include/mbgl/shaders/shader_program_base.hpp +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -41,14 +41,8 @@ public: /// Get the available vertex attributes and their default values virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; - template - bool setAttribute(const std::string& name, std::size_t i, T value) { - return set(mutableVertexAttributes(), name, i, value); - } - protected: virtual gfx::UniformBlockArray& mutableUniformBlocks() = 0; - virtual gfx::VertexAttributeArray& mutableVertexAttributes() = 0; protected: util::SimpleIdentity shaderProgramID; diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 8029f4f26..154d35908 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -40,12 +40,14 @@ class Drawable; class DrawableBuilder; class ShaderProgramBase; class Texture2D; +class VertexAttributeArray; using DrawablePtr = std::shared_ptr; -using UniqueDrawableBuilder = std::unique_ptr; -using UniformBufferPtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; using Texture2DPtr = std::shared_ptr; +using UniformBufferPtr = std::shared_ptr; +using UniqueDrawableBuilder = std::unique_ptr; +using VertexAttributeArrayPtr = std::shared_ptr; #endif class Context { @@ -57,24 +59,20 @@ public: static constexpr const uint32_t minimumRequiredVertexBindingCount = 8; const uint32_t maximumVertexBindingCount; -public: Context(Context&&) = delete; Context(const Context&) = delete; Context& operator=(Context&& other) = delete; Context& operator=(const Context& other) = delete; virtual ~Context() = default; -public: /// Called at the end of a frame. virtual void performCleanup() = 0; /// Called when the app receives a memory warning and before it goes to the background. virtual void reduceMemoryUsage() = 0; -public: virtual std::unique_ptr createOffscreenTexture(Size, TextureChannelDataType) = 0; -public: /// Creates an empty texture with the specified dimensions. Texture createTexture(const Size size, TexturePixelType format = TexturePixelType::RGBA, @@ -82,32 +80,19 @@ public: return {size, createTextureResource(size, format, type)}; } -protected: - virtual std::unique_ptr createTextureResource(Size, TexturePixelType, TextureChannelDataType) = 0; - -public: template Renderbuffer createRenderbuffer(const Size size) { return {size, createRenderbufferResource(pixelType, size)}; } -protected: - virtual std::unique_ptr createRenderbufferResource(RenderbufferPixelType, Size) = 0; - -public: DrawScope createDrawScope() { return DrawScope{createDrawScopeResource()}; } -protected: - virtual std::unique_ptr createDrawScopeResource() = 0; - -public: virtual std::unique_ptr createCommandEncoder() = 0; gfx::RenderingStats& renderingStats() { return stats; } const gfx::RenderingStats& renderingStats() const { return stats; } #if !defined(NDEBUG) -public: virtual void visualizeStencilBuffer() = 0; virtual void visualizeDepthBuffer(float depthRangeSize) = 0; #endif @@ -118,7 +103,9 @@ public: virtual void setDirtyState() = 0; #if MLN_DRAWABLE_RENDERER -public: + /// Create a new vertex attribute array + virtual gfx::VertexAttributeArrayPtr createVertexAttributeArray() const = 0; + /// Create a new drawable builder virtual UniqueDrawableBuilder createDrawableBuilder(std::string name) = 0; @@ -166,6 +153,10 @@ public: #endif protected: + virtual std::unique_ptr createTextureResource(Size, TexturePixelType, TextureChannelDataType) = 0; + virtual std::unique_ptr createRenderbufferResource(RenderbufferPixelType, Size) = 0; + virtual std::unique_ptr createDrawScopeResource() = 0; + gfx::RenderingStats stats; }; diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 254e26f82..e34dafcaf 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -33,10 +33,6 @@ void DrawableBuilder::setCullFaceMode(const gfx::CullFaceMode& value) { impl->cullFaceMode = value; } -const gfx::VertexAttributeArray& DrawableBuilder::getVertexAttributes() const { - return impl->vertexAttrs; -} - UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) { if (!currentDrawable && createIfNone) { currentDrawable = createDrawable(); @@ -44,11 +40,11 @@ UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) { return currentDrawable; } -void DrawableBuilder::flush() { +void DrawableBuilder::flush(gfx::Context& context) { if (curVertexCount()) { if (Impl::Mode::Polylines == impl->getMode()) { // setup for polylines - impl->setupForPolylines(*this); + impl->setupForPolylines(context, *this); } const auto& draw = getCurrentDrawable(/*createIfNone=*/true); @@ -68,9 +64,10 @@ void DrawableBuilder::flush() { draw->setTextures(textures); draw->setTweakers(tweakers); - const auto& builderAttrs = getVertexAttributes(); - if (auto drawAttrs = builderAttrs.clone()) { - draw->setVertexAttributes(std::move(*drawAttrs)); + if (vertexAttrs) { + draw->setVertexAttributes(vertexAttrs); + } else { + draw->setVertexAttributes(context.createVertexAttributeArray()); } init(); @@ -151,14 +148,6 @@ void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { appendTriangle(x1, y1); } -void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) { - impl->vertexAttrs = attrs; -} - -void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) { - impl->vertexAttrs = std::move(attrs); -} - std::size_t DrawableBuilder::addVertices(const std::vector>& vertices, std::size_t vertexOffset, std::size_t vertexLength) { diff --git a/src/mbgl/gfx/drawable_builder_impl.cpp b/src/mbgl/gfx/drawable_builder_impl.cpp index 46e7ffa43..b1498a806 100644 --- a/src/mbgl/gfx/drawable_builder_impl.cpp +++ b/src/mbgl/gfx/drawable_builder_impl.cpp @@ -59,7 +59,7 @@ void DrawableBuilder::Impl::addPolyline(gfx::DrawableBuilder& builder, generator.generate(coordinates, options); } -void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) { +void DrawableBuilder::Impl::setupForPolylines(gfx::Context& context, gfx::DrawableBuilder& builder) { // setup vertex attributes static const StringIdentity idVertexAttribName = stringIndexer().get("a_pos_normal"); static const StringIdentity idDataAttribName = stringIndexer().get("a_data"); @@ -68,11 +68,11 @@ void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) { builder.setRawVertices({}, polylineVertices.elements(), gfx::AttributeDataType::Short2); - gfx::VertexAttributeArray attrs; + auto attrs = context.createVertexAttributeArray(); using VertexVector = gfx::VertexVector; std::shared_ptr verts = std::make_shared(std::move(polylineVertices)); - if (const auto& attr = attrs.add(idVertexAttribName)) { + if (const auto& attr = attrs->add(idVertexAttribName)) { attr->setSharedRawData(verts, offsetof(LineLayoutVertex, a1), /*vertexOffset=*/0, @@ -80,7 +80,7 @@ void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) { gfx::AttributeDataType::Short2); } - if (const auto& attr = attrs.add(idDataAttribName)) { + if (const auto& attr = attrs->add(idDataAttribName)) { attr->setSharedRawData(verts, offsetof(LineLayoutVertex, a2), /*vertexOffset=*/0, diff --git a/src/mbgl/gfx/drawable_builder_impl.hpp b/src/mbgl/gfx/drawable_builder_impl.hpp index da12d46d6..2359960a3 100644 --- a/src/mbgl/gfx/drawable_builder_impl.hpp +++ b/src/mbgl/gfx/drawable_builder_impl.hpp @@ -47,13 +47,11 @@ public: gfx::ColorMode colorMode = gfx::ColorMode::disabled(); gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); - VertexAttributeArray vertexAttrs; - void addPolyline(gfx::DrawableBuilder& builder, const GeometryCoordinates& coordinates, const gfx::PolylineGeneratorOptions& options); - void setupForPolylines(gfx::DrawableBuilder& builder); + void setupForPolylines(gfx::Context&, gfx::DrawableBuilder&); bool checkAndSetMode(Mode); diff --git a/src/mbgl/gfx/index_vector.hpp b/src/mbgl/gfx/index_vector.hpp index f3854ef42..b42b63321 100644 --- a/src/mbgl/gfx/index_vector.hpp +++ b/src/mbgl/gfx/index_vector.hpp @@ -71,6 +71,9 @@ public: void clear() { dirty = true; v.clear(); +#if MLN_DRAWABLE_RENDERER + buffer.reset(); +#endif // MLN_DRAWABLE_RENDERER } /// Indicate that this shared index vector will no longer be updated. diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index 25e8c5fce..7d3e4c4ac 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -93,16 +93,6 @@ VertexAttributeArray& VertexAttributeArray::operator=(VertexAttributeArray&& oth return *this; } -VertexAttributeArray& VertexAttributeArray::operator=(const VertexAttributeArray& other) { - attrs.clear(); - for (const auto& kv : other.attrs) { - if (kv.second) { - add(kv.first, copy(*kv.second)); - } - } - return *this; -} - const std::unique_ptr& VertexAttributeArray::get(const StringIdentity id) const { const auto result = attrs.find(id); return (result != attrs.end()) ? result->second : nullref; diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 842a1eb58..1ece3d10c 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -532,6 +532,11 @@ Framebuffer Context::createFramebuffer(const gfx::Texture2D& color) { checkFramebuffer(); return {color.getSize(), std::move(fbo)}; } + +gfx::VertexAttributeArrayPtr Context::createVertexAttributeArray() const { + return std::make_shared(); +} + #endif void Context::clear(std::optional color, std::optional depth, std::optional stencil) { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index c1eb6ce44..810c9033c 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -117,6 +117,8 @@ public: Framebuffer createFramebuffer(const gfx::Texture2D& color); + gfx::VertexAttributeArrayPtr createVertexAttributeArray() const override; + void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) override; bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 97cd88297..7c368069a 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -88,21 +88,6 @@ void DrawableGL::setVertices(std::vector&& data, std::size_t count, gfx impl->vertexType = type_; } -const gfx::VertexAttributeArray& DrawableGL::getVertexAttributes() const { - return impl->vertexAttributes; -} - -gfx::VertexAttributeArray& DrawableGL::mutableVertexAttributes() { - return impl->vertexAttributes; -} - -void DrawableGL::setVertexAttributes(const gfx::VertexAttributeArray& value) { - impl->vertexAttributes = static_cast(value); -} -void DrawableGL::setVertexAttributes(gfx::VertexAttributeArray&& value) { - impl->vertexAttributes = std::move(static_cast(value)); -} - const gfx::UniformBufferArray& DrawableGL::getUniformBuffers() const { return impl->uniformBuffers; } @@ -157,10 +142,11 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { return; } - const bool build = impl->vertexAttributes.isDirty() || - std::any_of(impl->segments.begin(), impl->segments.end(), [](const auto& seg) { - return !static_cast(*seg).getVertexArray().isValid(); - }); + const bool build = vertexAttributes && + (vertexAttributes->isDirty() || + std::any_of(impl->segments.begin(), impl->segments.end(), [](const auto& seg) { + return !static_cast(*seg).getVertexArray().isValid(); + })); if (build) { auto& context = uploadPass.getContext(); @@ -169,7 +155,7 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { // Apply drawable values to shader defaults const auto& defaults = shader->getVertexAttributes(); - const auto& overrides = impl->vertexAttributes; + const auto& overrides = *vertexAttributes; const auto& indexAttribute = defaults.get(impl->idVertexAttrName); const auto vertexAttributeIndex = static_cast(indexAttribute ? indexAttribute->getIndex() : -1); diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index 5d4c4e21d..f92e82be2 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -39,8 +39,6 @@ public: std::size_t vertexCount = 0; gfx::AttributeDataType vertexType = static_cast(-1); - VertexAttributeArrayGL vertexAttributes; - gfx::IndexBuffer indexBuffer = {0, nullptr}; std::vector attributeBuffers; diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index 809890e49..4b5a210ad 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -444,6 +444,10 @@ std::unique_ptr Context::createDrawScopeResource() { return nullptr; } +gfx::VertexAttributeArrayPtr Context::createVertexAttributeArray() const { + return std::make_shared(); +} + #if !defined(NDEBUG) void Context::visualizeStencilBuffer() {} diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 1bb868dc2..00b0fa667 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -306,7 +306,10 @@ void Drawable::setVertices(std::vector&& data, std::size_t count, gfx:: impl->vertexType = type; if (count && type != gfx::AttributeDataType::Invalid && !data.empty()) { - if (auto& attrib = impl->vertexAttributes.getOrAdd(impl->idVertexAttrName, /*index=*/-1, type)) { + if (!vertexAttributes) { + vertexAttributes = std::make_shared(); + } + if (auto& attrib = vertexAttributes->getOrAdd(impl->idVertexAttrName, /*index=*/-1, type)) { attrib->setRawData(std::move(data)); attrib->setStride(VertexAttribute::getStrideOf(type)); } else { @@ -319,21 +322,6 @@ void Drawable::setVertices(std::vector&& data, std::size_t count, gfx:: } } -const gfx::VertexAttributeArray& Drawable::getVertexAttributes() const { - return impl->vertexAttributes; -} - -gfx::VertexAttributeArray& Drawable::mutableVertexAttributes() { - return impl->vertexAttributes; -} - -void Drawable::setVertexAttributes(const gfx::VertexAttributeArray& value) { - impl->vertexAttributes = static_cast(value); -} -void Drawable::setVertexAttributes(gfx::VertexAttributeArray&& value) { - impl->vertexAttributes = std::move(static_cast(value)); -} - const gfx::UniformBufferArray& Drawable::getUniformBuffers() const { return impl->uniformBuffers; } @@ -513,13 +501,17 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { impl->indexes->setDirty(false); } - const bool buildAttribs = impl->vertexAttributes.isDirty() || !impl->vertexDesc; + const bool buildAttribs = !vertexAttributes || vertexAttributes->isDirty() || !impl->vertexDesc; if (buildAttribs) { #if !defined(NDEBUG) const auto debugGroup = uploadPass.createDebugGroup(debugLabel(*this)); #endif + if (!vertexAttributes) { + vertexAttributes = std::make_shared(); + } + // Apply drawable values to shader defaults std::vector> vertexBuffers; auto attributeBindings_ = uploadPass.buildAttributeBindings(impl->vertexCount, @@ -527,13 +519,12 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { /*vertexAttributeIndex=*/-1, /*vertexData=*/{}, shader->getVertexAttributes(), - impl->vertexAttributes, + *vertexAttributes, usage, vertexBuffers); impl->attributeBuffers = std::move(vertexBuffers); - impl->vertexAttributes.visitAttributes( - [](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); }); + vertexAttributes->visitAttributes([](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); }); if (impl->attributeBindings != attributeBindings_) { impl->attributeBindings = std::move(attributeBindings_); diff --git a/src/mbgl/mtl/drawable_impl.hpp b/src/mbgl/mtl/drawable_impl.hpp index 42ba332b6..88768b6f0 100644 --- a/src/mbgl/mtl/drawable_impl.hpp +++ b/src/mbgl/mtl/drawable_impl.hpp @@ -44,7 +44,6 @@ public: gfx::IndexVectorBasePtr indexes; std::size_t vertexCount = 0; gfx::AttributeDataType vertexType = gfx::AttributeDataType::Invalid; - VertexAttributeArray vertexAttributes; std::vector attributeBuffers; diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index dd148cbb5..293ee2175 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -314,7 +314,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, auto verticesCopy = rawVertices; builder->setRawVertices(std::move(verticesCopy), vertexCount, gfx::AttributeDataType::Short2); builder->setSegments(gfx::Triangles(), indexes.vector(), segs.data(), segs.size()); - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 57787f3a8..955d4b9ab 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -380,14 +380,14 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); propertiesAsUniforms.clear(); - gfx::VertexAttributeArray circleVertexAttrs; - circleVertexAttrs.readDataDrivenPaintProperties( + auto circleVertexAttrs = context.createVertexAttributeArray(); + circleVertexAttrs->readDataDrivenPaintProperties( paintPropertyBinders, evaluated, propertiesAsUniforms); if (!circleShaderGroup) { @@ -402,7 +402,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } - if (const auto& attr = circleVertexAttrs.add(idVertexAttribName)) { + if (const auto& attr = circleVertexAttrs->add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(CircleLayoutVertex, a1), 0, @@ -423,7 +423,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, circleBuilder->setSegments( gfx::Triangles(), bucket.sharedTriangles, bucket.segments.data(), bucket.segments.size()); - circleBuilder->flush(); + circleBuilder->flush(context); for (auto& drawable : circleBuilder->clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index e43198bb7..02ef9f418 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -419,12 +419,13 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, continue; } - gfx::VertexAttributeArray vertexAttrs; propertiesAsUniforms.clear(); - vertexAttrs.readDataDrivenPaintProperties(binders, evaluated, propertiesAsUniforms); + + auto vertexAttrs = context.createVertexAttributeArray(); + vertexAttrs->readDataDrivenPaintProperties(binders, evaluated, propertiesAsUniforms); const auto shader = std::static_pointer_cast( shaderGroup->getOrCreateShader(context, propertiesAsUniforms)); @@ -487,14 +488,14 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } } - if (const auto& attr = vertexAttrs.getOrAdd(idPosAttribName)) { + if (const auto& attr = vertexAttrs->add(idPosAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a1), /*vertexOffset=*/0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(idNormAttribName)) { + if (const auto& attr = vertexAttrs->add(idNormAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a2), /*vertexOffset=*/0, @@ -502,16 +503,13 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short4); } - colorBuilder->setEnableStencil(doDepthPass); if (doDepthPass) { depthBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); + depthBuilder->setVertexAttributes(vertexAttrs); } - colorBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); - if (doDepthPass) { - auto copy = vertexAttrs.clone(); - depthBuilder->setVertexAttributes(std::move(*copy)); - } + colorBuilder->setEnableStencil(doDepthPass); + colorBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); colorBuilder->setVertexAttributes(std::move(vertexAttrs)); const auto finish = [&](gfx::DrawableBuilder& builder) { @@ -523,7 +521,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, bucket.triangleSegments.data(), bucket.triangleSegments.size()); - builder.flush(); + builder.flush(context); for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 69420f0cd..7b07ffc13 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -620,10 +620,11 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, return atlasTweaker; }; - // `Fill*Program` all use `style::FillPaintProperties` - gfx::VertexAttributeArray vertexAttrs; propertiesAsUniforms.clear(); - vertexAttrs.readDataDrivenPaintProperties( + + // `Fill*Program` all use `style::FillPaintProperties` + auto vertexAttrs = context.createVertexAttributeArray(); + vertexAttrs->readDataDrivenPaintProperties( binders, evaluated, propertiesAsUniforms); if (layerTweaker) { @@ -631,7 +632,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } const auto vertexCount = bucket.vertices.elements(); - if (const auto& attr = vertexAttrs.add(idPosAttribName)) { + if (const auto& attr = vertexAttrs->add(idPosAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillLayoutVertex, a1), /*vertexOffset=*/0, @@ -715,15 +716,16 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, builder->setVertexAttrNameId(idVertexAttribName); builder->setShader(outlineTriangulatedShader); builder->setRawVertices({}, bucket.lineVertices.elements(), gfx::AttributeDataType::Short2); - gfx::VertexAttributeArray attrs; - if (const auto& attr = attrs.add(idVertexAttribName)) { + + auto attrs = context.createVertexAttributeArray(); + if (const auto& attr = attrs->add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedLineVertices, offsetof(LineLayoutVertex, a1), /*vertexOffset=*/0, sizeof(LineLayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = attrs.add(idDataAttribName)) { + if (const auto& attr = attrs->add(idDataAttribName)) { attr->setSharedRawData(bucket.sharedLineVertices, offsetof(LineLayoutVertex, a2), /*vertexOffset=*/0, @@ -731,6 +733,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::UByte4); } builder->setVertexAttributes(std::move(attrs)); + builder->setSegments(gfx::Triangles(), bucket.sharedLineIndexes, bucket.lineSegments.data(), @@ -739,7 +742,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, auto tweaker = std::make_shared(color, opacity); // finish - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); drawable->addTweaker(tweaker); @@ -785,7 +788,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, const auto& interpolateUBO, FillVariant type) { builder.setVertexAttrNameId(idPosAttribName); - builder.flush(); + builder.flush(context); for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); @@ -919,7 +922,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, const StringIdentity tileUBONameId, const auto& tileUBO, FillVariant type) { - builder.flush(); + builder.flush(context); for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 928ccacb3..b62c5dd7a 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -72,7 +72,6 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters if (auto tileLayerGroup = renderTarget->getLayerGroup(0)) { auto newTweaker = std::make_shared(getID(), evaluatedProperties); - // propertiesAsUniforms isn't recalculated every update, so carry it over if (layerTweaker) { newTweaker->setPropertiesAsUniforms(layerTweaker->getPropertiesAsUniforms()); } @@ -352,7 +351,12 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - mbgl::unordered_set propertiesAsUniforms; + std::optional> propertiesAsUniforms; +#if !defined(NDEBUG) + std::optional> previousPropertiesAsUniforms; +#endif + + gfx::ShaderPtr heatmapShader; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -388,15 +392,6 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return interpolateBuffer; }; - gfx::VertexAttributeArray heatmapVertexAttrs; - propertiesAsUniforms.clear(); - heatmapVertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated, propertiesAsUniforms); - - if (layerTweaker) { - layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); - } - const auto updatedCount = tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { if (drawable.getLayerTweaker() != layerTweaker) { // This drawable was produced on a previous style/bucket, and should not be updated. @@ -417,12 +412,36 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, continue; } - const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms); + if (!propertiesAsUniforms) { + propertiesAsUniforms.emplace(); + } +#if !defined(NDEBUG) + else { + propertiesAsUniforms->clear(); + } +#endif + + auto heatmapVertexAttrs = context.createVertexAttributeArray(); + heatmapVertexAttrs->readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, *propertiesAsUniforms); + +#if !defined(NDEBUG) + // We assume the properties are the same across tiles. + if (previousPropertiesAsUniforms) { + assert(*propertiesAsUniforms == previousPropertiesAsUniforms); + } else { + previousPropertiesAsUniforms = propertiesAsUniforms; + } +#endif + if (!heatmapShader) { - continue; + heatmapShader = heatmapShaderGroup->getOrCreateShader(context, *propertiesAsUniforms); + if (!heatmapShader) { + continue; + } } - if (const auto& attr = heatmapVertexAttrs.add(idVertexAttribName)) { + if (const auto& attr = heatmapVertexAttrs->add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(HeatmapLayoutVertex, a1), /*vertexOffset=*/0, @@ -441,7 +460,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, heatmapBuilder->setSegments( gfx::Triangles(), bucket.sharedTriangles, bucket.segments.data(), bucket.segments.size()); - heatmapBuilder->flush(); + heatmapBuilder->flush(context); for (auto& drawable : heatmapBuilder->clearDrawables()) { drawable->setTileID(tileID); @@ -458,6 +477,10 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } } + if (layerTweaker && propertiesAsUniforms) { + layerTweaker->setPropertiesAsUniforms(*propertiesAsUniforms); + } + // Set up texture layer group if (!layerGroup) { if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { @@ -494,8 +517,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } const auto textureVertexCount = sharedTextureVertices->elements(); - gfx::VertexAttributeArray textureVertexAttrs; - if (const auto& attr = textureVertexAttrs.add(idVertexAttribName)) { + auto textureVertexAttrs = context.createVertexAttributeArray(); + if (const auto& attr = textureVertexAttrs->add(idVertexAttribName)) { attr->setSharedRawData(sharedTextureVertices, offsetof(HeatmapLayoutVertex, a1), /*vertexOffset=*/0, @@ -530,7 +553,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, heatmapTextureBuilder->setTexture(std::move(texture), colorRampLocation.value()); } - heatmapTextureBuilder->flush(); + heatmapTextureBuilder->flush(context); for (auto& drawable : heatmapTextureBuilder->clearDrawables()) { drawable->setLayerTweaker(textureTweaker); diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 700cc4c85..b28539516 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -365,6 +365,29 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, std::unique_ptr hillshadeBuilder; std::unique_ptr hillshadePrepareBuilder; + gfx::VertexAttributeArrayPtr hillshadePrepareVertexAttrs; + const auto getPrepareVertexAttributes = [&] { + if (!hillshadePrepareVertexAttrs) { + hillshadePrepareVertexAttrs = context.createVertexAttributeArray(); + + if (const auto& attr = hillshadePrepareVertexAttrs->add(idPosAttribName)) { + attr->setSharedRawData(staticDataSharedVertices, + offsetof(HillshadeLayoutVertex, a1), + 0, + sizeof(HillshadeLayoutVertex), + gfx::AttributeDataType::Short2); + } + if (const auto& attr = hillshadePrepareVertexAttrs->add(idTexturePosAttribName)) { + attr->setSharedRawData(staticDataSharedVertices, + offsetof(HillshadeLayoutVertex, a2), + 0, + sizeof(HillshadeLayoutVertex), + gfx::AttributeDataType::Short2); + } + } + return hillshadePrepareVertexAttrs; + }; + for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -406,31 +429,13 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, } singleTileLayerGroup->addLayerTweaker(prepareLayerTweaker); - gfx::VertexAttributeArray hillshadePrepareVertexAttrs; - - if (const auto& attr = hillshadePrepareVertexAttrs.add(idPosAttribName)) { - attr->setSharedRawData(staticDataSharedVertices, - offsetof(HillshadeLayoutVertex, a1), - 0, - sizeof(HillshadeLayoutVertex), - gfx::AttributeDataType::Short2); - } - if (const auto& attr = hillshadePrepareVertexAttrs.getOrAdd(idTexturePosAttribName)) { - attr->setSharedRawData(staticDataSharedVertices, - offsetof(HillshadeLayoutVertex, a2), - 0, - sizeof(HillshadeLayoutVertex), - gfx::AttributeDataType::Short2); - } - hillshadePrepareBuilder = context.createDrawableBuilder("hillshadePrepare"); hillshadePrepareBuilder->setShader(hillshadePrepareShader); hillshadePrepareBuilder->setDepthType(gfx::DepthMaskType::ReadOnly); hillshadePrepareBuilder->setColorMode(gfx::ColorMode::unblended()); hillshadePrepareBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - hillshadePrepareBuilder->setRenderPass(renderPass); - hillshadePrepareBuilder->setVertexAttributes(std::move(hillshadePrepareVertexAttrs)); + hillshadePrepareBuilder->setVertexAttributes(getPrepareVertexAttributes()); hillshadePrepareBuilder->setRawVertices( {}, staticDataSharedVertices->elements(), gfx::AttributeDataType::Short2); hillshadePrepareBuilder->setSegments( @@ -445,7 +450,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadePrepareBuilder->setTexture(texture, imageLocation.value()); } - hillshadePrepareBuilder->flush(); + hillshadePrepareBuilder->flush(context); for (auto& drawable : hillshadePrepareBuilder->clearDrawables()) { drawable->setTileID(tileID); @@ -468,33 +473,39 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, segments = &bucket.segments; } - gfx::VertexAttributeArray hillshadeVertexAttrs; - - if (const auto& attr = hillshadeVertexAttrs.add(idPosAttribName)) { - attr->setSharedRawData(vertices, - offsetof(HillshadeLayoutVertex, a1), - 0, - sizeof(HillshadeLayoutVertex), - gfx::AttributeDataType::Short2); - } - if (const auto& attr = hillshadeVertexAttrs.getOrAdd(idTexturePosAttribName)) { - attr->setSharedRawData(vertices, - offsetof(HillshadeLayoutVertex, a2), - 0, - sizeof(HillshadeLayoutVertex), - gfx::AttributeDataType::Short2); - } - hillshadeBuilder = context.createDrawableBuilder("hillshade"); - auto updateExisting = [&](gfx::Drawable& drawable) { + gfx::VertexAttributeArrayPtr hillshadeVertexAttrs; + auto buildVertexAttributes = [&] { + if (!hillshadeVertexAttrs) { + hillshadeVertexAttrs = context.createVertexAttributeArray(); + + if (const auto& attr = hillshadeVertexAttrs->add(idPosAttribName)) { + attr->setSharedRawData(vertices, + offsetof(HillshadeLayoutVertex, a1), + 0, + sizeof(HillshadeLayoutVertex), + gfx::AttributeDataType::Short2); + } + if (const auto& attr = hillshadeVertexAttrs->getOrAdd(idTexturePosAttribName)) { + attr->setSharedRawData(vertices, + offsetof(HillshadeLayoutVertex, a2), + 0, + sizeof(HillshadeLayoutVertex), + gfx::AttributeDataType::Short2); + } + } + return hillshadeVertexAttrs; + }; + + const auto updateExisting = [&](gfx::Drawable& drawable) { // Only current drawables are updated, ones produced for // a previous style retain the attribute values for that style. if (drawable.getLayerTweaker() != layerTweaker) { return false; } - drawable.setVertexAttributes(std::move(hillshadeVertexAttrs)); + drawable.setVertexAttributes(buildVertexAttributes()); drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); // Rebuild segments, since they're not shared. @@ -526,9 +537,8 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadeBuilder->setDepthType(gfx::DepthMaskType::ReadOnly); hillshadeBuilder->setColorMode(gfx::ColorMode::alphaBlended()); hillshadeBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - hillshadeBuilder->setRenderPass(renderPass); - hillshadeBuilder->setVertexAttributes(std::move(hillshadeVertexAttrs)); + hillshadeBuilder->setVertexAttributes(buildVertexAttributes()); hillshadeBuilder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); hillshadeBuilder->setSegments(gfx::Triangles(), indices->vector(), segments->data(), segments->size()); @@ -536,7 +546,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadeBuilder->setTexture(bucket.renderTarget->getTexture(), *hillshadeImageLocation); } - hillshadeBuilder->flush(); + hillshadeBuilder->flush(context); for (auto& drawable : hillshadeBuilder->clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index f5fee4499..a3f939bff 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -434,11 +434,11 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, }; auto addAttributes = - [&](gfx::DrawableBuilder& builder, const LineBucket& bucket, gfx::VertexAttributeArray&& vertexAttrs) { + [&](gfx::DrawableBuilder& builder, const LineBucket& bucket, gfx::VertexAttributeArrayPtr&& vertexAttrs) { const auto vertexCount = bucket.vertices.elements(); builder.setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); - if (const auto& attr = vertexAttrs.add(idVertexAttribName)) { + if (const auto& attr = vertexAttrs->add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a1), /*vertexOffset=*/0, @@ -446,7 +446,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.add(idDataAttribName)) { + if (const auto& attr = vertexAttrs->add(idDataAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a2), /*vertexOffset=*/0, @@ -584,14 +584,14 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // dash array line (SDF) propertiesAsUniforms.clear(); - gfx::VertexAttributeArray vertexAttrs; - vertexAttrs.readDataDrivenPaintProperties( + auto vertexAttrs = context.createVertexAttributeArray(); + vertexAttrs->readDataDrivenPaintProperties( paintPropertyBinders, evaluated, propertiesAsUniforms); auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms); @@ -610,7 +610,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, setSegments(builder, bucket); // finish - builder->flush(); + builder->flush(context); const LinePatternCap cap = bucket.layout.get() == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square; for (auto& drawable : builder->clearDrawables()) { @@ -633,10 +633,14 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); propertiesAsUniforms.clear(); - gfx::VertexAttributeArray vertexAttrs; - vertexAttrs - .readDataDrivenPaintProperties( - paintPropertyBinders, evaluated, propertiesAsUniforms); + auto vertexAttrs = context.createVertexAttributeArray(); + vertexAttrs->readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { @@ -670,7 +674,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, setSegments(builder, bucket); - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Pattern)); drawable->setTileID(tileID); @@ -691,8 +695,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // gradient line propertiesAsUniforms.clear(); - gfx::VertexAttributeArray vertexAttrs; - vertexAttrs.readDataDrivenPaintProperties( + auto vertexAttrs = context.createVertexAttributeArray(); + vertexAttrs->readDataDrivenPaintProperties( paintPropertyBinders, evaluated, propertiesAsUniforms); auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms); @@ -726,7 +730,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, setSegments(builder, bucket); // finish - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Gradient)); drawable->setTileID(tileID); @@ -746,9 +750,9 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // simple line propertiesAsUniforms.clear(); - gfx::VertexAttributeArray vertexAttrs; + auto vertexAttrs = context.createVertexAttributeArray(); vertexAttrs - .readDataDrivenPaintProperties( + ->readDataDrivenPaintProperties( paintPropertyBinders, evaluated, propertiesAsUniforms); auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); @@ -767,7 +771,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, setSegments(builder, bucket); // finish - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Simple)); drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index c47f8f945..cd4053bf4 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -341,11 +341,19 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, } }; + gfx::VertexAttributeArrayPtr staticAttrs; + // Build vertex attributes and apply them to a drawable or a builder. // Populates a drawable xor a drawable builder for creates and updates, respectively. // Returns false if the drawable must be re-created. const auto buildVertexData = - [this](const gfx::UniqueDrawableBuilder& builder, gfx::Drawable* drawable, const RasterBucket& bucket) { + [&](const gfx::UniqueDrawableBuilder& builder, gfx::Drawable* drawable, const RasterBucket& bucket) { + // The bucket may later add, remove, or change masking. In that case, the tile's + // shared data and segments are not updated, and it needs to be re-created. + if (drawable && (bucket.sharedVertices->getDirty() || bucket.sharedTriangles->getDirty())) { + return false; + } + // The bucket only fills in geometry for masked tiles, // otherwise the standard tile extent geometry should be used. const bool shared = (!bucket.sharedVertices->empty() && !bucket.sharedTriangles->empty() && @@ -354,34 +362,33 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, const auto& indices = shared ? bucket.sharedTriangles : staticDataIndices; const auto* segments = shared ? &bucket.segments : staticDataSegments.get(); - // The bucket may later add, remove, or change masking. In that case, the tile's - // shared data and segments are not updated, and it needs to be re-created. - if (drawable && (bucket.sharedVertices->getDirty() || bucket.sharedTriangles->getDirty())) { - return false; - } + gfx::VertexAttributeArrayPtr bucketAttrs; + auto& vertexAttrs = shared ? bucketAttrs : staticAttrs; + if (!vertexAttrs) { + vertexAttrs = context.createVertexAttributeArray(); - gfx::VertexAttributeArray vertexAttrs; - if (auto& attr = vertexAttrs.add(idPosAttribName)) { - attr->setSharedRawData(vertices, - offsetof(RasterLayoutVertex, a1), - /*vertexOffset=*/0, - sizeof(RasterLayoutVertex), - gfx::AttributeDataType::Short2); - } + if (auto& attr = vertexAttrs->add(idPosAttribName)) { + attr->setSharedRawData(vertices, + offsetof(RasterLayoutVertex, a1), + /*vertexOffset=*/0, + sizeof(RasterLayoutVertex), + gfx::AttributeDataType::Short2); + } - if (auto& attr = vertexAttrs.add(idTexturePosAttribName)) { - attr->setSharedRawData(vertices, - offsetof(RasterLayoutVertex, a2), - /*vertexOffset=*/0, - sizeof(RasterLayoutVertex), - gfx::AttributeDataType::Short2); + if (auto& attr = vertexAttrs->add(idTexturePosAttribName)) { + attr->setSharedRawData(vertices, + offsetof(RasterLayoutVertex, a2), + /*vertexOffset=*/0, + sizeof(RasterLayoutVertex), + gfx::AttributeDataType::Short2); + } } assert(!!drawable ^ !!builder); if (drawable) { - drawable->setVertexAttributes(std::move(vertexAttrs)); + drawable->setVertexAttributes(vertexAttrs); } else if (builder) { - builder->setVertexAttributes(std::move(vertexAttrs)); + builder->setVertexAttributes(vertexAttrs); builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); builder->setSegments(gfx::Triangles(), indices, segments->data(), segments->size()); } @@ -412,7 +419,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, setTextures(builder, bucket); // finish - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setData(std::make_unique(matrix_)); @@ -481,11 +488,11 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, } return true; }; - if (updateTile(renderPass, tileID, std::move(updateExisting))) { - // If we modified drawables without removing them, we're done with this tile. + // If we update existing drawables, don't build new ones. + // But if the geometry has changed, we need to drop and re-build them anyway. + if (updateTile(renderPass, tileID, std::move(updateExisting)) && !geometryChanged) { continue; } else if (geometryChanged) { - // If the geometry has changed, the drawable needs to be re-built removeTile(renderPass, tileID); } } @@ -502,7 +509,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, buildVertexData(builder, /*drawable=*/nullptr, bucket); // finish - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); drawable->setLayerTweaker(layerTweaker); diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 6344bbc01..1c9f6ab37 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -867,9 +867,9 @@ void updateTileDrawable(gfx::Drawable& drawable, // TODO: detect whether anything has actually changed // See `Placement::updateBucketDynamicVertices` - gfx::VertexAttributeArray attribs; - updateTileAttributes(buffer, isText, paintProps, evaluated, attribs, propertiesAsUniforms); - drawable.setVertexAttributes(std::move(attribs)); + if (auto& attribs = drawable.getVertexAttributes()) { + updateTileAttributes(buffer, isText, paintProps, evaluated, *attribs, propertiesAsUniforms); + } } const StringIdentity idCollisionPosAttribName = stringIndexer().get("a_pos"); @@ -878,25 +878,26 @@ const StringIdentity idCollisionExtrudeAttribName = stringIndexer().get("a_extru const StringIdentity idCollisionPlacedAttribName = stringIndexer().get("a_placed"); const StringIdentity idCollisionShiftAttribName = stringIndexer().get("a_shift"); -gfx::VertexAttributeArray getCollisionVertexAttributes(const SymbolBucket::CollisionBuffer& buffer) { - gfx::VertexAttributeArray vertexAttrs; +gfx::VertexAttributeArrayPtr getCollisionVertexAttributes(gfx::Context& context, + const SymbolBucket::CollisionBuffer& buffer) { + auto vertexAttrs = context.createVertexAttributeArray(); using LayoutVertex = gfx::Vertex; - if (const auto& attr = vertexAttrs.getOrAdd(idCollisionPosAttribName)) { + if (const auto& attr = vertexAttrs->add(idCollisionPosAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(LayoutVertex, a1), /*vertexOffset=*/0, sizeof(LayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(idCollisionAnchorPosAttribName)) { + if (const auto& attr = vertexAttrs->add(idCollisionAnchorPosAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(LayoutVertex, a2), /*vertexOffset=*/0, sizeof(LayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(idCollisionExtrudeAttribName)) { + if (const auto& attr = vertexAttrs->add(idCollisionExtrudeAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(LayoutVertex, a3), /*vertexOffset=*/0, @@ -906,14 +907,14 @@ gfx::VertexAttributeArray getCollisionVertexAttributes(const SymbolBucket::Colli using DynamicVertex = gfx::Vertex; - if (const auto& attr = vertexAttrs.getOrAdd(idCollisionPlacedAttribName)) { + if (const auto& attr = vertexAttrs->add(idCollisionPlacedAttribName)) { attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(DynamicVertex, a1), /*vertexOffset=*/0, sizeof(DynamicVertex), gfx::AttributeDataType::UShort2); } - if (const auto& attr = vertexAttrs.getOrAdd(idCollisionShiftAttribName)) { + if (const auto& attr = vertexAttrs->add(idCollisionShiftAttribName)) { attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(DynamicVertex, a2), /*vertexOffset=*/0, @@ -1109,12 +1110,12 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, collisionBuilder->setDrawableName(layerCollisionPrefix + suffix + "box"); collisionBuilder->setShader(shader); addVertices(collisionBox->vertices().vector()); - collisionBuilder->setVertexAttributes(getCollisionVertexAttributes(*collisionBox)); + collisionBuilder->setVertexAttributes(getCollisionVertexAttributes(context, *collisionBox)); collisionBuilder->setSegments(gfx::Lines(1.0f), collisionBox->sharedLines, collisionBox->segments.data(), collisionBox->segments.size()); - collisionBuilder->flush(); + collisionBuilder->flush(context); } } @@ -1126,12 +1127,12 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, collisionBuilder->setDrawableName(layerCollisionPrefix + suffix + "circle"); collisionBuilder->setShader(shader); addVertices(collisionCircle->vertices().vector()); - collisionBuilder->setVertexAttributes(getCollisionVertexAttributes(*collisionCircle)); + collisionBuilder->setVertexAttributes(getCollisionVertexAttributes(context, *collisionCircle)); collisionBuilder->setSegments(gfx::Triangles(), collisionCircle->sharedTriangles, collisionCircle->segments.data(), collisionCircle->segments.size()); - collisionBuilder->flush(); + collisionBuilder->flush(context); } } @@ -1258,8 +1259,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto vertexCount = buffer.vertices().elements(); propertiesAsUniforms.clear(); - gfx::VertexAttributeArray attribs; - updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs, propertiesAsUniforms); + auto attribs = context.createVertexAttributeArray(); + updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *attribs, propertiesAsUniforms); const auto textHalo = evaluated.get().constantOr(Color::black()).a > 0.0f && evaluated.get().constantOr(1); @@ -1342,7 +1343,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, &renderable.segment.get(), 1); - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index a412f2536..49f88a0cd 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -175,7 +175,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr debugBuilder->setTexture(texture, samplerLocation.value()); // finish - debugBuilder->flush(); + debugBuilder->flush(context); for (auto& drawable : debugBuilder->clearDrawables()) { drawable->setTileID(tileID); auto& uniforms = drawable->mutableUniformBuffers(); @@ -282,7 +282,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr auto tweaker = std::make_shared(linePropertiesUBO); // finish - polylineBuilder->flush(); + polylineBuilder->flush(context); for (auto& drawable : polylineBuilder->clearDrawables()) { drawable->setTileID(tile.getOverscaledTileID()); drawable->addTweaker(tweaker); diff --git a/src/mbgl/style/layers/custom_drawable_layer.cpp b/src/mbgl/style/layers/custom_drawable_layer.cpp index 03ee3e290..39215e259 100644 --- a/src/mbgl/style/layers/custom_drawable_layer.cpp +++ b/src/mbgl/style/layers/custom_drawable_layer.cpp @@ -302,8 +302,9 @@ void CustomDrawableLayerHost::Interface::addFill(const GeometryCollection& geome // add to builder static const StringIdentity idVertexAttribName = stringIndexer().get("a_pos"); builder->setVertexAttrNameId(idVertexAttribName); - gfx::VertexAttributeArray attrs; - if (const auto& attr = attrs.add(idVertexAttribName)) { + + auto attrs = context.createVertexAttributeArray(); + if (const auto& attr = attrs->add(idVertexAttribName)) { attr->setSharedRawData(sharedVertices, offsetof(FillLayoutVertex, a1), /*vertexOffset=*/0, @@ -315,14 +316,14 @@ void CustomDrawableLayerHost::Interface::addFill(const GeometryCollection& geome builder->setSegments(gfx::Triangles(), sharedTriangles, triangleSegments.data(), triangleSegments.size()); // flush current builder drawable - builder->flush(); + builder->flush(context); } void CustomDrawableLayerHost::Interface::finish() { if (builder && !builder->empty()) { // finish const auto finish_ = [this](auto& tweaker) { - builder->flush(); + builder->flush(context); for (auto& drawable : builder->clearDrawables()) { assert(tileID.has_value()); drawable->setTileID(tileID.value());