Skip to content

Commit

Permalink
Fix updates hillshade geometry (#2842)
Browse files Browse the repository at this point in the history
  • Loading branch information
TimSylvester authored Sep 23, 2024
1 parent cadb8d1 commit 84ca231
Show file tree
Hide file tree
Showing 28 changed files with 307 additions and 156 deletions.
19 changes: 17 additions & 2 deletions include/mbgl/gfx/drawable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PaintParameters;
class PaintPropertyBindersBase;
enum class RenderPass : uint8_t;
class RenderTile;
class SegmentBase;

using LayerTweakerPtr = std::shared_ptr<LayerTweaker>;
using RenderTiles = std::shared_ptr<const std::vector<std::reference_wrapper<const RenderTile>>>;
Expand Down Expand Up @@ -192,7 +193,20 @@ class Drawable {
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; }
Expand Down Expand Up @@ -261,6 +275,7 @@ class Drawable {
void setRenderTile(Immutable<std::vector<RenderTile>>, const RenderTile*);

const std::chrono::duration<double> createTime = util::MonotonicTimer::now();
std::optional<std::chrono::duration<double>> getAttributeUpdateTime() const { return attributeUpdateTime; }

protected:
bool enabled = true;
Expand All @@ -282,7 +297,7 @@ class Drawable {
UniqueDrawableData drawableData{};
gfx::VertexAttributeArrayPtr vertexAttributes;
gfx::VertexAttributeArrayPtr instanceAttributes;
std::chrono::duration<double> attributeUpdateTime = util::MonotonicTimer::now();
std::optional<std::chrono::duration<double>> attributeUpdateTime;

struct Impl;
std::unique_ptr<Impl> impl;
Expand Down
7 changes: 7 additions & 0 deletions include/mbgl/gl/drawable_gl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ class DrawableGL : public gfx::Drawable {

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> impl;
Expand Down
2 changes: 1 addition & 1 deletion include/mbgl/gl/vertex_attribute_gl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class VertexAttributeGL final : public gfx::VertexAttribute {

static const std::vector<std::uint8_t>& getRaw(gfx::VertexAttribute& attr,
platform::GLenum,
std::chrono::duration<double> lastUpdate);
std::optional<std::chrono::duration<double>> lastUpdate);

private:
static int getSize(platform::GLenum glType);
Expand Down
3 changes: 0 additions & 3 deletions include/mbgl/mtl/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ class Context final : public gfx::Context {
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();

Expand Down
7 changes: 7 additions & 0 deletions include/mbgl/mtl/drawable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ class Drawable : public gfx::Drawable {
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<Impl>);
Expand Down
6 changes: 4 additions & 2 deletions include/mbgl/mtl/upload_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ class UploadPass final : public gfx::UploadPass {

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,
Expand All @@ -66,7 +68,7 @@ class UploadPass final : public gfx::UploadPass {
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
const std::optional<std::chrono::duration<double>> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;

std::unique_ptr<gfx::TextureResource> createTextureResource(Size,
Expand Down
3 changes: 2 additions & 1 deletion include/mbgl/mtl/vertex_attribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class VertexAttribute final : public gfx::VertexAttribute {

static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&,
UploadPass&,
const gfx::BufferUsageType);
const gfx::BufferUsageType,
bool forceUpdate);
};

/// Stores a collection of vertex attributes by name
Expand Down
7 changes: 7 additions & 0 deletions include/mbgl/vulkan/drawable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class Drawable : public gfx::Drawable {
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;

Expand Down
6 changes: 4 additions & 2 deletions include/mbgl/vulkan/upload_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class UploadPass final : public gfx::UploadPass {
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,
Expand All @@ -61,7 +63,7 @@ class UploadPass final : public gfx::UploadPass {
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
const std::optional<std::chrono::duration<double>> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;

std::unique_ptr<gfx::TextureResource> createTextureResource(Size,
Expand Down
3 changes: 2 additions & 1 deletion include/mbgl/vulkan/vertex_attribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class VertexAttribute final : public gfx::VertexAttribute {

static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&,
UploadPass&,
const gfx::BufferUsageType);
const gfx::BufferUsageType,
bool forceUpdate);
};

/// Stores a collection of vertex attributes by name
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/gfx/upload_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class UploadPass {
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
const std::optional<std::chrono::duration<double>> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) = 0;
#endif

Expand Down
35 changes: 33 additions & 2 deletions src/mbgl/gl/drawable_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,36 @@ void DrawableGL::setIndexData(gfx::IndexVectorBasePtr indexes, std::vector<Uniqu
impl->segments = 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<std::unique_ptr<Drawable::DrawSegment>> 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<DrawableGL::DrawSegmentGL>(
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<uint8_t>&& data, std::size_t count, gfx::AttributeDataType type_) {
impl->vertexData = std::move(data);
impl->vertexCount = count;
Expand Down Expand Up @@ -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)};
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/gl/upload_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
const gfx::BufferUsageType usage,
const std::chrono::duration<double> lastUpdate,
const std::optional<std::chrono::duration<double>> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) {
MLN_TRACE_FUNC();
AttributeBindingArray bindings;
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/gl/upload_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class UploadPass final : public gfx::UploadPass {
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
const std::optional<std::chrono::duration<double>> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/gl/vertex_attribute_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ std::size_t VertexAttributeGL::getStride() const {

const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr,
platform::GLenum type,
std::chrono::duration<double> lastUpdate) {
std::optional<std::chrono::duration<double>> 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()) {
Expand Down
7 changes: 0 additions & 7 deletions src/mbgl/mtl/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,6 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer,
}
}

const BufferResource& Context::getEmptyBuffer() {
if (!emptyBuffer) {
emptyBuffer.emplace(const_cast<Context&>(*this), nullptr, 0, MTL::ResourceStorageModeShared, false, false);
}
return *emptyBuffer;
}

const BufferResource& Context::getTileVertexBuffer() {
if (!tileVertexBuffer) {
const auto vertices = RenderStaticData::tileVertices();
Expand Down
51 changes: 37 additions & 14 deletions src/mbgl/mtl/drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -341,6 +341,34 @@ void Drawable::setVertices(std::vector<uint8_t>&& 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<UniqueDrawSegment> 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<Drawable::DrawSegment>(mode, std::move(segCopy)));
}

impl->indexes = std::move(indexes);
impl->segments = std::move(drawSegs);
}

const gfx::UniformBufferArray& Drawable::getUniformBuffers() const {
return impl->uniformBuffers;
}
Expand All @@ -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;
}
Expand All @@ -380,9 +405,6 @@ void Drawable::bindInstanceAttributes(RenderPass& renderPass) const noexcept {
const auto* buffer = static_cast<const mtl::VertexBufferResource*>(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;
Expand Down Expand Up @@ -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(
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 84ca231

Please sign in to comment.