shared vertex buffers (#1310)

Co-authored-by: Stefan Karschti <stefan.karschti@gmail.com>
This commit is contained in:
Tim Sylvester
2023-07-07 15:03:39 -07:00
committed by Bart Louwers
parent d094b9928e
commit 5b3af77450
46 changed files with 647 additions and 479 deletions

View File

@@ -143,11 +143,10 @@ public:
const gfx::ColorMode& getColorMode() const;
void setColorMode(const gfx::ColorMode&);
/// Get the number of vertexes
std::size_t getVertexCount() const { return getVertexAttributes().getMaxCount(); }
/// Get the vertex attributes that override default values in the shader program
virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0;
virtual gfx::VertexAttributeArray& mutableVertexAttributes() = 0;
virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0;
virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0;
@@ -171,8 +170,8 @@ public:
static_cast<float>(components[3])};
}
virtual const UniqueDrawableData& getData() const { return drawableData; }
virtual void setData(UniqueDrawableData&& value) { drawableData = std::move(value); }
const UniqueDrawableData& getData() const { return drawableData; }
void setData(UniqueDrawableData&& value) { drawableData = std::move(value); }
protected:
bool enabled = true;

View File

@@ -100,7 +100,7 @@ public:
void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); }
/// Get the vertex attributes that override default values in the shader program
virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0;
const gfx::VertexAttributeArray& getVertexAttributes() const { return vertexAttrs; }
/// Set the name given to new drawables
void setDrawableName(std::string value) { drawableName = std::move(value); }
@@ -125,7 +125,7 @@ public:
void addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
/// A set of attribute values to be added for each vertex
void setVertexAttributes(const VertexAttributeArray&);
void setVertexAttributes(const VertexAttributeArray& value);
void setVertexAttributes(VertexAttributeArray&&);
/// Add some vertex elements, returns the index of the first one added

View File

@@ -21,6 +21,7 @@ using mat4 = std::array<double, 4 * 4>;
namespace gfx {
class ShaderProgramBase;
class VertexVectorBase;
class VertexAttribute {
public:
@@ -43,11 +44,26 @@ public:
stride((int)stride_),
dataType(dataType_),
items(count_) {}
VertexAttribute(const VertexAttribute&) = default;
VertexAttribute(const VertexAttribute& other)
: index(other.index),
dataType(other.dataType),
items(other.items),
sharedRawData(other.sharedRawData),
sharedType(other.sharedType),
sharedOffset(other.sharedOffset),
sharedVertexOffset(other.sharedVertexOffset),
sharedStride(other.sharedStride)
{}
VertexAttribute(VertexAttribute&& other)
: index(other.index),
dataType(other.dataType),
items(std::move(other.items)) {}
items(std::move(other.items)),
sharedRawData(std::move(other.sharedRawData)),
sharedType(other.sharedType),
sharedOffset(other.sharedOffset),
sharedVertexOffset(other.sharedVertexOffset),
sharedStride(other.sharedStride)
{}
public:
virtual ~VertexAttribute() = default;
@@ -57,7 +73,7 @@ public:
std::size_t getStride() const { return stride; }
std::size_t getCount() const { return items.size(); }
std::size_t getCount() const;
AttributeDataType getDataType() const { return dataType; }
const ElementType& get(std::size_t i) const { return items[i]; }
@@ -99,10 +115,7 @@ public:
}
bool isDirty() const { return dirty; }
void setDirty() {
dirty = true;
rawData.clear();
}
void setDirty(bool value = true) { dirty = value; }
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) {}
@@ -117,6 +130,23 @@ public:
}
}
std::vector<std::uint8_t>& getRawData() { return rawData; }
const std::vector<std::uint8_t>& getRawData() const { return rawData; }
const std::shared_ptr<VertexVectorBase>& getSharedRawData() const { return sharedRawData; }
AttributeDataType getSharedType() const { return sharedType; }
uint32_t getSharedOffset() const { return sharedOffset; }
uint32_t getSharedVertexOffset() const { return sharedVertexOffset; }
uint32_t getSharedStride() const { return sharedStride; }
void setSharedRawData(std::shared_ptr<VertexVectorBase> data, uint32_t offset, uint32_t vertexOffset, uint32_t stride_, AttributeDataType type) {
sharedRawData = std::move(data);
sharedType = type;
sharedOffset = offset;
sharedVertexOffset = vertexOffset;
sharedStride = stride_;
}
void resetSharedRawData() { sharedRawData.reset(); }
protected:
VertexAttribute& operator=(const VertexAttribute&) = default;
VertexAttribute& operator=(VertexAttribute&& other) {
@@ -135,7 +165,15 @@ protected:
AttributeDataType dataType;
std::vector<ElementType> items;
// Cache of attribute data
mutable std::vector<std::uint8_t> rawData;
std::shared_ptr<VertexVectorBase> sharedRawData;
AttributeDataType sharedType = AttributeDataType::Invalid;
uint32_t sharedOffset = 0;
uint32_t sharedVertexOffset = 0;
uint32_t sharedStride = 0;
};
/// Stores a collection of vertex attributes by name
@@ -215,7 +253,7 @@ public:
}
using ResolveDelegate =
std::function<void(const std::string&, const VertexAttribute&, const std::unique_ptr<VertexAttribute>&)>;
std::function<void(const std::string&, VertexAttribute&, const std::unique_ptr<VertexAttribute>&)>;
/// Call the provided delegate with each value, providing the override if one exists.
void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const;

View File

@@ -44,7 +44,7 @@ public:
void setVertexAttributes(const gfx::VertexAttributeArray& value) override;
void setVertexAttributes(gfx::VertexAttributeArray&& value) override;
gfx::VertexAttributeArray& mutableVertexAttributes();
gfx::VertexAttributeArray& mutableVertexAttributes() override;
const gfx::UniformBufferArray& getUniformBuffers() const override;
gfx::UniformBufferArray& mutableUniformBuffers() override;

View File

@@ -15,10 +15,6 @@ public:
: gfx::DrawableBuilder(std::move(name_)) {}
~DrawableGLBuilder() override = default;
const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; }
void setVertexAttributes(const VertexAttributeArrayGL& value) { vertexAttributes = value; }
void setVertexAttributes(VertexAttributeArrayGL&& value) { vertexAttributes = std::move(value); }
protected:
gfx::UniqueDrawable createDrawable() const override;
@@ -27,9 +23,6 @@ protected:
/// Setup the SDK-specific aspects after all the values are present
void init() override;
private:
VertexAttributeArrayGL vertexAttributes;
};
} // namespace gl

View File

