diff --git a/CMakeLists.txt b/CMakeLists.txt index 8756d70b6..908c50a17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 57a5108ee..b78c64ed0 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -23,6 +23,7 @@ namespace gfx { class CullFaceMode; enum class DepthMaskType : bool; class DrawableTweaker; +class DrawMode; class ShaderProgramBase; using ShaderProgramBasePtr = std::shared_ptr; using DrawPriority = int64_t; @@ -35,6 +36,9 @@ protected: public: virtual ~Drawable(); + struct DrawSegment; + using UniqueDrawSegment = std::unique_ptr; + 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& getLineIndexData() const = 0; - virtual std::vector& 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 - // void addTweakers(TIter beg, TIter end) { - // tweakers.insert(tweakers.end(), beg, end); - // } - /// Get the tweakers attached to this drawable const std::vector& getTweakers() const { return tweakers; } diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index f1183f832..3e04f9e3c 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -11,6 +11,8 @@ namespace mbgl { class Color; +template +class Segment; namespace gfx { @@ -126,6 +128,8 @@ public: std::size_t vertexOffset, std::size_t vertexLength); + void setSegments(gfx::DrawMode, std::vector indexes, const std::vector>&); + /// Add lines based on existing vertices void addLines(const std::vector& 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>& vertices, - std::size_t vertexOffset, - std::size_t vertexLength, - const std::vector& 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 createSegment(gfx::DrawMode, Segment&&) = 0; + /// Setup the SDK-specific aspects after all the values are present virtual void init() = 0; diff --git a/include/mbgl/gfx/drawable_impl.hpp b/include/mbgl/gfx/drawable_impl.hpp new file mode 100644 index 000000000..f03079dee --- /dev/null +++ b/include/mbgl/gfx/drawable_impl.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace mbgl { +namespace gfx { + +struct Drawable::DrawSegment { + DrawSegment(gfx::DrawMode mode_, Segment&& segment_) + : mode(mode_), + segment(std::move(segment_)) {} + + const gfx::DrawMode& getMode() const { return mode; } + const Segment& getSegment() const { return segment; } + +protected: + gfx::DrawMode mode; + Segment segment; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 8847da65c..45f8414e8 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -1,14 +1,23 @@ #pragma once #include +#include +#include #include +#include #include namespace mbgl { + +template +class Segment; + namespace gfx { +class Context; class IndexBuffer; +class UploadPass; class VertexBufferResource; using UniqueVertexBufferResource = std::unique_ptr; @@ -26,11 +35,8 @@ public: void draw(const PaintParameters&) const override; - void setLineIndexData(std::vector indexes); - void setTriangleIndexData(std::vector indexes); - - std::vector& getLineIndexData() const override; - std::vector& getTriangleIndexData() const override; + struct DrawSegmentGL; + void setIndexData(std::vector indexes, std::vector 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; diff --git a/include/mbgl/gl/drawable_gl_builder.hpp b/include/mbgl/gl/drawable_gl_builder.hpp index a58b3a5c0..e0c85c9b5 100644 --- a/include/mbgl/gl/drawable_gl_builder.hpp +++ b/include/mbgl/gl/drawable_gl_builder.hpp @@ -22,6 +22,9 @@ public: protected: gfx::UniqueDrawable createDrawable() const override; + using DrawSegment = gfx::Drawable::DrawSegment; + std::unique_ptr createSegment(gfx::DrawMode, Segment&&) override; + /// Setup the SDK-specific aspects after all the values are present void init() override; diff --git a/src/mbgl/gfx/attribute.hpp b/src/mbgl/gfx/attribute.hpp index ddcace025..16ae730c5 100644 --- a/src/mbgl/gfx/attribute.hpp +++ b/src/mbgl/gfx/attribute.hpp @@ -114,7 +114,7 @@ struct VertexDescriptor { class AttributeBinding { public: AttributeDescriptor attribute; - uint8_t vertexStride; + uint32_t vertexStride; const VertexBufferResource* vertexBufferResource; uint32_t vertexOffset; diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 10f73e793..f2c0a42ea 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -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; diff --git a/src/mbgl/gfx/draw_mode.hpp b/src/mbgl/gfx/draw_mode.hpp index 850821105..f631808d0 100644 --- a/src/mbgl/gfx/draw_mode.hpp +++ b/src/mbgl/gfx/draw_mode.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace mbgl { namespace gfx { diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 0044d74c8..43c08a2db 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -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(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(n + 1), static_cast(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(n - 2), static_cast(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 indexes, + const std::vector>& 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{ + // 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& 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(*i++ + baseIndex), - static_cast(*i++ + baseIndex)); + if (!indexLength) { + return; + } + + impl->segments.emplace_back(createSegment(Lines(lineWidth), + Segment{/*.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(*i + baseIndex)); } } @@ -164,30 +208,24 @@ void DrawableBuilder::addTriangles(const std::vector& 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(*i++ + baseIndex), - static_cast(*i++ + baseIndex), - static_cast(*i++ + baseIndex)); + if (!indexLength) { + return; } -} -void DrawableBuilder::addTriangles(const std::vector>& vertices, - std::size_t vertexOffset, - std::size_t vertexLength, - const std::vector& 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{/*.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(*i + baseIndex)); + } } } // namespace gfx diff --git a/src/mbgl/gfx/drawable_builder_impl.hpp b/src/mbgl/gfx/drawable_builder_impl.hpp index e01b5b276..f38b73367 100644 --- a/src/mbgl/gfx/drawable_builder_impl.hpp +++ b/src/mbgl/gfx/drawable_builder_impl.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace mbgl { namespace gfx { @@ -13,8 +14,9 @@ namespace gfx { struct DrawableBuilder::Impl { using VT = gfx::detail::VertexType>; gfx::VertexVector vertices; - gfx::IndexVector triangleIndexes; - gfx::IndexVector lineIndexes; + std::vector indexes; + std::vector> segments; + Color currentColor = Color::white(); std::vector colors; gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 7403c75e4..ee62527db 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -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(*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(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(std::move(name)); } diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 42c8fb193..a800c381e 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -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; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 3cd7c16e3..17e253f5b 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -1,7 +1,11 @@ #include -#include -#include +#include +#include +#include +#include +#include +#include #include namespace mbgl { @@ -12,43 +16,60 @@ DrawableGL::DrawableGL(std::string name_) impl(std::make_unique()) {} DrawableGL::~DrawableGL() { - impl->vertexArray = {{nullptr, false}}; impl->indexBuffer = {0, nullptr}; impl->attributeBuffer.reset(); } void DrawableGL::draw(const PaintParameters& parameters) const { + auto& context = static_cast(parameters.context); + + if (const auto& shader = getShader()) { + const auto& shaderGL = static_cast(*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(parameters.context); + const auto saveVertexArray = glContext.bindVertexArray.getCurrentValue(); + + for (const auto& seg : impl->segments) { + const auto& glSeg = static_cast(*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 indexes) { - impl->lineIndexes = std::move(indexes); -} - -void DrawableGL::setTriangleIndexData(std::vector indexes) { - impl->triangleIndexes = std::move(indexes); -} - -std::vector& DrawableGL::getLineIndexData() const { - return impl->lineIndexes; -} - -std::vector& 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 indexes, std::vector 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(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(*seg).getVertexArray().isValid(); + }); + + if (build) { + auto& glContext = static_cast(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 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(*seg); + const auto& mlSeg = glSeg.getSegment(); + + for (auto& binding : bindings) { + binding->vertexOffset = static_cast(mlSeg.vertexOffset); + } + + auto vertexArray = glContext.createVertexArray(); + + vertexArray.bind(glContext, impl->indexBuffer, bindings); + + assert(vertexArray.isValid()); + + glSeg.setVertexArray(std::move(vertexArray)); + }; + } +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index 83c453d94..4b8ea6e42 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -1,7 +1,9 @@ #include #include +#include #include +#include #include namespace mbgl { @@ -11,6 +13,10 @@ gfx::UniqueDrawable DrawableGLBuilder::createDrawable() const { return std::make_unique(drawableName.empty() ? name : drawableName); }; +std::unique_ptr DrawableGLBuilder::createSegment(gfx::DrawMode mode, Segment&& seg) { + return std::make_unique(mode, std::move(seg), VertexArray{{nullptr, false}}); +} + void DrawableGLBuilder::init() { auto& drawableGL = static_cast(*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(); } diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index 5ae50a879..0654b5cc1 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -27,26 +28,14 @@ public: Impl() = default; ~Impl() = default; - void draw(const PaintParameters& parameters, int32_t lineWidth) const { - auto& glContext = static_cast(parameters.context); - if (!triangleIndexes.empty()) { - glContext.draw(gfx::Triangles(), lineIndexes.size(), triangleIndexes.size()); - } - if (!lineIndexes.empty()) { - glContext.draw(gfx::Lines(static_cast(lineWidth)), 0, lineIndexes.size()); - } - } + std::vector segments; - // ShaderID shaderId; - // RenderbufferID renderTarget; std::vector textures; - std::vector lineIndexes; - std::vector triangleIndexes; + std::vector 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::UniformList> uniformValues; - // Segment::AttributeList> segment; - // gfx::AttributeBindings::AttributeList> attributeBindings; - // gfx::TextureBindings::TextureList> textureBindings; GLfloat pointSize = 0.0f; }; +struct DrawableGL::DrawSegmentGL final : public gfx::Drawable::DrawSegment { + DrawSegmentGL(gfx::DrawMode mode_, Segment&& 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 diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index a40593ba0..8ef6209ac 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -4,9 +4,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -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(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 vertexBuffer; - auto bindings = uploadPass.buildAttributeBindings(vertexCount, defaults, overrides, usage, vertexBuffer); - - auto& glContext = static_cast(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()) { diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index b01157e39..36259e546 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -127,8 +127,10 @@ static std::size_t padSize(std::size_t size, std::size_t padding) { return (padding - (size % padding)) % padding; } template -static void pad(std::vector& vector, std::size_t size, T value) { - vector.insert(vector.end(), padSize(vector.size(), size), value); +static std::size_t pad(std::vector& 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(effectiveAttr); - const auto& defaultGL = static_cast(defaultAttr); - const auto stride = defaultAttr.getStride(); - const auto offset = static_cast(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(effectiveAttr); + const auto& defaultGL = static_cast(defaultAttr); + const auto stride = defaultAttr.getStride(); + const auto offset = static_cast(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(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(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) { diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index c2d0399a8..ea2f157e8 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -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>&>(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>&>(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>&>(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>&>(bucket.lineSegments)); finish(*outlinePatternBuilder, renderPass, tileID); - outlinePatternBuilder->flush(); } // auto draw = [&](auto& programInstance,