Topic/vao per segment (#1188)
This commit is contained in:
committed by
Bart Louwers
parent
c4416a4ed0
commit
83882e1b73
@@ -141,6 +141,7 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/annotation/annotation.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/backend_scope.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_impl.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_builder.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/gfx_types.hpp
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace gfx {
|
||||
class CullFaceMode;
|
||||
enum class DepthMaskType : bool;
|
||||
class DrawableTweaker;
|
||||
class DrawMode;
|
||||
class ShaderProgramBase;
|
||||
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
|
||||
using DrawPriority = int64_t;
|
||||
@@ -35,6 +36,9 @@ protected:
|
||||
public:
|
||||
virtual ~Drawable();
|
||||
|
||||
struct DrawSegment;
|
||||
using UniqueDrawSegment = std::unique_ptr<DrawSegment>;
|
||||
|
||||
const util::SimpleIdentity& getId() const { return uniqueID; }
|
||||
|
||||
/// Draw the drawable
|
||||
@@ -101,16 +105,6 @@ public:
|
||||
virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0;
|
||||
virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0;
|
||||
|
||||
virtual std::vector<std::uint16_t>& getLineIndexData() const = 0;
|
||||
virtual std::vector<std::uint16_t>& getTriangleIndexData() const = 0;
|
||||
|
||||
/// Attach a tweaker to be run on this drawable for each frame
|
||||
// void addTweaker(DrawableTweakerPtr tweaker) { tweakers.emplace_back(std::move(tweaker)); }
|
||||
// template <typename TIter>
|
||||
// void addTweakers(TIter beg, TIter end) {
|
||||
// tweakers.insert(tweakers.end(), beg, end);
|
||||
// }
|
||||
|
||||
/// Get the tweakers attached to this drawable
|
||||
const std::vector<DrawableTweakerPtr>& getTweakers() const { return tweakers; }
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Color;
|
||||
template <typename VertexType>
|
||||
class Segment;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
@@ -126,6 +128,8 @@ public:
|
||||
std::size_t vertexOffset,
|
||||
std::size_t vertexLength);
|
||||
|
||||
void setSegments(gfx::DrawMode, std::vector<uint16_t> indexes, const std::vector<Segment<void>>&);
|
||||
|
||||
/// Add lines based on existing vertices
|
||||
void addLines(const std::vector<uint16_t>& indexes,
|
||||
std::size_t indexOffset,
|
||||
@@ -138,21 +142,13 @@ public:
|
||||
std::size_t indexLength,
|
||||
std::size_t baseIndex = 0);
|
||||
|
||||
/// Add already-set-up triangles directly
|
||||
void addTriangles(const std::vector<std::array<int16_t, 2>>& vertices,
|
||||
std::size_t vertexOffset,
|
||||
std::size_t vertexLength,
|
||||
const std::vector<uint16_t>& indexes,
|
||||
std::size_t indexOffset,
|
||||
std::size_t indexLength);
|
||||
|
||||
/// Add a tweaker to be attached to each emitted drawable
|
||||
// void addTweaker(DrawableTweakerPtr tweaker) { tweakers.emplace_back(std::move(tweaker)); }
|
||||
|
||||
protected:
|
||||
/// Create an instance of the appropriate drawable type
|
||||
virtual UniqueDrawable createDrawable() const = 0;
|
||||
|
||||
/// Create a segment wrapper
|
||||
virtual std::unique_ptr<Drawable::DrawSegment> createSegment(gfx::DrawMode, Segment<void>&&) = 0;
|
||||
|
||||
/// Setup the SDK-specific aspects after all the values are present
|
||||
virtual void init() = 0;
|
||||
|
||||
|
||||
22
include/mbgl/gfx/drawable_impl.hpp
Normal file
22
include/mbgl/gfx/drawable_impl.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
struct Drawable::DrawSegment {
|
||||
DrawSegment(gfx::DrawMode mode_, Segment<void>&& segment_)
|
||||
: mode(mode_),
|
||||
segment(std::move(segment_)) {}
|
||||
|
||||
const gfx::DrawMode& getMode() const { return mode; }
|
||||
const Segment<void>& getSegment() const { return segment; }
|
||||
|
||||
protected:
|
||||
gfx::DrawMode mode;
|
||||
Segment<void> segment;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
@@ -1,14 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/draw_mode.hpp>
|
||||
#include <mbgl/gl/vertex_array.hpp>
|
||||
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <class AttributeList>
|
||||
class Segment;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class Context;
|
||||
class IndexBuffer;
|
||||
class UploadPass;
|
||||
class VertexBufferResource;
|
||||
|
||||
using UniqueVertexBufferResource = std::unique_ptr<gfx::VertexBufferResource>;
|
||||
@@ -26,11 +35,8 @@ public:
|
||||
|
||||
void draw(const PaintParameters&) const override;
|
||||
|
||||
void setLineIndexData(std::vector<uint16_t> indexes);
|
||||
void setTriangleIndexData(std::vector<uint16_t> indexes);
|
||||
|
||||
std::vector<std::uint16_t>& getLineIndexData() const override;
|
||||
std::vector<std::uint16_t>& getTriangleIndexData() const override;
|
||||
struct DrawSegmentGL;
|
||||
void setIndexData(std::vector<std::uint16_t> indexes, std::vector<UniqueDrawSegment> segments);
|
||||
|
||||
const gfx::VertexAttributeArray& getVertexAttributes() const override;
|
||||
void setVertexAttributes(const gfx::VertexAttributeArray& value) override;
|
||||
@@ -38,18 +44,14 @@ public:
|
||||
|
||||
gfx::VertexAttributeArray& mutableVertexAttributes();
|
||||
|
||||
const gl::VertexArray& getVertexArray() const;
|
||||
void setVertexArray(gl::VertexArray&&, gfx::UniqueVertexBufferResource&&, gfx::IndexBuffer&&);
|
||||
|
||||
const gfx::UniqueVertexBufferResource& getBuffer() const;
|
||||
const gfx::IndexBuffer& getIndexBuffer() const;
|
||||
|
||||
const gfx::UniformBufferArray& getUniformBuffers() const override;
|
||||
gfx::UniformBufferArray& mutableUniformBuffers() override;
|
||||
|
||||
/// Reset a single color attribute for all vertexes
|
||||
void resetColor(const Color&) override;
|
||||
|
||||
void upload(gfx::Context&, gfx::UploadPass&);
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
const std::unique_ptr<Impl> impl;
|
||||
|
||||
@@ -22,6 +22,9 @@ public:
|
||||
protected:
|
||||
gfx::UniqueDrawable createDrawable() const override;
|
||||
|
||||
using DrawSegment = gfx::Drawable::DrawSegment;
|
||||
std::unique_ptr<DrawSegment> createSegment(gfx::DrawMode, Segment<void>&&) override;
|
||||
|
||||
/// Setup the SDK-specific aspects after all the values are present
|
||||
void init() override;
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ struct VertexDescriptor {
|
||||
class AttributeBinding {
|
||||
public:
|
||||
AttributeDescriptor attribute;
|
||||
uint8_t vertexStride;
|
||||
uint32_t vertexStride;
|
||||
const VertexBufferResource* vertexBufferResource;
|
||||
uint32_t vertexOffset;
|
||||
|
||||
|
||||
@@ -101,9 +101,6 @@ public:
|
||||
virtual void clearStencilBuffer(int32_t) = 0;
|
||||
|
||||
public:
|
||||
/// Activate the shader, vertex attributes, etc., specified by the drawable
|
||||
virtual bool setupDraw(const PaintParameters&, const gfx::Drawable&) = 0;
|
||||
|
||||
/// Create a new drawable builder
|
||||
virtual UniqueDrawableBuilder createDrawableBuilder(std::string name) = 0;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
|
||||
#include <mbgl/gfx/drawable_builder_impl.hpp>
|
||||
#include <mbgl/gfx/drawable_impl.hpp>
|
||||
#include <mbgl/renderer/render_pass.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
@@ -102,11 +103,11 @@ void DrawableBuilder::resetDrawPriority(DrawPriority value) {
|
||||
}
|
||||
|
||||
void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
|
||||
const auto n = (uint16_t)impl->vertices.elements();
|
||||
const auto n = static_cast<uint16_t>(impl->vertices.elements());
|
||||
impl->vertices.emplace_back(Impl::VT({{{x0, y0}}}));
|
||||
impl->vertices.emplace_back(Impl::VT({{{x1, y1}}}));
|
||||
impl->vertices.emplace_back(Impl::VT({{{x2, y2}}}));
|
||||
impl->triangleIndexes.emplace_back(n, n + 1, n + 2);
|
||||
impl->indexes.insert(impl->indexes.end(), {n, static_cast<uint16_t>(n + 1), static_cast<uint16_t>(n + 2)});
|
||||
if (colorAttrMode == ColorAttrMode::PerVertex) {
|
||||
impl->colors.insert(impl->colors.end(), 3, impl->currentColor);
|
||||
}
|
||||
@@ -115,7 +116,7 @@ void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1
|
||||
void DrawableBuilder::appendTriangle(int16_t x0, int16_t y0) {
|
||||
const auto n = (uint16_t)impl->vertices.elements();
|
||||
impl->vertices.emplace_back(Impl::VT({{{x0, y0}}}));
|
||||
impl->triangleIndexes.emplace_back(n - 2, n - 1, n);
|
||||
impl->indexes.insert(impl->indexes.end(), {static_cast<uint16_t>(n - 2), static_cast<uint16_t>(n - 1), n});
|
||||
if (colorAttrMode == ColorAttrMode::PerVertex) {
|
||||
impl->colors.emplace_back(impl->currentColor);
|
||||
}
|
||||
@@ -149,14 +150,57 @@ std::size_t DrawableBuilder::addVertices(const std::vector<std::array<int16_t, 2
|
||||
return baseIndex;
|
||||
}
|
||||
|
||||
void DrawableBuilder::setSegments(gfx::DrawMode mode,
|
||||
std::vector<uint16_t> indexes,
|
||||
const std::vector<Segment<void>>& segments) {
|
||||
impl->indexes = std::move(indexes);
|
||||
for (const auto& seg : segments) {
|
||||
#if !defined(NDEBUG)
|
||||
if (mode.type == DrawModeType::Triangles) {
|
||||
assert(seg.indexLength % 3 == 0);
|
||||
} else if (mode.type == DrawModeType::Lines) {
|
||||
assert(seg.indexLength % 2 == 0);
|
||||
}
|
||||
assert(seg.vertexOffset + seg.vertexLength <= impl->vertices.elements());
|
||||
assert(seg.indexOffset + seg.indexLength <= impl->indexes.size());
|
||||
for (decltype(seg.indexLength) i = 0; i < seg.indexLength; ++i) {
|
||||
assert(impl->indexes[seg.indexOffset + i] < impl->vertices.elements());
|
||||
}
|
||||
#endif
|
||||
|
||||
auto segCopy = Segment<void>{
|
||||
// no copy constructor
|
||||
seg.vertexOffset,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.sortKey,
|
||||
};
|
||||
impl->segments.emplace_back(createSegment(mode, std::move(segCopy)));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableBuilder::addLines(const std::vector<uint16_t>& indexes,
|
||||
std::size_t indexOffset,
|
||||
std::size_t indexLength,
|
||||
std::size_t baseIndex) {
|
||||
for (auto i = std::next(indexes.begin(), indexOffset);
|
||||
i != std::next(indexes.begin(), indexOffset + indexLength);) {
|
||||
impl->lineIndexes.emplace_back(static_cast<uint16_t>(*i++ + baseIndex),
|
||||
static_cast<uint16_t>(*i++ + baseIndex));
|
||||
if (!indexLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
impl->segments.emplace_back(createSegment(Lines(lineWidth),
|
||||
Segment<void>{/*.vertexOffset = */ 0,
|
||||
/*.indexOffset = */ indexes.size(),
|
||||
/*.vertexLength = */ 0,
|
||||
/*.indexLength = */ indexLength}));
|
||||
|
||||
if (impl->indexes.empty()) {
|
||||
impl->indexes.reserve(indexLength);
|
||||
}
|
||||
|
||||
for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength);
|
||||
++i) {
|
||||
impl->indexes.emplace_back(static_cast<uint16_t>(*i + baseIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,30 +208,24 @@ void DrawableBuilder::addTriangles(const std::vector<uint16_t>& indexes,
|
||||
std::size_t indexOffset,
|
||||
std::size_t indexLength,
|
||||
std::size_t baseIndex) {
|
||||
for (auto i = std::next(indexes.begin(), indexOffset);
|
||||
i != std::next(indexes.begin(), indexOffset + indexLength);) {
|
||||
impl->triangleIndexes.emplace_back(static_cast<uint16_t>(*i++ + baseIndex),
|
||||
static_cast<uint16_t>(*i++ + baseIndex),
|
||||
static_cast<uint16_t>(*i++ + baseIndex));
|
||||
if (!indexLength) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableBuilder::addTriangles(const std::vector<std::array<int16_t, 2>>& vertices,
|
||||
std::size_t vertexOffset,
|
||||
std::size_t vertexLength,
|
||||
const std::vector<uint16_t>& indexes,
|
||||
std::size_t indexOffset,
|
||||
std::size_t indexLength) {
|
||||
// TODO: bulk add in `gfx::VertexVector`... or use vector directly?
|
||||
// impl->vertices.insert(impl->vertices.end(),
|
||||
// std::next(vertices.begin(), vertexOffset),
|
||||
// std::next(vertices.begin(), vertexOffset + vertexLength));
|
||||
// impl->indexes.insert(impl->indexes.end(),
|
||||
// std::next(indexes.begin(), indexOffset),
|
||||
// std::next(indexes.begin(), indexOffset + indexLength));
|
||||
impl->segments.emplace_back(createSegment(Triangles(),
|
||||
Segment<void>{/*.vertexOffset = */ 0,
|
||||
/*.indexOffset = */ impl->indexes.size(),
|
||||
/*.vertexLength = */ impl->vertices.elements(),
|
||||
/*.indexLength = */ indexLength}));
|
||||
|
||||
const auto baseIndex = addVertices(vertices, vertexOffset, vertexLength);
|
||||
addTriangles(indexes, indexOffset, indexLength, baseIndex);
|
||||
if (impl->indexes.empty()) {
|
||||
impl->indexes.reserve(indexLength);
|
||||
}
|
||||
|
||||
for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength);
|
||||
++i) {
|
||||
impl->indexes.emplace_back(static_cast<uint16_t>(*i + baseIndex));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
@@ -13,8 +14,9 @@ namespace gfx {
|
||||
struct DrawableBuilder::Impl {
|
||||
using VT = gfx::detail::VertexType<gfx::AttributeType<std::int16_t, 2>>;
|
||||
gfx::VertexVector<VT> vertices;
|
||||
gfx::IndexVector<gfx::Triangles> triangleIndexes;
|
||||
gfx::IndexVector<gfx::Lines> lineIndexes;
|
||||
std::vector<uint16_t> indexes;
|
||||
std::vector<std::unique_ptr<Drawable::DrawSegment>> segments;
|
||||
|
||||
Color currentColor = Color::white();
|
||||
std::vector<Color> colors;
|
||||
gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled();
|
||||
|
||||
@@ -454,43 +454,6 @@ void Context::setDirtyState() {
|
||||
globalVertexArrayState.setDirty();
|
||||
}
|
||||
|
||||
bool Context::setupDraw(const PaintParameters& parameters, const gfx::Drawable& drawable) {
|
||||
if (const auto& shader = drawable.getShader()) {
|
||||
const auto& shaderGL = static_cast<const ShaderProgramGL&>(*shader);
|
||||
if (shaderGL.getGLProgramID() != program.getCurrentValue()) {
|
||||
program = shaderGL.getGLProgramID();
|
||||
}
|
||||
} else if (program != value::Program::Default) {
|
||||
program = value::Program::Default;
|
||||
}
|
||||
|
||||
setDepthMode(parameters.depthModeForSublayer(drawable.getSubLayerIndex(), drawable.getDepthType()));
|
||||
|
||||
// force disable depth test for debugging
|
||||
// setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}});
|
||||
|
||||
if (auto tileID = drawable.getTileID()) {
|
||||
// Doesn't work until the clipping masks are generated
|
||||
// parameters.stencilModeForClipping(tileID->toUnwrapped());
|
||||
setStencilMode(gfx::StencilMode::disabled());
|
||||
} else {
|
||||
setStencilMode(gfx::StencilMode::disabled());
|
||||
}
|
||||
|
||||
setColorMode(parameters.colorModeForRenderPass());
|
||||
setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
auto& drawableGL = static_cast<const DrawableGL&>(drawable);
|
||||
auto& vao = drawableGL.getVertexArray();
|
||||
if (vao.isValid()) {
|
||||
bindVertexArray = vao.getID();
|
||||
return true;
|
||||
} else {
|
||||
bindVertexArray = value::BindVertexArray::Default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::UniqueDrawableBuilder Context::createDrawableBuilder(std::string name) {
|
||||
return std::make_unique<gl::DrawableGLBuilder>(std::move(name));
|
||||
}
|
||||
|
||||
@@ -102,8 +102,6 @@ public:
|
||||
|
||||
void setCleanupOnDestruction(bool cleanup) { cleanupOnDestruction = cleanup; }
|
||||
|
||||
bool setupDraw(const PaintParameters&, const gfx::Drawable&) override;
|
||||
|
||||
gfx::UniqueDrawableBuilder createDrawableBuilder(std::string name) override;
|
||||
gfx::DrawableTweakerPtr createDrawableTweaker() override;
|
||||
gfx::UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) override;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <mbgl/gl/drawable_gl.hpp>
|
||||
#include <mbgl/gl/drawable_gl_impl.hpp>
|
||||
#include <mbgl/gl/vertex_buffer_resource.hpp>
|
||||
|
||||
#include <mbgl/gl/drawable_gl_impl.hpp>
|
||||
#include <mbgl/gl/upload_pass.hpp>
|
||||
#include <mbgl/gl/vertex_array.hpp>
|
||||
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
||||
#include <mbgl/gl/vertex_buffer_resource.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -12,43 +16,60 @@ DrawableGL::DrawableGL(std::string name_)
|
||||
impl(std::make_unique<Impl>()) {}
|
||||
|
||||
DrawableGL::~DrawableGL() {
|
||||
impl->vertexArray = {{nullptr, false}};
|
||||
impl->indexBuffer = {0, nullptr};
|
||||
impl->attributeBuffer.reset();
|
||||
}
|
||||
|
||||
void DrawableGL::draw(const PaintParameters& parameters) const {
|
||||
auto& context = static_cast<gl::Context&>(parameters.context);
|
||||
|
||||
if (const auto& shader = getShader()) {
|
||||
const auto& shaderGL = static_cast<const ShaderProgramGL&>(*shader);
|
||||
if (shaderGL.getGLProgramID() != context.program.getCurrentValue()) {
|
||||
context.program = shaderGL.getGLProgramID();
|
||||
}
|
||||
} else {
|
||||
context.program = value::Program::Default;
|
||||
}
|
||||
|
||||
context.setDepthMode(parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType()));
|
||||
|
||||
// force disable depth test for debugging
|
||||
// setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}});
|
||||
|
||||
if (auto tileID = getTileID()) {
|
||||
// Doesn't work until the clipping masks are generated
|
||||
// parameters.stencilModeForClipping(tileID->toUnwrapped());
|
||||
context.setStencilMode(gfx::StencilMode::disabled());
|
||||
} else {
|
||||
context.setStencilMode(gfx::StencilMode::disabled());
|
||||
}
|
||||
|
||||
context.setColorMode(parameters.colorModeForRenderPass());
|
||||
context.setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
bindUniformBuffers();
|
||||
impl->draw(parameters, lineWidth);
|
||||
|
||||
auto& glContext = static_cast<gl::Context&>(parameters.context);
|
||||
const auto saveVertexArray = glContext.bindVertexArray.getCurrentValue();
|
||||
|
||||
for (const auto& seg : impl->segments) {
|
||||
const auto& glSeg = static_cast<DrawSegmentGL&>(*seg);
|
||||
const auto& mlSeg = glSeg.getSegment();
|
||||
if (glSeg.getVertexArray().isValid()) {
|
||||
glContext.bindVertexArray = glSeg.getVertexArray().getID();
|
||||
}
|
||||
glContext.draw(glSeg.getMode(), mlSeg.indexOffset, mlSeg.indexLength);
|
||||
}
|
||||
|
||||
glContext.bindVertexArray = saveVertexArray;
|
||||
|
||||
unbindUniformBuffers();
|
||||
}
|
||||
|
||||
void DrawableGL::setLineIndexData(std::vector<std::uint16_t> indexes) {
|
||||
impl->lineIndexes = std::move(indexes);
|
||||
}
|
||||
|
||||
void DrawableGL::setTriangleIndexData(std::vector<std::uint16_t> indexes) {
|
||||
impl->triangleIndexes = std::move(indexes);
|
||||
}
|
||||
|
||||
std::vector<std::uint16_t>& DrawableGL::getLineIndexData() const {
|
||||
return impl->lineIndexes;
|
||||
}
|
||||
|
||||
std::vector<std::uint16_t>& DrawableGL::getTriangleIndexData() const {
|
||||
return impl->triangleIndexes;
|
||||
}
|
||||
|
||||
const gl::VertexArray& DrawableGL::getVertexArray() const {
|
||||
return impl->vertexArray;
|
||||
}
|
||||
|
||||
const gfx::IndexBuffer& DrawableGL::getIndexBuffer() const {
|
||||
return impl->indexBuffer;
|
||||
}
|
||||
|
||||
const gfx::UniqueVertexBufferResource& DrawableGL::getBuffer() const {
|
||||
return impl->attributeBuffer;
|
||||
void DrawableGL::setIndexData(std::vector<std::uint16_t> indexes, std::vector<UniqueDrawSegment> segments) {
|
||||
impl->indexes = std::move(indexes);
|
||||
impl->segments = std::move(segments);
|
||||
}
|
||||
|
||||
const gfx::VertexAttributeArray& DrawableGL::getVertexAttributes() const {
|
||||
@@ -66,14 +87,6 @@ void DrawableGL::setVertexAttributes(gfx::VertexAttributeArray&& value) {
|
||||
impl->vertexAttributes = std::move(static_cast<VertexAttributeArrayGL&&>(value));
|
||||
}
|
||||
|
||||
void DrawableGL::setVertexArray(gl::VertexArray&& vertexArray_,
|
||||
gfx::UniqueVertexBufferResource&& attributeBuffer_,
|
||||
gfx::IndexBuffer&& indexBuffer_) {
|
||||
impl->vertexArray = std::move(vertexArray_);
|
||||
impl->attributeBuffer = std::move(attributeBuffer_);
|
||||
impl->indexBuffer = std::move(indexBuffer_);
|
||||
}
|
||||
|
||||
const gfx::UniformBufferArray& DrawableGL::getUniformBuffers() const {
|
||||
return impl->uniformBuffers;
|
||||
}
|
||||
@@ -111,5 +124,54 @@ void DrawableGL::unbindUniformBuffers() const {
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) {
|
||||
if (!shader) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool build = impl->vertexAttributes.isDirty() ||
|
||||
std::any_of(impl->segments.begin(), impl->segments.end(), [](const auto& seg) {
|
||||
return !static_cast<const DrawSegmentGL&>(*seg).getVertexArray().isValid();
|
||||
});
|
||||
|
||||
if (build) {
|
||||
auto& glContext = static_cast<gl::Context&>(context);
|
||||
constexpr auto usage = gfx::BufferUsageType::StaticDraw;
|
||||
|
||||
const auto indexBytes = impl->indexes.size() * sizeof(decltype(impl->indexes)::value_type);
|
||||
auto indexBufferResource = uploadPass.createIndexBufferResource(impl->indexes.data(), indexBytes, usage);
|
||||
auto indexBuffer = gfx::IndexBuffer{impl->indexes.size(), std::move(indexBufferResource)};
|
||||
|
||||
// Apply drawable values to shader defaults
|
||||
const auto& defaults = shader->getVertexAttributes();
|
||||
const auto& overrides = impl->vertexAttributes;
|
||||
const auto vertexCount = overrides.getMaxCount();
|
||||
|
||||
std::unique_ptr<gfx::VertexBufferResource> vertexBuffer;
|
||||
auto bindings = uploadPass.buildAttributeBindings(vertexCount, defaults, overrides, usage, vertexBuffer);
|
||||
|
||||
impl->attributeBuffer = std::move(vertexBuffer);
|
||||
impl->indexBuffer = std::move(indexBuffer);
|
||||
|
||||
// Create a VAO for each group of vertexes described by a segment
|
||||
for (const auto& seg : impl->segments) {
|
||||
auto& glSeg = static_cast<DrawSegmentGL&>(*seg);
|
||||
const auto& mlSeg = glSeg.getSegment();
|
||||
|
||||
for (auto& binding : bindings) {
|
||||
binding->vertexOffset = static_cast<uint32_t>(mlSeg.vertexOffset);
|
||||
}
|
||||
|
||||
auto vertexArray = glContext.createVertexArray();
|
||||
|
||||
vertexArray.bind(glContext, impl->indexBuffer, bindings);
|
||||
|
||||
assert(vertexArray.isValid());
|
||||
|
||||
glSeg.setVertexArray(std::move(vertexArray));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <mbgl/gl/drawable_gl_builder.hpp>
|
||||
|
||||
#include <mbgl/gfx/drawable_builder_impl.hpp>
|
||||
#include <mbgl/gfx/drawable_impl.hpp>
|
||||
#include <mbgl/gl/drawable_gl.hpp>
|
||||
#include <mbgl/gl/drawable_gl_impl.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -11,6 +13,10 @@ gfx::UniqueDrawable DrawableGLBuilder::createDrawable() const {
|
||||
return std::make_unique<DrawableGL>(drawableName.empty() ? name : drawableName);
|
||||
};
|
||||
|
||||
std::unique_ptr<gfx::Drawable::DrawSegment> DrawableGLBuilder::createSegment(gfx::DrawMode mode, Segment<void>&& seg) {
|
||||
return std::make_unique<DrawableGL::DrawSegmentGL>(mode, std::move(seg), VertexArray{{nullptr, false}});
|
||||
}
|
||||
|
||||
void DrawableGLBuilder::init() {
|
||||
auto& drawableGL = static_cast<DrawableGL&>(*currentDrawable);
|
||||
|
||||
@@ -41,11 +47,10 @@ void DrawableGLBuilder::init() {
|
||||
}
|
||||
}
|
||||
|
||||
drawableGL.setLineIndexData(impl->lineIndexes.vector());
|
||||
drawableGL.setTriangleIndexData(impl->triangleIndexes.vector());
|
||||
drawableGL.setIndexData(std::move(impl->indexes), std::move(impl->segments));
|
||||
|
||||
impl->lineIndexes.clear();
|
||||
impl->triangleIndexes.clear();
|
||||
impl->indexes.clear();
|
||||
impl->segments.clear();
|
||||
impl->vertices.clear();
|
||||
impl->colors.clear();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/drawable_impl.hpp>
|
||||
#include <mbgl/gfx/index_buffer.hpp>
|
||||
#include <mbgl/gfx/program.hpp>
|
||||
#include <mbgl/gfx/uniform.hpp>
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/gl/uniform_buffer_gl.hpp>
|
||||
#include <mbgl/gl/vertex_array.hpp>
|
||||
#include <mbgl/platform/gl_functions.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
|
||||
@@ -27,26 +28,14 @@ public:
|
||||
Impl() = default;
|
||||
~Impl() = default;
|
||||
|
||||
void draw(const PaintParameters& parameters, int32_t lineWidth) const {
|
||||
auto& glContext = static_cast<gl::Context&>(parameters.context);
|
||||
if (!triangleIndexes.empty()) {
|
||||
glContext.draw(gfx::Triangles(), lineIndexes.size(), triangleIndexes.size());
|
||||
}
|
||||
if (!lineIndexes.empty()) {
|
||||
glContext.draw(gfx::Lines(static_cast<float>(lineWidth)), 0, lineIndexes.size());
|
||||
}
|
||||
}
|
||||
std::vector<UniqueDrawSegment> segments;
|
||||
|
||||
// ShaderID shaderId;
|
||||
// RenderbufferID renderTarget;
|
||||
std::vector<TextureID> textures;
|
||||
|
||||
std::vector<std::uint16_t> lineIndexes;
|
||||
std::vector<std::uint16_t> triangleIndexes;
|
||||
std::vector<std::uint16_t> indexes;
|
||||
|
||||
VertexAttributeArrayGL vertexAttributes;
|
||||
|
||||
VertexArray vertexArray = {{nullptr, false}};
|
||||
gfx::IndexBuffer indexBuffer = {0, nullptr};
|
||||
gfx::UniqueVertexBufferResource attributeBuffer;
|
||||
|
||||
@@ -56,12 +45,20 @@ public:
|
||||
gfx::StencilMode stencilMode;
|
||||
gfx::ColorMode colorMode;
|
||||
gfx::CullFaceMode cullFaceMode;
|
||||
// gfx::UniformValues<typename Program<>::UniformList> uniformValues;
|
||||
// Segment<Program<>::AttributeList> segment;
|
||||
// gfx::AttributeBindings<Program<>::AttributeList> attributeBindings;
|
||||
// gfx::TextureBindings<Program<>::TextureList> textureBindings;
|
||||
GLfloat pointSize = 0.0f;
|
||||
};
|
||||
|
||||
struct DrawableGL::DrawSegmentGL final : public gfx::Drawable::DrawSegment {
|
||||
DrawSegmentGL(gfx::DrawMode mode_, Segment<void>&& segment_, VertexArray&& vertexArray_)
|
||||
: gfx::Drawable::DrawSegment(mode_, std::move(segment_)),
|
||||
vertexArray(std::move(vertexArray_)) {}
|
||||
|
||||
const VertexArray& getVertexArray() const { return vertexArray; }
|
||||
void setVertexArray(VertexArray&& value) { vertexArray = std::move(value); }
|
||||
|
||||
protected:
|
||||
VertexArray vertexArray;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gfx/renderer_backend.hpp>
|
||||
#include <mbgl/gl/drawable_gl.hpp>
|
||||
#include <mbgl/gl/upload_pass.hpp>
|
||||
#include <mbgl/gl/vertex_array.hpp>
|
||||
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
@@ -20,40 +17,11 @@ TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapac
|
||||
void TileLayerGroupGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) {
|
||||
observeDrawables([&](gfx::Drawable& drawable) {
|
||||
auto& drawableGL = static_cast<gl::DrawableGL&>(drawable);
|
||||
const auto& shader = drawable.getShader();
|
||||
|
||||
// Generate a vertex array object for the drawable state, if necessary
|
||||
if (shader && (!drawableGL.getVertexArray().isValid() || drawableGL.getVertexAttributes().isDirty())) {
|
||||
const auto usage = gfx::BufferUsageType::StaticDraw;
|
||||
|
||||
// Build index buffer
|
||||
auto indexData = drawable.getLineIndexData();
|
||||
indexData.insert(
|
||||
indexData.end(), drawable.getTriangleIndexData().begin(), drawable.getTriangleIndexData().end());
|
||||
auto indexBuffer = gfx::IndexBuffer{
|
||||
indexData.size(),
|
||||
uploadPass.createIndexBufferResource(indexData.data(), indexData.size() * sizeof(indexData[0]), usage)};
|
||||
|
||||
// Apply drawable values to shader defaults
|
||||
const auto& defaults = shader->getVertexAttributes();
|
||||
const auto& overrides = drawable.getVertexAttributes();
|
||||
const auto vertexCount = drawable.getVertexCount();
|
||||
std::unique_ptr<gfx::VertexBufferResource> vertexBuffer;
|
||||
auto bindings = uploadPass.buildAttributeBindings(vertexCount, defaults, overrides, usage, vertexBuffer);
|
||||
|
||||
auto& glContext = static_cast<gl::Context&>(context);
|
||||
auto vertexArray = glContext.createVertexArray();
|
||||
vertexArray.bind(glContext, indexBuffer, bindings);
|
||||
glContext.bindVertexArray = gl::value::BindVertexArray::Default;
|
||||
|
||||
drawableGL.setVertexArray(std::move(vertexArray), std::move(vertexBuffer), std::move(indexBuffer));
|
||||
}
|
||||
drawableGL.upload(context, uploadPass);
|
||||
});
|
||||
}
|
||||
|
||||
void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) {
|
||||
auto& context = parameters.context;
|
||||
|
||||
// TODO: Render tile masks
|
||||
// for (auto& layer : renderLayers) {
|
||||
// parameters.renderTileClippingMasks(renderTiles);
|
||||
@@ -66,9 +34,6 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters)
|
||||
if (drawable.hasRenderPass(RenderPass::Opaque) && parameters.currentLayer >= parameters.opaquePassCutoff) {
|
||||
return;
|
||||
}
|
||||
if (!context.setupDraw(parameters, drawable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string label;
|
||||
if (const auto& tileID = drawable.getTileID()) {
|
||||
|
||||
@@ -127,8 +127,10 @@ static std::size_t padSize(std::size_t size, std::size_t padding) {
|
||||
return (padding - (size % padding)) % padding;
|
||||
}
|
||||
template <typename T>
|
||||
static void pad(std::vector<T>& vector, std::size_t size, T value) {
|
||||
vector.insert(vector.end(), padSize(vector.size(), size), value);
|
||||
static std::size_t pad(std::vector<T>& vector, std::size_t size, T value) {
|
||||
const auto count = padSize(vector.size(), size);
|
||||
vector.insert(vector.end(), count, value);
|
||||
return count;
|
||||
}
|
||||
|
||||
gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
|
||||
@@ -147,56 +149,64 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
|
||||
allData.reserve(defaults.getTotalSize() * vertexCount);
|
||||
|
||||
// For each attribute in the program, with the corresponding default and optional override...
|
||||
defaults.resolve(overrides,
|
||||
[&](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 stride = defaultAttr.getStride();
|
||||
const auto offset = static_cast<uint32_t>(allData.size());
|
||||
uint32_t vertexStride = 0;
|
||||
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 stride = defaultAttr.getStride();
|
||||
const auto offset = static_cast<uint32_t>(allData.size());
|
||||
|
||||
// Get the raw data for the values in the desired format
|
||||
const auto& rawData = effectiveGL.getRaw(defaultGL.getGLType());
|
||||
// Get the raw data for the values in the desired format
|
||||
const auto& rawData = effectiveGL.getRaw(defaultGL.getGLType());
|
||||
|
||||
if (rawData.size() == stride * vertexCount) {
|
||||
// The override provided a value for each vertex, append it as-is
|
||||
allData.insert(allData.end(), rawData.begin(), rawData.end());
|
||||
} else if (rawData.size() == stride) {
|
||||
// We only have one value, append a copy for each vertex
|
||||
for (std::size_t i = 0; i < vertexCount; ++i) {
|
||||
allData.insert(allData.end(), rawData.begin(), rawData.end());
|
||||
}
|
||||
} else {
|
||||
// something else, the binding is invalid
|
||||
// TODO: throw?
|
||||
Log::Warning(Event::General,
|
||||
"Got " + util::toString(rawData.size()) + " bytes for attribute '" + name +
|
||||
"' (" + util::toString(defaultGL.getIndex()) + "), expected " +
|
||||
util::toString(stride) + " or " + util::toString(stride * vertexCount));
|
||||
return;
|
||||
}
|
||||
|
||||
bindings[defaultGL.getIndex()] = {
|
||||
/*.attribute = */ {defaultAttr.getDataType(), offset},
|
||||
/*.vertexStride = */ static_cast<uint8_t>(stride),
|
||||
/*.vertexBufferResource = */ nullptr, // buffer pointer established later
|
||||
/*.vertexOffset = */ 0,
|
||||
};
|
||||
|
||||
pad(allData, align, padding);
|
||||
});
|
||||
|
||||
auto vertBuf = createVertexBufferResource(allData.data(), allData.size(), usage);
|
||||
|
||||
// Go back and fill in the newly-allocated buffer in each binding that was generated
|
||||
std::for_each(bindings.begin(), bindings.end(), [&](auto& b) {
|
||||
if (b) {
|
||||
b->vertexBufferResource = vertBuf.get();
|
||||
if (rawData.size() == stride * vertexCount) {
|
||||
// The override provided a value for each vertex, append it as-is
|
||||
allData.insert(allData.end(), rawData.begin(), rawData.end());
|
||||
} else if (rawData.size() == stride) {
|
||||
// We only have one value, append a copy for each vertex
|
||||
for (std::size_t i = 0; i < vertexCount; ++i) {
|
||||
allData.insert(allData.end(), rawData.begin(), rawData.end());
|
||||
}
|
||||
} else {
|
||||
// something else, the binding is invalid
|
||||
// TODO: throw?
|
||||
Log::Warning(Event::General,
|
||||
"Got " + util::toString(rawData.size()) + " bytes for attribute '" + name + "' (" +
|
||||
util::toString(defaultGL.getIndex()) + "), expected " + util::toString(stride) + " or " +
|
||||
util::toString(stride * vertexCount));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
outBuffer = std::move(vertBuf);
|
||||
return bindings;
|
||||
bindings[defaultGL.getIndex()] = {
|
||||
/*.attribute = */ {defaultAttr.getDataType(), offset},
|
||||
/* vertexStride = */ static_cast<uint32_t>(stride),
|
||||
/* vertexBufferResource = */ nullptr, // buffer details established later
|
||||
/* vertexOffset = */ 0,
|
||||
};
|
||||
|
||||
pad(allData, align, padding);
|
||||
|
||||
// The vertex stride is the sum of the attribute strides
|
||||
vertexStride += stride;
|
||||
};
|
||||
defaults.resolve(overrides, resolveAttr);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void UploadPass::pushDebugGroup(const char* name) {
|
||||
|
||||
@@ -507,21 +507,19 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (fillBuilder) {
|
||||
buildVertices();
|
||||
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.triangleSegments) {
|
||||
fillBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
fillBuilder->setSegments(
|
||||
gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*fillBuilder, renderPass, tileID);
|
||||
}
|
||||
if (outlineBuilder) {
|
||||
buildVertices();
|
||||
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.lineSegments) {
|
||||
outlineBuilder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
outlineBuilder->setSegments(
|
||||
gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlineBuilder, renderPass, tileID);
|
||||
}
|
||||
} else { // FillPattern is defined
|
||||
@@ -575,23 +573,20 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (patternBuilder) {
|
||||
buildVertices();
|
||||
patternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.triangleSegments) {
|
||||
patternBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
patternBuilder->setSegments(
|
||||
gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*patternBuilder, renderPass, tileID);
|
||||
}
|
||||
if (outlinePatternBuilder) {
|
||||
buildVertices();
|
||||
outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.lineSegments) {
|
||||
outlinePatternBuilder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
outlinePatternBuilder->setSegments(
|
||||
gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlinePatternBuilder, renderPass, tileID);
|
||||
outlinePatternBuilder->flush();
|
||||
}
|
||||
|
||||
// auto draw = [&](auto& programInstance,
|
||||
|
||||
Reference in New Issue
Block a user