Use timestamps for attribute updates (#2629)

This commit is contained in:
Tim Sylvester
2024-08-20 07:33:29 -07:00
committed by GitHub
parent c3a2fa247c
commit fceaa18caf
43 changed files with 439 additions and 163 deletions

View File

@@ -5,9 +5,10 @@
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/identity.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/containers.hpp>
#include <mbgl/util/identity.hpp>
#include <mbgl/util/monotonic_timer.hpp>
#include <mbgl/util/traits.hpp>
#include <cstdint>
#include <cstddef>
@@ -244,6 +245,8 @@ public:
/// Set origin point
void setOrigin(std::optional<Point<double>> p) { origin = std::move(p); }
const std::chrono::duration<double> 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<double> attributeUpdateTime = util::MonotonicTimer::now();
struct Impl;
std::unique_ptr<Impl> impl;

View File

@@ -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<double> time) const {
if (sharedRawData) {
return sharedRawData->isModifiedAfter(time);
}
return dirty;
}
template <std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type set(std::size_t, std::tuple<Tp...>, 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<double> 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 <typename Func /* void(const size_t, VertexAttribute&, const std::unique_ptr<VertexAttribute>&) */>
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 ResolveFunc /* void(const size_t, VertexAttribute&, const std::unique_ptr<VertexAttribute>&) */,
typename MissingFunc /* void(const size_t, const std::unique_ptr<VertexAttribute>&) */>
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);
}
}
}

View File