@@ -1,13 +1,18 @@
#pragma once
#include <mbgl/gfx/types.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/platform/gl_functions.hpp>
namespace mbgl {
namespace gfx {
class VertexBufferResource;
} // namespace gfx
namespace gl {
class VertexAttributeArrayGL;
class UploadPass;
class VertexAttributeGL final : public gfx::VertexAttribute {
// Can only be created by VertexAttributeArrayGL
@@ -25,7 +30,6 @@ private:
public:
~VertexAttributeGL() override = default;
public:
platform::GLenum getGLType() const { return glType; }
void setGLType(platform::GLenum value);
@@ -34,7 +38,7 @@ public:
std::size_t getStride() const;
const std::vector<std::uint8_t>& getRaw(platform::GLenum) const;
static const std::vector<std::uint8_t>& getRaw(gfx::VertexAttribute& attr, platform::GLenum);
private:
static int getSize(platform::GLenum glType);
@@ -43,7 +47,6 @@ private:
private:
platform::GLenum glType = 0;
mutable platform::GLenum rawType = 0;
bool normalized = false;
};

View File

@@ -38,8 +38,8 @@ UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) {
}
void DrawableBuilder::flush() {
const auto vertexCount = curVertexCount();
if (vertexCount) {
if (curVertexCount())
{
const auto& draw = getCurrentDrawable(/*createIfNone=*/true);
draw->setEnabled(enabled);
draw->setLineWidth(static_cast<int32_t>(lineWidth));
@@ -56,25 +56,8 @@ void DrawableBuilder::flush() {
draw->setTextures(textures);
draw->setTweakers(tweakers);
if (auto drawAttrs = getVertexAttributes().clone()) {
vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) {
if (auto& drawAttr = drawAttrs->getOrAdd(iName)) {
if (iAttr.getCount() == 1) {
// Apply the value to all vertexes
for (std::size_t i = 0; i < vertexCount; ++i) {
drawAttr->setVariant(i, iAttr.get(0));
}
} else if (iAttr.getCount() == vertexCount) {
for (std::size_t i = 0; i < vertexCount; ++i) {
drawAttr->setVariant(i, iAttr.get(i));
}
} else {
// throw?
Log::Warning(Event::General, "Invalid attribute count");
}
}
});
const auto& builderAttrs = getVertexAttributes();
if (auto drawAttrs = builderAttrs.clone()) {
draw->setVertexAttributes(std::move(*drawAttrs));
}
@@ -147,7 +130,7 @@ void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) {
}
void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) {
vertexAttrs = attrs;
vertexAttrs = std::move(attrs);
}
std::size_t DrawableBuilder::addVertices(const std::vector<std::array<int16_t, 2>>& vertices,
@@ -169,7 +152,7 @@ void DrawableBuilder::setRawVertices(std::vector<uint8_t>&& data, std::size_t co
void DrawableBuilder::setSegments(gfx::DrawMode mode,
std::vector<uint16_t> indexes,
const std::vector<SegmentBase>& segments) {
setSegments(mode, indexes, segments.data(), segments.size());
setSegments(mode, std::move(indexes), segments.data(), segments.size());
}
void DrawableBuilder::setSegments(gfx::DrawMode mode,
@@ -185,10 +168,13 @@ void DrawableBuilder::setSegments(gfx::DrawMode mode,
} else if (mode.type == DrawModeType::Lines) {
assert(seg.indexLength % 2 == 0);
}
assert(seg.vertexOffset + seg.vertexLength <= curVertexCount());
const auto vertexCount = curVertexCount();
assert(!vertexCount || seg.vertexOffset + seg.vertexLength <= curVertexCount());
assert(seg.indexOffset + seg.indexLength <= impl->indexes.size());
for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) {
assert(impl->indexes[seg.indexOffset + j] < curVertexCount());
if (vertexCount) {
for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) {
assert(impl->indexes[seg.indexOffset + j] < vertexCount);
}
}
#endif

View File

@@ -51,13 +51,13 @@ public:
public:
template <class Vertex>
VertexBuffer<Vertex> createVertexBuffer(VertexVector<Vertex>&& v,
VertexBuffer<Vertex> createVertexBuffer(const VertexVector<Vertex>& v,
const BufferUsageType usage = BufferUsageType::StaticDraw) {
return {v.elements(), createVertexBufferResource(v.data(), v.bytes(), usage)};
}
template <class Vertex>
void updateVertexBuffer(VertexBuffer<Vertex>& buffer, VertexVector<Vertex>&& v) {
void updateVertexBuffer(VertexBuffer<Vertex>& buffer, const VertexVector<Vertex>& v) {
assert(v.elements() == buffer.elements);
updateVertexBufferResource(buffer.getResource(), v.data(), v.bytes());
}
@@ -83,7 +83,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
/*out*/ std::unique_ptr<gfx::VertexBufferResource>& outBuffer) = 0;
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) = 0;
#endif
protected:

View File

@@ -1,5 +1,7 @@
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/gfx/vertex_vector.hpp>
#include <algorithm>
#include <numeric>
#include <optional>
@@ -7,6 +9,11 @@
namespace mbgl {
namespace gfx {
std::size_t VertexAttribute::getCount() const {
return sharedRawData ? sharedRawData->getRawCount() : items.size();
}
std::unique_ptr<VertexAttribute> VertexAttributeArray::nullref = nullptr;
VertexAttributeArray::VertexAttributeArray(int initCapacity)

View File

@@ -7,19 +7,67 @@
namespace mbgl {
namespace gfx {
struct VertexBufferBase {
virtual ~VertexBufferBase() = default;
};
class VertexVectorBase {
public:
VertexVectorBase() = default;
VertexVectorBase(const VertexVectorBase&) {} // buffer is not copied
VertexVectorBase(VertexVectorBase&& other) :
buffer(std::move(other.buffer)),
dirty(other.dirty),
released(other.released)
{}
virtual ~VertexVectorBase() = default;
virtual const void* getRawData() const = 0;
virtual std::size_t getRawSize() const = 0;
virtual std::size_t getRawCount() const = 0;
VertexBufferBase* getBuffer() const { return buffer.get(); }
void setBuffer(std::unique_ptr<VertexBufferBase>&& value) { buffer = std::move(value); }
bool getDirty() const { return dirty; }
void setDirty(bool value = true) { dirty = value; }
bool isReleased() const { return released; }
protected:
std::unique_ptr<VertexBufferBase> buffer;
bool dirty = true;
bool released = false;
};
using VertexVectorBasePtr = std::shared_ptr<VertexVectorBase>;
template <class V>
class VertexVector {
class VertexVector final : public VertexVectorBase {
public:
using Vertex = V;
VertexVector() = default;
VertexVector(const VertexVector<V>& other) :
VertexVectorBase(other),
v(other.v) {}
VertexVector(VertexVector<V>&& other) :
VertexVectorBase(std::move(other)),
v(std::move(other.v)) {}
~VertexVector() override = default;
template <typename Arg>
void emplace_back(Arg&& vertex) {
v.emplace_back(std::forward<Arg>(vertex));
}
void extend(std::size_t n, const Vertex& val) { v.resize(v.size() + n, val); }
void extend(std::size_t n, const Vertex& val) {
v.resize(v.size() + n, val);
dirty = true;
}
Vertex& at(std::size_t n) {
assert(n < v.size());
dirty = true;
return v.at(n);
}
const Vertex& at(std::size_t n) const {
@@ -33,12 +81,27 @@ public:
bool empty() const { return v.empty(); }
void clear() { v.clear(); }
void clear() {
dirty = true;
v.clear();
}
void release() {
// If we've already created a buffer, we don't need the raw data any more.
if (buffer) {
clear();
}
released = true;
}
const Vertex* data() const { return v.data(); }
const std::vector<Vertex>& vector() const { return v; }
const void* getRawData() const override { return v.data(); }
std::size_t getRawSize() const override { return sizeof(Vertex); }
std::size_t getRawCount() const override { return v.size(); }
private:
std::vector<Vertex> v;
};

View File

@@ -18,7 +18,7 @@ DrawableGL::DrawableGL(std::string name_)
DrawableGL::~DrawableGL() {
impl->indexBuffer = {0, nullptr};
impl->attributeBuffer.reset();
impl->attributeBuffers.clear();
}
void DrawableGL::draw(PaintParameters& parameters) const {
@@ -159,7 +159,7 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) {
const auto& indexAttribute = defaults.get(impl->vertexAttrName);
const auto vertexAttributeIndex = static_cast<std::size_t>(indexAttribute ? indexAttribute->getIndex() : -1);
std::unique_ptr<gfx::VertexBufferResource> vertexBuffer;
std::vector<std::unique_ptr<gfx::VertexBufferResource>> vertexBuffers;
auto bindings = uploadPass.buildAttributeBindings(impl->vertexCount,
impl->vertexType,
vertexAttributeIndex,
@@ -167,9 +167,9 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) {
defaults,
overrides,
usage,
vertexBuffer);
vertexBuffers);
impl->attributeBuffer = std::move(vertexBuffer);
impl->attributeBuffers = std::move(vertexBuffers);
impl->indexBuffer = std::move(indexBuffer);
// Create a VAO for each group of vertexes described by a segment

View File

@@ -41,7 +41,7 @@ public:
VertexAttributeArrayGL vertexAttributes;
gfx::IndexBuffer indexBuffer = {0, nullptr};
gfx::UniqueVertexBufferResource attributeBuffer;
std::vector<gfx::UniqueVertexBufferResource> attributeBuffers;
UniformBufferArrayGL uniformBuffers;

View File

@@ -1,4 +1,7 @@
#include <mbgl/gl/upload_pass.hpp>
#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/gfx/vertex_vector.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/enum.hpp>
#include <mbgl/gl/defines.hpp>
@@ -25,7 +28,7 @@ UploadPass::UploadPass(gl::CommandEncoder& commandEncoder_, const char* name)
debugGroup(commandEncoder.createDebugGroup(name)) {}
std::unique_ptr<gfx::VertexBufferResource> UploadPass::createVertexBufferResource(const void* data,
std::size_t size,
const std::size_t size,
const gfx::BufferUsageType usage) {
BufferID id = 0;
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
@@ -126,7 +129,44 @@ void UploadPass::updateTextureResourceSub(gfx::TextureResource& resource,
data));
}
struct VertexBufferGL : public gfx::VertexBufferBase {
~VertexBufferGL() override = default;
std::unique_ptr<gfx::VertexBufferResource> resource;
};
#if MLN_DRAWABLE_RENDERER
namespace {
const std::unique_ptr<gfx::VertexBufferResource> noBuffer;
}
const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec, const gfx::BufferUsageType usage) {
if (vec) {
const auto* rawBufPtr = vec->getRawData();
const auto rawBufSize = static_cast<int>(vec->getRawCount() * vec->getRawSize());
// If we already have a buffer...
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()) {
updateVertexBufferResource(resource, rawBufPtr, rawBufSize);
}
return rawData->resource;
}
}
// Otherwise, create a new one
if (rawBufSize > 0) {
auto buffer = std::make_unique<VertexBufferGL>();
buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage);
vec->setBuffer(std::move(buffer));
return static_cast<VertexBufferGL*>(vec->getBuffer())->resource;
}
}
return noBuffer;
}
static std::size_t padSize(std::size_t size, std::size_t padding) {
return (padding - (size % padding)) % padding;
}
@@ -145,7 +185,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
const gfx::BufferUsageType usage,
/*out*/ std::unique_ptr<gfx::VertexBufferResource>& outBuffer) {
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) {
AttributeBindingArray bindings;
bindings.resize(defaults.size());
@@ -170,21 +210,35 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
}
// For each attribute in the program, with the corresponding default and optional override...
const auto resolveAttr = [&](const std::string& name, const auto& defaultAttr, const auto& overrideAttr) -> void {
const auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr;
const auto& effectiveGL = static_cast<const gl::VertexAttributeGL&>(effectiveAttr);
const auto& defaultGL = static_cast<const gl::VertexAttributeGL&>(defaultAttr);
const auto resolveAttr = [&](const std::string& name, auto& defaultAttr, auto& overrideAttr) -> void {
auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr;
const auto& defaultGL = static_cast<const VertexAttributeGL&>(defaultAttr);
const auto stride = defaultAttr.getStride();
const auto offset = static_cast<uint32_t>(allData.size());
const auto index = static_cast<std::size_t>(defaultGL.getIndex());
bindings.resize(std::max(bindings.size(), index + 1));
if (const auto& buffer = getBuffer(effectiveAttr.getSharedRawData(), usage)) {
bindings[index] = {
/*.attribute = */ {effectiveAttr.getSharedType(), effectiveAttr.getSharedOffset()},
/*.vertexStride = */ effectiveAttr.getSharedStride(),
/*.vertexBufferResource = */ buffer.get(),
/*.vertexOffset = */ effectiveAttr.getSharedVertexOffset(),
};
return;
}
if (index == vertexAttributeIndex) {
// already handled
return;
}
// Get the raw data for the values in the desired format
const auto& rawData = effectiveGL.getRaw(defaultGL.getGLType());
const auto& rawData = VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType());
if (rawData.empty()) {
VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType());
}
if (rawData.size() == stride * vertexCount) {
// The override provided a value for each vertex, append it as-is
@@ -204,7 +258,6 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
return;
}
bindings.resize(std::max(bindings.size(), index + 1));
bindings[index] = {
/*.attribute = */ {defaultAttr.getDataType(), offset},
/* vertexStride = */ static_cast<uint32_t>(stride),
@@ -221,19 +274,25 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
assert(vertexStride * vertexCount <= allData.size());
if (auto vertBuf = createVertexBufferResource(allData.data(), allData.size(), usage)) {
// Fill in the buffer in each binding that was generated
std::for_each(bindings.begin(), bindings.end(), [&](auto& b) {
if (b) {
b->vertexBufferResource = vertBuf.get();
}
});
outBuffer = std::move(vertBuf);
return bindings;
if (!allData.empty()) {
if (auto vertBuf = createVertexBufferResource(allData.data(), allData.size(), usage)) {
// Fill in the buffer in each binding that was generated without its own buffer
std::for_each(bindings.begin(), bindings.end(), [&](auto& b) {
if (b && !b->vertexBufferResource) {
b->vertexBufferResource = vertBuf.get();
}
});
outBuffers.emplace_back(std::move(vertBuf));
} else {
assert(false);
return {};
}
}
return {};
assert(std::all_of(bindings.begin(), bindings.end(), [](const auto& b){ return !b || b->vertexBufferResource; }));
return bindings;
}
#endif

View File

@@ -7,6 +7,8 @@ namespace mbgl {
namespace gfx {
class CommandEncoder;
class VertexVectorBase;
using VertexVectorBasePtr = std::shared_ptr<VertexVectorBase>;
} // namespace gfx
@@ -41,6 +43,8 @@ public:
void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override;
#if MLN_DRAWABLE_RENDERER
const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, gfx::BufferUsageType);
gfx::AttributeBindingArray buildAttributeBindings(
const std::size_t vertexCount,
const gfx::AttributeDataType vertexType,
@@ -49,7 +53,7 @@ public:
const gfx::VertexAttributeArray& defaults,
const gfx::VertexAttributeArray& overrides,
gfx::BufferUsageType,
/*out*/ std::unique_ptr<gfx::VertexBufferResource>& outBuffer) override;
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
#endif
public:

View File

@@ -483,7 +483,7 @@ GLint components(const gfx::AttributeDataType type) {
#endif
void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocation location) {
if (binding) {
if (binding && binding->vertexBufferResource) {
context.vertexBuffer = reinterpret_cast<const gl::VertexBufferResource&>(*binding->vertexBufferResource).buffer;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttribPointer(

View File

@@ -1,6 +1,9 @@
#include <mbgl/gl/vertex_attribute_gl.hpp>
#include <mbgl/gfx/vertex_vector.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/upload_pass.hpp>
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
@@ -112,7 +115,9 @@ bool VertexAttributeGL::get(const gfx::VertexAttribute::ElementType& element, GL
case GL_FLOAT_MAT2:
return gl::get<float4>(element, buffer) || gl::get<int4, float4>(element, buffer, [](int4 x) {
return float4{(float)x[0], (float)x[1], (float)x[2], (float)x[3]};
});
}) || gl::get<ushort8, float4>(element, buffer, [](ushort8 x) {
return float4{(float)x[0], (float)x[1], (float)x[2], (float)x[3]};
});
case GL_INT:
return gl::get<std::int32_t>(element, buffer) || gl::get<float, std::int32_t>(element, buffer);
case GL_UNSIGNED_INT:
@@ -146,27 +151,29 @@ std::size_t VertexAttributeGL::getStride() const {
return getStride(getGLType());
}
const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(platform::GLenum type) const {
if (dirty || rawType != type) {
const auto count = getCount();
// const auto size_ = getSize(type);
const auto stride_ = getStride(type);
namespace {
const std::vector<std::uint8_t> noData;
}
const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(gfx::VertexAttribute& attr, platform::GLenum type) {
const auto count = attr.getCount();
const auto stride_ = getStride(type);
auto& rawData = attr.getRawData();
if (attr.isDirty() || rawData.size() != count * stride_) {
rawData.resize(stride_ * count);
std::fill(rawData.begin(), rawData.end(), 0);
if (!rawData.empty()) {
std::fill(rawData.begin(), rawData.end(), 0);
std::uint8_t* outPtr = rawData.data();
for (std::size_t i = 0; i < count; ++i) {
if (!get(items[i], type, outPtr)) {
// throw?
if (!get(attr.get(i), type, outPtr)) {
// missing type conversion
assert(false);
}
outPtr += stride_;
}
}
dirty = false;
rawType = type;
attr.setDirty(false);
}
return rawData;
}

View File

@@ -844,7 +844,7 @@ void SymbolLayout::createBucket(const ImagePositions&,
for (auto& pair : bucket->paintProperties) {
pair.second.iconBinders.populateVertexVectors(
feature, iconBuffer.vertices.elements(), symbolInstance.dataFeatureIndex, {}, {}, canonical);
feature, iconBuffer.vertices().elements(), symbolInstance.dataFeatureIndex, {}, {}, canonical);
}
}
@@ -932,7 +932,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket,
const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex));
for (auto& pair : bucket.paintProperties) {
pair.second.textBinders.populateVertexVectors(
feature, bucket.text.vertices.elements(), feature.index, {}, {}, canonical, formattedSection);
feature, bucket.text.vertices().elements(), feature.index, {}, {}, canonical, formattedSection);
}
}
@@ -1002,7 +1002,7 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
if (buffer.segments.empty() ||
buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max() ||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
buffer.segments.emplace_back(buffer.vertices.elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey);
buffer.segments.emplace_back(buffer.vertices().elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey);
}
// We're generating triangle fans, so we always start with the first
@@ -1012,57 +1012,58 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
auto index = static_cast<uint16_t>(segment.vertexLength);
// coordinates (2 triangles)
buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
tl,
symbol.glyphOffset.y,
tex.x,
tex.y,
sizeData,
symbol.isSDF,
pixelOffsetTL,
minFontScale));
buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
tr,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y,
sizeData,
symbol.isSDF,
{pixelOffsetBR.x, pixelOffsetTL.y},
minFontScale));
buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
bl,
symbol.glyphOffset.y,
tex.x,
tex.y + tex.h,
sizeData,
symbol.isSDF,
{pixelOffsetTL.x, pixelOffsetBR.y},
minFontScale));
buffer.vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
br,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y + tex.h,
sizeData,
symbol.isSDF,
pixelOffsetBR,
minFontScale));
auto& vertices = buffer.vertices();
vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
tl,
symbol.glyphOffset.y,
tex.x,
tex.y,
sizeData,
symbol.isSDF,
pixelOffsetTL,
minFontScale));
vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
tr,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y,
sizeData,
symbol.isSDF,
{pixelOffsetBR.x, pixelOffsetTL.y},
minFontScale));
vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
bl,
symbol.glyphOffset.y,
tex.x,
tex.y + tex.h,
sizeData,
symbol.isSDF,
{pixelOffsetTL.x, pixelOffsetBR.y},
minFontScale));
vertices.emplace_back(SymbolSDFIconProgram::layoutVertex(labelAnchor.point,
br,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y + tex.h,
sizeData,
symbol.isSDF,
pixelOffsetBR,
minFontScale));
// Dynamic/Opacity vertices are initialized so that the vertex count always
// agrees with the layout vertex buffer, but they will always be updated
// before rendering happens
auto dynamicVertex = SymbolSDFIconProgram::dynamicLayoutVertex(labelAnchor.point, 0);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
auto opacityVertex = SymbolSDFIconProgram::opacityVertex(1.0, 1.0);
buffer.opacityVertices.emplace_back(opacityVertex);
buffer.opacityVertices.emplace_back(opacityVertex);
buffer.opacityVertices.emplace_back(opacityVertex);
buffer.opacityVertices.emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
// add the two triangles, referencing the four coordinates we just inserted.
buffer.triangles.emplace_back(index + 0, index + 1, index + 2);

