From fceaa18caf9baea83c86e836e20cb377dcbc91d5 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 20 Aug 2024 07:33:29 -0700 Subject: [PATCH] Use timestamps for attribute updates (#2629) --- include/mbgl/gfx/drawable.hpp | 8 +- include/mbgl/gfx/vertex_attribute.hpp | 32 +++-- include/mbgl/gl/vertex_attribute_gl.hpp | 9 +- include/mbgl/mtl/upload_pass.hpp | 1 + include/mbgl/mtl/vertex_attribute.hpp | 2 +- include/mbgl/mtl/vertex_buffer_resource.hpp | 5 + include/mbgl/util/instrumentation.hpp | 12 +- include/mbgl/vulkan/upload_pass.hpp | 1 + include/mbgl/vulkan/vertex_attribute.hpp | 3 - .../mbgl/vulkan/vertex_buffer_resource.hpp | 4 + src/mbgl/gfx/index_vector.hpp | 14 +- src/mbgl/gfx/upload_pass.hpp | 1 + src/mbgl/gfx/vertex_vector.hpp | 15 +- src/mbgl/gl/drawable_gl.cpp | 28 +++- src/mbgl/gl/layer_group_gl.cpp | 3 + src/mbgl/gl/upload_pass.cpp | 29 ++-- src/mbgl/gl/upload_pass.hpp | 1 + src/mbgl/gl/value.cpp | 134 +++++++++++++++++- src/mbgl/gl/vertex_attribute_gl.cpp | 19 +-- src/mbgl/gl/vertex_buffer_resource.hpp | 10 ++ src/mbgl/mtl/drawable.cpp | 25 +++- src/mbgl/mtl/upload_pass.cpp | 32 +++-- src/mbgl/mtl/vertex_attribute.cpp | 14 +- src/mbgl/renderer/buckets/circle_bucket.cpp | 3 + src/mbgl/renderer/buckets/fill_bucket.cpp | 4 + .../buckets/fill_extrusion_bucket.cpp | 3 + src/mbgl/renderer/buckets/line_bucket.cpp | 3 + src/mbgl/renderer/buckets/symbol_bucket.cpp | 6 + src/mbgl/renderer/buckets/symbol_bucket.hpp | 16 +++ .../renderer/layers/render_raster_layer.cpp | 29 ++-- .../renderer/layers/render_symbol_layer.cpp | 2 +- src/mbgl/renderer/paint_property_binder.hpp | 19 ++- src/mbgl/renderer/render_orchestrator.cpp | 15 +- src/mbgl/renderer/source_state.cpp | 3 +- .../renderer/sources/render_image_source.cpp | 6 +- src/mbgl/text/placement.cpp | 14 +- src/mbgl/text/placement.hpp | 2 +- src/mbgl/util/thread_pool.hpp | 3 + src/mbgl/vulkan/buffer_resource.cpp | 2 +- src/mbgl/vulkan/drawable.cpp | 39 ++--- src/mbgl/vulkan/render_pass.cpp | 4 +- src/mbgl/vulkan/upload_pass.cpp | 13 +- src/mbgl/vulkan/vertex_attribute.cpp | 14 +- 43 files changed, 439 insertions(+), 163 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index c90448036..f653fd3d3 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -5,9 +5,10 @@ #include #include #include -#include -#include #include +#include +#include +#include #include #include @@ -244,6 +245,8 @@ public: /// Set origin point void setOrigin(std::optional> p) { origin = std::move(p); } + const std::chrono::duration createTime = util::MonotonicTimer::now(); + protected: bool enabled = true; bool enableColor = true; @@ -264,6 +267,7 @@ protected: UniqueDrawableData drawableData{}; gfx::VertexAttributeArrayPtr vertexAttributes; gfx::VertexAttributeArrayPtr instanceAttributes; + std::chrono::duration attributeUpdateTime = util::MonotonicTimer::now(); struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index fccce52b3..fefb7f624 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -117,7 +117,7 @@ public: void setIndex(int value) { index = value; } /// @brief Get the stride of the vertex attribute - std::size_t getStride() const { return stride; } + virtual std::size_t getStride() const { return stride; } void setStride(std::size_t value) { stride = value; } /// @brief Get the count of vertex attribute items @@ -180,12 +180,16 @@ public: items.clear(); } - /// @brief Get dirty state - bool isDirty() const { return dirty; } - /// @brief Set dirty state void setDirty(bool value = true) { dirty = value; } + bool isModifiedAfter(std::chrono::duration time) const { + if (sharedRawData) { + return sharedRawData->isModifiedAfter(time); + } + return dirty; + } + template inline typename std::enable_if::type set(std::size_t, std::tuple, std::size_t) {} @@ -255,6 +259,9 @@ protected: } protected: + friend class VertexAttributeArray; + bool isDirty() const { return dirty; } + int index; std::size_t stride; @@ -310,8 +317,9 @@ public: std::size_t count = 0); /// Indicates whether any values have changed - virtual bool isDirty() const { - return std::any_of(attrs.begin(), attrs.end(), [](const auto& attr) { return attr && attr->isDirty(); }); + bool isModifiedAfter(std::chrono::duration time) const { + return std::any_of( + attrs.begin(), attrs.end(), [&](const auto& attr) { return attr && attr->isModifiedAfter(time); }); } /// Clear the collection @@ -328,11 +336,17 @@ public: } /// Call the provided delegate with each value, providing the override if one exists. - template &) */> - void resolve(const VertexAttributeArray& overrides, Func delegate) const { + /// @param foundDelegate Called for each attribute in `default`, with the corresponding override, if present + /// @param missingDelegate Called for any overrides with no corresponding default + template &) */, + typename MissingFunc /* void(const size_t, const std::unique_ptr&) */> + void resolve(const VertexAttributeArray& overrides, ResolveFunc foundDelegate, MissingFunc missingDelegate) const { for (size_t id = 0; id < attrs.size(); id++) { + const auto& override = overrides.get(id); if (const auto& attr = attrs[id]) { - delegate(id, *attr, overrides.get(id)); + foundDelegate(id, *attr, override); + } else if (override) { + missingDelegate(id, override); } } } diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index ec83bd899..f5b895e59 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -31,9 +31,11 @@ public: bool getNormalized() const { return normalized; } void setNormalized(bool value) { normalized = value; } - std::size_t getStride() const; + std::size_t getStride() const override; - static const std::vector& getRaw(gfx::VertexAttribute& attr, platform::GLenum); + static const std::vector& getRaw(gfx::VertexAttribute& attr, + platform::GLenum, + std::chrono::duration lastUpdate); private: static int getSize(platform::GLenum glType); @@ -58,9 +60,6 @@ public: } VertexAttributeArrayGL& operator=(const VertexAttributeArrayGL&) = delete; - /// Indicates whether any values have changed - bool isDirty() const override; - private: std::unique_ptr create(int index, gfx::AttributeDataType dataType, diff --git a/include/mbgl/mtl/upload_pass.hpp b/include/mbgl/mtl/upload_pass.hpp index ce6081bcc..676cf57de 100644 --- a/include/mbgl/mtl/upload_pass.hpp +++ b/include/mbgl/mtl/upload_pass.hpp @@ -66,6 +66,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, + const std::chrono::duration lastUpdate, /*out*/ std::vector>& outBuffers) override; std::unique_ptr createTextureResource(Size, diff --git a/include/mbgl/mtl/vertex_attribute.hpp b/include/mbgl/mtl/vertex_attribute.hpp index b956b8a00..625714107 100644 --- a/include/mbgl/mtl/vertex_attribute.hpp +++ b/include/mbgl/mtl/vertex_attribute.hpp @@ -39,7 +39,7 @@ public: VertexAttributeArray& operator=(const VertexAttributeArray& other) = delete; /// Indicates whether any values have changed - bool isDirty() const override; + bool isModifiedAfter(std::chrono::duration time) const; private: gfx::UniqueVertexAttribute create(int index, gfx::AttributeDataType dataType, std::size_t count) const override { diff --git a/include/mbgl/mtl/vertex_buffer_resource.hpp b/include/mbgl/mtl/vertex_buffer_resource.hpp index 0312e8beb..aa9f2c16e 100644 --- a/include/mbgl/mtl/vertex_buffer_resource.hpp +++ b/include/mbgl/mtl/vertex_buffer_resource.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -21,8 +22,12 @@ public: BufferResource& get() noexcept { return buffer; } const BufferResource& get() const noexcept { return buffer; } + std::chrono::duration getLastUpdated() const { return lastUpdated; } + void setLastUpdated(std::chrono::duration time) { lastUpdated = time; } + protected: BufferResource buffer; + std::chrono::duration lastUpdated; }; using UniqueVertexBufferResource = std::unique_ptr; diff --git a/include/mbgl/util/instrumentation.hpp b/include/mbgl/util/instrumentation.hpp index 511b95a0f..3528a540a 100644 --- a/include/mbgl/util/instrumentation.hpp +++ b/include/mbgl/util/instrumentation.hpp @@ -25,12 +25,12 @@ const void* castGpuIdToTracyPtr(GpuId id) { "MLN_RENDER_BACKEND_OPENGL is not defined. MLN_RENDER_BACKEND_OPENGL is expected to be defined in CMake and Bazel" #endif -#define MLN_TRACE_FUNC() ZoneScoped; -#define MLN_TRACE_ZONE(label) ZoneScopedN(#label); +#define MLN_TRACE_FUNC() ZoneScoped +#define MLN_TRACE_ZONE(label) ZoneScopedN(#label) -#define MLN_ZONE_TEXT(label) ZoneText(#label, strlen(#label)); -#define MLN_ZONE_STR(str) ZoneText(str.c_str(), str.size()); -#define MLN_ZONE_VALUE(val) ZoneValue(static_cast(val)); +#define MLN_ZONE_TEXT(text, size) ZoneText(text, size) +#define MLN_ZONE_STR(str) ZoneText(str.c_str(), str.size()) +#define MLN_ZONE_VALUE(n) ZoneValue(n) constexpr const char* tracyTextureMemoryLabel = "Texture Memory"; #define MLN_TRACE_ALLOC_TEXTURE(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyTextureMemoryLabel); @@ -119,4 +119,4 @@ constexpr const char* tracyConstMemoryLabel = "Constant Buffer Memory"; #define MLN_TRACE_FUNC() #define MLN_TRACE_ZONE(label) -#endif // MLN_TRACY_ENABLE \ No newline at end of file +#endif // MLN_TRACY_ENABLE diff --git a/include/mbgl/vulkan/upload_pass.hpp b/include/mbgl/vulkan/upload_pass.hpp index d799b14b0..abbc9d247 100644 --- a/include/mbgl/vulkan/upload_pass.hpp +++ b/include/mbgl/vulkan/upload_pass.hpp @@ -61,6 +61,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, + const std::chrono::duration lastUpdate, /*out*/ std::vector>& outBuffers) override; std::unique_ptr createTextureResource(Size, diff --git a/include/mbgl/vulkan/vertex_attribute.hpp b/include/mbgl/vulkan/vertex_attribute.hpp index 80bc0e40b..f830366a4 100644 --- a/include/mbgl/vulkan/vertex_attribute.hpp +++ b/include/mbgl/vulkan/vertex_attribute.hpp @@ -39,9 +39,6 @@ public: } VertexAttributeArray& operator=(const VertexAttributeArray& other) = delete; - /// Indicates whether any values have changed - bool isDirty() const override; - private: gfx::UniqueVertexAttribute create(int index, gfx::AttributeDataType dataType, std::size_t count) const override { return std::make_unique(index, dataType, count); diff --git a/include/mbgl/vulkan/vertex_buffer_resource.hpp b/include/mbgl/vulkan/vertex_buffer_resource.hpp index ac23cf832..5b2b85910 100644 --- a/include/mbgl/vulkan/vertex_buffer_resource.hpp +++ b/include/mbgl/vulkan/vertex_buffer_resource.hpp @@ -22,8 +22,12 @@ public: BufferResource& get() noexcept { return buffer; } const BufferResource& get() const noexcept { return buffer; } + std::chrono::duration getLastUpdated() const { return lastUpdated; } + void setLastUpdated(std::chrono::duration time) { lastUpdated = time; } + protected: BufferResource buffer; + std::chrono::duration lastUpdated; }; using UniqueVertexBufferResource = std::unique_ptr; diff --git a/src/mbgl/gfx/index_vector.hpp b/src/mbgl/gfx/index_vector.hpp index 3f20c8076..be69874d7 100644 --- a/src/mbgl/gfx/index_vector.hpp +++ b/src/mbgl/gfx/index_vector.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -40,8 +41,15 @@ public: void setBuffer(std::unique_ptr&& value) { buffer = std::move(value); } #endif // MLN_DRAWABLE_RENDERER - bool getDirty() const { return dirty; } - void setDirty(bool value = true) { dirty = value; } + std::chrono::duration getLastModified() const { return lastModified; } + bool isModifiedAfter(std::chrono::duration t) const { return t < lastModified; } + + void updateModified() { + if (dirty) { + lastModified = util::MonotonicTimer::now(); + dirty = false; + } + } bool isReleased() const { return released; } @@ -99,6 +107,8 @@ protected: #endif // MLN_DRAWABLE_RENDERER bool dirty = true; bool released = false; + + std::chrono::duration lastModified = util::MonotonicTimer::now(); }; using IndexVectorBasePtr = std::shared_ptr; diff --git a/src/mbgl/gfx/upload_pass.hpp b/src/mbgl/gfx/upload_pass.hpp index a9d77d0b3..92fcd3bec 100644 --- a/src/mbgl/gfx/upload_pass.hpp +++ b/src/mbgl/gfx/upload_pass.hpp @@ -87,6 +87,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, + const std::chrono::duration lastUpdate, /*out*/ std::vector>& outBuffers) = 0; #endif diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index c46069a37..9fedaadc5 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -35,9 +36,17 @@ public: void setBuffer(std::unique_ptr&& value) { buffer = std::move(value); } #endif // MLN_DRAWABLE_RENDERER - bool getDirty() const { return dirty; } - void setDirty(bool value = true) { dirty = value; } + std::chrono::duration getLastModified() const { return lastModified; } + bool isModifiedAfter(std::chrono::duration t) const { return t < lastModified; } + void updateModified() { + if (dirty) { + lastModified = util::MonotonicTimer::now(); + dirty = false; + } + } + + // Indicates that the owner/producer will not modify this again bool isReleased() const { return released; } protected: @@ -46,6 +55,8 @@ protected: #endif // MLN_DRAWABLE_RENDERER bool dirty = true; bool released = false; + + std::chrono::duration lastModified = util::MonotonicTimer::now(); }; using VertexVectorBasePtr = std::shared_ptr; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 2030accbf..899b86719 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace mbgl { @@ -22,6 +23,8 @@ DrawableGL::~DrawableGL() { } void DrawableGL::draw(PaintParameters& parameters) const { + MLN_TRACE_FUNC(); + if (isCustom) { return; } @@ -147,13 +150,22 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { return; } + MLN_TRACE_FUNC(); +#ifdef MLN_TRACY_ENABLE + { + auto str = name + "/" + (tileID ? util::toString(*tileID) : std::string()); + MLN_ZONE_STR(str); + } +#endif + const bool build = vertexAttributes && - (vertexAttributes->isDirty() || + (vertexAttributes->isModifiedAfter(attributeUpdateTime) || std::any_of(impl->segments.begin(), impl->segments.end(), [](const auto& seg) { return !static_cast(*seg).getVertexArray().isValid(); })); if (build) { + MLN_TRACE_ZONE(build attributes); auto& context = uploadPass.getContext(); auto& glContext = static_cast(context); constexpr auto usage = gfx::BufferUsageType::StaticDraw; @@ -173,11 +185,16 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { defaults, overrides, usage, + attributeUpdateTime, vertexBuffers); impl->attributeBuffers = std::move(vertexBuffers); - if (impl->indexes->getDirty()) { + if (impl->indexes) { + impl->indexes->updateModified(); + } + if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { + MLN_TRACE_ZONE(build indexes); auto indexBufferResource{ uploadPass.createIndexBufferResource(impl->indexes->data(), impl->indexes->bytes(), usage)}; auto indexBuffer = std::make_unique(impl->indexes->elements(), @@ -185,11 +202,11 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { auto buffer = std::make_unique(std::move(indexBuffer)); impl->indexes->setBuffer(std::move(buffer)); - impl->indexes->setDirty(false); } // Create a VAO for each group of vertexes described by a segment for (const auto& seg : impl->segments) { + MLN_TRACE_ZONE(segment); auto& glSeg = static_cast(*seg); const auto& mlSeg = glSeg.getSegment(); @@ -212,7 +229,9 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { glSeg.setVertexArray(std::move(vertexArray)); } } - }; + } + + attributeUpdateTime = util::MonotonicTimer::now(); } const bool texturesNeedUpload = std::any_of( @@ -238,6 +257,7 @@ gfx::StencilMode DrawableGL::makeStencilMode(PaintParameters& parameters) const } void DrawableGL::uploadTextures() const { + MLN_TRACE_FUNC(); for (const auto& texture : textures) { if (texture) { texture->upload(); diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index e3f847f56..4aca74fbe 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -21,6 +21,9 @@ TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapac : TileLayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) { + MLN_TRACE_FUNC(); + MLN_ZONE_STR(name); + if (!enabled) { return; } diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index e0b71b6b9..a53b3d878 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #if MLN_DRAWABLE_RENDERER @@ -43,7 +44,7 @@ std::unique_ptr UploadPass::createVertexBufferResourc } void UploadPass::updateVertexBufferResource(gfx::VertexBufferResource& resource, const void* data, std::size_t size) { - commandEncoder.context.vertexBuffer = static_cast(resource).buffer; + commandEncoder.context.vertexBuffer = static_cast(resource).getBuffer(); MBGL_CHECK_ERROR(glBufferSubData(GL_ARRAY_BUFFER, 0, size, data)); } @@ -151,11 +152,12 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe 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()) { + // If the already-allocated buffer is large enough, we can re-use it + if (rawBufSize <= resource.getByteSize()) { + // If the source changed, update the buffer contents + if (vec->isModifiedAfter(resource.getLastUpdated())) { updateVertexBufferResource(resource, rawBufPtr, rawBufSize); - vec->setDirty(false); + resource.setLastUpdated(vec->getLastModified()); } return rawData->resource; } @@ -165,7 +167,6 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe auto buffer = std::make_unique(); buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false); vec->setBuffer(std::move(buffer)); - vec->setDirty(false); return static_cast(vec->getBuffer())->resource; } } @@ -190,7 +191,9 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, + const std::chrono::duration lastUpdate, /*out*/ std::vector>& outBuffers) { + MLN_TRACE_FUNC(); AttributeBindingArray bindings; bindings.resize(defaults.allocatedSize()); @@ -217,6 +220,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( // For each attribute in the program, with the corresponding default and optional override... const auto resolveAttr = [&](const size_t id, auto& defaultAttr, auto& overrideAttr) -> void { + MLN_TRACE_ZONE(binding); auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr; const auto& defaultGL = static_cast(defaultAttr); const auto stride = defaultAttr.getStride(); @@ -245,10 +249,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( } // Get the raw data for the values in the desired format - const auto& rawData = VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType()); - if (rawData.empty()) { - VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType()); - } + const auto& rawData = VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType(), lastUpdate); if (rawData.size() == stride * vertexCount) { // The override provided a value for each vertex, append it as-is @@ -268,6 +269,8 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( return; } + overrideAttr->setDirty(false); + bindings[index] = { /*.attribute = */ {defaultAttr.getDataType(), offset}, /* vertexStride = */ static_cast(stride), @@ -280,7 +283,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( // The vertex stride is the sum of the attribute strides vertexStride += static_cast(stride); }; - defaults.resolve(overrides, resolveAttr); + // This version is called when the attribute is available, but isn't being used by the shader + const auto missingAttr = [&](const size_t, auto& missingAttr) -> void { + missingAttr->setDirty(false); + }; + defaults.resolve(overrides, resolveAttr, missingAttr); assert(vertexStride * vertexCount <= allData.size()); diff --git a/src/mbgl/gl/upload_pass.hpp b/src/mbgl/gl/upload_pass.hpp index b3b9a2bbf..a1d1cfb2c 100644 --- a/src/mbgl/gl/upload_pass.hpp +++ b/src/mbgl/gl/upload_pass.hpp @@ -56,6 +56,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, + const std::chrono::duration lastUpdate, /*out*/ std::vector>& outBuffers) override; #endif diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index d77e7b501..fe0840c72 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { namespace gl { @@ -13,10 +14,14 @@ using namespace platform; const constexpr ClearDepth::Type ClearDepth::Default; void ClearDepth::Set(const Type& value) { + MLN_TRACE_ZONE(ClearDepth::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glClearDepthf(value)); } ClearDepth::Type ClearDepth::Get() { + MLN_TRACE_ZONE(ClearDepth::Get); + MLN_TRACE_FUNC_GL(); GLfloat clearDepth; MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth)); return clearDepth; @@ -25,10 +30,14 @@ ClearDepth::Type ClearDepth::Get() { const ClearColor::Type ClearColor::Default{0, 0, 0, 0}; void ClearColor::Set(const Type& value) { + MLN_TRACE_ZONE(ClearColor::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glClearColor(value.r, value.g, value.b, value.a)); } ClearColor::Type ClearColor::Get() { + MLN_TRACE_ZONE(ClearColor::Get); + MLN_TRACE_FUNC_GL(); GLfloat clearColor[4]; MBGL_CHECK_ERROR(glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor)); return {clearColor[0], clearColor[1], clearColor[2], clearColor[3]}; @@ -37,10 +46,14 @@ ClearColor::Type ClearColor::Get() { const constexpr ClearStencil::Type ClearStencil::Default; void ClearStencil::Set(const Type& value) { + MLN_TRACE_ZONE(ClearStencil::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glClearStencil(value)); } ClearStencil::Type ClearStencil::Get() { + MLN_TRACE_ZONE(ClearStencil::Get); + MLN_TRACE_FUNC_GL(); GLint clearStencil; MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil)); return clearStencil; @@ -49,10 +62,14 @@ ClearStencil::Type ClearStencil::Get() { const constexpr StencilMask::Type StencilMask::Default; void StencilMask::Set(const Type& value) { + MLN_TRACE_ZONE(StencilMask::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glStencilMask(value)); } StencilMask::Type StencilMask::Get() { + MLN_TRACE_ZONE(StencilMask::Get); + MLN_TRACE_FUNC_GL(); GLint stencilMask; MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_WRITEMASK, &stencilMask)); return stencilMask; @@ -61,10 +78,14 @@ StencilMask::Type StencilMask::Get() { const constexpr DepthMask::Type DepthMask::Default; void DepthMask::Set(const Type& value) { + MLN_TRACE_ZONE(DepthMask::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glDepthMask(Enum::to(value))); } DepthMask::Type DepthMask::Get() { + MLN_TRACE_ZONE(DepthMask::Get); + MLN_TRACE_FUNC_GL(); GLboolean depthMask; MBGL_CHECK_ERROR(glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask)); return Enum::from(depthMask); @@ -73,10 +94,14 @@ DepthMask::Type DepthMask::Get() { const constexpr ColorMask::Type ColorMask::Default; void ColorMask::Set(const Type& value) { + MLN_TRACE_ZONE(ColorMask::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glColorMask(value.r, value.g, value.b, value.a)); } ColorMask::Type ColorMask::Get() { + MLN_TRACE_ZONE(ColorMask::Get); + MLN_TRACE_FUNC_GL(); GLboolean bools[4]; MBGL_CHECK_ERROR(glGetBooleanv(GL_COLOR_WRITEMASK, bools)); return {static_cast(bools[0]), @@ -88,10 +113,14 @@ ColorMask::Type ColorMask::Get() { const constexpr StencilFunc::Type StencilFunc::Default; void StencilFunc::Set(const Type& value) { + MLN_TRACE_ZONE(StencilFunc::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glStencilFunc(Enum::to(value.func), value.ref, value.mask)); } StencilFunc::Type StencilFunc::Get() { + MLN_TRACE_ZONE(StencilFunc::Get); + MLN_TRACE_FUNC_GL(); GLint func; GLint ref; GLint mask; @@ -104,10 +133,14 @@ StencilFunc::Type StencilFunc::Get() { const constexpr StencilTest::Type StencilTest::Default; void StencilTest::Set(const Type& value) { + MLN_TRACE_ZONE(StencilTest::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(value ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST)); } StencilTest::Type StencilTest::Get() { + MLN_TRACE_ZONE(StencilTest::Get); + MLN_TRACE_FUNC_GL(); Type stencilTest; MBGL_CHECK_ERROR(stencilTest = glIsEnabled(GL_STENCIL_TEST)); return stencilTest; @@ -116,12 +149,16 @@ StencilTest::Type StencilTest::Get() { const constexpr StencilOp::Type StencilOp::Default; void StencilOp::Set(const Type& value) { + MLN_TRACE_ZONE(StencilOp::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glStencilOp(Enum::to(value.sfail), Enum::to(value.dpfail), Enum::to(value.dppass))); } StencilOp::Type StencilOp::Get() { + MLN_TRACE_ZONE(StencilOp::Get); + MLN_TRACE_FUNC_GL(); GLint sfail; GLint dpfail; GLint dppass; @@ -137,10 +174,14 @@ StencilOp::Type StencilOp::Get() { const constexpr DepthRange::Type DepthRange::Default; void DepthRange::Set(const Type& value) { + MLN_TRACE_ZONE(DepthRange::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glDepthRangef(value.min, value.max)); } DepthRange::Type DepthRange::Get() { + MLN_TRACE_ZONE(DepthRange::Get); + MLN_TRACE_FUNC_GL(); GLfloat floats[2]; MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_RANGE, floats)); return {floats[0], floats[1]}; @@ -150,10 +191,14 @@ DepthRange::Type DepthRange::Get() { const constexpr DepthTest::Type DepthTest::Default; void DepthTest::Set(const Type& value) { + MLN_TRACE_ZONE(DepthTest::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(value ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST)); } DepthTest::Type DepthTest::Get() { + MLN_TRACE_ZONE(DepthTest::Get); + MLN_TRACE_FUNC_GL(); Type depthTest; MBGL_CHECK_ERROR(depthTest = glIsEnabled(GL_DEPTH_TEST)); return depthTest; @@ -162,10 +207,14 @@ DepthTest::Type DepthTest::Get() { const constexpr DepthFunc::Type DepthFunc::Default; void DepthFunc::Set(const DepthFunc::Type& value) { + MLN_TRACE_ZONE(DepthFunc::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glDepthFunc(Enum::to(value))); } DepthFunc::Type DepthFunc::Get() { + MLN_TRACE_ZONE(DepthFunc::Get); + MLN_TRACE_FUNC_GL(); GLint depthFunc; MBGL_CHECK_ERROR(glGetIntegerv(GL_DEPTH_FUNC, &depthFunc)); return Enum::from(depthFunc); @@ -174,10 +223,14 @@ DepthFunc::Type DepthFunc::Get() { const constexpr Blend::Type Blend::Default; void Blend::Set(const Type& value) { + MLN_TRACE_ZONE(Blend::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(value ? glEnable(GL_BLEND) : glDisable(GL_BLEND)); } Blend::Type Blend::Get() { + MLN_TRACE_ZONE(Blend::Get); + MLN_TRACE_FUNC_GL(); Type blend; MBGL_CHECK_ERROR(blend = glIsEnabled(GL_BLEND)); return blend; @@ -186,10 +239,14 @@ Blend::Type Blend::Get() { const constexpr BlendEquation::Type BlendEquation::Default; void BlendEquation::Set(const Type& value) { + MLN_TRACE_ZONE(BlendEquation::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBlendEquation(Enum::to(value))); } BlendEquation::Type BlendEquation::Get() { + MLN_TRACE_ZONE(BlendEquation::Get); + MLN_TRACE_FUNC_GL(); GLint blend; MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend)); return Enum::from(blend); @@ -198,11 +255,15 @@ BlendEquation::Type BlendEquation::Get() { const constexpr BlendFunc::Type BlendFunc::Default; void BlendFunc::Set(const Type& value) { + MLN_TRACE_ZONE(BlendFunc::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBlendFunc(Enum::to(value.sfactor), Enum::to(value.dfactor))); } BlendFunc::Type BlendFunc::Get() { + MLN_TRACE_ZONE(BlendFunc::Get); + MLN_TRACE_FUNC_GL(); GLint sfactor; GLint dfactor; MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor)); @@ -213,10 +274,14 @@ BlendFunc::Type BlendFunc::Get() { const BlendColor::Type BlendColor::Default{0, 0, 0, 0}; void BlendColor::Set(const Type& value) { + MLN_TRACE_ZONE(BlendColor::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBlendColor(value.r, value.g, value.b, value.a)); } BlendColor::Type BlendColor::Get() { + MLN_TRACE_ZONE(BlendColor::Get); + MLN_TRACE_FUNC_GL(); GLfloat floats[4]; MBGL_CHECK_ERROR(glGetFloatv(GL_BLEND_COLOR, floats)); return {floats[0], floats[1], floats[2], floats[3]}; @@ -225,10 +290,14 @@ BlendColor::Type BlendColor::Get() { const constexpr Program::Type Program::Default; void Program::Set(const Type& value) { + MLN_TRACE_ZONE(Program::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glUseProgram(value)); } Program::Type Program::Get() { + MLN_TRACE_ZONE(Program::Get); + MLN_TRACE_FUNC_GL(); GLint program; MBGL_CHECK_ERROR(glGetIntegerv(GL_CURRENT_PROGRAM, &program)); return program; @@ -237,10 +306,14 @@ Program::Type Program::Get() { const constexpr LineWidth::Type LineWidth::Default; void LineWidth::Set(const Type& value) { + MLN_TRACE_ZONE(LineWidth::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glLineWidth(value)); } LineWidth::Type LineWidth::Get() { + MLN_TRACE_ZONE(LineWidth::Get); + MLN_TRACE_FUNC_GL(); GLfloat lineWidth; MBGL_CHECK_ERROR(glGetFloatv(GL_LINE_WIDTH, &lineWidth)); return lineWidth; @@ -249,10 +322,14 @@ LineWidth::Type LineWidth::Get() { const constexpr ActiveTextureUnit::Type ActiveTextureUnit::Default; void ActiveTextureUnit::Set(const Type& value) { + MLN_TRACE_ZONE(ActiveTextureUnit::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0 + value)); } ActiveTextureUnit::Type ActiveTextureUnit::Get() { + MLN_TRACE_ZONE(ActiveTextureUnit::Get); + MLN_TRACE_FUNC_GL(); GLint activeTexture; MBGL_CHECK_ERROR(glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture)); return static_cast(activeTexture - GL_TEXTURE0); @@ -261,10 +338,14 @@ ActiveTextureUnit::Type ActiveTextureUnit::Get() { const constexpr Viewport::Type Viewport::Default; void Viewport::Set(const Type& value) { + MLN_TRACE_ZONE(Viewport::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glViewport(value.x, value.y, value.size.width, value.size.height)); } Viewport::Type Viewport::Get() { + MLN_TRACE_ZONE(Viewport::Get); + MLN_TRACE_FUNC_GL(); GLint viewport[4]; MBGL_CHECK_ERROR(glGetIntegerv(GL_VIEWPORT, viewport)); return {static_cast(viewport[0]), @@ -275,10 +356,14 @@ Viewport::Type Viewport::Get() { const constexpr ScissorTest::Type ScissorTest::Default; void ScissorTest::Set(const Type& value) { + MLN_TRACE_ZONE(ScissorTest::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(value ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST)); } ScissorTest::Type ScissorTest::Get() { + MLN_TRACE_ZONE(ScissorTest::Get); + MLN_TRACE_FUNC_GL(); Type scissorTest; MBGL_CHECK_ERROR(scissorTest = glIsEnabled(GL_SCISSOR_TEST)); return scissorTest; @@ -287,10 +372,14 @@ ScissorTest::Type ScissorTest::Get() { const constexpr BindFramebuffer::Type BindFramebuffer::Default; void BindFramebuffer::Set(const Type& value) { + MLN_TRACE_ZONE(BindFramebuffer::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, value)); } BindFramebuffer::Type BindFramebuffer::Get() { + MLN_TRACE_ZONE(BindFramebuffer::Get); + MLN_TRACE_FUNC_GL(); GLint binding; MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &binding)); return binding; @@ -299,10 +388,14 @@ BindFramebuffer::Type BindFramebuffer::Get() { const constexpr BindRenderbuffer::Type BindRenderbuffer::Default; void BindRenderbuffer::Set(const Type& value) { + MLN_TRACE_ZONE(BindRenderbuffer::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, value)); } BindRenderbuffer::Type BindRenderbuffer::Get() { + MLN_TRACE_ZONE(BindRenderbuffer::Get); + MLN_TRACE_FUNC_GL(); GLint binding; MBGL_CHECK_ERROR(glGetIntegerv(GL_RENDERBUFFER_BINDING, &binding)); return binding; @@ -311,10 +404,14 @@ BindRenderbuffer::Type BindRenderbuffer::Get() { const constexpr CullFace::Type CullFace::Default; void CullFace::Set(const Type& value) { + MLN_TRACE_ZONE(CullFace::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(value ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE)); } CullFace::Type CullFace::Get() { + MLN_TRACE_ZONE(CullFace::Get); + MLN_TRACE_FUNC_GL(); GLboolean cullFace; MBGL_CHECK_ERROR(cullFace = glIsEnabled(GL_CULL_FACE)); return cullFace; @@ -323,10 +420,14 @@ CullFace::Type CullFace::Get() { const constexpr CullFaceSide::Type CullFaceSide::Default; void CullFaceSide::Set(const Type& value) { + MLN_TRACE_ZONE(CullFaceSide::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glCullFace(Enum::to(value))); } CullFaceSide::Type CullFaceSide::Get() { + MLN_TRACE_ZONE(CullFaceSide::Get); + MLN_TRACE_FUNC_GL(); GLint cullFaceMode; MBGL_CHECK_ERROR(glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode)); return Enum::from(cullFaceMode); @@ -335,10 +436,14 @@ CullFaceSide::Type CullFaceSide::Get() { const constexpr CullFaceWinding::Type CullFaceWinding::Default; void CullFaceWinding::Set(const Type& value) { + MLN_TRACE_ZONE(CullFaceWinding::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glFrontFace(Enum::to(value))); } CullFaceWinding::Type CullFaceWinding::Get() { + MLN_TRACE_ZONE(CullFaceWinding::Get); + MLN_TRACE_FUNC_GL(); GLint frontFace; MBGL_CHECK_ERROR(glGetIntegerv(GL_FRONT_FACE, &frontFace)); return Enum::from(frontFace); @@ -347,10 +452,14 @@ CullFaceWinding::Type CullFaceWinding::Get() { const constexpr BindTexture::Type BindTexture::Default; void BindTexture::Set(const Type& value) { + MLN_TRACE_ZONE(BindTexture::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, value)); } BindTexture::Type BindTexture::Get() { + MLN_TRACE_ZONE(BindTexture::Get); + MLN_TRACE_FUNC_GL(); GLint binding; MBGL_CHECK_ERROR(glGetIntegerv(GL_TEXTURE_BINDING_2D, &binding)); return binding; @@ -359,10 +468,14 @@ BindTexture::Type BindTexture::Get() { const constexpr BindVertexBuffer::Type BindVertexBuffer::Default; void BindVertexBuffer::Set(const Type& value) { + MLN_TRACE_ZONE(BindVertexBuffer::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, value)); } BindVertexBuffer::Type BindVertexBuffer::Get() { + MLN_TRACE_ZONE(BindVertexBuffer::Get); + MLN_TRACE_FUNC_GL(); GLint binding; MBGL_CHECK_ERROR(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &binding)); return binding; @@ -371,10 +484,14 @@ BindVertexBuffer::Type BindVertexBuffer::Get() { const constexpr BindElementBuffer::Type BindElementBuffer::Default; void BindElementBuffer::Set(const Type& value) { + MLN_TRACE_ZONE(BindElementBuffer::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, value)); } BindElementBuffer::Type BindElementBuffer::Get() { + MLN_TRACE_ZONE(BindElementBuffer::Get); + MLN_TRACE_FUNC_GL(); GLint binding; MBGL_CHECK_ERROR(glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &binding)); return binding; @@ -383,10 +500,14 @@ BindElementBuffer::Type BindElementBuffer::Get() { const constexpr BindVertexArray::Type BindVertexArray::Default; void BindVertexArray::Set(const Type& value) { + MLN_TRACE_ZONE(BindVertexArray::Set); + MLN_TRACE_FUNC_GL(); MBGL_CHECK_ERROR(glBindVertexArray(value)); } BindVertexArray::Type BindVertexArray::Get() { + MLN_TRACE_ZONE(BindVertexArray::Get); + MLN_TRACE_FUNC_GL(); GLint binding = 0; MBGL_CHECK_ERROR(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &binding)); return binding; @@ -485,8 +606,11 @@ GLint components(const gfx::AttributeDataType type) { #endif void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocation location) { + MLN_TRACE_ZONE(VertexAttribute::Set); + MLN_TRACE_FUNC_GL(); if (binding && binding->vertexBufferResource) { - context.vertexBuffer = reinterpret_cast(*binding->vertexBufferResource).buffer; + context.vertexBuffer = + reinterpret_cast(*binding->vertexBufferResource).getBuffer(); MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( location, @@ -507,11 +631,15 @@ void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocati const constexpr PixelStorePack::Type PixelStorePack::Default; void PixelStorePack::Set(const Type& value) { + MLN_TRACE_ZONE(PixelStorePack::Set); + MLN_TRACE_FUNC_GL(); assert(value.alignment == 1 || value.alignment == 2 || value.alignment == 4 || value.alignment == 8); MBGL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, value.alignment)); } PixelStorePack::Type PixelStorePack::Get() { + MLN_TRACE_ZONE(PixelStorePack::Get); + MLN_TRACE_FUNC_GL(); Type value; MBGL_CHECK_ERROR(glGetIntegerv(GL_PACK_ALIGNMENT, &value.alignment)); return value; @@ -520,11 +648,15 @@ PixelStorePack::Type PixelStorePack::Get() { const constexpr PixelStoreUnpack::Type PixelStoreUnpack::Default; void PixelStoreUnpack::Set(const Type& value) { + MLN_TRACE_ZONE(PixelStoreUnpack::Set); + MLN_TRACE_FUNC_GL(); assert(value.alignment == 1 || value.alignment == 2 || value.alignment == 4 || value.alignment == 8); MBGL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, value.alignment)); } PixelStoreUnpack::Type PixelStoreUnpack::Get() { + MLN_TRACE_ZONE(PixelStoreUnpack::Get); + MLN_TRACE_FUNC_GL(); Type value; MBGL_CHECK_ERROR(glGetIntegerv(GL_UNPACK_ALIGNMENT, &value.alignment)); return value; diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index 02fa811d7..5fbb3d65d 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -153,11 +153,13 @@ std::size_t VertexAttributeGL::getStride() const { return getStride(getGLType()); } -const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, platform::GLenum type) { +const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, + platform::GLenum type, + std::chrono::duration lastUpdate) { const auto count = attr.getCount(); const auto stride_ = getStride(type); auto& rawData = attr.getRawData(); - if (attr.isDirty() || rawData.size() != count * stride_) { + if (attr.isModifiedAfter(lastUpdate) || rawData.size() != count * stride_) { rawData.resize(stride_ * count); if (!rawData.empty()) { @@ -177,18 +179,5 @@ const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& return rawData; } -bool VertexAttributeArrayGL::isDirty() const { - return std::any_of(attrs.begin(), attrs.end(), [](const auto& attr) { - if (attr) { - // If we have shared data, the dirty flag from that overrides ours - const auto& glAttrib = static_cast(*attr); - if (const auto& shared = glAttrib.getSharedRawData()) { - return shared->getDirty(); - } - } - return attr && attr->isDirty(); - }); -} - } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/vertex_buffer_resource.hpp b/src/mbgl/gl/vertex_buffer_resource.hpp index 1bd48ed94..d7ec725d0 100644 --- a/src/mbgl/gl/vertex_buffer_resource.hpp +++ b/src/mbgl/gl/vertex_buffer_resource.hpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace gl { @@ -11,8 +12,17 @@ public: VertexBufferResource(UniqueBuffer&& buffer_, int byteSize_); ~VertexBufferResource() noexcept override; + int getByteSize() const { return byteSize; } + + const UniqueBuffer& getBuffer() const { return buffer; } + + std::chrono::duration getLastUpdated() const { return lastUpdated; } + void setLastUpdated(std::chrono::duration time) { lastUpdated = time; } + +protected: UniqueBuffer buffer; int byteSize; + std::chrono::duration lastUpdated = util::MonotonicTimer::now(); }; } // namespace gl diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index a3bc354b2..d139f023c 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -191,13 +191,13 @@ void Drawable::draw(PaintParameters& parameters) const { bindUniformBuffers(renderPass); bindTextures(renderPass); - if (!impl->indexes->getBuffer() || impl->indexes->getDirty()) { + if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { assert(!"Index buffer not uploaded"); return; } const auto* indexBuffer = getMetalBuffer(impl->indexes); - if (!indexBuffer || impl->indexes->getDirty()) { + if (!indexBuffer || impl->indexes->isModifiedAfter(attributeUpdateTime)) { assert(!"Index buffer not uploaded"); return; } @@ -526,14 +526,19 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { auto& context = static_cast(contextBase); constexpr auto usage = gfx::BufferUsageType::StaticDraw; + if (impl->indexes) { + impl->indexes->updateModified(); + } + // We need either raw index data or a buffer already created from them. // We can have a buffer and no indexes, but only if it's not marked dirty. - if (!impl->indexes || (impl->indexes->empty() && (!impl->indexes->getBuffer() || impl->indexes->getDirty()))) { + if (!impl->indexes || (impl->indexes->empty() && + (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)))) { assert(!"Missing index data"); return; } - if (impl->indexes->getDirty()) { + if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { // Create or update a buffer for the index data. We don't update any // existing buffer because it may still be in use by the previous frame. auto indexBufferResource{uploadPass.createIndexBufferResource( @@ -543,10 +548,10 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { auto buffer = std::make_unique(std::move(indexBuffer)); impl->indexes->setBuffer(std::move(buffer)); - impl->indexes->setDirty(false); } - const bool buildAttribs = !vertexAttributes || vertexAttributes->isDirty() || !impl->vertexDesc; + const bool buildAttribs = !vertexAttributes || vertexAttributes->isModifiedAfter(attributeUpdateTime) || + !impl->vertexDesc; if (buildAttribs) { #if !defined(NDEBUG) @@ -566,6 +571,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { shader->getVertexAttributes(), *vertexAttributes, usage, + attributeUpdateTime, vertexBuffers); impl->attributeBuffers = std::move(vertexBuffers); @@ -626,7 +632,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } // build instance buffer - const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isDirty()); + const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isModifiedAfter(attributeUpdateTime)); if (buildInstanceBuffer) { // Build instance attribute buffers @@ -638,6 +644,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { shader->getInstanceAttributes(), *instanceAttributes, usage, + attributeUpdateTime, instanceBuffers); impl->instanceBuffers = std::move(instanceBuffers); @@ -655,6 +662,10 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { if (texturesNeedUpload) { uploadTextures(uploadPass); } + + if (buildAttribs || buildInstanceBuffer) { + attributeUpdateTime = util::MonotonicTimer::now(); + } } } // namespace mtl diff --git a/src/mbgl/mtl/upload_pass.cpp b/src/mbgl/mtl/upload_pass.cpp index af9729026..735dd7aae 100644 --- a/src/mbgl/mtl/upload_pass.cpp +++ b/src/mbgl/mtl/upload_pass.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -127,21 +128,21 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe if (auto* rawData = static_cast(vec->getBuffer()); rawData && rawData->resource) { auto& resource = static_cast(*rawData->resource); - // If it's changed, update it + // If the already-allocated buffer is large enough, we can re-use it if (rawBufSize <= resource.getSizeInBytes()) { - if (vec->getDirty()) { + // If the source changed, update the buffer contents + if (vec->isModifiedAfter(resource.getLastUpdated())) { updateVertexBufferResource(resource, rawBufPtr, rawBufSize); - vec->setDirty(false); + resource.setLastUpdated(vec->getLastModified()); } return rawData->resource; } } // Otherwise, create a new one if (rawBufSize > 0) { - auto buffer = std::make_unique(); - buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false); - vec->setBuffer(std::move(buffer)); - vec->setDirty(false); + auto buffer_ = std::make_unique(); + buffer_->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false); + vec->setBuffer(std::move(buffer_)); return static_cast(vec->getBuffer())->resource; } } @@ -156,7 +157,10 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, + const std::chrono::duration /*lastUpdate*/, /*out*/ std::vector>& outBuffers) { + MLN_TRACE_FUNC(); + gfx::AttributeBindingArray bindings; bindings.resize(defaults.allocatedSize()); @@ -187,14 +191,14 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( } // If the attribute references data shared with a bucket, get the corresponding buffer. - if (const auto& buffer = getBuffer(effectiveAttr.getSharedRawData(), usage)) { + if (const auto& buffer_ = getBuffer(effectiveAttr.getSharedRawData(), usage)) { assert(effectiveAttr.getSharedStride() * effectiveAttr.getSharedVertexOffset() < effectiveAttr.getSharedRawData()->getRawSize() * effectiveAttr.getSharedRawData()->getRawCount()); bindings[index] = { /*.attribute = */ {effectiveAttr.getSharedType(), effectiveAttr.getSharedOffset()}, /*.vertexStride = */ effectiveAttr.getSharedStride(), - /*.vertexBufferResource = */ buffer.get(), + /*.vertexBufferResource = */ buffer_.get(), /*.vertexOffset = */ effectiveAttr.getSharedVertexOffset(), }; return; @@ -203,11 +207,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( assert(effectiveAttr.getStride() > 0); // Otherwise, turn the data managed by the attribute into a buffer. - if (const auto& buffer = VertexAttribute::getBuffer(effectiveAttr, *this, gfx::BufferUsageType::StaticDraw)) { + if (const auto& buffer_ = VertexAttribute::getBuffer(effectiveAttr, *this, gfx::BufferUsageType::StaticDraw)) { bindings[index] = { /*.attribute = */ {effectiveAttr.getDataType(), /*offset=*/0}, /*.vertexStride = */ static_cast(effectiveAttr.getStride()), - /*.vertexBufferResource = */ buffer.get(), + /*.vertexBufferResource = */ buffer_.get(), /*.vertexOffset = */ 0, }; return; @@ -215,7 +219,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( assert(false); }; - defaults.resolve(overrides, resolveAttr); + // This version is called when the attribute is available, but isn't being used by the shader + const auto missingAttr = [&](const size_t, auto& missingAttr) -> void { + missingAttr->setDirty(false); + }; + defaults.resolve(overrides, resolveAttr, missingAttr); return bindings; } diff --git a/src/mbgl/mtl/vertex_attribute.cpp b/src/mbgl/mtl/vertex_attribute.cpp index d30feea4b..bb7b923ff 100644 --- a/src/mbgl/mtl/vertex_attribute.cpp +++ b/src/mbgl/mtl/vertex_attribute.cpp @@ -25,6 +25,7 @@ const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAtt attrib.rawData.data(), attrib.rawData.size(), usage, false); attrib.setBuffer(std::move(buffer)); attrib.setRawData({}); + attrib_.setDirty(false); } else { assert(false); } @@ -33,18 +34,5 @@ const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAtt return attrib_.getBuffer(); } -bool VertexAttributeArray::isDirty() const { - return std::any_of(attrs.begin(), attrs.end(), [](const auto& attr) { - if (attr) { - // If we have shared data, the dirty flag from that overrides ours - const auto& attrib = static_cast(*attr); - if (const auto& shared = attrib.getSharedRawData()) { - return shared->getDirty(); - } - } - return attr && attr->isDirty(); - }); -} - } // namespace mtl } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index c2140338d..378370639 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -72,6 +72,9 @@ void CircleBucket::update(const FeatureStates& states, if (it != paintPropertyBinders.end()) { it->second.updateVertexVectors(states, layer, imagePositions); uploaded = false; + + sharedVertices->updateModified(); + sharedTriangles->updateModified(); } } diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index f6048c652..88ae37f04 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -111,6 +111,10 @@ void FillBucket::update(const FeatureStates& states, if (it != paintPropertyBinders.end()) { it->second.updateVertexVectors(states, layer, imagePositions); uploaded = false; + + sharedVertices->updateModified(); + sharedBasicLineIndexes->updateModified(); + sharedTriangles->updateModified(); } } diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index e45ba52a5..58942cfbe 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -204,6 +204,9 @@ void FillExtrusionBucket::update(const FeatureStates& states, if (it != paintPropertyBinders.end()) { it->second.updateVertexVectors(states, layer, imagePositions); uploaded = false; + + sharedVertices->updateModified(); + sharedTriangles->updateModified(); } } diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 5e2825b1b..bf67d23bf 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -166,6 +166,9 @@ void LineBucket::update(const FeatureStates& states, if (it != paintPropertyBinders.end()) { it->second.updateVertexVectors(states, layer, imagePositions); uploaded = false; + + sharedVertices->updateModified(); + sharedTriangles->updateModified(); } } diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index 872e9ed93..2ee049653 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -352,6 +352,12 @@ void SymbolBucket::updateVertices(const Placement& placement, dynamicUploaded = false; uploaded = false; } + + if (!uploaded) { + text.updateModified(); + icon.updateModified(); + sdfIcon.updateModified(); + } } } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index 878b008e0..896eee45e 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -146,6 +146,22 @@ public: sharedDynamicVertices->release(); sharedOpacityVertices->release(); } + + void updateModified() { + if (sharedVertices) { + sharedVertices->updateModified(); + } + if (sharedDynamicVertices) { + sharedDynamicVertices->updateModified(); + } + if (sharedOpacityVertices) { + sharedOpacityVertices->updateModified(); + } + if (sharedTriangles) { + sharedTriangles->updateModified(); + } + } + std::shared_ptr sharedVertices = std::make_shared(); VertexVector& vertices() { return *sharedVertices; } const VertexVector& vertices() const { return *sharedVertices; } diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 4d252a237..8ae01ec29 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -340,7 +340,8 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, [&](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())) { + if (drawable && (bucket.sharedVertices->isModifiedAfter(drawable->createTime) || + bucket.sharedTriangles->isModifiedAfter(drawable->createTime))) { return false; } @@ -447,19 +448,27 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, bool cleared = false; auto& bucket = static_cast(*bucket_); - // If the bucket data has changed, rebuild the drawables. - const bool bucketSharedData = (!bucket.vertices.empty() && !bucket.indices.empty() && - !bucket.segments.empty()); - const bool bucketDirty = bucketSharedData && (bucket.vertices.getDirty() || bucket.indices.getDirty()); - if (bucketDirty) { - // Note, vertex/index dirty flags will be reset when those buffers are uploaded. - removeTile(renderPass, tileID); - cleared = true; - } else if (setRenderTileBucketID(tileID, bucket.getID())) { + if (setRenderTileBucketID(tileID, bucket.getID())) { // Bucket ID changed, we need to rebuild the drawables removeTile(renderPass, tileID); cleared = true; } + // If the bucket data has changed, rebuild the drawables. + else if (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()) { + // Find the earliest time on existing drawables + std::optional> tileUpdateTime; + tileLayerGroup->visitDrawables(renderPass, tileID, [&](const auto& drawable) { + if (!tileUpdateTime || drawable.createTime < *tileUpdateTime) { + tileUpdateTime = drawable.createTime; + } + }); + + if (tileUpdateTime && (bucket.vertices.isModifiedAfter(*tileUpdateTime) || + bucket.indices.isModifiedAfter(*tileUpdateTime))) { + removeTile(renderPass, tileID); + cleared = true; + } + } if (!cleared) { // Update existing drawables diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index f969588da..81b8b4471 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -1344,7 +1344,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, auto drawData = std::make_unique( /*.isHalo=*/isHalo, - /*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement, + /*.bucketVariablePlacement=*/bucket.hasVariablePlacement, /*.symbolType=*/renderable.type, /*.pitchAlignment=*/values.pitchAlignment, /*.rotationAlignment=*/values.rotationAlignment, diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index b98221695..b239f1822 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -320,12 +320,15 @@ public: const FeatureState& state) override { using style::expression::EvaluationContext; - auto evaluated = expression.evaluate(EvaluationContext(&feature).withFeatureState(&state), defaultValue); + const auto evaluated = expression.evaluate(EvaluationContext(&feature).withFeatureState(&state), defaultValue); this->statistics.add(evaluated); - auto value = attributeValue(evaluated); + + const auto value = BaseVertex{attributeValue(evaluated)}; for (std::size_t i = start; i < end; ++i) { - vertexVector.at(i) = BaseVertex{value}; + vertexVector.at(i) = value; } + + vertexVector.updateModified(); } #if MLN_LEGACY_RENDERER @@ -449,17 +452,21 @@ public: const GeometryTileFeature& feature, const FeatureState& state) override { using style::expression::EvaluationContext; - Range range = { + const Range range = { expression.evaluate(EvaluationContext(zoomRange.min, &feature, &state), defaultValue), expression.evaluate(EvaluationContext(zoomRange.max, &feature, &state), defaultValue), }; this->statistics.add(range.min); this->statistics.add(range.max); - AttributeValue value = zoomInterpolatedAttributeValue(attributeValue(range.min), attributeValue(range.max)); + + const Vertex value = Vertex{ + zoomInterpolatedAttributeValue(attributeValue(range.min), attributeValue(range.max))}; for (std::size_t i = start; i < end; ++i) { - vertexVector.at(i) = Vertex{value}; + vertexVector.at(i) = value; } + + vertexVector.updateModified(); } #if MLN_LEGACY_RENDERER diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 5901fc828..00c5ede7b 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -252,6 +252,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Remove render layers for removed layers. for (const auto& entry : layerDiff.removed) { + MLN_TRACE_ZONE(remove layer); const auto hit = renderLayers.find(entry.first); if (hit != renderLayers.end()) { #if MLN_DRAWABLE_RENDERER @@ -263,6 +264,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Create render layers for newly added layers. for (const auto& entry : layerDiff.added) { + MLN_TRACE_ZONE(add layer); auto renderLayer = LayerManager::get()->createRenderLayer(entry.second); renderLayer->transition(transitionParameters); renderLayers.emplace(entry.first, std::move(renderLayer)); @@ -270,6 +272,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Update render layers for changed layers. for (const auto& entry : layerDiff.changed) { + MLN_TRACE_ZONE(change layer); if (const auto& renderLayer = renderLayers.at(entry.first)) { const auto& newLayer = entry.second.after; @@ -305,6 +308,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Update layers for class and zoom changes. std::unordered_set constantsMaskChanged; for (RenderLayer& layer : orderedLayers) { + MLN_TRACE_ZONE(update layer); const std::string& id = layer.getID(); const bool layerAddedOrChanged = layerDiff.added.contains(id) || layerDiff.changed.contains(id); evaluationParameters.layerChanged = layerAddedOrChanged; @@ -335,6 +339,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Create render sources for newly added sources. for (const auto& entry : sourceDiff.added) { + MLN_TRACE_ZONE(create source); std::unique_ptr renderSource = RenderSource::create(entry.second, threadPool); renderSource->setObserver(this); renderSource->enableCache(tileCacheEnabled); @@ -439,6 +444,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( // Prepare. Update all matrices and generate data that we should upload to the GPU. for (const auto& entry : renderSources) { + MLN_TRACE_ZONE(prepare source); if (entry.second->isEnabled()) { entry.second->prepare( {renderTreeParameters->transformParams, updateParameters->debugOptions, *imageManager}); @@ -447,9 +453,8 @@ std::unique_ptr RenderOrchestrator::createRenderTree( auto opaquePassCutOffEstimation = layerRenderItems.size(); for (auto& renderItem : layerRenderItems) { - MLN_TRACE_ZONE(prepare layer) - RenderLayer& renderLayer = renderItem.layer; + MLN_TRACE_ZONE(prepare layer) MLN_ZONE_STR(renderLayer.getID()) renderLayer.prepare( @@ -472,6 +477,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( std::set usedSymbolLayers; const auto longitude = static_cast(updateParameters->transformState.getLatLng().longitude()); for (auto it = layersNeedPlacement.crbegin(); it != layersNeedPlacement.crend(); ++it) { + MLN_TRACE_ZONE(placement layer); RenderLayer& layer = *it; auto result = crossTileSymbolIndex.addLayer(layer, longitude); if (isMapModeContinuous) { @@ -482,7 +488,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( } if (isMapModeContinuous) { - MLN_TRACE_ZONE(placement) + MLN_TRACE_ZONE(placement); std::optional placementUpdatePeriodOverride; if (symbolBucketsAdded && !tiltedView) { @@ -518,7 +524,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( updateParameters->timePoint); renderTreeParameters->needsRepaint = hasTransitions(updateParameters->timePoint); } else { - MLN_TRACE_ZONE(placement) + MLN_TRACE_ZONE(placement); renderTreeParameters->placementChanged = symbolBucketsChanged = !layersNeedPlacement.empty(); if (renderTreeParameters->placementChanged) { @@ -533,6 +539,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( } if (!renderTreeParameters->needsRepaint && renderTreeParameters->loaded) { + MLN_TRACE_ZONE(reduce); // Notify observer about unused images when map is fully loaded // and there are no ongoing transitions. imageManager->reduceMemoryUseIfCacheSizeExceedsLimit(); diff --git a/src/mbgl/renderer/source_state.cpp b/src/mbgl/renderer/source_state.cpp index 1ac0cd8eb..f36d49c5c 100644 --- a/src/mbgl/renderer/source_state.cpp +++ b/src/mbgl/renderer/source_state.cpp @@ -43,7 +43,8 @@ void SourceFeatureState::getState(FeatureState& result, } void SourceFeatureState::coalesceChanges(std::vector& tiles) { - MLN_TRACE_FUNC() + MLN_TRACE_FUNC(); + LayerFeatureStates changes; for (const auto& layerStatesEntry : stateChanges) { const auto& sourceLayer = layerStatesEntry.first; diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index f860e0316..76c9e71dd 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -8,10 +8,11 @@ #include #include #include +#include +#include +#include #include #include -#include -#include namespace mbgl { @@ -89,6 +90,7 @@ std::unique_ptr RenderImageSource::createRenderItem() { } void RenderImageSource::prepare(const SourcePrepareParameters& parameters) { + MLN_TRACE_FUNC(); assert(!renderData); if (!isLoaded()) { renderData = std::make_unique(bucket, std::vector{}, baseImpl->id); diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 05b35df4d..f43c6cad8 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -151,7 +151,7 @@ public: std::optional avoidEdges; }; -// PlacementController implemenation +// PlacementController implementation PlacementController::PlacementController() : placement(makeMutable()) {} @@ -754,12 +754,12 @@ Point calculateVariableRenderShift(style::SymbolAnchorType anchor, std::array textOffset, float textBoxScale, float renderTextSize) { - AnchorAlignment alignment = AnchorAlignment::getAnchorAlignment(anchor); - float shiftX = -(alignment.horizontalAlign - 0.5f) * width; - float shiftY = -(alignment.verticalAlign - 0.5f) * height; - auto variablOffset = SymbolLayout::evaluateVariableOffset(anchor, textOffset); - return {(shiftX / textBoxScale + variablOffset[0]) * renderTextSize, - (shiftY / textBoxScale + variablOffset[1]) * renderTextSize}; + const AnchorAlignment alignment = AnchorAlignment::getAnchorAlignment(anchor); + const float shiftX = -(alignment.horizontalAlign - 0.5f) * width; + const float shiftY = -(alignment.verticalAlign - 0.5f) * height; + const auto variableOffset = SymbolLayout::evaluateVariableOffset(anchor, textOffset); + return {(shiftX / textBoxScale + variableOffset[0]) * renderTextSize, + (shiftY / textBoxScale + variableOffset[1]) * renderTextSize}; } } // namespace diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp index 8fb3f11f4..72c23ad84 100644 --- a/src/mbgl/text/placement.hpp +++ b/src/mbgl/text/placement.hpp @@ -155,7 +155,7 @@ protected: const std::vector& /*textBoxes*/, const std::vector& /*iconBoxes*/ ) {} - // Implentation specific hooks, which get called during a symbol bucket placement. + // Implementation specific hooks, which get called during a symbol bucket placement. virtual std::optional getAvoidEdges(const SymbolBucket&, const mat4& /*posMatrix*/) { return std::nullopt; } diff --git a/src/mbgl/util/thread_pool.hpp b/src/mbgl/util/thread_pool.hpp index be4cf95d4..b16146661 100644 --- a/src/mbgl/util/thread_pool.hpp +++ b/src/mbgl/util/thread_pool.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,7 @@ public: } void runRenderJobs(const util::SimpleIdentity tag, bool closeQueue = false) override { + MLN_TRACE_FUNC(); std::shared_ptr queue; std::unique_lock lock(taggedRenderQueueLock); @@ -130,6 +132,7 @@ public: auto fn = std::move(queue->queue.front()); queue->queue.pop(); if (fn) { + MLN_TRACE_ZONE(render job); fn(); } } diff --git a/src/mbgl/vulkan/buffer_resource.cpp b/src/mbgl/vulkan/buffer_resource.cpp index 26419d5f7..4b9a9bddb 100644 --- a/src/mbgl/vulkan/buffer_resource.cpp +++ b/src/mbgl/vulkan/buffer_resource.cpp @@ -133,7 +133,7 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept { } void BufferResource::update(const void* newData, std::size_t updateSize, std::size_t offset) noexcept { - assert(size >= 0 && updateSize + offset <= size); + assert(updateSize + offset <= size); updateSize = std::min(updateSize, size - offset); if (updateSize <= 0) { return; diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 0eb42011e..30964c3f6 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -116,13 +116,14 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { // We need either raw index data or a buffer already created from them. // We can have a buffer and no indexes, but only if it's not marked dirty. - if (!impl->indexes || (impl->indexes->empty() && (!impl->indexes->getBuffer() || impl->indexes->getDirty()))) { + if (!impl->indexes || (impl->indexes->empty() && + (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)))) { assert(!"Missing index data"); return; } - if (impl->indexes->getDirty()) { - // Create or update a buffer for the index data. We don't update any + if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { + // Create a buffer for the index data. We don't update any // existing buffer because it may still be in use by the previous frame. auto indexBufferResource{uploadPass.createIndexBufferResource( impl->indexes->data(), impl->indexes->bytes(), usage, /*persistent=*/false)}; @@ -131,10 +132,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { auto buffer = std::make_unique(std::move(indexBuffer)); impl->indexes->setBuffer(std::move(buffer)); - impl->indexes->setDirty(false); } - const bool buildAttribs = !vertexAttributes || vertexAttributes->isDirty() || + const bool buildAttribs = !vertexAttributes || vertexAttributes->isModifiedAfter(attributeUpdateTime) || impl->pipelineInfo.inputAttributes.empty(); if (buildAttribs) { @@ -155,6 +155,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { shader->getVertexAttributes(), *vertexAttributes, usage, + attributeUpdateTime, vertexBuffers); vertexAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); }); @@ -165,7 +166,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } // build instance buffer - const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isDirty()); + const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isModifiedAfter(attributeUpdateTime)); if (buildInstanceBuffer) { // Build instance attribute buffers @@ -177,6 +178,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { shader->getInstanceAttributes(), *instanceAttributes, usage, + attributeUpdateTime, instanceBuffers); // clear dirty flag @@ -185,6 +187,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { if (impl->instanceBindings != instanceBindings_) { impl->instanceBindings = std::move(instanceBindings_); } + + attributeUpdateTime = util::MonotonicTimer::now(); } if (buildAttribs || buildInstanceBuffer) { @@ -205,8 +209,8 @@ void Drawable::draw(PaintParameters& parameters) const { } auto& context = static_cast(parameters.context); - auto& renderPass = static_cast(*parameters.renderPass); - auto& encoder = renderPass.getEncoder(); + auto& renderPass_ = static_cast(*parameters.renderPass); + auto& encoder = renderPass_.getEncoder(); auto& commandBuffer = encoder.getCommandBuffer(); auto& shaderImpl = static_cast(*shader); @@ -233,7 +237,7 @@ void Drawable::draw(PaintParameters& parameters) const { } } - impl->pipelineInfo.setRenderable(renderPass.getDescriptor().renderable); + impl->pipelineInfo.setRenderable(renderPass_.getDescriptor().renderable); const uint32_t instances = instanceAttributes ? instanceAttributes->getMaxCount() : 1; @@ -264,17 +268,17 @@ void Drawable::setIndexData(gfx::IndexVectorBasePtr indexes, std::vectorsegments = std::move(segments); } -void Drawable::setVertices(std::vector&& data, std::size_t count, gfx::AttributeDataType type) { +void Drawable::setVertices(std::vector&& data, std::size_t count, gfx::AttributeDataType type_) { impl->vertexCount = count; - impl->vertexType = type; + impl->vertexType = type_; - if (count && type != gfx::AttributeDataType::Invalid && !data.empty()) { + if (count && type_ != gfx::AttributeDataType::Invalid && !data.empty()) { if (!vertexAttributes) { vertexAttributes = std::make_shared(); } - if (auto& attrib = vertexAttributes->set(impl->vertexAttrId, /*index=*/-1, type)) { + if (auto& attrib = vertexAttributes->set(impl->vertexAttrId, /*index=*/-1, type_)) { attrib->setRawData(std::move(data)); - attrib->setStride(VertexAttribute::getStrideOf(type)); + attrib->setStride(VertexAttribute::getStrideOf(type_)); } else { using namespace std::string_literals; Log::Warning(Event::General, @@ -352,9 +356,10 @@ bool Drawable::bindAttributes(CommandEncoder& encoder) const noexcept { commandBuffer->bindVertexBuffers(0, impl->vulkanVertexBuffers, impl->vulkanVertexOffsets); if (impl->indexes) { - const auto* indexBuffer = static_cast(impl->indexes->getBuffer()); - const auto& indexBufferResource = indexBuffer->buffer->getResource().get(); - commandBuffer->bindIndexBuffer(indexBufferResource.getVulkanBuffer(), 0, vk::IndexType::eUint16); + if (const auto* indexBuffer = static_cast(impl->indexes->getBuffer())) { + const auto& indexBufferResource = indexBuffer->buffer->getResource().get(); + commandBuffer->bindIndexBuffer(indexBufferResource.getVulkanBuffer(), 0, vk::IndexType::eUint16); + } } return true; diff --git a/src/mbgl/vulkan/render_pass.cpp b/src/mbgl/vulkan/render_pass.cpp index 5e5624798..3bb40a5bd 100644 --- a/src/mbgl/vulkan/render_pass.cpp +++ b/src/mbgl/vulkan/render_pass.cpp @@ -8,8 +8,8 @@ namespace mbgl { namespace vulkan { -RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const gfx::RenderPassDescriptor& descriptor) - : descriptor(descriptor), +RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const gfx::RenderPassDescriptor& descriptor_) + : descriptor(descriptor_), commandEncoder(commandEncoder_) { auto& resource = descriptor.renderable.getResource(); diff --git a/src/mbgl/vulkan/upload_pass.cpp b/src/mbgl/vulkan/upload_pass.cpp index e41a2f1d3..27441e175 100644 --- a/src/mbgl/vulkan/upload_pass.cpp +++ b/src/mbgl/vulkan/upload_pass.cpp @@ -95,9 +95,9 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe // If it's changed, update it if (rawBufSize <= resource.getSizeInBytes()) { - if (vec->getDirty()) { + if (vec->isModifiedAfter(resource.getLastUpdated())) { updateVertexBufferResource(resource, rawBufPtr, rawBufSize); - vec->setDirty(false); + resource.setLastUpdated(vec->getLastModified()); } return rawData->resource; } @@ -107,7 +107,6 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe auto buffer = std::make_unique(); buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false); vec->setBuffer(std::move(buffer)); - vec->setDirty(false); return static_cast(vec->getBuffer())->resource; } } @@ -122,6 +121,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, + const std::chrono::duration /*lastUpdate*/, /*out*/ std::vector>&) { gfx::AttributeBindingArray bindings; @@ -175,8 +175,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( assert(false); }; - - defaults.resolve(overrides, resolveAttr); + // This version is called when the attribute is available, but isn't being used by the shader + const auto missingAttr = [&](const size_t, auto& attr_) -> void { + attr_->setDirty(false); + }; + defaults.resolve(overrides, resolveAttr, missingAttr); return bindings; } diff --git a/src/mbgl/vulkan/vertex_attribute.cpp b/src/mbgl/vulkan/vertex_attribute.cpp index bba5f69c4..0c99b6a27 100644 --- a/src/mbgl/vulkan/vertex_attribute.cpp +++ b/src/mbgl/vulkan/vertex_attribute.cpp @@ -25,6 +25,7 @@ const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAtt attrib.rawData.data(), attrib.rawData.size(), usage, false); attrib.setBuffer(std::move(buffer)); attrib.setRawData({}); + attrib_.setDirty(false); } else { assert(false); } @@ -33,18 +34,5 @@ const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAtt return attrib_.getBuffer(); } -bool VertexAttributeArray::isDirty() const { - return std::any_of(attrs.begin(), attrs.end(), [](const auto& attr) { - if (attr) { - // If we have shared data, the dirty flag from that overrides ours - const auto& attrib = static_cast(*attr); - if (const auto& shared = attrib.getSharedRawData()) { - return shared->getDirty(); - } - } - return attr && attr->isDirty(); - }); -} - } // namespace vulkan } // namespace mbgl