Topic/vao per segment (#1188)

This commit is contained in:
Tim Sylvester
2023-05-30 07:06:42 -07:00
committed by Bart Louwers
parent c4416a4ed0
commit 83882e1b73
19 changed files with 322 additions and 271 deletions

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

@@ -114,7 +114,7 @@ struct VertexDescriptor {
class AttributeBinding {
public:
AttributeDescriptor attribute;
uint8_t vertexStride;
uint32_t vertexStride;
const VertexBufferResource* vertexBufferResource;
uint32_t vertexOffset;

View File

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

View File

@@ -3,6 +3,7 @@
#include <mbgl/gfx/types.hpp>
#include <cassert>
#include <cstddef>
namespace mbgl {
namespace gfx {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()) {

View File

@@ -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) {

View File

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