View File

@@ -21,9 +21,12 @@ CircleBucket::CircleBucket(const std::map<std::string, Immutable<LayerProperties
}
}
CircleBucket::~CircleBucket() = default;
CircleBucket::~CircleBucket() {
sharedVertices->release();
}
void CircleBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (!uploaded) {
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
@@ -32,6 +35,7 @@ void CircleBucket::upload(gfx::UploadPass& uploadPass) {
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}

View File

@@ -30,12 +30,17 @@ public:
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
gfx::VertexVector<CircleLayoutVertex> vertices;
using VertexVector = gfx::VertexVector<CircleLayoutVertex>;
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices = *sharedVertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<CircleAttributes> segments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<CircleLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
std::map<std::string, CircleProgram::Binders> paintPropertyBinders;

View File

@@ -71,6 +71,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id,
}
void DebugBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (!vertices.empty()) {
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
indexBuffer = uploadPass.createIndexBuffer(std::move(indices));
@@ -80,6 +81,7 @@ void DebugBucket::upload(gfx::UploadPass& uploadPass) {
static const PremultipliedImage emptyImage{Size(1, 1), data.data(), data.size()};
texture = uploadPass.createTexture(emptyImage);
}
#endif // MLN_LEGACY_RENDERER
}
} // namespace mbgl

View File

@@ -49,7 +49,9 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties&,
}
}
FillBucket::~FillBucket() = default;
FillBucket::~FillBucket() {
sharedVertices->release();
}
void FillBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
@@ -131,6 +133,7 @@ void FillBucket::addFeature(const GeometryTileFeature& feature,
}
void FillBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (!uploaded) {
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines));
@@ -141,6 +144,7 @@ void FillBucket::upload(gfx::UploadPass& uploadPass) {
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}

View File

@@ -40,15 +40,20 @@ public:
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
gfx::VertexVector<FillLayoutVertex> vertices;
using VertexVector = gfx::VertexVector<FillLayoutVertex>;
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices = *sharedVertices;
gfx::IndexVector<gfx::Lines> lines;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<FillAttributes> lineSegments;
SegmentVector<FillAttributes> triangleSegments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<FillLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> lineIndexBuffer;
std::optional<gfx::IndexBuffer> triangleIndexBuffer;
#endif // MLN_LEGACY_RENDERER
std::map<std::string, FillProgram::Binders> paintPropertyBinders;
};

View File

@@ -52,7 +52,9 @@ FillExtrusionBucket::FillExtrusionBucket(
}
}
FillExtrusionBucket::~FillExtrusionBucket() = default;
FillExtrusionBucket::~FillExtrusionBucket() {
sharedVertices->release();
}
void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
@@ -168,6 +170,7 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
}
void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (!uploaded) {
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
@@ -176,6 +179,7 @@ void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) {
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}