@@ -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<std::uint8_t>& getRaw(gfx::VertexAttribute& attr, platform::GLenum);
static const std::vector<std::uint8_t>& getRaw(gfx::VertexAttribute& attr,
platform::GLenum,
std::chrono::duration<double> 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<gfx::VertexAttribute> create(int index,
gfx::AttributeDataType dataType,

View File

@@ -66,6 +66,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
std::unique_ptr<gfx::TextureResource> createTextureResource(Size,

View File

@@ -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<double> time) const;
private:
gfx::UniqueVertexAttribute create(int index, gfx::AttributeDataType dataType, std::size_t count) const override {

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/mtl/buffer_resource.hpp>
#include <mbgl/util/monotonic_timer.hpp>
#include <memory>
@@ -21,8 +22,12 @@ public:
BufferResource& get() noexcept { return buffer; }
const BufferResource& get() const noexcept { return buffer; }
std::chrono::duration<double> getLastUpdated() const { return lastUpdated; }
void setLastUpdated(std::chrono::duration<double> time) { lastUpdated = time; }
protected:
BufferResource buffer;
std::chrono::duration<double> lastUpdated;
};
using UniqueVertexBufferResource = std::unique_ptr<VertexBufferResource>;

View File

@@ -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<uint64_t>(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
#endif // MLN_TRACY_ENABLE

View File

@@ -61,6 +61,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
std::unique_ptr<gfx::TextureResource> createTextureResource(Size,

View File

@@ -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<VertexAttribute>(index, dataType, count);

View File

@@ -22,8 +22,12 @@ public:
BufferResource& get() noexcept { return buffer; }
const BufferResource& get() const noexcept { return buffer; }
std::chrono::duration<double> getLastUpdated() const { return lastUpdated; }
void setLastUpdated(std::chrono::duration<double> time) { lastUpdated = time; }
protected:
BufferResource buffer;
std::chrono::duration<double> lastUpdated;
};
using UniqueVertexBufferResource = std::unique_ptr<VertexBufferResource>;

View File

@@ -2,6 +2,7 @@
#include <mbgl/gfx/draw_mode.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/monotonic_timer.hpp>
#include <memory>
#include <vector>
@@ -40,8 +41,15 @@ public:
void setBuffer(std::unique_ptr<IndexBufferBase>&& value) { buffer = std::move(value); }
#endif // MLN_DRAWABLE_RENDERER
bool getDirty() const { return dirty; }
void setDirty(bool value = true) { dirty = value; }
std::chrono::duration<double> getLastModified() const { return lastModified; }
bool isModifiedAfter(std::chrono::duration<double> 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<double> lastModified = util::MonotonicTimer::now();
};
using IndexVectorBasePtr = std::shared_ptr<IndexVectorBase>;

View File

@@ -87,6 +87,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) = 0;
#endif

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/monotonic_timer.hpp>
#include <memory>
#include <vector>
@@ -35,9 +36,17 @@ public:
void setBuffer(std::unique_ptr<VertexBufferBase>&& value) { buffer = std::move(value); }
#endif // MLN_DRAWABLE_RENDERER
bool getDirty() const { return dirty; }
void setDirty(bool value = true) { dirty = value; }
std::chrono::duration<double> getLastModified() const { return lastModified; }
bool isModifiedAfter(std::chrono::duration<double> 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<double> lastModified = util::MonotonicTimer::now();
};
using VertexVectorBasePtr = std::shared_ptr<VertexVectorBase>;

View File

@@ -7,6 +7,7 @@
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/programs/segment.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
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<const DrawSegmentGL&>(*seg).getVertexArray().isValid();
}));
if (build) {
MLN_TRACE_ZONE(build attributes);
auto& context = uploadPass.getContext();
auto& glContext = static_cast<gl::Context&>(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<gfx::IndexBuffer>(impl->indexes->elements(),
@@ -185,11 +202,11 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) {
auto buffer = std::make_unique<IndexBufferGL>(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<DrawSegmentGL&>(*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();

View File

@@ -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;
}

View File

@@ -9,6 +9,7 @@
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/gl/index_buffer_resource.hpp>
#include <mbgl/gl/texture_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#if MLN_DRAWABLE_RENDERER
@@ -43,7 +44,7 @@ std::unique_ptr<gfx::VertexBufferResource> UploadPass::createVertexBufferResourc
}
void UploadPass::updateVertexBufferResource(gfx::VertexBufferResource& resource, const void* data, std::size_t size) {
commandEncoder.context.vertexBuffer = static_cast<gl::VertexBufferResource&>(resource).buffer;
commandEncoder.context.vertexBuffer = static_cast<gl::VertexBufferResource&>(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<VertexBufferGL*>(vec->getBuffer()); rawData && rawData->resource) {
auto& resource = static_cast<gl::VertexBufferResource&>(*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<VertexBufferGL>();
buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false);
vec->setBuffer(std::move(buffer));
vec->setDirty(false);
return static_cast<VertexBufferGL*>(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<double> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& 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<const VertexAttributeGL&>(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<uint32_t>(stride),
@@ -280,7 +283,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
// The vertex stride is the sum of the attribute strides
vertexStride += static_cast<uint32_t>(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());

View File

@@ -56,6 +56,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
const std::chrono::duration<double> lastUpdate,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
#endif

View File

@@ -3,6 +3,7 @@
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/enum.hpp>
#include <mbgl/util/instrumentation.hpp>
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<gfx::DepthMaskType>::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<gfx::DepthMaskType>::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<bool>(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<gfx::StencilFunctionType>::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<gfx::StencilOpType>::to(value.sfail),
Enum<gfx::StencilOpType>::to(value.dpfail),
Enum<gfx::StencilOpType>::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<gfx::DepthFunctionType>::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<gfx::DepthFunctionType>::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<gfx::ColorBlendEquationType>::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<gfx::ColorBlendEquationType>::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<gfx::ColorBlendFactorType>::to(value.sfactor),
Enum<gfx::ColorBlendFactorType>::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<Type>(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<int32_t>(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<gfx::CullFaceSideType>::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<gfx::CullFaceSideType>::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<gfx::CullFaceWindingType>::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<gfx::CullFaceWindingType>::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<const gl::VertexBufferResource&>(*binding->vertexBufferResource).buffer;
context.vertexBuffer =
reinterpret_cast<const gl::VertexBufferResource&>(*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;

View File

@@ -153,11 +153,13 @@ std::size_t VertexAttributeGL::getStride() const {
return getStride(getGLType());
}
const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, platform::GLenum type) {
const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr,
platform::GLenum type,
std::chrono::duration<double> 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<std::uint8_t>& 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<const VertexAttributeGL&>(*attr);
if (const auto& shared = glAttrib.getSharedRawData()) {
return shared->getDirty();
}
}
return attr && attr->isDirty();
});
}
} // namespace gl
} // namespace mbgl

View File

@@ -2,6 +2,7 @@
#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/gl/object.hpp>
#include <mbgl/util/monotonic_timer.hpp>
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<double> getLastUpdated() const { return lastUpdated; }
void setLastUpdated(std::chrono::duration<double> time) { lastUpdated = time; }
protected:
UniqueBuffer buffer;
int byteSize;
std::chrono::duration<double> lastUpdated = util::MonotonicTimer::now();
};
} // namespace gl

View File

@@ -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<Context&>(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<IndexBuffer>(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

View File

@@ -6,6 +6,7 @@
#include <mbgl/mtl/renderable_resource.hpp>
#include <mbgl/mtl/vertex_attribute.hpp>
#include <mbgl/mtl/vertex_buffer_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#include <Metal/Metal.hpp>
@@ -127,21 +128,21 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe
if (auto* rawData = static_cast<VertexBuffer*>(vec->getBuffer()); rawData && rawData->resource) {
auto& resource = static_cast<VertexBufferResource&>(*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<VertexBuffer>();
buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false);
vec->setBuffer(std::move(buffer));
vec->setDirty(false);
auto buffer_ = std::make_unique<VertexBuffer>();
buffer_->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false);
vec->setBuffer(std::move(buffer_));
return static_cast<VertexBuffer*>(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<double> /*lastUpdate*/,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& 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<uint32_t>(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;
}

View File

@@ -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<const VertexAttribute&>(*attr);
if (const auto& shared = attrib.getSharedRawData()) {
return shared->getDirty();
}
}
return attr && attr->isDirty();
});
}
} // namespace mtl
} // namespace mbgl

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -352,6 +352,12 @@ void SymbolBucket::updateVertices(const Placement& placement,
dynamicUploaded = false;
uploaded = false;
}
if (!uploaded) {
text.updateModified();
icon.updateModified();
sdfIcon.updateModified();
}
}
} // namespace mbgl

