shared vertex buffers (#1310)
Co-authored-by: Stefan Karschti <stefan.karschti@gmail.com>
This commit is contained in:
committed by
Bart Louwers
parent
d094b9928e
commit
5b3af77450
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
VertexAttributeArrayGL vertexAttributes;
|
||||
|
||||
gfx::IndexBuffer indexBuffer = {0, nullptr};
|
||||
gfx::UniqueVertexBufferResource attributeBuffer;
|
||||
std::vector<gfx::UniqueVertexBufferResource> attributeBuffers;
|
||||
|
||||
UniformBufferArrayGL uniformBuffers;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user