View File

@@ -39,12 +39,17 @@ public:
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
gfx::VertexVector<FillExtrusionLayoutVertex> vertices;
using VertexVector = gfx::VertexVector<FillExtrusionLayoutVertex>;
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices = *sharedVertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<FillExtrusionAttributes> triangleSegments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<FillExtrusionLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
std::unordered_map<std::string, FillExtrusionProgram::Binders> paintPropertyBinders;
};

View File

@@ -21,15 +21,19 @@ HeatmapBucket::HeatmapBucket(const BucketParameters& parameters,
}
}
HeatmapBucket::~HeatmapBucket() = default;
HeatmapBucket::~HeatmapBucket() {
sharedVertices->release();
}
void HeatmapBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}

View File

@@ -30,12 +30,17 @@ public:
float getQueryRadius(const RenderLayer&) const override;
gfx::VertexVector<HeatmapLayoutVertex> vertices;
using VertexVector = gfx::VertexVector<HeatmapLayoutVertex>;
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices = *sharedVertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<HeatmapAttributes> segments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<HeatmapLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
std::map<std::string, HeatmapProgram::Binders> paintPropertyBinders;

View File

@@ -29,6 +29,7 @@ void HillshadeBucket::upload(gfx::UploadPass& uploadPass) {
return;
}
#if MLN_LEGACY_RENDERER
const PremultipliedImage* image = demdata.getImage();
dem = uploadPass.createTexture(*image);
@@ -38,13 +39,17 @@ void HillshadeBucket::upload(gfx::UploadPass& uploadPass) {
if (!indices.empty()) {
indexBuffer = uploadPass.createIndexBuffer(std::move(indices));
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}
void HillshadeBucket::clear() {
#if MLN_LEGACY_RENDERER
vertexBuffer = {};
indexBuffer = {};
#endif // MLN_LEGACY_RENDERER
segments.clear();
vertices.clear();
indices.clear();

View File

@@ -44,8 +44,10 @@ public:
gfx::IndexVector<gfx::Triangles> indices;
SegmentVector<HillshadeAttributes> segments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<HillshadeLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
private:
DEMData demdata;

View File

@@ -25,7 +25,9 @@ LineBucket::LineBucket(LineBucket::PossiblyEvaluatedLayoutProperties layout_,
}
}
LineBucket::~LineBucket() = default;
LineBucket::~LineBucket() {
sharedVertices->release();
}
void LineBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometryCollection,
@@ -575,6 +577,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
}
void LineBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (!uploaded) {
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
@@ -583,6 +586,7 @@ void LineBucket::upload(gfx::UploadPass& uploadPass) {
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}

View File

@@ -42,12 +42,17 @@ public:
PossiblyEvaluatedLayoutProperties layout;
gfx::VertexVector<LineLayoutVertex> vertices;
using VertexVector = gfx::VertexVector<LineLayoutVertex>;
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices = *sharedVertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<LineAttributes> segments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<LineLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
std::map<std::string, LineProgram::Binders> paintPropertyBinders;

View File

@@ -19,6 +19,7 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) {
if (!hasData()) {
return;
}
#if MLN_LEGACY_RENDERER
if (!texture) {
texture = uploadPass.createTexture(*image);
}
@@ -28,12 +29,16 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) {
if (!indices.empty()) {
indexBuffer = uploadPass.createIndexBuffer(std::move(indices));
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}
void RasterBucket::clear() {
#if MLN_LEGACY_RENDERER
vertexBuffer = {};
indexBuffer = {};
#endif // MLN_LEGACY_RENDERER
segments.clear();
vertices.clear();
indices.clear();

View File

@@ -36,8 +36,10 @@ public:
gfx::IndexVector<gfx::Triangles> indices;
SegmentVector<RasterAttributes> segments;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<RasterLayoutVertex>> vertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
};
} // namespace mbgl

View File

@@ -63,12 +63,13 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
SymbolBucket::~SymbolBucket() = default;
void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
#if MLN_LEGACY_RENDERER
if (hasTextData()) {
if (!staticUploaded) {
text.indexBuffer = uploadPass.createIndexBuffer(
std::move(text.triangles),
sortFeaturesByY ? gfx::BufferUsageType::StreamDraw : gfx::BufferUsageType::StaticDraw);
text.vertexBuffer = uploadPass.createVertexBuffer(std::move(text.vertices));
text.vertexBuffer = uploadPass.createVertexBuffer(text.vertices());
for (auto& pair : paintProperties) {
pair.second.textBinders.upload(uploadPass);
}
@@ -78,18 +79,18 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
if (!dynamicUploaded) {
if (!text.dynamicVertexBuffer) {
text.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(text.dynamicVertices),
text.dynamicVertexBuffer = uploadPass.createVertexBuffer(text.dynamicVertices(),
gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*text.dynamicVertexBuffer, std::move(text.dynamicVertices));
uploadPass.updateVertexBuffer(*text.dynamicVertexBuffer, text.dynamicVertices());
}
}
if (!placementChangesUploaded) {
if (!text.opacityVertexBuffer) {
text.opacityVertexBuffer = uploadPass.createVertexBuffer(std::move(text.opacityVertices),
text.opacityVertexBuffer = uploadPass.createVertexBuffer(text.opacityVertices(),
gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*text.opacityVertexBuffer, std::move(text.opacityVertices));
uploadPass.updateVertexBuffer(*text.opacityVertexBuffer, text.opacityVertices());
}
}
}
@@ -99,7 +100,7 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
iconBuffer.indexBuffer = uploadPass.createIndexBuffer(
std::move(iconBuffer.triangles),
sortFeaturesByY ? gfx::BufferUsageType::StreamDraw : gfx::BufferUsageType::StaticDraw);
iconBuffer.vertexBuffer = uploadPass.createVertexBuffer(std::move(iconBuffer.vertices));
iconBuffer.vertexBuffer = uploadPass.createVertexBuffer(iconBuffer.vertices());
for (auto& pair : paintProperties) {
pair.second.iconBinders.upload(uploadPass);
}
@@ -108,18 +109,18 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
}
if (!dynamicUploaded) {
if (!iconBuffer.dynamicVertexBuffer) {
iconBuffer.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(iconBuffer.dynamicVertices),
iconBuffer.dynamicVertexBuffer = uploadPass.createVertexBuffer(iconBuffer.dynamicVertices(),
gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*iconBuffer.dynamicVertexBuffer, std::move(iconBuffer.dynamicVertices));
uploadPass.updateVertexBuffer(*iconBuffer.dynamicVertexBuffer, iconBuffer.dynamicVertices());
}
}
if (!placementChangesUploaded) {
if (!iconBuffer.opacityVertexBuffer) {
iconBuffer.opacityVertexBuffer = uploadPass.createVertexBuffer(std::move(iconBuffer.opacityVertices),
iconBuffer.opacityVertexBuffer = uploadPass.createVertexBuffer(iconBuffer.opacityVertices(),
gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*iconBuffer.opacityVertexBuffer, std::move(iconBuffer.opacityVertices));
uploadPass.updateVertexBuffer(*iconBuffer.opacityVertexBuffer, iconBuffer.opacityVertices());
}
}
};
@@ -175,6 +176,7 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
if (hasTextCollisionCircleData()) {
updateCollisionCircle(*textCollisionCircle);
}
#endif // MLN_LEGACY_RENDERER
uploaded = true;
staticUploaded = true;

View File

@@ -13,6 +13,7 @@
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/text/placement.hpp>
#include <memory>
#include <vector>
namespace mbgl {
@@ -132,18 +133,41 @@ public:
std::unique_ptr<SymbolSizeBinder> textSizeBinder;
struct Buffer {
gfx::VertexVector<SymbolLayoutVertex> vertices;
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>> dynamicVertices;
gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>> opacityVertices;
using VertexVector = gfx::VertexVector<SymbolLayoutVertex>;
using VertexBuffer = gfx::VertexBuffer<SymbolLayoutVertex>;
using DynamicVertexVector = gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
using DynamicVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
using OpacityVertexVector = gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>>;
using OpacityVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>;
struct Buffer final {
~Buffer() {
sharedVertices->release();
sharedDynamicVertices->release();
sharedOpacityVertices->release();
}
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices() { return *sharedVertices; }
const VertexVector& vertices() const { return *sharedVertices; }
std::shared_ptr<DynamicVertexVector> sharedDynamicVertices = std::make_shared<DynamicVertexVector>();
DynamicVertexVector& dynamicVertices() { return *sharedDynamicVertices; }
const DynamicVertexVector& dynamicVertices() const { return *sharedDynamicVertices; }
std::shared_ptr<OpacityVertexVector> sharedOpacityVertices = std::make_shared<OpacityVertexVector>();
OpacityVertexVector& opacityVertices() { return *sharedOpacityVertices; }
const OpacityVertexVector& opacityVertices() const { return *sharedOpacityVertices; }
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<SymbolTextAttributes> segments;
std::vector<PlacedSymbol> placedSymbols;
std::optional<gfx::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
std::optional<gfx::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>> dynamicVertexBuffer;
std::optional<gfx::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>> opacityVertexBuffer;
#if MLN_LEGACY_RENDERER
std::optional<VertexBuffer> vertexBuffer;
std::optional<DynamicVertexBuffer> dynamicVertexBuffer;
std::optional<OpacityVertexBuffer> opacityVertexBuffer;
std::optional<gfx::IndexBuffer> indexBuffer;
#endif // MLN_LEGACY_RENDERER
} text;
std::unique_ptr<SymbolSizeBinder> iconSizeBinder;

View File

@@ -60,6 +60,13 @@ RenderCircleLayer::RenderCircleLayer(Immutable<style::CircleLayer::Impl> _impl)
: RenderLayer(makeMutable<CircleLayerProperties>(std::move(_impl))),
unevaluated(impl_cast(baseImpl).paint.untransitioned()) {}
void RenderCircleLayer::prepare(const LayerPrepareParameters& parameters) {
RenderLayer::prepare(parameters);
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
void RenderCircleLayer::transition(const TransitionParameters& parameters) {
unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
}
@@ -256,6 +263,9 @@ bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryG
}
#if MLN_DRAWABLE_RENDERER
namespace {
struct alignas(16) CircleInterpolateUBO {
float color_t;
float radius_t;
@@ -268,8 +278,11 @@ struct alignas(16) CircleInterpolateUBO {
};
static_assert(sizeof(CircleInterpolateUBO) % 16 == 0);
static const std::string CircleShaderGroupName = "CircleShader";
static constexpr std::string_view CircleInterpolateUBOName = "CircleInterpolateUBO";
constexpr auto CircleShaderGroupName = "CircleShader";
constexpr auto CircleInterpolateUBOName = "CircleInterpolateUBO";
constexpr auto VertexAttribName = "a_pos";
} // namespace
void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context,
@@ -301,8 +314,6 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
}
std::unique_ptr<gfx::DrawableBuilder> circleBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray circleVertexAttrs;
constexpr auto renderPass = RenderPass::Translucent;
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
@@ -324,10 +335,11 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
auto& bucket = static_cast<CircleBucket&>(*renderData->bucket);
const auto& bucket = static_cast<const CircleBucket&>(*renderData->bucket);
const auto vertexCount = bucket.vertices.elements();
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
float zoom = static_cast<float>(state.getZoom());
const float zoom = static_cast<float>(state.getZoom());
const CircleInterpolateUBO interpolateUBO = {
/* .color_t = */ std::get<0>(paintPropertyBinders.get<CircleColor>()->interpolationFactor(zoom)),
/* .radius_t = */ std::get<0>(paintPropertyBinders.get<CircleRadius>()->interpolationFactor(zoom)),
@@ -349,9 +361,8 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
circleVertexAttrs.clear();
auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
gfx::VertexAttributeArray circleVertexAttrs;
const auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
CircleRadius,
CircleBlur,
CircleOpacity,
@@ -360,34 +371,25 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
CircleStrokeOpacity>(
paintPropertyBinders, evaluated);
auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!circleShader) {
continue;
}
std::vector<std::array<int16_t, 2>> rawVerts;
const auto buildVertices = [&]() {
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
verts = bucket.vertices.vector();
if (rawVerts.size() < verts.size()) {
rawVerts.resize(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
}
};
if (const auto& attr = circleVertexAttrs.add(VertexAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(CircleLayoutVertex, a1), 0, sizeof(CircleLayoutVertex), gfx::AttributeDataType::Short2);
}
circleBuilder = context.createDrawableBuilder("circle");
circleBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(circleShader));
circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
: gfx::DepthMaskType::ReadOnly);
circleBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
circleBuilder->setColorMode(gfx::ColorMode::alphaBlended());
circleBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
circleBuilder->setRenderPass(renderPass);
circleBuilder->setVertexAttributes(circleVertexAttrs);
buildVertices();
circleBuilder->addVertices(rawVerts, 0, rawVerts.size());
circleBuilder->setVertexAttributes(std::move(circleVertexAttrs));
circleBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
circleBuilder->setSegments(
gfx::Triangles(), bucket.triangles.vector(), bucket.segments.data(), bucket.segments.size());

View File

@@ -23,6 +23,7 @@ public:
#endif
private:
void prepare(const LayerPrepareParameters&) override;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;

View File

@@ -39,6 +39,7 @@ namespace {
constexpr std::string_view FillExtrusionShaderName = "FillExtrusionShader";
constexpr std::string_view FillExtrusionPatternShaderName = "FillExtrusionPatternShader";
constexpr auto PosAttribName = "a_pos";
constexpr auto NormAttribName = "a_normal_ed";
constexpr auto IconTextureName = "u_image";
@@ -350,8 +351,6 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
}
const auto vertexCount = bucket.vertices.elements();
constexpr auto vertexSize = sizeof(FillExtrusionLayoutVertex::a1);
const auto defPattern = mbgl::Faded<expression::Image>{"", ""};
const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(defPattern);
const auto patternPosA = tile.getPattern(fillPatternValue.from.id());
@@ -450,30 +449,22 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
}
}
if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) {
const auto count = bucket.vertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, util::cast<float>(bucket.vertices.at(i).a2)); // int16_t x4
}
if (const auto& attr = vertexAttrs.getOrAdd(PosAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a1), 0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short2);
}
std::vector<uint8_t> rawVertices(vertexSize * vertexCount);
for (std::size_t i = 0; i < vertexCount; ++i) {
std::memcpy(&rawVertices[vertexSize * i], &bucket.vertices.at(i).a1, vertexSize);
if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a2), 0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short4);
}
colorBuilder->setEnableStencil(doDepthPass);
if (doDepthPass) {
auto vertexCopy = rawVertices;
depthBuilder->setRawVertices(std::move(vertexCopy), vertexCount, gfx::AttributeDataType::Short2);
depthBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
}
colorBuilder->setRawVertices(std::move(rawVertices), vertexCount, gfx::AttributeDataType::Short2);
colorBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
if (doDepthPass) {
gfx::VertexAttributeArray attribCopy;
attribCopy.copy(vertexAttrs);
depthBuilder->setVertexAttributes(std::move(attribCopy));
auto copy = vertexAttrs.clone();
depthBuilder->setVertexAttributes(std::move(*copy));
}
colorBuilder->setVertexAttributes(std::move(vertexAttrs));

