From 84ca231da5761e32706e8fa50bd568701ce45ae8 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 23 Sep 2024 08:36:00 -0700 Subject: [PATCH] Fix updates hillshade geometry (#2842) --- include/mbgl/gfx/drawable.hpp | 19 +- include/mbgl/gl/drawable_gl.hpp | 7 + include/mbgl/gl/vertex_attribute_gl.hpp | 2 +- include/mbgl/mtl/context.hpp | 3 - include/mbgl/mtl/drawable.hpp | 7 + include/mbgl/mtl/upload_pass.hpp | 6 +- include/mbgl/mtl/vertex_attribute.hpp | 3 +- include/mbgl/vulkan/drawable.hpp | 7 + include/mbgl/vulkan/upload_pass.hpp | 6 +- include/mbgl/vulkan/vertex_attribute.hpp | 3 +- src/mbgl/gfx/upload_pass.hpp | 2 +- src/mbgl/gl/drawable_gl.cpp | 35 +++- src/mbgl/gl/upload_pass.cpp | 2 +- src/mbgl/gl/upload_pass.hpp | 2 +- src/mbgl/gl/vertex_attribute_gl.cpp | 4 +- src/mbgl/mtl/context.cpp | 7 - src/mbgl/mtl/drawable.cpp | 51 ++++-- src/mbgl/mtl/upload_pass.cpp | 12 +- src/mbgl/mtl/vertex_attribute.cpp | 5 +- .../renderer/buckets/hillshade_bucket.cpp | 6 + .../renderer/buckets/hillshade_bucket.hpp | 5 +- src/mbgl/renderer/buckets/raster_bucket.cpp | 3 + .../renderer/layers/render_fill_layer.cpp | 168 ++++++++++-------- .../layers/render_hillshade_layer.cpp | 38 ++-- .../renderer/layers/render_raster_layer.cpp | 3 +- src/mbgl/vulkan/drawable.cpp | 40 ++++- src/mbgl/vulkan/upload_pass.cpp | 12 +- src/mbgl/vulkan/vertex_attribute.cpp | 5 +- 28 files changed, 307 insertions(+), 156 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 034177c9d..11809b1d5 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -25,6 +25,7 @@ class PaintParameters; class PaintPropertyBindersBase; enum class RenderPass : uint8_t; class RenderTile; +class SegmentBase; using LayerTweakerPtr = std::shared_ptr; using RenderTiles = std::shared_ptr>>; @@ -192,7 +193,20 @@ public: const gfx::VertexAttributeArrayPtr& getVertexAttributes() const noexcept { return vertexAttributes; } /// Set vertex attribute array - void setVertexAttributes(gfx::VertexAttributeArrayPtr value) noexcept { vertexAttributes = std::move(value); } + void setVertexAttributes(gfx::VertexAttributeArrayPtr value) noexcept { + vertexAttributes = std::move(value); + // The attribute bindings need to be rebuilt, we can't rely on the update + // time check as these new values may not have been modified recently. + attributeUpdateTime.reset(); + } + + /// Update vertices, indices, and segments + virtual void updateVertexAttributes(gfx::VertexAttributeArrayPtr, + std::size_t vertexCount, + gfx::DrawMode, + gfx::IndexVectorBasePtr, + const SegmentBase* segments, + std::size_t segmentCount) = 0; /// Get the instance attributes const gfx::VertexAttributeArrayPtr& getInstanceAttributes() const noexcept { return instanceAttributes; } @@ -261,6 +275,7 @@ public: void setRenderTile(Immutable>, const RenderTile*); const std::chrono::duration createTime = util::MonotonicTimer::now(); + std::optional> getAttributeUpdateTime() const { return attributeUpdateTime; } protected: bool enabled = true; @@ -282,7 +297,7 @@ protected: UniqueDrawableData drawableData{}; gfx::VertexAttributeArrayPtr vertexAttributes; gfx::VertexAttributeArrayPtr instanceAttributes; - std::chrono::duration attributeUpdateTime = util::MonotonicTimer::now(); + std::optional> attributeUpdateTime; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 6746939c2..f088003dc 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -48,6 +48,13 @@ public: void upload(gfx::UploadPass&); + void updateVertexAttributes(gfx::VertexAttributeArrayPtr, + std::size_t vertexCount, + gfx::DrawMode, + gfx::IndexVectorBasePtr, + const SegmentBase* segments, + std::size_t segmentCount) override; + protected: class Impl; const std::unique_ptr impl; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index f5b895e59..e8216b481 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -35,7 +35,7 @@ public: static const std::vector& getRaw(gfx::VertexAttribute& attr, platform::GLenum, - std::chrono::duration lastUpdate); + std::optional> lastUpdate); private: static int getSize(platform::GLenum glType); diff --git a/include/mbgl/mtl/context.hpp b/include/mbgl/mtl/context.hpp index 99e54e00a..cf1be121e 100644 --- a/include/mbgl/mtl/context.hpp +++ b/include/mbgl/mtl/context.hpp @@ -130,9 +130,6 @@ public: std::size_t size, bool persistent) override; - /// Get an empty buffer to act as a placeholder - const BufferResource& getEmptyBuffer(); - /// Get a reusable buffer containing the standard fixed tile vertices (+/- `util::EXTENT`) const BufferResource& getTileVertexBuffer(); diff --git a/include/mbgl/mtl/drawable.hpp b/include/mbgl/mtl/drawable.hpp index 685da891d..7abc89919 100644 --- a/include/mbgl/mtl/drawable.hpp +++ b/include/mbgl/mtl/drawable.hpp @@ -57,6 +57,13 @@ public: void setSubLayerIndex(int32_t) override; void setDepthType(gfx::DepthMaskType) override; + void updateVertexAttributes(gfx::VertexAttributeArrayPtr, + std::size_t vertexCount, + gfx::DrawMode, + gfx::IndexVectorBasePtr, + const SegmentBase* segments, + std::size_t segmentCount) override; + protected: // For testing only. Drawable(std::unique_ptr); diff --git a/include/mbgl/mtl/upload_pass.hpp b/include/mbgl/mtl/upload_pass.hpp index 676cf57de..99598529a 100644 --- a/include/mbgl/mtl/upload_pass.hpp +++ b/include/mbgl/mtl/upload_pass.hpp @@ -56,7 +56,9 @@ public: void updateResource(BufferResource&, const void* data, std::size_t size); - const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, gfx::BufferUsageType); + const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, + gfx::BufferUsageType, + bool forceUpdate); gfx::AttributeBindingArray buildAttributeBindings( const std::size_t vertexCount, @@ -66,7 +68,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - const std::chrono::duration lastUpdate, + const std::optional> 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 625714107..49c0c65fc 100644 --- a/include/mbgl/mtl/vertex_attribute.hpp +++ b/include/mbgl/mtl/vertex_attribute.hpp @@ -22,7 +22,8 @@ public: static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&, UploadPass&, - const gfx::BufferUsageType); + const gfx::BufferUsageType, + bool forceUpdate); }; /// Stores a collection of vertex attributes by name diff --git a/include/mbgl/vulkan/drawable.hpp b/include/mbgl/vulkan/drawable.hpp index 92bf8aaf9..9ed2c2982 100644 --- a/include/mbgl/vulkan/drawable.hpp +++ b/include/mbgl/vulkan/drawable.hpp @@ -44,6 +44,13 @@ public: void setLineWidth(int32_t value) override; void setCullFaceMode(const gfx::CullFaceMode&) override; + void updateVertexAttributes(gfx::VertexAttributeArrayPtr, + std::size_t vertexCount, + gfx::DrawMode, + gfx::IndexVectorBasePtr, + const SegmentBase* segments, + std::size_t segmentCount) override; + protected: void buildVulkanInputBindings() noexcept; diff --git a/include/mbgl/vulkan/upload_pass.hpp b/include/mbgl/vulkan/upload_pass.hpp index abbc9d247..5a9a0232c 100644 --- a/include/mbgl/vulkan/upload_pass.hpp +++ b/include/mbgl/vulkan/upload_pass.hpp @@ -51,7 +51,9 @@ public: bool persistent) override; void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override; - const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, gfx::BufferUsageType); + const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, + gfx::BufferUsageType, + bool forceUpdate); gfx::AttributeBindingArray buildAttributeBindings( const std::size_t vertexCount, @@ -61,7 +63,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - const std::chrono::duration lastUpdate, + const std::optional> 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 f830366a4..b1ecb4ab8 100644 --- a/include/mbgl/vulkan/vertex_attribute.hpp +++ b/include/mbgl/vulkan/vertex_attribute.hpp @@ -23,7 +23,8 @@ public: static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&, UploadPass&, - const gfx::BufferUsageType); + const gfx::BufferUsageType, + bool forceUpdate); }; /// Stores a collection of vertex attributes by name diff --git a/src/mbgl/gfx/upload_pass.hpp b/src/mbgl/gfx/upload_pass.hpp index 92fcd3bec..f70b432fe 100644 --- a/src/mbgl/gfx/upload_pass.hpp +++ b/src/mbgl/gfx/upload_pass.hpp @@ -87,7 +87,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - const std::chrono::duration lastUpdate, + const std::optional> lastUpdate, /*out*/ std::vector>& outBuffers) = 0; #endif diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index b034b4f8e..80404029a 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -86,6 +86,36 @@ void DrawableGL::setIndexData(gfx::IndexVectorBasePtr indexes, std::vectorsegments = std::move(segments); } +void DrawableGL::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, + std::size_t vertexCount, + gfx::DrawMode mode, + gfx::IndexVectorBasePtr indexes, + const SegmentBase* segments, + std::size_t segmentCount) { + gfx::Drawable::setVertexAttributes(std::move(vertices)); + impl->vertexCount = vertexCount; + + std::vector> drawSegs; + drawSegs.reserve(segmentCount); + for (std::size_t i = 0; i < segmentCount; ++i) { + const auto& seg = segments[i]; + auto segCopy = SegmentBase{ + // no copy constructor + seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.sortKey, + }; + auto drawSeg = std::make_unique( + mode, std::move(segCopy), VertexArray{{nullptr, false}}); + drawSegs.push_back(std::move(drawSeg)); + } + + impl->indexes = std::move(indexes); + impl->segments = std::move(drawSegs); +} + void DrawableGL::setVertices(std::vector&& data, std::size_t count, gfx::AttributeDataType type_) { impl->vertexData = std::move(data); impl->vertexCount = count; @@ -166,7 +196,8 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { if (impl->indexes) { impl->indexes->updateModified(); } - if (impl->indexes && (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime))) { + if (impl->indexes && + (!impl->indexes->getBuffer() || !attributeUpdateTime || impl->indexes->isModifiedAfter(*attributeUpdateTime))) { MLN_TRACE_ZONE(build indexes); auto indexBufferResource{ uploadPass.createIndexBufferResource(impl->indexes->data(), impl->indexes->bytes(), usage)}; @@ -178,7 +209,7 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { // Build the vertex attributes and bindings, if necessary if (impl->attributeBindings.empty() || - (vertexAttributes && vertexAttributes->isModifiedAfter(attributeUpdateTime))) { + (vertexAttributes && (!attributeUpdateTime || vertexAttributes->isModifiedAfter(*attributeUpdateTime)))) { MLN_TRACE_ZONE(build attributes); // Apply drawable values to shader defaults diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 3f6f7933f..8243675ff 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -193,7 +193,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, - const std::chrono::duration lastUpdate, + const std::optional> lastUpdate, /*out*/ std::vector>& outBuffers) { MLN_TRACE_FUNC(); AttributeBindingArray bindings; diff --git a/src/mbgl/gl/upload_pass.hpp b/src/mbgl/gl/upload_pass.hpp index a1d1cfb2c..4c6a38c7d 100644 --- a/src/mbgl/gl/upload_pass.hpp +++ b/src/mbgl/gl/upload_pass.hpp @@ -56,7 +56,7 @@ public: const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, gfx::BufferUsageType, - const std::chrono::duration lastUpdate, + const std::optional> lastUpdate, /*out*/ std::vector>& outBuffers) override; #endif diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index 5fbb3d65d..abd8740fd 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -155,11 +155,11 @@ std::size_t VertexAttributeGL::getStride() const { const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, platform::GLenum type, - std::chrono::duration lastUpdate) { + std::optional> lastUpdate) { const auto count = attr.getCount(); const auto stride_ = getStride(type); auto& rawData = attr.getRawData(); - if (attr.isModifiedAfter(lastUpdate) || rawData.size() != count * stride_) { + if (!lastUpdate || attr.isModifiedAfter(*lastUpdate) || rawData.size() != count * stride_) { rawData.resize(stride_ * count); if (!rawData.empty()) { diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index 2710b9cc8..60a035162 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -241,13 +241,6 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, } } -const BufferResource& Context::getEmptyBuffer() { - if (!emptyBuffer) { - emptyBuffer.emplace(const_cast(*this), nullptr, 0, MTL::ResourceStorageModeShared, false, false); - } - return *emptyBuffer; -} - const BufferResource& Context::getTileVertexBuffer() { if (!tileVertexBuffer) { const auto vertices = RenderStaticData::tileVertices(); diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 2cc8d6174..90caacc9b 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->isModifiedAfter(attributeUpdateTime)) { + if (!impl->indexes->getBuffer() || !attributeUpdateTime || impl->indexes->isModifiedAfter(*attributeUpdateTime)) { assert(!"Index buffer not uploaded"); return; } const auto* indexBuffer = getMetalBuffer(impl->indexes); - if (!indexBuffer || impl->indexes->isModifiedAfter(attributeUpdateTime)) { + if (!indexBuffer || !attributeUpdateTime || impl->indexes->isModifiedAfter(*attributeUpdateTime)) { assert(!"Index buffer not uploaded"); return; } @@ -341,6 +341,34 @@ void Drawable::setVertices(std::vector&& data, std::size_t count, gfx:: } } +void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, + std::size_t vertexCount, + gfx::DrawMode mode, + gfx::IndexVectorBasePtr indexes, + const SegmentBase* segments, + std::size_t segmentCount) { + gfx::Drawable::setVertexAttributes(std::move(vertices)); + impl->vertexCount = vertexCount; + + std::vector drawSegs; + drawSegs.reserve(segmentCount); + for (std::size_t i = 0; i < segmentCount; ++i) { + const auto& seg = segments[i]; + auto segCopy = SegmentBase{ + // no copy constructor + seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.sortKey, + }; + drawSegs.push_back(std::make_unique(mode, std::move(segCopy))); + } + + impl->indexes = std::move(indexes); + impl->segments = std::move(drawSegs); +} + const gfx::UniformBufferArray& Drawable::getUniformBuffers() const { return impl->uniformBuffers; } @@ -363,9 +391,6 @@ void Drawable::bindAttributes(RenderPass& renderPass) const noexcept { if (buffer && buffer->get()) { assert(binding->vertexStride * impl->vertexCount <= getBufferSize(binding->vertexBufferResource)); renderPass.bindVertex(buffer->get(), /*offset=*/0, attributeIndex); - } else { - auto& context = renderPass.getCommandEncoder().getContext(); - renderPass.bindVertex(context.getEmptyBuffer(), /*offset=*/0, attributeIndex); } attributeIndex += 1; } @@ -380,9 +405,6 @@ void Drawable::bindInstanceAttributes(RenderPass& renderPass) const noexcept { const auto* buffer = static_cast(binding->vertexBufferResource); if (buffer && buffer->get()) { renderPass.bindVertex(buffer->get(), /*offset=*/0, attributeIndex); - } else { - auto& context = renderPass.getCommandEncoder().getContext(); - renderPass.bindVertex(context.getEmptyBuffer(), /*offset=*/0, attributeIndex); } } attributeIndex += 1; @@ -530,13 +552,13 @@ 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->isModifiedAfter(attributeUpdateTime)))) { + if (!impl->indexes || (impl->indexes->empty() && (!impl->indexes->getBuffer() || !attributeUpdateTime || + impl->indexes->isModifiedAfter(*attributeUpdateTime)))) { assert(!"Missing index data"); return; } - if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { + if (!impl->indexes->getBuffer() || !attributeUpdateTime || 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( @@ -548,8 +570,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { impl->indexes->setBuffer(std::move(buffer)); } - const bool buildAttribs = !vertexAttributes || vertexAttributes->isModifiedAfter(attributeUpdateTime) || - !impl->vertexDesc; + const bool buildAttribs = !impl->vertexDesc || !vertexAttributes || !attributeUpdateTime || + vertexAttributes->isModifiedAfter(*attributeUpdateTime); if (buildAttribs) { #if !defined(NDEBUG) @@ -630,7 +652,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } // build instance buffer - const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isModifiedAfter(attributeUpdateTime)); + const bool buildInstanceBuffer = + (instanceAttributes && (!attributeUpdateTime || instanceAttributes->isModifiedAfter(*attributeUpdateTime))); if (buildInstanceBuffer) { // Build instance attribute buffers diff --git a/src/mbgl/mtl/upload_pass.cpp b/src/mbgl/mtl/upload_pass.cpp index 735dd7aae..f003e0614 100644 --- a/src/mbgl/mtl/upload_pass.cpp +++ b/src/mbgl/mtl/upload_pass.cpp @@ -119,7 +119,8 @@ namespace { const std::unique_ptr noBuffer; } const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec, - const gfx::BufferUsageType usage) { + const gfx::BufferUsageType usage, + bool forceUpdate) { if (vec) { const auto* rawBufPtr = vec->getRawData(); const auto rawBufSize = vec->getRawCount() * vec->getRawSize(); @@ -131,7 +132,7 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe // If the already-allocated buffer is large enough, we can re-use it if (rawBufSize <= resource.getSizeInBytes()) { // If the source changed, update the buffer contents - if (vec->isModifiedAfter(resource.getLastUpdated())) { + if (forceUpdate || vec->isModifiedAfter(resource.getLastUpdated())) { updateVertexBufferResource(resource, rawBufPtr, rawBufSize); resource.setLastUpdated(vec->getLastModified()); } @@ -157,7 +158,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, - const std::chrono::duration /*lastUpdate*/, + const std::optional> lastUpdate, /*out*/ std::vector>& outBuffers) { MLN_TRACE_FUNC(); @@ -191,7 +192,7 @@ 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, !lastUpdate)) { assert(effectiveAttr.getSharedStride() * effectiveAttr.getSharedVertexOffset() < effectiveAttr.getSharedRawData()->getRawSize() * effectiveAttr.getSharedRawData()->getRawCount()); @@ -207,7 +208,8 @@ 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, !lastUpdate)) { bindings[index] = { /*.attribute = */ {effectiveAttr.getDataType(), /*offset=*/0}, /*.vertexStride = */ static_cast(effectiveAttr.getStride()), diff --git a/src/mbgl/mtl/vertex_attribute.cpp b/src/mbgl/mtl/vertex_attribute.cpp index bb7b923ff..bdd5ea435 100644 --- a/src/mbgl/mtl/vertex_attribute.cpp +++ b/src/mbgl/mtl/vertex_attribute.cpp @@ -14,11 +14,12 @@ namespace mtl { const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAttribute& attrib_, UploadPass& uploadPass, - const gfx::BufferUsageType usage) { + const gfx::BufferUsageType usage, + bool forceUpdate) { if (!attrib_.getBuffer()) { auto& attrib = static_cast(attrib_); if (attrib.sharedRawData) { - return uploadPass.getBuffer(attrib.sharedRawData, usage); + return uploadPass.getBuffer(attrib.sharedRawData, usage, forceUpdate); } else { if (!attrib.rawData.empty()) { auto buffer = uploadPass.createVertexBufferResource( diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.cpp b/src/mbgl/renderer/buckets/hillshade_bucket.cpp index f66cdd873..dd020479a 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.cpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.cpp @@ -56,6 +56,9 @@ void HillshadeBucket::clear() { vertices.clear(); indices.clear(); + vertices.updateModified(); + indices.updateModified(); + uploaded = false; } @@ -116,6 +119,9 @@ void HillshadeBucket::setMask(TileMask&& mask_) { segment.vertexLength += vertexLength; segment.indexLength += 6; } + + vertices.updateModified(); + indices.updateModified(); } bool HillshadeBucket::hasData() const { diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.hpp b/src/mbgl/renderer/buckets/hillshade_bucket.hpp index 202642228..4a9ae5dde 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.hpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.hpp @@ -49,7 +49,10 @@ public: std::shared_ptr sharedVertices = std::make_shared(); VertexVector& vertices = *sharedVertices; - gfx::IndexVector indices; + using IndexVector = gfx::IndexVector; + std::shared_ptr sharedIndices = std::make_shared(); + IndexVector& indices = *sharedIndices; + SegmentVector segments; #if MLN_LEGACY_RENDERER diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp index 07bd109f2..b7073f5df 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.cpp +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -46,6 +46,9 @@ void RasterBucket::clear() { vertices.clear(); indices.clear(); + vertices.updateModified(); + indices.updateModified(); + uploaded = false; } diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 853292d6e..effd117bc 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -351,6 +351,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, const auto layerPrefix = getID() + "/"; constexpr auto renderPass = RenderPass::Translucent; + constexpr auto lineWidth = 2.0f; const auto commonInit = [&](gfx::DrawableBuilder& builder) { builder.setCullFaceMode(gfx::CullFaceMode::disabled()); @@ -415,7 +416,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, vertexAttrs->readDataDrivenPaintProperties( binders, evaluated, propertiesAsUniforms, idFillColorVertexAttribute); - const auto vertexCount = bucket.vertices.elements(); + const auto fillVertexCount = bucket.vertices.elements(); if (const auto& attr = vertexAttrs->set(idFillPosVertexAttribute)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillLayoutVertex, a1), @@ -424,27 +425,91 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } +#if MLN_TRIANGULATE_FILL_OUTLINES + const auto lineVertexCount = bucket.lineVertices.elements(); + const auto getTriangulatedAttributes = [&]() { + auto attrs = context.createVertexAttributeArray(); + if (const auto& attr = attrs->set(idLinePosNormalVertexAttribute)) { + attr->setSharedRawData(bucket.sharedLineVertices, + offsetof(LineLayoutVertex, a1), + /*vertexOffset=*/0, + sizeof(LineLayoutVertex), + gfx::AttributeDataType::Short2); + } + if (const auto& attr = attrs->set(idLineDataVertexAttribute)) { + attr->setSharedRawData(bucket.sharedLineVertices, + offsetof(LineLayoutVertex, a2), + /*vertexOffset=*/0, + sizeof(LineLayoutVertex), + gfx::AttributeDataType::UByte4); + } + return attrs; + }; +#endif + // If we already have drawables for this tile, update them. auto updateExisting = [&](gfx::Drawable& drawable) { if (drawable.getLayerTweaker() != layerTweaker) { // This drawable was produced on a previous style/bucket, and should not be updated. return false; } - drawable.setVertexAttributes(vertexAttrs); + + switch (static_cast(drawable.getType())) { + case FillVariant::Fill: + case FillVariant::FillPattern: + drawable.updateVertexAttributes(vertexAttrs, + fillVertexCount, + gfx::Triangles(), + bucket.sharedTriangles, + bucket.triangleSegments.data(), + bucket.triangleSegments.size()); + break; + case FillVariant::FillOutline: + case FillVariant::FillOutlinePattern: + drawable.updateVertexAttributes(vertexAttrs, + fillVertexCount, + gfx::Lines(lineWidth), + bucket.sharedBasicLineIndexes, + bucket.basicLineSegments.data(), + bucket.basicLineSegments.size()); + break; +#if MLN_TRIANGULATE_FILL_OUTLINES + case FillVariant::FillOutlineTriangulated: + if (const auto updated = drawable.getAttributeUpdateTime(); + !updated || bucket.lineVertices.getLastModified() > *updated) { + drawable.updateVertexAttributes(getTriangulatedAttributes(), + lineVertexCount, + gfx::Triangles(), + bucket.sharedLineIndexes, + bucket.lineSegments.data(), + bucket.lineSegments.size()); + } + break; +#endif + default: + Log::Error(Event::General, "Invalid fill type " + util::toString(drawable.getType())); + assert(false); + return false; + } + return true; }; if (updateTile(renderPass, tileID, std::move(updateExisting))) { continue; } - const auto addDrawable = [&](std::unique_ptr drawable, FillVariant type) { - drawable->setTileID(tileID); - drawable->setType(static_cast(type)); - drawable->setLayerTweaker(layerTweaker); - drawable->setBinders(renderData->bucket, &binders); - drawable->setRenderTile(renderTilesOwner, &tile); - fillTileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); - ++stats.drawablesAdded; + const auto finish = [&](gfx::DrawableBuilder& builder, FillVariant type) { + builder.flush(context); + + for (auto& drawable : builder.clearDrawables()) { + drawable->setTileID(tileID); + drawable->setType(static_cast(type)); + drawable->setLayerTweaker(layerTweaker); + drawable->setBinders(renderData->bucket, &binders); + drawable->setRenderTile(renderTilesOwner, &tile); + fillTileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); + ++stats.drawablesAdded; + } }; // Outline always occurs in translucent pass, defaults to fill color @@ -475,36 +540,15 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, : nullptr; auto createOutlineTriangulated = [&](auto& builder) { - if (doOutline && builder && bucket.sharedLineIndexes->elements()) { + if (doOutline && builder && lineVertexCount) { builder->setShader(outlineTriangulatedShader); - builder->setRawVertices({}, bucket.lineVertices.elements(), gfx::AttributeDataType::Short2); - - auto attrs = context.createVertexAttributeArray(); - if (const auto& attr = attrs->set(idLinePosNormalVertexAttribute)) { - attr->setSharedRawData(bucket.sharedLineVertices, - offsetof(LineLayoutVertex, a1), - /*vertexOffset=*/0, - sizeof(LineLayoutVertex), - gfx::AttributeDataType::Short2); - } - if (const auto& attr = attrs->set(idLineDataVertexAttribute)) { - attr->setSharedRawData(bucket.sharedLineVertices, - offsetof(LineLayoutVertex, a2), - /*vertexOffset=*/0, - sizeof(LineLayoutVertex), - gfx::AttributeDataType::UByte4); - } - builder->setVertexAttributes(std::move(attrs)); - + builder->setRawVertices({}, lineVertexCount, gfx::AttributeDataType::Short2); + builder->setVertexAttributes(getTriangulatedAttributes()); builder->setSegments(gfx::Triangles(), bucket.sharedLineIndexes, bucket.lineSegments.data(), bucket.lineSegments.size()); - - builder->flush(context); - for (auto& drawable : builder->clearDrawables()) { - addDrawable(std::move(drawable), FillVariant::FillOutlineTriangulated); - } + finish(*builder, FillVariant::FillOutlineTriangulated); } }; #endif @@ -531,7 +575,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) { commonInit(*builder); builder->setDepthType(gfx::DepthMaskType::ReadOnly); - builder->setLineWidth(2.0f); + builder->setLineWidth(lineWidth); builder->setSubLayerIndex(unevaluated.get().isUndefined() ? 2 : 0); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setRenderPass(RenderPass::Translucent); @@ -539,32 +583,20 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } } - const auto finish = [&](gfx::DrawableBuilder& builder, FillVariant type) { - builder.flush(context); - - for (auto& drawable : builder.clearDrawables()) { - addDrawable(std::move(drawable), type); - } - }; - if (fillBuilder && bucket.sharedTriangles->elements()) { fillBuilder->setShader(fillShader); #if MLN_TRIANGULATE_FILL_OUTLINES if (doOutline && dataDrivenOutline && outlineBuilder) { - fillBuilder->setVertexAttributes(vertexAttrs); - outlineBuilder->setVertexAttributes(std::move(vertexAttrs)); - } else { - fillBuilder->setVertexAttributes(std::move(vertexAttrs)); + outlineBuilder->setVertexAttributes(vertexAttrs); } #else if (doOutline && outlineBuilder) { - fillBuilder->setVertexAttributes(vertexAttrs); - outlineBuilder->setVertexAttributes(std::move(vertexAttrs)); - } else { - fillBuilder->setVertexAttributes(std::move(vertexAttrs)); + outlineBuilder->setVertexAttributes(vertexAttrs); } #endif - fillBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); + fillBuilder->setVertexAttributes(std::move(vertexAttrs)); + + fillBuilder->setRawVertices({}, fillVertexCount, gfx::AttributeDataType::Short2); fillBuilder->setSegments(gfx::Triangles(), bucket.sharedTriangles, bucket.triangleSegments.data(), @@ -580,8 +612,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } else { if (bucket.sharedBasicLineIndexes->elements()) { outlineBuilder->setShader(outlineShader); - outlineBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); - outlineBuilder->setSegments(gfx::Lines(2), + outlineBuilder->setRawVertices({}, fillVertexCount, gfx::AttributeDataType::Short2); + outlineBuilder->setSegments(gfx::Lines(lineWidth), bucket.sharedBasicLineIndexes, bucket.basicLineSegments.data(), bucket.basicLineSegments.size()); @@ -592,8 +624,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, #else if (doOutline && outlineBuilder && bucket.sharedBasicLineIndexes->elements()) { outlineBuilder->setShader(outlineShader); - outlineBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); - outlineBuilder->setSegments(gfx::Lines(2), + outlineBuilder->setRawVertices({}, fillVertexCount, gfx::AttributeDataType::Short2); + outlineBuilder->setSegments(gfx::Lines(lineWidth), bucket.sharedBasicLineIndexes, bucket.basicLineSegments.data(), bucket.basicLineSegments.size()); @@ -632,7 +664,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) { commonInit(*builder); builder->setShader(outlineShader); - builder->setLineWidth(2.0f); + builder->setLineWidth(lineWidth); builder->setDepthType(gfx::DepthMaskType::ReadOnly); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setSubLayerIndex(2); @@ -650,24 +682,14 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, outlinePatternBuilder->addTweaker(getAtlasTweaker()); } - const auto finish = [&](gfx::DrawableBuilder& builder, FillVariant type) { - builder.flush(context); - - for (auto& drawable : builder.clearDrawables()) { - addDrawable(std::move(drawable), type); - } - }; - if (patternBuilder && bucket.sharedTriangles->elements()) { patternBuilder->setShader(fillShader); patternBuilder->setRenderPass(renderPass); if (doOutline && outlinePatternBuilder) { - patternBuilder->setVertexAttributes(vertexAttrs); - outlinePatternBuilder->setVertexAttributes(std::move(vertexAttrs)); - } else { - patternBuilder->setVertexAttributes(std::move(vertexAttrs)); + outlinePatternBuilder->setVertexAttributes(vertexAttrs); } - patternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); + patternBuilder->setVertexAttributes(std::move(vertexAttrs)); + patternBuilder->setRawVertices({}, fillVertexCount, gfx::AttributeDataType::Short2); patternBuilder->setSegments(gfx::Triangles(), bucket.sharedTriangles, bucket.triangleSegments.data(), @@ -679,8 +701,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, if (doOutline && outlinePatternBuilder && bucket.sharedBasicLineIndexes->elements()) { outlinePatternBuilder->setShader(outlineShader); outlinePatternBuilder->setRenderPass(renderPass); - outlinePatternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); - outlinePatternBuilder->setSegments(gfx::Lines(2), + outlinePatternBuilder->setRawVertices({}, fillVertexCount, gfx::AttributeDataType::Short2); + outlinePatternBuilder->setSegments(gfx::Lines(lineWidth), bucket.sharedBasicLineIndexes, bucket.basicLineSegments.data(), bucket.basicLineSegments.size()); diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 6e8b4ef2c..d3b8fdfb2 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -450,17 +450,22 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, } // Set up tile drawable - auto vertices = staticDataSharedVertices; - auto* indices = &staticDataIndices; + std::shared_ptr vertices; + std::shared_ptr> indices; auto* segments = &staticDataSegments; if (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()) { vertices = bucket.sharedVertices; - indices = &bucket.indices; + indices = bucket.sharedIndices; segments = &bucket.segments; + } else { + vertices = staticDataSharedVertices; + indices = std::make_shared>(staticDataIndices); } - hillshadeBuilder = context.createDrawableBuilder("hillshade"); + if (!hillshadeBuilder) { + hillshadeBuilder = context.createDrawableBuilder("hillshade"); + } gfx::VertexAttributeArrayPtr hillshadeVertexAttrs; auto buildVertexAttributes = [&] { @@ -492,25 +497,14 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, return false; } - drawable.setVertexAttributes(buildVertexAttributes()); - drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); - - // Rebuild segments, since they're not shared. - std::vector> drawSegments; - drawSegments.reserve(segments->size()); - for (const auto& seg : *segments) { - auto segCopy = SegmentBase{ - // no copy constructor - seg.vertexOffset, - seg.indexOffset, - seg.vertexLength, - seg.indexLength, - seg.sortKey, - }; - drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy))); - } - drawable.setIndexData(indices->vector(), std::move(drawSegments)); + drawable.updateVertexAttributes(buildVertexAttributes(), + vertices->elements(), + gfx::Triangles(), + std::move(indices), + segments->data(), + segments->size()); drawable.setTexture(bucket.renderTarget->getTexture(), idHillshadeImageTexture); + return true; }; if (updateTile(renderPass, tileID, std::move(updateExisting))) { diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 8ae01ec29..a639c3e47 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -377,7 +377,8 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, assert(!!drawable ^ !!builder); if (drawable) { - drawable->setVertexAttributes(vertexAttrs); + drawable->updateVertexAttributes( + vertexAttrs, vertices->elements(), gfx::Triangles(), indices, segments->data(), segments->size()); } else if (builder) { builder->setVertexAttributes(vertexAttrs); builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 2ca9b4605..b310edf8f 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -100,6 +100,34 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& mode) { impl->pipelineInfo.setCullMode(mode); } +void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, + std::size_t vertexCount, + gfx::DrawMode mode, + gfx::IndexVectorBasePtr indexes, + const SegmentBase* segments, + std::size_t segmentCount) { + gfx::Drawable::setVertexAttributes(std::move(vertices)); + impl->vertexCount = vertexCount; + + std::vector> drawSegs; + drawSegs.reserve(segmentCount); + for (std::size_t i = 0; i < segmentCount; ++i) { + const auto& seg = segments[i]; + auto segCopy = SegmentBase{ + // no copy constructor + seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.sortKey, + }; + drawSegs.push_back(std::make_unique(mode, std::move(segCopy))); + } + + impl->indexes = std::move(indexes); + impl->segments = std::move(drawSegs); +} + void Drawable::upload(gfx::UploadPass& uploadPass_) { if (isCustom) { return; @@ -116,13 +144,13 @@ 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->isModifiedAfter(attributeUpdateTime)))) { + if (!impl->indexes || (impl->indexes->empty() && (!impl->indexes->getBuffer() || !attributeUpdateTime || + impl->indexes->isModifiedAfter(*attributeUpdateTime)))) { assert(!"Missing index data"); return; } - if (!impl->indexes->getBuffer() || impl->indexes->isModifiedAfter(attributeUpdateTime)) { + if (!impl->indexes->getBuffer() || !attributeUpdateTime || 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( @@ -134,7 +162,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { impl->indexes->setBuffer(std::move(buffer)); } - const bool buildAttribs = !vertexAttributes || vertexAttributes->isModifiedAfter(attributeUpdateTime) || + const bool buildAttribs = !vertexAttributes || !attributeUpdateTime || + vertexAttributes->isModifiedAfter(*attributeUpdateTime) || impl->pipelineInfo.inputAttributes.empty(); if (buildAttribs) { @@ -166,7 +195,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } // build instance buffer - const bool buildInstanceBuffer = (instanceAttributes && instanceAttributes->isModifiedAfter(attributeUpdateTime)); + const bool buildInstanceBuffer = + (instanceAttributes && (!attributeUpdateTime || instanceAttributes->isModifiedAfter(*attributeUpdateTime))); if (buildInstanceBuffer) { // Build instance attribute buffers diff --git a/src/mbgl/vulkan/upload_pass.cpp b/src/mbgl/vulkan/upload_pass.cpp index 27441e175..57b05eb64 100644 --- a/src/mbgl/vulkan/upload_pass.cpp +++ b/src/mbgl/vulkan/upload_pass.cpp @@ -84,7 +84,8 @@ struct VertexBuffer : public gfx::VertexBufferBase { static const std::unique_ptr noBuffer; const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec, - const gfx::BufferUsageType usage) { + const gfx::BufferUsageType usage, + bool forceUpdate) { if (vec) { const auto* rawBufPtr = vec->getRawData(); const auto rawBufSize = vec->getRawCount() * vec->getRawSize(); @@ -95,7 +96,7 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe // If it's changed, update it if (rawBufSize <= resource.getSizeInBytes()) { - if (vec->isModifiedAfter(resource.getLastUpdated())) { + if (forceUpdate || vec->isModifiedAfter(resource.getLastUpdated())) { updateVertexBufferResource(resource, rawBufPtr, rawBufSize); resource.setLastUpdated(vec->getLastModified()); } @@ -121,7 +122,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, const gfx::BufferUsageType usage, - const std::chrono::duration /*lastUpdate*/, + const std::optional> lastUpdate, /*out*/ std::vector>&) { gfx::AttributeBindingArray bindings; @@ -147,7 +148,7 @@ 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, !lastUpdate)) { assert(effectiveAttr.getSharedStride() * effectiveAttr.getSharedVertexOffset() < effectiveAttr.getSharedRawData()->getRawSize() * effectiveAttr.getSharedRawData()->getRawCount()); @@ -163,7 +164,8 @@ 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, !lastUpdate)) { bindings[index] = { /*.attribute = */ {effectiveAttr.getDataType(), /*offset=*/0}, /*.vertexStride = */ static_cast(effectiveAttr.getStride()), diff --git a/src/mbgl/vulkan/vertex_attribute.cpp b/src/mbgl/vulkan/vertex_attribute.cpp index 0c99b6a27..5515efe8c 100644 --- a/src/mbgl/vulkan/vertex_attribute.cpp +++ b/src/mbgl/vulkan/vertex_attribute.cpp @@ -14,11 +14,12 @@ namespace vulkan { const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAttribute& attrib_, UploadPass& uploadPass, - const gfx::BufferUsageType usage) { + const gfx::BufferUsageType usage, + bool forceUpdate) { if (!attrib_.getBuffer()) { auto& attrib = static_cast(attrib_); if (attrib.sharedRawData) { - return uploadPass.getBuffer(attrib.sharedRawData, usage); + return uploadPass.getBuffer(attrib.sharedRawData, usage, forceUpdate); } else { if (!attrib.rawData.empty()) { auto buffer = uploadPass.createVertexBufferResource(