View File

@@ -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<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices() { return *sharedVertices; }
const VertexVector& vertices() const { return *sharedVertices; }

View File

@@ -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<RasterBucket&>(*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<std::chrono::duration<double>> 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

View File

@@ -1344,7 +1344,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
auto drawData = std::make_unique<gfx::SymbolDrawableData>(
/*.isHalo=*/isHalo,
/*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement,
/*.bucketVariablePlacement=*/bucket.hasVariablePlacement,
/*.symbolType=*/renderable.type,
/*.pitchAlignment=*/values.pitchAlignment,
/*.rotationAlignment=*/values.rotationAlignment,

View File

@@ -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<T> range = {
const Range<T> 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

View File

@@ -252,6 +252,7 @@ std::unique_ptr<RenderTree> 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<RenderTree> 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<RenderTree> 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<RenderTree> RenderOrchestrator::createRenderTree(
// Update layers for class and zoom changes.
std::unordered_set<std::string> 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<RenderTree> 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 = RenderSource::create(entry.second, threadPool);
renderSource->setObserver(this);
renderSource->enableCache(tileCacheEnabled);
@@ -439,6 +444,7 @@ std::unique_ptr<RenderTree> 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<RenderTree> 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<RenderTree> RenderOrchestrator::createRenderTree(
std::set<std::string> usedSymbolLayers;
const auto longitude = static_cast<float>(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<RenderTree> RenderOrchestrator::createRenderTree(
}
if (isMapModeContinuous) {
MLN_TRACE_ZONE(placement)
MLN_TRACE_ZONE(placement);
std::optional<Duration> placementUpdatePeriodOverride;
if (symbolBucketsAdded && !tiltedView) {
@@ -518,7 +524,7 @@ std::unique_ptr<RenderTree> 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<RenderTree> 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();

View File

@@ -43,7 +43,8 @@ void SourceFeatureState::getState(FeatureState& result,
}
void SourceFeatureState::coalesceChanges(std::vector<RenderTile>& tiles) {
MLN_TRACE_FUNC()
MLN_TRACE_FUNC();
LayerFeatureStates changes;
for (const auto& layerStatesEntry : stateChanges) {
const auto& sourceLayer = layerStatesEntry.first;

View File

@@ -8,10 +8,11 @@
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
namespace mbgl {
@@ -89,6 +90,7 @@ std::unique_ptr<RenderItem> RenderImageSource::createRenderItem() {
}
void RenderImageSource::prepare(const SourcePrepareParameters& parameters) {
MLN_TRACE_FUNC();
assert(!renderData);
if (!isLoaded()) {
renderData = std::make_unique<ImageSourceRenderData>(bucket, std::vector<mat4>{}, baseImpl->id);

View File

@@ -151,7 +151,7 @@ public:
std::optional<CollisionBoundaries> avoidEdges;
};
// PlacementController implemenation
// PlacementController implementation
PlacementController::PlacementController()
: placement(makeMutable<Placement>()) {}
@@ -754,12 +754,12 @@ Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor,
std::array<float, 2> 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

View File

@@ -155,7 +155,7 @@ protected:
const std::vector<ProjectedCollisionBox>& /*textBoxes*/,
const std::vector<ProjectedCollisionBox>& /*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<CollisionBoundaries> getAvoidEdges(const SymbolBucket&, const mat4& /*posMatrix*/) {
return std::nullopt;
}

View File

@@ -5,6 +5,7 @@
#include <mbgl/util/thread_local.hpp>
#include <mbgl/util/containers.hpp>
#include <mbgl/util/identity.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <algorithm>
#include <condition_variable>
@@ -107,6 +108,7 @@ public:
}
void runRenderJobs(const util::SimpleIdentity tag, bool closeQueue = false) override {
MLN_TRACE_FUNC();
std::shared_ptr<RenderQueue> queue;
std::unique_lock<std::mutex> 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();
}
}

View File

@@ -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;

View File

@@ -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<IndexBuffer>(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<Context&>(parameters.context);
auto& renderPass = static_cast<RenderPass&>(*parameters.renderPass);
auto& encoder = renderPass.getEncoder();
auto& renderPass_ = static_cast<RenderPass&>(*parameters.renderPass);
auto& encoder = renderPass_.getEncoder();
auto& commandBuffer = encoder.getCommandBuffer();
auto& shaderImpl = static_cast<mbgl::vulkan::ShaderProgram&>(*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::vector<UniqueD
impl->segments = std::move(segments);
}
void Drawable::setVertices(std::vector<uint8_t>&& data, std::size_t count, gfx::AttributeDataType type) {
void Drawable::setVertices(std::vector<uint8_t>&& 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<VertexAttributeArray>();
}
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<const IndexBuffer*>(impl->indexes->getBuffer());
const auto& indexBufferResource = indexBuffer->buffer->getResource<IndexBufferResource>().get();
commandBuffer->bindIndexBuffer(indexBufferResource.getVulkanBuffer(), 0, vk::IndexType::eUint16);
if (const auto* indexBuffer = static_cast<const IndexBuffer*>(impl->indexes->getBuffer())) {
const auto& indexBufferResource = indexBuffer->buffer->getResource<IndexBufferResource>().get();
commandBuffer->bindIndexBuffer(indexBufferResource.getVulkanBuffer(), 0, vk::IndexType::eUint16);
}
}
return true;

View File

@@ -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<RenderableResource>();

View File

@@ -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<VertexBuffer>();
buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false);
vec->setBuffer(std::move(buffer));
vec->setDirty(false);
return static_cast<VertexBuffer*>(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<double> /*lastUpdate*/,
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>&) {
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;
}

View File

@@ -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<const VertexAttribute&>(*attr);
if (const auto& shared = attrib.getSharedRawData()) {
return shared->getDirty();
}
}
return attr && attr->isDirty();
});
}
} // namespace vulkan
} // namespace mbgl