View File

@@ -42,6 +42,7 @@ constexpr auto FillOutlineShaderName = "FillOutlineShader";
constexpr auto FillPatternShaderName = "FillPatternShader";
constexpr auto FillOutlinePatternShaderName = "FillOutlinePatternShader";
constexpr auto PosAttribName = "a_pos";
constexpr auto IconTextureName = "u_image";
#endif // MLN_DRAWABLE_RENDERER
@@ -58,6 +59,13 @@ RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl)
RenderFillLayer::~RenderFillLayer() = default;
void RenderFillLayer::prepare(const LayerPrepareParameters& params) {
RenderLayer::prepare(params);
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
void RenderFillLayer::transition(const TransitionParameters& parameters) {
unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
}
@@ -329,10 +337,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
std::unique_ptr<gfx::DrawableBuilder> outlineBuilder;
std::unique_ptr<gfx::DrawableBuilder> patternBuilder;
std::unique_ptr<gfx::DrawableBuilder> outlinePatternBuilder;
gfx::VertexAttributeArray fillVertexAttrs;
gfx::VertexAttributeArray outlineVertexAttrs;
gfx::VertexAttributeArray patternVertexAttrs;
gfx::VertexAttributeArray patternOutlineVertexAttrs;
const auto layerPrefix = getID() + "/";
const auto renderPass = static_cast<RenderPass>(evaluatedProperties->renderPasses);
@@ -414,36 +418,27 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
std::vector<std::array<int16_t, 2>> rawVerts;
const auto buildVertices = [&]() {
const auto& verts = bucket.vertices.vector();
if (rawVerts.size() < verts.size()) {
rawVerts.resize(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
}
};
fillVertexAttrs.clear();
outlineVertexAttrs.clear();
// `Fill*Program` all use `style::FillPaintProperties`
const auto fillUniformProps =
fillVertexAttrs.readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
binders, evaluated);
const auto outlineUniformProps =
outlineVertexAttrs.readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
gfx::VertexAttributeArray vertexAttrs;
const auto uniformProps =
vertexAttrs.readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
binders, evaluated);
const auto vertexCount = bucket.vertices.elements();
if (const auto& attr = vertexAttrs.add(PosAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(FillLayoutVertex, a1), 0, sizeof(FillLayoutVertex), gfx::AttributeDataType::Short2);
}
if (unevaluated.get<FillPattern>().isUndefined()) {
// Fill will occur in opaque or translucent pass based on `opaquePassCutoff`.
// Outline always occurs in translucent pass, defaults to fill color
const auto doOutline = evaluated.get<FillAntialias>();
const auto fillShader = std::static_pointer_cast<gfx::ShaderProgramBase>(
fillShaderGroup->getOrCreateShader(context, fillUniformProps));
fillShaderGroup->getOrCreateShader(context, uniformProps));
const auto outlineShader = doOutline
? std::static_pointer_cast<gfx::ShaderProgramBase>(
outlineShaderGroup->getOrCreateShader(context, outlineUniformProps))
outlineShaderGroup->getOrCreateShader(context, uniformProps))
: nullptr;
if (!fillBuilder && fillShader) {
@@ -471,10 +466,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
}
if (fillBuilder) {
buildVertices();
fillBuilder->setShader(fillShader);
fillBuilder->setVertexAttributes(fillVertexAttrs);
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
if (outlineBuilder) {
fillBuilder->setVertexAttributes(vertexAttrs);
} else {
fillBuilder->setVertexAttributes(std::move(vertexAttrs));
}
fillBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
fillBuilder->setSegments(gfx::Triangles(),
bucket.triangles.vector(),
bucket.triangleSegments.data(),
@@ -482,10 +480,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
finish(*fillBuilder, tileID, interpolateUBO, tileProps);
}
if (outlineBuilder) {
buildVertices();
outlineBuilder->setShader(outlineShader);
outlineBuilder->setVertexAttributes(outlineVertexAttrs);
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
outlineBuilder->setVertexAttributes(std::move(vertexAttrs));
outlineBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
outlineBuilder->setSegments(
gfx::Lines(2), bucket.lines.vector(), bucket.lineSegments.data(), bucket.lineSegments.size());
finish(*outlineBuilder, tileID, interpolateUBO, tileProps);
@@ -499,10 +496,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
const auto doOutline = evaluated.get<FillAntialias>() && unevaluated.get<FillOutlineColor>().isUndefined();
const auto fillShader = std::static_pointer_cast<gfx::ShaderProgramBase>(
patternShaderGroup->getOrCreateShader(context, fillUniformProps));
patternShaderGroup->getOrCreateShader(context, uniformProps));
const auto outlineShader = doOutline ? std::static_pointer_cast<gfx::ShaderProgramBase>(
outlinePatternShaderGroup->getOrCreateShader(
context, outlineUniformProps))
context, uniformProps))
: nullptr;
if (!patternBuilder) {
@@ -527,14 +524,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
}
}
gfx::DrawableTweakerPtr tweaker;
if (patternBuilder) {
patternBuilder->clearTweakers();
}
if (outlinePatternBuilder) {
outlinePatternBuilder->clearTweakers();
}
if ((patternBuilder || outlinePatternBuilder) && !tweaker) {
if (patternBuilder || outlinePatternBuilder) {
if (const auto& atlases = tile.getAtlasTextures()) {
auto tweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(atlases,
/*glyphName=*/std::string(),
@@ -550,11 +546,14 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
}
if (patternBuilder) {
buildVertices();
patternBuilder->setShader(fillShader);
patternBuilder->setRenderPass(renderPass);
patternBuilder->setVertexAttributes(fillVertexAttrs);
patternBuilder->addVertices(rawVerts, 0, rawVerts.size());
if (outlinePatternBuilder) {
patternBuilder->setVertexAttributes(vertexAttrs);
} else {
patternBuilder->setVertexAttributes(std::move(vertexAttrs));
}
patternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
patternBuilder->setSegments(gfx::Triangles(),
bucket.triangles.vector(),
bucket.triangleSegments.data(),
@@ -563,11 +562,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
finish(*patternBuilder, tileID, interpolateUBO, tileProps);
}
if (outlinePatternBuilder) {
buildVertices();
outlinePatternBuilder->setShader(outlineShader);
outlinePatternBuilder->setRenderPass(renderPass);
outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs);
outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size());
outlinePatternBuilder->setVertexAttributes(std::move(vertexAttrs));
outlinePatternBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
outlinePatternBuilder->setSegments(
gfx::Lines(2), bucket.lines.vector(), bucket.lineSegments.data(), bucket.lineSegments.size());

View File

@@ -30,6 +30,7 @@ public:
#endif
private:
void prepare(const LayerPrepareParameters&) override;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;

View File

@@ -45,6 +45,13 @@ RenderHeatmapLayer::RenderHeatmapLayer(Immutable<HeatmapLayer::Impl> _impl)
RenderHeatmapLayer::~RenderHeatmapLayer() = default;
void RenderHeatmapLayer::prepare(const LayerPrepareParameters& parameters) {
RenderLayer::prepare(parameters);
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
void RenderHeatmapLayer::transition(const TransitionParameters& parameters) {
unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
updateColorRamp();
@@ -260,6 +267,8 @@ void RenderHeatmapLayer::removeAllDrawables() {
}
}
namespace {
struct alignas(16) HeatmapInterpolateUBO {
float weight_t;
float radius_t;
@@ -267,9 +276,12 @@ struct alignas(16) HeatmapInterpolateUBO {
};
static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0);
static const std::string HeatmapShaderGroupName = "HeatmapShader";
static const std::string HeatmapTextureShaderGroupName = "HeatmapTextureShader";
static constexpr std::string_view HeatmapInterpolateUBOName = "HeatmapInterpolateUBO";
constexpr auto HeatmapShaderGroupName = "HeatmapShader";
constexpr auto HeatmapTextureShaderGroupName = "HeatmapTextureShader";
constexpr auto HeatmapInterpolateUBOName = "HeatmapInterpolateUBO";
constexpr auto VertexAttribName = "a_pos";
}
void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context,
@@ -318,9 +330,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
}
std::unique_ptr<gfx::DrawableBuilder> heatmapBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray heatmapVertexAttrs;
auto renderPass = RenderPass::Translucent;
constexpr auto renderPass = RenderPass::Translucent;
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
return;
@@ -341,10 +351,11 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
auto& bucket = static_cast<HeatmapBucket&>(*renderData->bucket);
const auto& bucket = static_cast<HeatmapBucket&>(*renderData->bucket);
const auto vertexCount = bucket.vertices.elements();
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
float zoom = static_cast<float>(state.getZoom());
const float zoom = static_cast<float>(state.getZoom());
const HeatmapInterpolateUBO interpolateUBO = {
/* .weight_t = */ std::get<0>(paintPropertyBinders.get<HeatmapWeight>()->interpolationFactor(zoom)),
/* .radius_t = */ std::get<0>(paintPropertyBinders.get<HeatmapRadius>()->interpolationFactor(zoom)),
@@ -358,25 +369,19 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
heatmapVertexAttrs.clear();
gfx::VertexAttributeArray heatmapVertexAttrs;
auto propertiesAsUniforms = heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(
const auto propertiesAsUniforms = heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(
paintPropertyBinders, evaluated);
auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!heatmapShader) {
continue;
}
std::vector<std::array<int16_t, 2>> rawVerts;
const auto buildVertices = [&]() {
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
verts = bucket.vertices.vector();
if (rawVerts.size() < verts.size()) {
rawVerts.resize(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
}
};
if (const auto& attr = heatmapVertexAttrs.add(VertexAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(HeatmapLayoutVertex, a1), 0, sizeof(HeatmapLayoutVertex), gfx::AttributeDataType::Short2);
}
heatmapBuilder = context.createDrawableBuilder("heatmap");
heatmapBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(heatmapShader));
@@ -384,13 +389,9 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
: gfx::DepthMaskType::ReadOnly);
heatmapBuilder->setColorMode(gfx::ColorMode::additive());
heatmapBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
heatmapBuilder->setRenderPass(renderPass);
heatmapBuilder->setVertexAttributes(heatmapVertexAttrs);
buildVertices();
heatmapBuilder->addVertices(rawVerts, 0, rawVerts.size());
heatmapBuilder->setVertexAttributes(std::move(heatmapVertexAttrs));
heatmapBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2);
heatmapBuilder->setSegments(
gfx::Triangles(), bucket.triangles.vector(), bucket.segments.data(), bucket.segments.size());
@@ -415,8 +416,6 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
setLayerGroup(std::move(layerGroup_), changes);
}
auto* textureLayerGroup = static_cast<LayerGroup*>(layerGroup.get());
if (!heatmapTextureShader) {
heatmapTextureShader = context.getGenericShader(shaders, HeatmapTextureShaderGroupName);
}
@@ -425,19 +424,20 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
return;
}
auto* textureLayerGroup = static_cast<LayerGroup*>(layerGroup.get());
textureLayerGroup->clearDrawables();
std::unique_ptr<gfx::DrawableBuilder> heatmapTextureBuilder;
std::vector<std::array<int16_t, 2>> textureRawVerts;
const auto buildTextureVertices = [&]() {
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex> verts =
RenderStaticData::heatmapTextureVertices().vector();
if (textureRawVerts.size() < verts.size()) {
textureRawVerts.resize(verts.size());
std::transform(verts.begin(), verts.end(), textureRawVerts.begin(), [](const auto& x) { return x.a1; });
}
};
if (!sharedTextureVertices) {
sharedTextureVertices = std::make_shared<TextureVertexVector>(RenderStaticData::heatmapTextureVertices());
}
const auto textureVertexCount = sharedTextureVertices->elements();
gfx::VertexAttributeArray textureVertexAttrs;
if (const auto& attr = textureVertexAttrs.add(VertexAttribName)) {
attr->setSharedRawData(sharedTextureVertices, offsetof(HeatmapLayoutVertex, a1), 0, sizeof(HeatmapLayoutVertex), gfx::AttributeDataType::Short2);
}
heatmapTextureBuilder = context.createDrawableBuilder("heatmapTexture");
heatmapTextureBuilder->setShader(heatmapTextureShader);
@@ -445,16 +445,12 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
: gfx::DepthMaskType::ReadOnly);
heatmapTextureBuilder->setColorMode(gfx::ColorMode::alphaBlended());
heatmapTextureBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
heatmapTextureBuilder->setRenderPass(renderPass);
buildTextureVertices();
heatmapTextureBuilder->addVertices(textureRawVerts, 0, textureRawVerts.size());
heatmapTextureBuilder->setVertexAttributes(std::move(textureVertexAttrs));
heatmapTextureBuilder->setRawVertices({}, textureVertexCount, gfx::AttributeDataType::Short2);
if (segments.empty()) {
segments = RenderStaticData::heatmapTextureSegments();
}
heatmapTextureBuilder->setSegments(
gfx::Triangles(), RenderStaticData::quadTriangleIndices().vector(), segments.data(), segments.size());
@@ -468,7 +464,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
texture->setImage(colorRamp);
texture->setSamplerConfiguration(
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
heatmapTextureBuilder->setTexture(texture, colorRampLocation.value());
heatmapTextureBuilder->setTexture(std::move(texture), colorRampLocation.value());
}
heatmapTextureBuilder->flush();

View File

@@ -28,6 +28,7 @@ public:
#endif
private:
void prepare(const LayerPrepareParameters&) override;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
@@ -72,6 +73,9 @@ private:
gfx::ShaderGroupPtr heatmapShaderGroup;
gfx::ShaderProgramBasePtr heatmapTextureShader;
RenderTargetPtr renderTarget;
using TextureVertexVector = gfx::VertexVector<HeatmapTextureLayoutVertex>;
std::shared_ptr<TextureVertexVector> sharedTextureVertices;
#endif
};

View File

@@ -38,6 +38,13 @@ inline const LineLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& imp
return static_cast<const LineLayer::Impl&>(*impl);
}
#if MLN_DRAWABLE_RENDERER
constexpr auto VertexAttribName = "a_pos_normal";
constexpr auto DataAttribName = "a_data";
#endif // MLN_DRAWABLE_RENDERER
} // namespace
RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl)
@@ -97,6 +104,10 @@ void RenderLineLayer::prepare(const LayerPrepareParameters& params) {
params.lineAtlas.getDashPatternTexture(
evaluated.get<LineDasharray>().from, evaluated.get<LineDasharray>().to, cap);
}
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
void RenderLineLayer::upload(gfx::UploadPass& uploadPass) {
@@ -461,31 +472,27 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
: gfx::ColorMode::unblended());
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
builder->setEnableStencil(true);
builder->setVertexAttrName("a_pos_normal");
builder->setVertexAttrName(VertexAttribName);
return builder;
};
auto addVertices = [&](std::unique_ptr<gfx::DrawableBuilder>& builder, const LineBucket& bucket) {
std::vector<std::array<int16_t, 2>> vertices;
vertices.resize(bucket.vertices.vector().size());
std::transform(
bucket.vertices.vector().begin(), bucket.vertices.vector().end(), vertices.begin(), [](const auto& x) {
return x.a1;
});
builder->addVertices(vertices, 0, vertices.size());
};
auto addAttributes = [&](std::unique_ptr<gfx::DrawableBuilder>& builder,
auto addAttributes = [&](gfx::DrawableBuilder& builder,
const LineBucket& bucket,
gfx::VertexAttributeArray& vertexAttrs) {
if (auto& attr = vertexAttrs.getOrAdd("a_data")) {
size_t index{0};
for (const auto& vert : bucket.vertices.vector()) {
attr->set(index++, gfx::VertexAttribute::int4{vert.a2[0], vert.a2[1], vert.a2[2], vert.a2[3]});
}
gfx::VertexAttributeArray&& vertexAttrs) {
const auto vertexCount = bucket.vertices.elements();
builder.setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4);
if (const auto& attr = vertexAttrs.add(VertexAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a1), 0, sizeof(LineLayoutVertex), gfx::AttributeDataType::Short2);
}
builder->setVertexAttributes(std::move(vertexAttrs));
if (const auto& attr = vertexAttrs.add(DataAttribName)) {
attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a2), 0, sizeof(LineLayoutVertex), gfx::AttributeDataType::UByte4);
}
builder.setVertexAttributes(std::move(vertexAttrs));
};
auto setSegments = [&](std::unique_ptr<gfx::DrawableBuilder>& builder, const LineBucket& bucket) {
@@ -508,8 +515,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
const auto& crossfade = getCrossfade<LineLayerProperties>(renderData->layerProperties);
// interpolation UBOs
float zoom = static_cast<float>(state.getZoom());
LineInterpolationUBO lineInterpolationUBO{
const float zoom = static_cast<float>(state.getZoom());
const LineInterpolationUBO lineInterpolationUBO{
/*color_t =*/std::get<0>(paintPropertyBinders.get<LineColor>()->interpolationFactor(zoom)),
/*blur_t =*/std::get<0>(paintPropertyBinders.get<LineBlur>()->interpolationFactor(zoom)),
/*opacity_t =*/std::get<0>(paintPropertyBinders.get<LineOpacity>()->interpolationFactor(zoom)),
@@ -518,7 +525,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
/*width_t =*/std::get<0>(paintPropertyBinders.get<LineWidth>()->interpolationFactor(zoom)),
0,
0};
LineGradientInterpolationUBO lineGradientInterpolationUBO{
const LineGradientInterpolationUBO lineGradientInterpolationUBO{
/*blur_t =*/std::get<0>(paintPropertyBinders.get<LineBlur>()->interpolationFactor(zoom)),
/*opacity_t =*/std::get<0>(paintPropertyBinders.get<LineOpacity>()->interpolationFactor(zoom)),
/*gapwidth_t =*/std::get<0>(paintPropertyBinders.get<LineGapWidth>()->interpolationFactor(zoom)),
@@ -526,7 +533,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
/*width_t =*/std::get<0>(paintPropertyBinders.get<LineWidth>()->interpolationFactor(zoom)),
0,
{0, 0}};
LinePatternInterpolationUBO linePatternInterpolationUBO{
const LinePatternInterpolationUBO linePatternInterpolationUBO{
/*blur_t =*/std::get<0>(paintPropertyBinders.get<LineBlur>()->interpolationFactor(zoom)),
/*opacity_t =*/std::get<0>(paintPropertyBinders.get<LineOpacity>()->interpolationFactor(zoom)),
/*offset_t =*/std::get<0>(paintPropertyBinders.get<LineOffset>()->interpolationFactor(zoom)),
@@ -535,7 +542,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
/*pattern_from_t =*/std::get<0>(paintPropertyBinders.get<LinePattern>()->interpolationFactor(zoom)),
/*pattern_to_t =*/std::get<1>(paintPropertyBinders.get<LinePattern>()->interpolationFactor(zoom)),
0};
LineSDFInterpolationUBO lineSDFInterpolationUBO{
const LineSDFInterpolationUBO lineSDFInterpolationUBO{
/*color_t =*/std::get<0>(paintPropertyBinders.get<LineColor>()->interpolationFactor(zoom)),
/*blur_t =*/std::get<0>(paintPropertyBinders.get<LineBlur>()->interpolationFactor(zoom)),
/*opacity_t =*/std::get<0>(paintPropertyBinders.get<LineOpacity>()->interpolationFactor(zoom)),
@@ -547,9 +554,9 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
// tile dependent properties UBOs:
const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<expression::Image>{"", ""});
std::optional<ImagePosition> patternPosA = tile.getPattern(linePatternValue.from.id());
std::optional<ImagePosition> patternPosB = tile.getPattern(linePatternValue.to.id());
LinePatternTilePropertiesUBO linePatternTilePropertiesUBO{
const std::optional<ImagePosition> patternPosA = tile.getPattern(linePatternValue.from.id());
const std::optional<ImagePosition> patternPosB = tile.getPattern(linePatternValue.to.id());
const LinePatternTilePropertiesUBO linePatternTilePropertiesUBO{
/*pattern_from =*/patternPosA ? util::cast<float>(patternPosA->tlbr()) : std::array<float, 4>{0},
/*pattern_to =*/patternPosB ? util::cast<float>(patternPosB->tlbr()) : std::array<float, 4>{0}};
@@ -586,7 +593,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
if (!evaluated.get<LineDasharray>().from.empty()) {
// dash array line (SDF)
gfx::VertexAttributeArray vertexAttrs;
auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
const auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
LineBlur,
LineOpacity,
LineGapWidth,
@@ -598,8 +605,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms));
// vertices, attributes and segments
addVertices(builder, bucket);
addAttributes(builder, bucket, vertexAttrs);
addAttributes(*builder, bucket, std::move(vertexAttrs));
setSegments(builder, bucket);
// finish
@@ -630,8 +636,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms));
// vertices and attributes
addVertices(builder, bucket);
addAttributes(builder, bucket, vertexAttrs);
addAttributes(*builder, bucket, std::move(vertexAttrs));
// texture
if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) {
@@ -667,8 +672,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms));
// vertices and attributes
addVertices(builder, bucket);
addAttributes(builder, bucket, vertexAttrs);
addAttributes(*builder, bucket, std::move(vertexAttrs));
// texture
if (const auto samplerLocation = builder->getShader()->getSamplerLocation("u_image")) {
@@ -702,7 +706,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
} else {
// simple line
gfx::VertexAttributeArray vertexAttrs;
auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
const auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
LineBlur,
LineOpacity,
LineGapWidth,
@@ -712,8 +716,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
auto builder = createLineBuilder("line", lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms));
// vertices, attributes and segments
addVertices(builder, bucket);
addAttributes(builder, bucket, vertexAttrs);
addAttributes(*builder, bucket, std::move(vertexAttrs));
setSegments(builder, bucket);
// finish

View File

@@ -756,44 +756,34 @@ void updateTileDrawable(gfx::Drawable& drawable,
if (!drawable.getData()) {
return;
}
auto& drawData = static_cast<gfx::SymbolDrawableData&>(*drawable.getData());
const auto isText = (drawData.symbolType == SymbolType::Text);
const auto currentZoom = static_cast<float>(state.getZoom());
// This property can be set after the initial appearance of the tile, as part of the layout process.
drawData.bucketVariablePlacement = bucket.hasVariablePlacement;
const auto tileUBO = buildTileUBO(bucket, drawData, currentZoom);
const auto interpolateUBO = buildInterpUBO(paintProps, isText, currentZoom);
auto& uniforms = drawable.mutableUniformBuffers();
uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableTilePropsUBOName, &tileUBO, context);
uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableInterpolateUBOName, &interpolateUBO, context);
// TODO: detect whether anything has actually changed
// See `Placement::updateBucketDynamicVertices`
if (const auto newAttribs = drawable.getVertexAttributes().clone()) {
const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF);
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF);
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
if (auto& attr = newAttribs->getOrAdd(projPosAttribName)) {
const auto count = buffer.dynamicVertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, util::cast<float>(buffer.dynamicVertices.at(i).a1));
}
}
if (auto& attr = newAttribs->getOrAdd(fadeOpacityAttribName)) {
const auto count = buffer.opacityVertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, buffer.opacityVertices.at(i).a1[0]);
}
}
drawable.setVertexAttributes(std::move(*newAttribs));
auto& attribs = drawable.mutableVertexAttributes();
if (const auto& attr = attribs.get(projPosAttribName)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3);
}
if (const auto& attr = attribs.get(fadeOpacityAttribName)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float);
}
}
@@ -884,7 +874,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
const SymbolType type) mutable {
for (const auto& segment : buffer.segments) {
const auto key = sortFeaturesByKey ? segment.sortKey : (serialKey += 1.0);
assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices.elements());
assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices().elements());
it = renderableSegments.emplace_hint(
it, std::ref(segment), tile, renderData, bucketPaintProperties, key, type, tileID.overscaledZ);
}
@@ -927,46 +917,25 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
auto& tileInfo = tileCache[tile.id];
const auto buildVertices = [&](const SymbolBucket::Buffer& buffer_, RawVertexVec& dest) -> auto& {
const std::vector<SymbolLayoutVertex>& src = buffer_.vertices.vector();
const auto vertSize = sizeof(SymbolLayoutVertex::a1);
if (dest.size() != vertSize * src.size()) {
dest.resize(vertSize * src.size());
for (std::size_t i = 0; i < src.size(); ++i) {
std::memcpy(&dest[vertSize * i], &src[i].a1, vertSize);
}
}
return dest;
};
gfx::VertexAttributeArray attrs;
if (const auto& attr = attrs.getOrAdd(dataAttibName)) {
const auto count = buffer.vertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, util::cast<float>(buffer.vertices.at(i).a2));
}
const auto vertexCount = buffer.vertices().elements();
if (const auto& attr = attrs.add(posOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a1), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::Short4);
}
if (const auto& attr = attrs.getOrAdd(pixOffsetAttribName)) {
const auto count = buffer.vertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, util::cast<float>(buffer.vertices.at(i).a3));
}
if (const auto& attr = attrs.add(dataAttibName)) {
attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a2), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attrs.getOrAdd(projPosAttribName)) {
const auto count = buffer.dynamicVertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, util::cast<float>(buffer.dynamicVertices.at(i).a1));
}
if (const auto& attr = attrs.add(pixOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a3), 0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::Short4);
}
if (const auto& attr = attrs.getOrAdd(fadeOpacityAttribName)) {
const auto count = buffer.opacityVertices.elements();
attr->reserve(count);
for (auto i = 0ULL; i < count; ++i) {
attr->set(i, buffer.opacityVertices.at(i).a1[0]);
}
if (const auto& attr = attrs.add(projPosAttribName)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3);
}
if (const auto& attr = attrs.add(fadeOpacityAttribName)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float);
}
const auto uniformProps = isText ? attrs.readDataDrivenPaintProperties<TextOpacity,
@@ -997,10 +966,6 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
}
const auto draw = [&](const gfx::ShaderGroupPtr& shaderGroup,
const Segment<SymbolTextAttributes>& segment,
const gfx::IndexVector<gfx::Triangles>& indices,
const RawVertexVec& vertices,
const std::size_t vertexCount,
const bool isHalo,
const std::string_view suffix) {
if (!shaderGroup) {
@@ -1031,9 +996,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
builder->clearTweakers();
builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker);
builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4);
builder->setDrawableName(layerPrefix + std::string(suffix));
builder->setVertexAttributes(std::move(attrs));
builder->setVertexAttributes(attrs);
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(
shaderGroup->getOrCreateShader(context, uniformProps, posOffsetAttribName));
@@ -1047,9 +1012,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
// !partiallyEvaluatedTextSize.isZoomConstant; const auto filterType = linear ?
// gfx::TextureFilterType::Linear : gfx::TextureFilterType::Nearest;
auto raw = vertices;
builder->setRawVertices(std::move(raw), vertexCount, gfx::AttributeDataType::Short4);
builder->setSegments(gfx::Triangles(), indices.vector(), &segment, 1);
auto indexes = buffer.triangles.vector();
builder->setSegments(gfx::Triangles(), std::move(indexes), &renderable.segment.get(), 1);
builder->flush();
@@ -1078,82 +1042,34 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
};
if (isText) {
const auto& vertices = buildVertices(buffer, tileInfo.textVertices);
const auto vertexCount = buffer.vertices.elements();
const auto& indices = buffer.triangles;
if (bucket.iconsInText) {
if (textHalo) {
draw(symbolTextAndIconGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ true,
"halo");
draw(symbolTextAndIconGroup, /* isHalo = */ true, "halo");
}
if (textFill) {
draw(symbolTextAndIconGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ false,
"fill");
draw(symbolTextAndIconGroup, /* isHalo = */ false, "fill");
}
} else {
if (textHalo) {
draw(symbolSDFTextGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ true,
"halo");
draw(symbolSDFTextGroup, /* isHalo = */ true, "halo");
}
if (textFill) {
draw(symbolSDFTextGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ false,
"fill");
draw(symbolSDFTextGroup, /* isHalo = */ false, "fill");
}
}
} else { // icons
const auto& vertices = buildVertices(buffer, tileInfo.iconVertices);
const auto vertexCount = buffer.vertices.elements();
const auto& indices = buffer.triangles;
if (sdfIcons) {
if (iconHalo) {
draw(symbolSDFIconGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ true,
"halo");
draw(symbolSDFIconGroup, /* isHalo = */ true, "halo");
}
if (iconFill) {
draw(symbolSDFIconGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ false,
"fill");
draw(symbolSDFIconGroup, /* isHalo = */ false, "fill");
}
} else {
draw(symbolIconGroup,
renderable.segment,
indices,
vertices,
vertexCount,
/* isHalo = */ false,
"icon");
draw(symbolIconGroup, /* isHalo = */ false, "icon");
}
}
}

View File

@@ -303,7 +303,9 @@ public:
}
void upload(gfx::UploadPass& uploadPass) override {
#if MLN_LEGACY_RENDERER
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector));
#endif // MLN_LEGACY_RENDERER
}
std::tuple<std::optional<gfx::AttributeBinding>> attributeBinding(
@@ -424,7 +426,9 @@ public:
}
void upload(gfx::UploadPass& uploadPass) override {
#if MLN_LEGACY_RENDERER
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector));
#endif // MLN_LEGACY_RENDERER
}
std::tuple<std::optional<gfx::AttributeBinding>> attributeBinding(
@@ -533,9 +537,11 @@ public:
if (!patternToVertexVector.empty()) {
assert(!zoomInVertexVector.empty());
assert(!zoomOutVertexVector.empty());
#if MLN_LEGACY_RENDERER
patternToVertexBuffer = uploadPass.createVertexBuffer(std::move(patternToVertexVector));
zoomInVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomInVertexVector));
zoomOutVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomOutVertexVector));
#endif // MLN_LEGACY_RENDERER
}
}

View File

@@ -86,11 +86,14 @@ SegmentVector<HeatmapTextureAttributes> RenderStaticData::heatmapTextureSegments
void RenderStaticData::upload(gfx::UploadPass& uploadPass) {
if (!uploaded) {
// these are still used by stencil buffer rendering
tileVertexBuffer = uploadPass.createVertexBuffer(tileVertices());
quadTriangleIndexBuffer = uploadPass.createIndexBuffer(quadTriangleIndices());
#if MLN_LEGACY_RENDERER
rasterVertexBuffer = uploadPass.createVertexBuffer(rasterVertices());
heatmapTextureVertexBuffer = uploadPass.createVertexBuffer(heatmapTextureVertices());
quadTriangleIndexBuffer = uploadPass.createIndexBuffer(quadTriangleIndices());
tileBorderIndexBuffer = uploadPass.createIndexBuffer(tileLineStripIndices());
#endif // MLN_LEGACY_RENDERER
uploaded = true;
}
}

View File

@@ -777,7 +777,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
const bool pitchWithMap = layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map;
const bool keepUpright = layout.get<style::IconKeepUpright>();
if (bucket.hasSdfIconData()) {
reprojectLineLabels(bucket.sdfIcon.dynamicVertices,
reprojectLineLabels(bucket.sdfIcon.dynamicVertices(),
bucket.sdfIcon.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -789,7 +789,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
}
if (bucket.hasIconData()) {
reprojectLineLabels(bucket.icon.dynamicVertices,
reprojectLineLabels(bucket.icon.dynamicVertices(),
bucket.icon.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -805,7 +805,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
if (bucket.hasTextData() && layout.get<TextRotationAlignment>() == AlignmentType::Map) {
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
const bool keepUpright = layout.get<style::TextKeepUpright>();
reprojectLineLabels(bucket.text.dynamicVertices,
reprojectLineLabels(bucket.text.dynamicVertices(),
bucket.text.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -817,7 +817,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
}
} else if (hasVariableAnchors) {
bucket.text.dynamicVertices.clear();
bucket.text.sharedDynamicVertices->clear();
bucket.hasVariablePlacement = false;
const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(static_cast<float>(state.getZoom()));
@@ -846,7 +846,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
// These symbols are from a justification that is not being
// used, or a label that wasn't placed so we don't need to do
// the extra math to figure out what incremental shift to apply.
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices);
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices());
} else {
const Point<float> tileAnchor = symbol.anchorPoint;
const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix);
@@ -889,25 +889,25 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
}
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices);
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices());
}
}
}
if (updateTextFitIcon && bucket.hasVariablePlacement) {
auto updateIcon = [&](SymbolBucket::Buffer& iconBuffer) {
iconBuffer.dynamicVertices.clear();
iconBuffer.sharedDynamicVertices->clear();
for (std::size_t i = 0; i < iconBuffer.placedSymbols.size(); ++i) {
const PlacedSymbol& placedIcon = iconBuffer.placedSymbols[i];
if (placedIcon.hidden || (!placedIcon.placedOrientation && bucket.allowVerticalPlacement)) {
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices);
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
} else {
const auto& pair = placedTextShifts.find(i);
if (pair == placedTextShifts.end()) {
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices);
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
} else {
for (std::size_t j = 0; j < placedIcon.glyphOffsets.size(); ++j) {
addDynamicAttributes(pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices);
addDynamicAttributes(pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices());
}
}
}
@@ -920,13 +920,13 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
} else if (bucket.allowVerticalPlacement && bucket.hasTextData()) {
const auto updateDynamicVertices = [](SymbolBucket::Buffer& buffer) {
buffer.dynamicVertices.clear();
buffer.sharedDynamicVertices->clear();
for (const PlacedSymbol& symbol : buffer.placedSymbols) {
if (symbol.hidden || !symbol.placedOrientation) {
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices);
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices());
} else {
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices);
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices());
}
}
}
@@ -948,9 +948,9 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
void Placement::updateBucketOpacities(SymbolBucket& bucket,
const TransformState& state,
std::set<uint32_t>& seenCrossTileIDs) const {
if (bucket.hasTextData()) bucket.text.opacityVertices.clear();
if (bucket.hasIconData()) bucket.icon.opacityVertices.clear();
if (bucket.hasSdfIconData()) bucket.sdfIcon.opacityVertices.clear();
if (bucket.hasTextData()) bucket.text.sharedOpacityVertices->clear();
if (bucket.hasIconData()) bucket.icon.sharedOpacityVertices->clear();
if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityVertices->clear();
if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices.clear();
if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices.clear();
if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices.clear();
@@ -1015,7 +1015,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden();
}
bucket.text.opacityVertices.extend(textOpacityVerticesSize, opacityVertex);
bucket.text.opacityVertices().extend(textOpacityVerticesSize, opacityVertex);
style::TextWritingModeType previousOrientation = style::TextWritingModeType::Horizontal;
if (bucket.allowVerticalPlacement) {
@@ -1047,7 +1047,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
iconBuffer.placedSymbols[*symbolInstance.placedVerticalIconIndex].hidden = opacityState.isHidden();
}
iconBuffer.opacityVertices.extend(iconOpacityVerticesSize, opacityVertex);
iconBuffer.opacityVertices().extend(iconOpacityVerticesSize, opacityVertex);
}
auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {