diff --git a/CMakeLists.txt b/CMakeLists.txt index 78fef9f7e..3f6edaa83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,11 +140,16 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/actor/scheduler.hpp ${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_builder.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/gfx_types.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderable.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderer_backend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/rendering_stats.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_registry.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/background_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/circle_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp @@ -177,6 +182,9 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_frontend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_state.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_program_base.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_program_gl.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program_mtl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/storage/database_file_source.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/storage/file_source.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/storage/file_source_manager.hpp @@ -296,6 +304,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/util/geo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/geojson.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/geometry.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/util/identity.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/ignore.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/image.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/immutable.hpp @@ -364,6 +373,10 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/depth_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/draw_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/draw_scope.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/index_buffer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/index_vector.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/offscreen_texture.hpp @@ -378,6 +391,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/types.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/upload_pass.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_attribute.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_buffer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_vector.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/background_layer_factory.cpp @@ -572,6 +586,9 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/transition_parameters.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/update_parameters.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/upload_parameters.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/shaders/shader_program_base.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/shader_program_gl.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program_mtl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader_observer.hpp @@ -824,6 +841,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/util/http_header.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/http_timeout.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/http_timeout.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/util/identity.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/interpolate.cpp @@ -886,10 +904,15 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/backend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/custom_layer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/custom_layer_factory.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_builder.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_tweaker.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderable_resource.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderer_backend.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/location_indicator_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/platform/gl_functions.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/change_request.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/location_indicator_layer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_source.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_manifest.hpp @@ -937,6 +960,10 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/debugging_extension.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/defines.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/draw_scope_resource.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_builder.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_impl.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/enum.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/enum.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/extension.hpp @@ -968,10 +995,12 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/value.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_array.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_array.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_attribute_gl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/location_indicator_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/platform/gl_functions.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/change_request.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_location_indicator_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_location_indicator_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer.cpp @@ -982,6 +1011,26 @@ if(MLN_WITH_OPENGL) ) endif() +if(MBGL_WITH_METAL) + message(STATUS "Configuring Metal renderer backend") + target_compile_definitions( + mbgl-core + PRIVATE MBGL_RENDER_BACKEND_METAL=1 + ) + list(APPEND + INCLUDE_FILES + ${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_mtl.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_mtl_builder.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_mtl_tweaker.hpp + ) + list(APPEND + SRC_FILES + ${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_mtl.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_mtl_builder.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_mtl_tweaker.cpp + ) +endif() + target_sources( mbgl-core PRIVATE ${INCLUDE_FILES} diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp new file mode 100644 index 000000000..620eecf24 --- /dev/null +++ b/include/mbgl/gfx/drawable.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include + +#include +#include +#include + +namespace mbgl { + +class PaintParameters; + +namespace gfx { + +class DrawableTweaker; + +using DrawPriority = int64_t; +using DrawableTweakerPtr = std::shared_ptr; + +class Drawable { +protected: + Drawable() { + } + +public: + virtual ~Drawable() = default; + + const util::SimpleIdentity& getId() const { return uniqueID; } + + /// Draw the drawable + virtual void draw(const PaintParameters &) const = 0; + + /// Which shader to use when rendering this drawable + //util::SimpleIdentity getShaderID() const { return shaderID; } + //void setShaderID(util::SimpleIdentity value) { shaderID = value; } + const std::string& getShaderID() const { return shaderID; } + void setShaderID(std::string value) { shaderID = std::move(value); } + + /// DrawPriority determines the drawing order + DrawPriority getDrawPriority() const { return drawPriority; } + void setDrawPriority(DrawPriority value) { drawPriority = value; } + + /// Get the vertex attributes that override default values in the shader program + virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0; + virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0; + + virtual std::vector& getIndexData() 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 + std::vector getTweakers() const { return tweakers; } + +protected: + util::SimpleIdentity uniqueID; + //util::SimpleIdentity shaderID = util::SimpleIdentity::Empty; + std::string shaderID; + + DrawPriority drawPriority = 0; + + std::vector tweakers; +}; + +using DrawablePtr = std::shared_ptr; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp new file mode 100644 index 000000000..cd0c856e8 --- /dev/null +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include +#include + +#include +#include + +namespace mbgl { + +class Color; + +namespace gfx { + +class DrawableTweaker; + +using DrawableTweakerPtr = std::shared_ptr; + +/** + Base class for drawable builders, which construct Drawables from primitives + */ +class DrawableBuilder { +protected: + DrawableBuilder(); + +public: + virtual ~DrawableBuilder(); + + /// Get the drawable we're currently working on, if any + DrawablePtr getCurrentDrawable(bool createIfNone); + + /// Close the current drawable, using a new one for any further work + void flush(); + + /// Get all the completed drawables + const std::vector& getDrawables() const { return drawables; } + + /// Get all the completed drawables and release ownership + std::vector clearDrawables() const { return std::move(drawables); } + + /// Get the ID of the drawable we're currently working on, if any + util::SimpleIdentity getDrawableId(); + + /// Get the draw priority assigned to generated drawables + DrawPriority getDrawPriority() const; + /// Set the draw priority assigned to generated drawables + void setDrawPriority(DrawPriority); + + /// Set the draw priority on all drawables including those already generated + void resetDrawPriority(DrawPriority); + + /// The color used for emitted vertexes + const Color& getColor() const; + void setColor(const Color& value); + + /// Which shader to use when rendering emitted drawables + //util::SimpleIdentity getShaderID() const { return shaderID; } + //void setShaderID(util::SimpleIdentity value) { shaderID = value; } + const std::string& getShaderID() const { return shaderID; } + void setShaderID(std::string value) { shaderID = std::move(value); } + + /// Get the vertex attributes that override default values in the shader program + virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + + /// Add a triangle + void addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); + /// Add another triangle based on the previous two points + void appendTriangle(int16_t x0, int16_t y0); + + /// Add a rectangle consisting of two triangles + void addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1); + + /// 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 DrawablePtr createDrawable() const = 0; + + /// Setup the SDK-specific aspects after all the values are present + virtual void init() = 0; + +protected: + DrawPriority drawPriority = 0; + + //util::SimpleIdentity shaderID = util::SimpleIdentity::Empty; + std::string shaderID; + + DrawablePtr currentDrawable; + std::vector drawables; + + std::vector tweakers; + + struct Impl; + std::unique_ptr impl; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/drawable_tweaker.hpp b/include/mbgl/gfx/drawable_tweaker.hpp new file mode 100644 index 000000000..7e4199adf --- /dev/null +++ b/include/mbgl/gfx/drawable_tweaker.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace mbgl { + +class PaintParameters; + +namespace gfx { + +class Drawable; + +/** + Base class for drawable tweakers, which manipulate drawables per frame + */ +class DrawableTweaker { +protected: + DrawableTweaker() = default; + +public: + virtual ~DrawableTweaker() = default; + + virtual void execute(Drawable&, const PaintParameters&) = 0; +}; + +using DrawableTweakerPtr = std::shared_ptr; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/gfx_types.hpp b/include/mbgl/gfx/gfx_types.hpp new file mode 100644 index 000000000..2f87cf000 --- /dev/null +++ b/include/mbgl/gfx/gfx_types.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include + +namespace mbgl { +namespace gfx { + +enum class PrimitiveType : uint8_t { + Point, + Line, + Triangle, +}; + +enum class DrawModeType : uint8_t { + Points, + Lines, + LineLoop, + LineStrip, + Triangles, + TriangleStrip, + TriangleFan, +}; + +enum class AttributeDataType : uint8_t { + Byte, + Byte2, + Byte3, + Byte4, + + UByte, + UByte2, + UByte3, + UByte4, + + Short, + Short2, + Short3, + Short4, + + UShort, + UShort2, + UShort3, + UShort4, + + Int, + Int2, + Int3, + Int4, + + UInt, + UInt2, + UInt3, + UInt4, + + Float, + Float2, + Float3, + Float4, + + Invalid = 255, +}; + +} // namespace gfx +} // namespace mbgl + diff --git a/include/mbgl/gfx/shader.hpp b/include/mbgl/gfx/shader.hpp index c629536d7..81d26128f 100644 --- a/include/mbgl/gfx/shader.hpp +++ b/include/mbgl/gfx/shader.hpp @@ -11,7 +11,7 @@ class Shader; // Assert that a type is a valid shader for downcasting. // A valid shader must: // * Inherit gfx::Shader -// * Declare a public, unique type name (string_view T::Name) +// * Have properly called DECLARE_SHADER_TYPEINFO in the class body // * Be a final class template inline constexpr bool is_shader_v = std::is_base_of_v && diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp new file mode 100644 index 000000000..4ff5bb56a --- /dev/null +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -0,0 +1,142 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using mat2 = std::array; +using mat3 = std::array; +using mat4 = std::array; + +namespace gfx { + +// static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); +// static_assert(std::is_standard_layout_v, "vertex type must use standard layout"); +// static_assert(I < Descriptor::data.count, "attribute index must be in range"); + +class VertexAttributeArray; + +class VertexAttribute { +public: + using float2 = std::array; + using float3 = std::array; + using matf2 = std::array; + using matf3 = std::array; + using matf4 = std::array; + using int2 = std::array; + using int3 = std::array; + using int4 = std::array; + + using ElementType = std::variant; + + // Can only be created by VertexAttributeArray implementations +protected: + VertexAttribute(int index_, AttributeDataType dataType_, std::size_t count_) + : index(index_), + dataType(dataType_), + items(count_) { + } + VertexAttribute(const VertexAttribute &) = default; + VertexAttribute(VertexAttribute&& other) + : index(other.index), + dataType(other.dataType), + items(std::move(other.items)) { + } + +public: + ~VertexAttribute() = default; + + int getIndex() const { return index; } + std::size_t getCount() const { return items.size(); } + AttributeDataType getDataType() const { return dataType; } + + const ElementType& get(std::size_t i) const { return items[i]; } + + template + const ElementType& set(std::size_t i, T value) { + dirty = true; // need to rebuild the raw data next time + return items[i] = value; + } + +protected: + VertexAttribute& operator=(const VertexAttribute&) = default; + VertexAttribute& operator=(const VertexAttribute&& other) { + index = other.index; + dataType = other.dataType; + items = std::move(other.items); + return *this; + } + +protected: + int index; + + /// indicates that a value has changed and any cached result should be discarded + mutable bool dirty = true; + + AttributeDataType dataType; + std::vector items; +}; + +/// Stores a collection of vertex attributes by name +class VertexAttributeArray { +public: + using AttributeMap = std::unordered_map>; + + VertexAttributeArray(int initCapacity = 10); + VertexAttributeArray(VertexAttributeArray &&); + VertexAttributeArray(const VertexAttributeArray&); + virtual ~VertexAttributeArray() = default; + + std::size_t size() const { return attrs.size(); } + + /// Add a new attribute element. + /// Returns a pointer to the new element on success, or null if the attribute already exists. + /// The result is valid only until the next non-const method call on this class. + VertexAttribute* get(const std::string& name) const; + + /// Add a new attribute element. + /// Returns a pointer to the new element on success, or null if the attribute already exists. + /// The result is valid only until the next non-const method call on this class. + VertexAttribute* add(std::string name, int index, AttributeDataType, std::size_t count); + + /// Add a new attribute element if it doesn't already exist. + /// Returns a pointer to the new element on success, or null if the type or count conflict with an existing entry. + /// The result is valid only until the next non-const method call on this class. + VertexAttribute* getOrAdd(std::string name, int index, AttributeDataType, std::size_t count); + + using ResolveDelegate = std::function; + /// Call the provided delegate with each value, providing the override if one exists. + void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const; + + VertexAttributeArray& operator=(VertexAttributeArray &&); + VertexAttributeArray& operator=(const VertexAttributeArray&); + +protected: + VertexAttribute* add(std::string name, std::unique_ptr&& attr) { + const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); + if (result.second) { + result.first->second = std::move(attr); + return result.first->second.get(); + } else { + return nullptr; + } + } + + virtual std::unique_ptr create(int index, AttributeDataType dataType, std::size_t count) = 0; + virtual std::unique_ptr copy(const VertexAttribute& attr) = 0; + +protected: + AttributeMap attrs; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp new file mode 100644 index 000000000..68e11d437 --- /dev/null +++ b/include/mbgl/gl/drawable_gl.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { + +namespace gfx { + +class IndexBuffer; +class VertexBufferResource; + +using UniqueVertexBufferResource = std::unique_ptr; + +} // namespace gfx + +namespace gl { + +class VertexArray; + +class DrawableGL : public gfx::Drawable { +public: + DrawableGL(); + virtual ~DrawableGL(); + + void draw(const PaintParameters &) const override; + + void setVertData(std::vector vertexData_, std::vector indexes_); + + const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } + void setVertexAttributes(const gfx::VertexAttributeArray& value) override { + vertexAttributes = static_cast(value); + } + void setVertexAttributes(gfx::VertexAttributeArray&& value) override { + vertexAttributes = std::move(static_cast(value)); + } + + const gl::VertexArray& getVertexArray() const; + void setVertexArray(gl::VertexArray&&, gfx::UniqueVertexBufferResource&&, gfx::IndexBuffer&&); + + std::vector& getIndexData() const override; + +protected: + class Impl; + const std::unique_ptr impl; + + // For testing only. + DrawableGL(std::unique_ptr); + +private: + VertexAttributeArrayGL vertexAttributes; +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/gl/drawable_gl_builder.hpp b/include/mbgl/gl/drawable_gl_builder.hpp new file mode 100644 index 000000000..639c30d07 --- /dev/null +++ b/include/mbgl/gl/drawable_gl_builder.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace gl { + +/** + Base class for OpenGL-specific drawable builders. + */ +class DrawableGLBuilder final : public gfx::DrawableBuilder { +public: + DrawableGLBuilder() { + } + virtual ~DrawableGLBuilder() = default; + + const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } + void setVertexAttributes(const VertexAttributeArrayGL& value) { vertexAttributes = value; } + void setVertexAttributes(VertexAttributeArrayGL&& value) { vertexAttributes = std::move(value); } + +protected: + gfx::DrawablePtr createDrawable() const override; + + /// Setup the SDK-specific aspects after all the values are present + void init() override; + +private: + VertexAttributeArrayGL vertexAttributes; +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/gl/drawable_gl_tweaker.hpp b/include/mbgl/gl/drawable_gl_tweaker.hpp new file mode 100644 index 000000000..51d69072a --- /dev/null +++ b/include/mbgl/gl/drawable_gl_tweaker.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace mbgl { + +namespace gfx { + class Drawable; +} + +namespace gl { + +/** + OpenGL-specific drawable tweaker + */ +class DrawableGLTweaker : public gfx::DrawableTweaker { +public: + DrawableGLTweaker() = default; + +public: + virtual ~DrawableGLTweaker() = default; + + virtual void execute(gfx::Drawable&, const PaintParameters&) override; +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp new file mode 100644 index 000000000..8e706af01 --- /dev/null +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace gl { + +class VertexAttributeArrayGL; + +class VertexAttributeGL final : public gfx::VertexAttribute { + // Can only be created by VertexAttributeArrayGL +private: + friend VertexAttributeArrayGL; + VertexAttributeGL(int index_, gfx::AttributeDataType dataType_, std::size_t count_) + : VertexAttribute(index_, dataType_, count_) { + } + VertexAttributeGL(const VertexAttributeGL& other) + : VertexAttribute(other), + glType(other.glType) { + } + VertexAttributeGL(VertexAttributeGL&& other) + : VertexAttribute(std::move(other)), + glType(other.glType) { + } + +public: + platform::GLenum getGLType() const { return glType; } + void setGLType(platform::GLenum value) { glType = value; } + + bool getNormalized() const { return normalized; } + void setNormalized(bool value) { normalized = value; } + + std::size_t getStride() const { return stride; } + const std::vector& getRaw() const; + +private: + platform::GLenum glType = 0; + bool normalized = false; + mutable int stride = 0; + mutable std::vector rawData; +}; + +/// Stores a collection of vertex attributes by name +class VertexAttributeArrayGL final : public gfx::VertexAttributeArray { +public: + VertexAttributeArrayGL(int initCapacity = 10) : VertexAttributeArray(initCapacity) { } + VertexAttributeArrayGL(VertexAttributeArray &&other) : VertexAttributeArray(std::move(other)) { } + VertexAttributeArrayGL(const VertexAttributeArray& other) : VertexAttributeArray(other) { } + ~VertexAttributeArrayGL() = default; + + VertexAttributeArrayGL& operator=(VertexAttributeArrayGL &&other) { + VertexAttributeArray::operator=(std::move(other)); + return *this; + } + VertexAttributeArrayGL& operator=(const VertexAttributeArrayGL& other) { + VertexAttributeArray::operator=(other); + return *this; + } + +private: + std::unique_ptr create(int index, gfx::AttributeDataType dataType, std::size_t count) override { + return std::unique_ptr(new VertexAttributeGL(index, dataType, count)); + } + std::unique_ptr copy(const gfx::VertexAttribute& attr) override { + return std::unique_ptr(new VertexAttributeGL(static_cast(attr))); + } +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/mtl/drawable_mtl.hpp b/include/mbgl/mtl/drawable_mtl.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/mbgl/mtl/drawable_mtl_builder.hpp b/include/mbgl/mtl/drawable_mtl_builder.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/mbgl/mtl/drawable_mtl_tweaker.hpp b/include/mbgl/mtl/drawable_mtl_tweaker.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/mbgl/mtl/shader_program_mtl.hpp b/include/mbgl/mtl/shader_program_mtl.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/mbgl/renderer/change_request.hpp b/include/mbgl/renderer/change_request.hpp new file mode 100644 index 000000000..3b2ddcc99 --- /dev/null +++ b/include/mbgl/renderer/change_request.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include + +#include +#include + +namespace mbgl { + +class RenderOrchestrator; + +namespace gfx { + class Drawable; + using DrawablePtr = std::shared_ptr; +} // namespace gfx + + +/** + Base class for changes to be made to the scene + */ +class ChangeRequest { +protected: + ChangeRequest() = default; + +public: + virtual ~ChangeRequest() = default; + + virtual void execute(RenderOrchestrator &) = 0; + +protected: +}; + +using ChangeRequestPtr = std::shared_ptr; +using UniqueChangeRequest = std::unique_ptr; +using UniqueChangeRequestVec = std::vector; + + +/** + Add a new drawable to the scene + */ +class AddDrawableRequest : public ChangeRequest { +public: + AddDrawableRequest(gfx::DrawablePtr drawable_) + : drawable(std::move(drawable_)) { + } + AddDrawableRequest(AddDrawableRequest&& other) + : drawable(std::move(other.drawable)) { + } + + void execute(RenderOrchestrator &) override; + +protected: + gfx::DrawablePtr drawable; +}; + + +/** + Remove a drawable from the scene + */ +class RemoveDrawableRequest : public ChangeRequest { +public: + RemoveDrawableRequest(util::SimpleIdentity drawableId_) : drawableId(drawableId_) { } + RemoveDrawableRequest(const RemoveDrawableRequest& other) : drawableId(other.drawableId) { } + + void execute(RenderOrchestrator &) override; + +protected: + util::SimpleIdentity drawableId; +}; + + +} // namespace mbgl diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp index 69c01a56f..c264d6e93 100644 --- a/include/mbgl/renderer/renderer.hpp +++ b/include/mbgl/renderer/renderer.hpp @@ -107,6 +107,11 @@ public: */ const std::vector& getPlacedSymbolsData() const; + /** + Update the layers + */ + void update(const std::shared_ptr&); + // Memory void reduceMemoryUse(); void clearData(); diff --git a/include/mbgl/renderer/renderer_frontend.hpp b/include/mbgl/renderer/renderer_frontend.hpp index 3c9fb8218..b07822ef4 100644 --- a/include/mbgl/renderer/renderer_frontend.hpp +++ b/include/mbgl/renderer/renderer_frontend.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include namespace mbgl { @@ -25,6 +27,8 @@ public: /// Coalescing updates is up to the implementer virtual void update(std::shared_ptr) = 0; + +protected: }; } // namespace mbgl diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp new file mode 100644 index 000000000..7d8439f2e --- /dev/null +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { +namespace gl { + +class ShaderProgramGL final : public gfx::ShaderProgramBase { +public: + ShaderProgramGL(UniqueProgram&& glProgram_); + ShaderProgramGL(ShaderProgramGL&& other); + virtual ~ShaderProgramGL() noexcept = default; + + static constexpr std::string_view Name{"GenericGLShader"}; + const std::string_view typeName() const noexcept override { return Name; } + + static std::shared_ptr create( + Context&, + std::string_view name, + std::string_view vertexSource, + std::string_view fragmentSource) noexcept(false); + + const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } + +protected: + UniqueProgram glProgram; + + VertexAttributeArrayGL vertexAttributes; +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/shader_program_mtl.hpp b/include/mbgl/shaders/mtl/shader_program_mtl.hpp new file mode 100644 index 000000000..1ca6ee770 --- /dev/null +++ b/include/mbgl/shaders/mtl/shader_program_mtl.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace mbgl { +namespace mtl { + +class ShaderProgramMTL : public gfx::ShaderProgramBase { +public: + ShaderProgramMTL() : ShaderProgramBase() { } + virtual ~ShaderProgramMTL() = default; + + static constexpr std::string_view Name{"GenericMTLShader"}; + const std::string_view typeName() const noexcept override { return Name; } + + //bool compile(std::string_view vert, std::string_view frag); + // Load compiled Metal functions from the default library in a bundle + //bool load(NSBundle*, std::string_view vertFuncName, std::string_view fragFuncName); + // Load compiled Metal functions from a specific library + //bool load(id, std::string_view vertFuncName, std::string_view fragFuncName); + +protected: +}; + +} // namespace mtl +} // namespace mbgl diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp new file mode 100644 index 000000000..431a3d78f --- /dev/null +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include + +namespace mbgl { +namespace gfx { + +class ShaderProgramBase : public gfx::Shader { +protected: + ShaderProgramBase() { } + ShaderProgramBase(ShaderProgramBase&&) { } + +public: + virtual ~ShaderProgramBase() noexcept = default; + + const util::SimpleIdentity& getID() const { return shaderProgramID; } + + /// Get the available vertex attributes and their default values + virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + +protected: + util::SimpleIdentity shaderProgramID; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/util/identity.hpp b/include/mbgl/util/identity.hpp new file mode 100644 index 000000000..4ab2d5217 --- /dev/null +++ b/include/mbgl/util/identity.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +namespace mbgl { +namespace util { + +/** + A simple unique identifier + */ +class SimpleIdentity final { +private: + constexpr SimpleIdentity(std::int64_t id) : uniqueID(id) { } +public: + SimpleIdentity(); + SimpleIdentity(const SimpleIdentity&) = default; + ~SimpleIdentity() = default; + + static const SimpleIdentity Empty; + + bool operator<(const SimpleIdentity& other) const { return uniqueID < other.uniqueID; } + bool operator==(const SimpleIdentity& other) const { return uniqueID == other.uniqueID; } + bool operator!=(const SimpleIdentity& other) const { return uniqueID != other.uniqueID; } + + operator bool() const { return uniqueID != emptyID; } + bool operator!() const { return uniqueID == emptyID; } + +private: + static constexpr std::int64_t emptyID = 0; + std::int64_t uniqueID; +}; + + +/** + Base class for objects that inherit an automatically-assigned unique identity + */ +class SimpleIdentifiable { +protected: + SimpleIdentifiable() = default; + SimpleIdentifiable(const SimpleIdentifiable&) = default; + virtual ~SimpleIdentifiable() = default; + + const util::SimpleIdentity& getId() const { return uniqueID; } + +protected: + util::SimpleIdentity uniqueID; +}; + + +} // namespace util +} // namespace mbgl diff --git a/platform/darwin/src/MLNRendererFrontend.h b/platform/darwin/src/MLNRendererFrontend.h index 001c7aff8..ea5a802f3 100644 --- a/platform/darwin/src/MLNRendererFrontend.h +++ b/platform/darwin/src/MLNRendererFrontend.h @@ -35,6 +35,9 @@ public: } else { [nativeView setNeedsRerender]; } + if (renderer) { + renderer->update(updateParameters); + } } void setObserver(mbgl::RendererObserver& observer) override { diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp new file mode 100644 index 000000000..59cee65b4 --- /dev/null +++ b/src/mbgl/gfx/drawable.cpp @@ -0,0 +1,9 @@ +#include + +namespace mbgl { +namespace gfx { + + +} // namespace gfx +} // namespace mbgl + diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp new file mode 100644 index 000000000..9124e65cf --- /dev/null +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -0,0 +1,86 @@ +#include +#include + +namespace mbgl { +namespace gfx { + +DrawableBuilder::DrawableBuilder() + : impl(std::make_unique()) { +} + +DrawableBuilder::~DrawableBuilder() = default; + +const Color& DrawableBuilder::getColor() const { + return impl->currentColor; +} +void DrawableBuilder::setColor(const Color& value) { + impl->currentColor = value; +} + +DrawablePtr DrawableBuilder::getCurrentDrawable(bool createIfNone) { + if (!currentDrawable && createIfNone) { + currentDrawable = createDrawable(); + } + return currentDrawable; +} + +void DrawableBuilder::flush() { + if (!impl->vertices.empty()) { + auto draw = getCurrentDrawable(/*create=*/true); + currentDrawable->setDrawPriority(drawPriority); + currentDrawable->setShaderID(shaderID); + currentDrawable->setVertexAttributes(getVertexAttributes()); + currentDrawable->addTweakers(tweakers.begin(), tweakers.end()); + init(); + } + if (currentDrawable) { + drawables.push_back(currentDrawable); + currentDrawable.reset(); + } +} + +util::SimpleIdentity DrawableBuilder::getDrawableId() { + return currentDrawable ? currentDrawable->getId() : util::SimpleIdentity::Empty; +} + +DrawPriority DrawableBuilder::getDrawPriority() const { + return drawPriority; +} + +void DrawableBuilder::setDrawPriority(DrawPriority value) { + drawPriority = value; + if (currentDrawable) { + currentDrawable->setDrawPriority(value); + } +} + +void DrawableBuilder::resetDrawPriority(DrawPriority value) { + setDrawPriority(value); + for (auto &drawble : drawables) { + drawble->setDrawPriority(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(); + 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->indexes.emplace_back(n, n+1, n+2); + impl->colors.insert(impl->colors.end(), 3, impl->currentColor); +} + +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->indexes.emplace_back(n-1, n, n+1); + impl->colors.emplace_back(impl->currentColor); +} + +void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { + addTriangle(x0, y0, x1, y0, x0, y1); + appendTriangle(x1, y1); +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/drawable_builder_impl.hpp b/src/mbgl/gfx/drawable_builder_impl.hpp new file mode 100644 index 000000000..7fc6e1ca2 --- /dev/null +++ b/src/mbgl/gfx/drawable_builder_impl.hpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +namespace mbgl { +namespace gfx { + +struct DrawableBuilder::Impl { + using VT = gfx::detail::VertexType>; + gfx::VertexVector vertices; + gfx::IndexVector indexes; + SegmentVector> segments; + Color currentColor = Color::white(); + std::vector colors; +}; + +} // namespace gfx +} // namespace mbgl + diff --git a/src/mbgl/gfx/drawable_tweaker.cpp b/src/mbgl/gfx/drawable_tweaker.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/mbgl/gfx/types.hpp b/src/mbgl/gfx/types.hpp index cafb2f3f8..d848ae270 100644 --- a/src/mbgl/gfx/types.hpp +++ b/src/mbgl/gfx/types.hpp @@ -1,65 +1,12 @@ #pragma once +#include + #include namespace mbgl { namespace gfx { -enum class PrimitiveType : uint8_t { - Point, - Line, - Triangle, -}; - -enum class DrawModeType : uint8_t { - Points, - Lines, - LineLoop, - LineStrip, - Triangles, - TriangleStrip, - TriangleFan, -}; - -enum class AttributeDataType : uint8_t { - Byte, - Byte2, - Byte3, - Byte4, - - UByte, - UByte2, - UByte3, - UByte4, - - Short, - Short2, - Short3, - Short4, - - UShort, - UShort2, - UShort3, - UShort4, - - Int, - Int2, - Int3, - Int4, - - UInt, - UInt2, - UInt3, - UInt4, - - Float, - Float2, - Float3, - Float4, - - Invalid = 255, -}; - enum class ColorBlendEquationType : uint8_t { Add, Subtract, diff --git a/src/mbgl/gfx/upload_pass.hpp b/src/mbgl/gfx/upload_pass.hpp index bbb429b84..d48c37be7 100644 --- a/src/mbgl/gfx/upload_pass.hpp +++ b/src/mbgl/gfx/upload_pass.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -8,9 +9,16 @@ #include #include +#include +#include + namespace mbgl { namespace gfx { +class VertexAttributeArray; + +using AttributeBindingArray = std::vector>; + class UploadPass { protected: UploadPass() = default; @@ -51,12 +59,18 @@ public: updateIndexBufferResource(buffer.getResource(), v.data(), v.bytes()); } + virtual std::pair> + buildAttributeBindings(const gfx::VertexAttributeArray& defaults, + const gfx::VertexAttributeArray& overrides, + gfx::BufferUsageType) = 0; + protected: virtual std::unique_ptr createVertexBufferResource(const void* data, std::size_t size, BufferUsageType) = 0; virtual void updateVertexBufferResource(VertexBufferResource&, const void* data, std::size_t size) = 0; +public: virtual std::unique_ptr createIndexBufferResource(const void* data, std::size_t size, BufferUsageType) = 0; diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp new file mode 100644 index 000000000..1bf4f81a7 --- /dev/null +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -0,0 +1,70 @@ +#include + +namespace mbgl { +namespace gfx { + +VertexAttributeArray::VertexAttributeArray(int initCapacity) + : attrs(initCapacity) { +} + +VertexAttributeArray::VertexAttributeArray(VertexAttributeArray &&other) + : attrs(std::move(other.attrs)) { +} + +VertexAttributeArray::VertexAttributeArray(const VertexAttributeArray& other) + : attrs(other.attrs.size()) { + operator=(other); +} + +VertexAttributeArray& VertexAttributeArray::operator=(VertexAttributeArray &&other) { + attrs = std::move(other.attrs); + return *this; +} + +VertexAttributeArray& VertexAttributeArray::operator=(const VertexAttributeArray& other) { + attrs.clear(); + for (const auto &kv : other.attrs) { + add(kv.first, copy(*kv.second)); + } + return *this; +} + +VertexAttribute* VertexAttributeArray::get(const std::string& name) const { + const auto result = attrs.find(name); + return (result != attrs.end()) ? result->second.get() : nullptr; +} + +VertexAttribute* VertexAttributeArray::add(std::string name, int index, + AttributeDataType dataType, std::size_t count) { + const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); + if (result.second) { + result.first->second = create(index, dataType, count); + return result.first->second.get(); + } else { + return nullptr; + } +} + +VertexAttribute* VertexAttributeArray::getOrAdd(std::string name, int index, + AttributeDataType dataType, std::size_t count) { + //attrs.emplace_back(std::make_unique(dataType, count)); + const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); + if (result.second) { + result.first->second = create(index, dataType, count); + } else if (result.first->second->getDataType() != dataType || + result.first->second->getCount() != count) { + return nullptr; + } + return result.first->second.get(); +} + +void VertexAttributeArray::resolve(const VertexAttributeArray& overrides, + ResolveDelegate delegate) const { + for (auto& kv : attrs) { + const auto overrideAttr = overrides.get(kv.first); + delegate(kv.first, *kv.second, overrideAttr); + } +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/vertex_buffer.hpp b/src/mbgl/gfx/vertex_buffer.hpp index a70fee050..c14f5f34f 100644 --- a/src/mbgl/gfx/vertex_buffer.hpp +++ b/src/mbgl/gfx/vertex_buffer.hpp @@ -14,15 +14,16 @@ public: virtual ~VertexBufferResource() = default; }; -// This class has a template argument that we use to specify the vertex type. It -// is not used by the implementation, but serves type checking purposes during -// build time. +using UniqueVertexBufferResource = std::unique_ptr; + +// This class has a template argument that we use to specify the vertex type. It is not used by +// the implementation, but serves type checking purposes during build time. template class VertexBuffer { public: - VertexBuffer(const std::size_t elements_, std::unique_ptr&& resource_) - : elements(elements_), - resource(std::move(resource_)) {} + VertexBuffer(const std::size_t elements_, UniqueVertexBufferResource&& resource_) + : elements(elements_), resource(std::move(resource_)) { + } std::size_t elements; @@ -33,7 +34,7 @@ public: } protected: - std::unique_ptr resource; + UniqueVertexBufferResource resource; }; } // namespace gfx diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 0cecda772..88b7dc1bb 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -163,8 +163,10 @@ private: UniqueFramebuffer createFramebuffer(); std::unique_ptr readFramebuffer(Size, gfx::TexturePixelType, bool flip); +public: VertexArray createVertexArray(); +private: friend detail::ProgramDeleter; friend detail::ShaderDeleter; friend detail::BufferDeleter; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp new file mode 100644 index 000000000..3e76e22c9 --- /dev/null +++ b/src/mbgl/gl/drawable_gl.cpp @@ -0,0 +1,42 @@ +#include +#include + +namespace mbgl { +namespace gl { + +DrawableGL::DrawableGL() + : impl(std::make_unique()) { +} + +DrawableGL::~DrawableGL() { +} + +void DrawableGL::draw(const PaintParameters ¶meters) const +{ + impl->draw(parameters); +} + +void DrawableGL::setVertData(std::vector vertexData_, + std::vector indexes_) { + impl->vertData = std::move(vertexData_); + impl->indexes = std::move(indexes_); +} + +std::vector& DrawableGL::getIndexData() const { + return impl->indexes; +} + +const gl::VertexArray& DrawableGL::getVertexArray() const { + return impl->vertexArray; +} + +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_); +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp new file mode 100644 index 000000000..1e344ffad --- /dev/null +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -0,0 +1,36 @@ +#include + +#include +#include + +namespace mbgl { +namespace gl { + +gfx::DrawablePtr DrawableGLBuilder::createDrawable() const { + return std::make_shared(); +}; + +void DrawableGLBuilder::init() { + const auto n = impl->vertices.elements(); + assert(n <= impl->indexes.elements()); + assert(n == impl->colors.size()); + + // temp + const auto vertSize = sizeof(Impl::VT) + 4 * sizeof(float); + std::vector rawVert(n * vertSize); + + auto p = &rawVert[0]; + for (auto i = 0ULL; i < n; ++i) { + *(Impl::VT*)p = impl->vertices.at(i); p += sizeof(Impl::VT); + *(float*)p = impl->colors[i].r; p += sizeof(float); + *(float*)p = impl->colors[i].g; p += sizeof(float); + *(float*)p = impl->colors[i].b; p += sizeof(float); + *(float*)p = impl->colors[i].a; p += sizeof(float); + } + + ((DrawableGL*)currentDrawable.get())->setVertData(std::move(rawVert), impl->indexes.vector()); +} + +} // namespace gl +} // namespace mbgl + diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp new file mode 100644 index 000000000..43d1890f3 --- /dev/null +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mbgl { +namespace gl { + +using namespace platform; + +class DrawableGL::Impl final { + +public: + Impl() { + } + ~Impl() = default; + + void draw(const PaintParameters& /*parameters*/) const { + MBGL_CHECK_ERROR(glDrawElements( + Enum::to(type), + static_cast(indexLength), + GL_UNSIGNED_SHORT, + reinterpret_cast(sizeof(uint16_t) * indexOffset))); + + } + + const gfx::DrawModeType type = gfx::DrawModeType::Triangles; + ShaderID shaderId; + RenderbufferID renderTarget; + std::vector textures; + + std::vector vertData; + std::vector indexes; + + VertexArray vertexArray = { { nullptr, false } }; + gfx::IndexBuffer indexBuffer = { 0, nullptr }; + gfx::UniqueVertexBufferResource attributeBuffer; + + std::size_t indexOffset = 0; + std::size_t indexLength = 0; + mat4 matrix; + gfx::DepthMode depthMode = gfx::DepthMode::disabled(); + 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; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/drawable_gl_tweaker.cpp b/src/mbgl/gl/drawable_gl_tweaker.cpp new file mode 100644 index 000000000..c24b01324 --- /dev/null +++ b/src/mbgl/gl/drawable_gl_tweaker.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +namespace mbgl { +namespace gl { + +void DrawableGLTweaker::execute(gfx::Drawable& drawable, const PaintParameters &) { + auto& drawGL = (gl::DrawableGL&)drawable; + // apply expressions based on current state, update attributes, uniforms, etc. + drawGL.getId(); +} + +} // namespace gl +} // namespace mbgl + diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 6a366cd65..9f6d9f876 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -3,10 +3,13 @@ #include #include #include +#include #include #include #include +#include + namespace mbgl { namespace gl { @@ -119,6 +122,54 @@ void UploadPass::updateTextureResourceSub(gfx::TextureResource& resource, data)); } + +std::pair> + UploadPass::buildAttributeBindings(const gfx::VertexAttributeArray& defaults, + const gfx::VertexAttributeArray& overrides, + const gfx::BufferUsageType usage) { + + AttributeBindingArray bindings; + bindings.reserve(defaults.size()); + + std::vector allData; + constexpr auto ExpectedSize = 32; + allData.reserve(defaults.size() * ExpectedSize); + + defaults.resolve(overrides, [&](const std::string& /*name*/, + const gfx::VertexAttribute& defaultAttr, + const gfx::VertexAttribute* overrideAttr) { + + const auto& effectiveAttr = *(overrideAttr ? overrideAttr : &defaultAttr); + const auto& effectiveGL = static_cast(effectiveAttr); + const auto& defaultGL = static_cast(defaultAttr); + + // Pad to 16 bytes + allData.insert(allData.end(), 16 - allData.size() % 16, 0); + + const auto offset = static_cast(allData.size()); + + bindings.emplace_back(gfx::AttributeBinding{ + gfx::AttributeDescriptor{ defaultAttr.getDataType(), offset }, + static_cast(effectiveGL.getStride()), + nullptr, // buffer pointer established later + static_cast(defaultGL.getIndex()) + }); + + const auto& rawData = effectiveGL.getRaw(); + allData.insert(allData.begin(), rawData.begin(), rawData.end()); + }); + + auto vertBuf = createVertexBufferResource(&allData[0], allData.size(), usage); + + // Assign to each element + std::for_each(bindings.begin(), bindings.end(), [&](auto& b){ b->vertexBufferResource = vertBuf.get(); }); + + gfx::AttributeBindingArray& a = bindings; + std::unique_ptr& b = vertBuf; + return std::make_pair(std::move(a), std::move(b)); + //return std::make_pair(bindings, vertBuf); +} + void UploadPass::pushDebugGroup(const char* name) { commandEncoder.pushDebugGroup(name); } diff --git a/src/mbgl/gl/upload_pass.hpp b/src/mbgl/gl/upload_pass.hpp index 841ddc892..0beb9a034 100644 --- a/src/mbgl/gl/upload_pass.hpp +++ b/src/mbgl/gl/upload_pass.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace mbgl { namespace gfx { @@ -13,6 +14,7 @@ namespace gl { class CommandEncoder; class Context; +class VertexArray; class UploadPass final : public gfx::UploadPass { public: @@ -32,6 +34,11 @@ public: gfx::BufferUsageType) override; void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override; + std::pair> + buildAttributeBindings(const gfx::VertexAttributeArray& defaults, + const gfx::VertexAttributeArray& overrides, + gfx::BufferUsageType) override; + public: std::unique_ptr createTextureResource(Size, const void* data, diff --git a/src/mbgl/gl/vertex_array.hpp b/src/mbgl/gl/vertex_array.hpp index 8ad6742de..47a32facc 100644 --- a/src/mbgl/gl/vertex_array.hpp +++ b/src/mbgl/gl/vertex_array.hpp @@ -57,10 +57,21 @@ using UniqueVertexArrayState = std::unique_ptr + +#include + +#include + +namespace mbgl { +namespace gl { + +class VertexAttributeArrayGL; + +using namespace platform; + +static std::pair getSizeAndStride(GLenum glType) { + switch (glType) { + case GL_FLOAT: return { 4*1, 4*1 }; + case GL_FLOAT_VEC2: return { 4*2, 4*2 }; + case GL_FLOAT_VEC3: return { 4*3, 4*4 }; + case GL_FLOAT_VEC4: return { 4*4, 4*4 }; + case GL_FLOAT_MAT2: return { 4*4, 4*4 }; + case GL_INT: return { 4*1, 4*1 }; + case GL_UNSIGNED_INT: return { 4*1, 4*1 }; + case GL_INT_VEC2: return { 4*2, 4*2 }; + case GL_INT_VEC3: return { 4*3, 4*4 }; + case GL_INT_VEC4: return { 4*4, 4*4 }; + default: return { 0, 0 }; + } +} + +static const void* getPtr(const gfx::VertexAttribute::ElementType& element, GLenum glType) { + switch (glType) { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: return std::get_if(&element); + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: return std::get_if(&element); + default: return nullptr; + } +} + +const std::vector& VertexAttributeGL::getRaw() const { + if (dirty) { + const auto count = getCount(); + const auto sizes = getSizeAndStride(getGLType()); + + stride = sizes.second; + + rawData.resize(stride * count); + std::fill(rawData.begin(), rawData.end(), 0); + + if (rawData.size() > 0) { + std::uint8_t* outPtr = &rawData[0]; + + for (std::size_t i = 0; i < count; ++i) { + if (const auto rawPtr = getPtr(items[i], getGLType())) { + std::memcpy(outPtr, rawPtr, sizes.first); + } + outPtr += stride; + } + } + + dirty = false; + } + return rawData; +} + +} // namespace gfx +} // namespace mbgl + diff --git a/src/mbgl/mtl/drawable_mtl.cpp b/src/mbgl/mtl/drawable_mtl.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/mbgl/mtl/drawable_mtl_builder.cpp b/src/mbgl/mtl/drawable_mtl_builder.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/mbgl/mtl/drawable_mtl_tweaker.cpp b/src/mbgl/mtl/drawable_mtl_tweaker.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/mbgl/renderer/change_request.cpp b/src/mbgl/renderer/change_request.cpp new file mode 100644 index 000000000..7b80b7604 --- /dev/null +++ b/src/mbgl/renderer/change_request.cpp @@ -0,0 +1,14 @@ +#include +#include + +namespace mbgl { + +void AddDrawableRequest::execute(RenderOrchestrator &orchestrator) { + orchestrator.addDrawable(std::move(drawable)); +} + +void RemoveDrawableRequest::execute(RenderOrchestrator &orchestrator) { + orchestrator.removeDrawable(drawableId); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 1a63e776b..1ca51e62b 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -1,16 +1,19 @@ +#include +#include #include #include #include +#include #include #include #include #include #include #include +#include #include #include -#include -#include +#include namespace mbgl { @@ -35,10 +38,12 @@ void RenderBackgroundLayer::transition(const TransitionParameters& parameters) { unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } -void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& parameters) { - auto properties = makeMutable(staticImmutableCast(baseImpl), - parameters.getCrossfadeParameters(), - unevaluated.evaluate(parameters)); +void RenderBackgroundLayer::evaluate( + const PropertyEvaluationParameters ¶meters) { + auto properties = makeMutable( + staticImmutableCast(baseImpl), + parameters.getCrossfadeParameters(), + unevaluated.evaluate(parameters)); passes = properties->evaluated.get() == 0.0f ? RenderPass::None : (!unevaluated.get().isUndefined() || @@ -159,7 +164,8 @@ std::optional RenderBackgroundLayer::getSolidBackground() const { return std::nullopt; } - return {evaluated.get() * evaluated.get()}; + return std::nullopt; + //return { evaluated.get() * evaluated.get() }; } namespace { diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index f0cfd2012..e7ad07ac3 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -5,8 +5,19 @@ #include #include +#include +#include +#include + namespace mbgl { +namespace gfx { + class Drawable; + using DrawablePtr = std::shared_ptr; +} // namespace gfc + +class ChangeRequest; + class RenderBackgroundLayer final : public RenderLayer { public: explicit RenderBackgroundLayer(Immutable); diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index a0d2c39f6..fb3e2211e 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index b6bacb680..50071f9db 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -12,6 +13,7 @@ namespace mbgl { class Bucket; +class ChangeRequest; class TransitionParameters; class PropertyEvaluationParameters; class UploadParameters; @@ -147,6 +149,8 @@ protected: LayerPlacementData placementData; + gfx::DrawablePtr drawables; + private: // Some layers may not render correctly on some hardware when the vertex // attribute limit of that GPU is exceeded. More attributes are used when diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 0553ae507..ab8677093 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -137,6 +138,10 @@ void RenderOrchestrator::setObserver(RendererObserver* observer_) { std::unique_ptr RenderOrchestrator::createRenderTree( const std::shared_ptr& updateParameters) { + + layersAdded.clear(); + layersRemoved.clear(); + const bool isMapModeContinuous = updateParameters->mode == MapMode::Continuous; if (!isMapModeContinuous) { // Reset zoom history state. @@ -217,7 +222,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( imageManager->notifyIfMissingImageAdded(); imageManager->setLoaded(updateParameters->spriteLoaded); - const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters->layers); + LayerDifference layerDiff = diffLayers(layerImpls, updateParameters->layers); layerImpls = updateParameters->layers; const bool layersAddedOrRemoved = !layerDiff.added.empty() || !layerDiff.removed.empty(); @@ -452,6 +457,9 @@ std::unique_ptr RenderOrchestrator::createRenderTree( } } + layersAdded = std::move(layerDiff.added); + layersRemoved = std::move(layerDiff.removed); + return std::make_unique(std::move(renderTreeParameters), std::move(layerRenderItems), std::move(sourceRenderItems), @@ -711,13 +719,18 @@ bool RenderOrchestrator::hasTransitions(TimePoint timePoint) const { } bool RenderOrchestrator::isLoaded() const { - for (const auto& entry : renderSources) { + // do the simple boolean check before iterating over all the tiles in all the sources + if (!imageManager->isLoaded()) { + return false; + } + + for (const auto& entry: renderSources) { if (!entry.second->isLoaded()) { return false; } } - return imageManager->isLoaded(); + return true; } void RenderOrchestrator::clearData() { @@ -737,13 +750,59 @@ void RenderOrchestrator::clearData() { glyphManager->evict(fontStacks(*layerImpls)); } -void RenderOrchestrator::onGlyphsError(const FontStack& fontStack, - const GlyphRange& glyphRange, - std::exception_ptr error) { - Log::Error(Event::Style, - "Failed to load glyph range " + std::to_string(glyphRange.first) + "-" + - std::to_string(glyphRange.second) + " for font stack " + fontStackToString(fontStack) + ": " + - util::toString(error)); +void RenderOrchestrator::update(const std::shared_ptr& parameters) { + if (!parameters) { + return; + } + + // TODO: Removed layers need a chance to remove their drawables + std::vector> changes; + for (auto& layer : *parameters->layers) { + layer->update(changes); + addChanges(changes); + } +} + +void RenderOrchestrator::addChanges(UniqueChangeRequestVec& changes) { + pendingChanges.insert(pendingChanges.end(), + std::make_move_iterator(changes.begin()), + std::make_move_iterator(changes.end())); + changes.clear(); +} + +void RenderOrchestrator::addDrawable(gfx::DrawablePtr drawable) { + if (drawable) { + const auto id = drawable->getId(); + drawables.insert(std::make_pair(id, std::move(drawable))); + } +} + +void RenderOrchestrator::removeDrawable(const util::SimpleIdentity& drawableId) { + drawables.erase(drawableId); +} + +void RenderOrchestrator::updateLayers(PaintParameters& parameters) { + std::vector> changes; + for (auto& kv : layersRemoved) { + kv.second->layerRemoved(parameters, changes); + addChanges(changes); + } + for (auto& kv : layersAdded) { + kv.second->layerAdded(parameters, changes); + addChanges(changes); + } +} + +void RenderOrchestrator::processChanges() { + auto localChanges = std::move(pendingChanges); + for (auto &change : localChanges) { + change->execute(*this); + } +} + +void RenderOrchestrator::onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) { + Log::Error(Event::Style, "Failed to load glyph range " + std::to_string(glyphRange.first) + "-" + std::to_string(glyphRange.second) + + " for font stack " + fontStackToString(fontStack) + ": " + util::toString(error)); observer->onResourceError(error); } diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 7cea91074..fede95068 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -15,10 +15,12 @@ #include #include +#include #include namespace mbgl { +class ChangeRequest; class RendererObserver; class RenderSource; class UpdateParameters; @@ -32,11 +34,20 @@ class PatternAtlas; class CrossTileSymbolIndex; class RenderTree; +namespace gfx { + class Drawable; + using DrawablePtr = std::shared_ptr; +} // namespace gfx + namespace style { class LayerProperties; } // namespace style -class RenderOrchestrator final : public GlyphManagerObserver, public ImageManagerObserver, public RenderSourceObserver { +using ImmutableLayer = Immutable; + +class RenderOrchestrator final : public GlyphManagerObserver, + public ImageManagerObserver, + public RenderSourceObserver { public: RenderOrchestrator(bool backgroundLayerAsColor_, const std::optional& localFontFamily_); ~RenderOrchestrator() override; @@ -78,6 +89,18 @@ public: const std::vector& getPlacedSymbolsData() const; void clearData(); + void update(const std::shared_ptr&); + + using DrawableMap = std::map; + const DrawableMap& getDrawables() const { return drawables; } + + void addDrawable(gfx::DrawablePtr); + void removeDrawable(const util::SimpleIdentity& drawableId); + + void updateLayers(PaintParameters&); + + void processChanges(); + private: bool isLoaded() const; bool hasTransitions(TimePoint) const; @@ -107,6 +130,9 @@ private: void onStyleImageMissing(const std::string&, const std::function&) override; void onRemoveUnusedStyleImages(const std::vector&) override; + /// Move changes into the pending set, clearing the provided collection + void addChanges(UniqueChangeRequestVec&); + RendererObserver* observer; ZoomHistory zoomHistory; @@ -125,6 +151,10 @@ private: std::unordered_map> renderLayers; RenderLight renderLight; + // Layers added and removed in the last update + std::unordered_map layersAdded; + std::unordered_map layersRemoved; + CrossTileSymbolIndex crossTileSymbolIndex; PlacementController placementController; @@ -137,6 +167,10 @@ private: std::vector> filteredLayersForSource; RenderLayerReferences orderedLayers; RenderLayerReferences layersNeedPlacement; + +protected: + DrawableMap drawables; + std::vector> pendingChanges; }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_tree.hpp b/src/mbgl/renderer/render_tree.hpp index e47fcf904..48b6970bd 100644 --- a/src/mbgl/renderer/render_tree.hpp +++ b/src/mbgl/renderer/render_tree.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index b35f9d6c3..247069877 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -129,6 +129,10 @@ const std::vector& Renderer::getPlacedSymbolsData() const { return impl->orchestrator.getPlacedSymbolsData(); } +void Renderer::update(const std::shared_ptr& parameters) { + impl->orchestrator.update(parameters); +} + void Renderer::reduceMemoryUse() { gfx::BackendScope guard{impl->backend}; impl->reduceMemoryUse(); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 5cb47e850..967107243 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -2,17 +2,20 @@ #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -73,6 +76,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { renderTree.getLineAtlas(), renderTree.getPatternAtlas()}; + orchestrator.updateLayers(parameters); + parameters.symbolFadeChange = renderTreeParameters.symbolFadeChange; parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; const auto& sourceRenderItems = renderTree.getSourceRenderItems(); @@ -93,6 +98,47 @@ void Renderer::Impl::render(const RenderTree& renderTree) { staticData->upload(*uploadPass); renderTree.getLineAtlas().upload(*uploadPass); renderTree.getPatternAtlas().upload(*uploadPass); + + for (const auto& pair : orchestrator.getDrawables()) { + auto& drawable = *pair.second; + + // Run tweakers to update any dynamic elements + for (auto& tweaker : drawable.getTweakers()) { + tweaker->execute(drawable, parameters); + } + + // Generate a vertex array object for the drawable state, if necessary + auto& drawableGL = static_cast(drawable); + if (!drawableGL.getVertexArray().isValid() && !drawable.getShaderID().empty()) { + // TODO: avoid having to do this lookup twice + if (auto shader = parameters.shaders.get(drawable.getShaderID())) { + const auto usage = gfx::BufferUsageType::StaticDraw; + + // Build index buffer + const auto& indexData = drawable.getIndexData(); + auto indexBuffer = gfx::IndexBuffer { + indexData.size(), + uploadPass->createIndexBufferResource( + &indexData[0], + indexData.size() * sizeof(indexData[0]), + usage) + }; + + // Apply drawable values to shader defaults + const auto& defaults = shader->getVertexAttributes(); + const auto& overrides = drawable.getVertexAttributes(); + auto bindingsAndBuffer = uploadPass->buildAttributeBindings(defaults, overrides, usage); + + auto& glContext = static_cast(context); + auto vertexArray = glContext.createVertexArray(); + vertexArray.bind(glContext, indexBuffer, bindingsAndBuffer.first); + + drawableGL.setVertexArray(std::move(vertexArray), + std::move(bindingsAndBuffer.second), + std::move(indexBuffer)); + } + } + } } // - 3D PASS @@ -143,6 +189,27 @@ void Renderer::Impl::render(const RenderTree& renderTree) { parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * parameters.numSublayers * parameters.depthEpsilon; + // Run changes + orchestrator.processChanges(); + + // Draw Drawables + { + for (const auto &pair : orchestrator.getDrawables()) { + const auto& drawable = *pair.second; + + if (!drawable.getShaderID().empty()) { + // if shader != currentShader + if (auto shader = parameters.shaders.get(drawable.getShaderID())) { + // Context.activate(shader) + } + } + + // Context.bind(drawable vao) + + drawable.draw(parameters); + } + } + // - OPAQUE PASS ------------------------------------------------------------------------------- // Render everything top-to-bottom by using reverse iterators. Render opaque objects first. { diff --git a/src/mbgl/shaders/gl/shader_program_gl.cpp b/src/mbgl/shaders/gl/shader_program_gl.cpp new file mode 100644 index 000000000..74665eda3 --- /dev/null +++ b/src/mbgl/shaders/gl/shader_program_gl.cpp @@ -0,0 +1,118 @@ +#include + +#include +#include +#include +#include + +#include + +namespace mbgl { +namespace gl { + +static gfx::AttributeDataType mapType(platform::GLenum attrType) { + using T = gfx::AttributeDataType; + switch (attrType) { + case GL_FLOAT: return T::Float; + case GL_FLOAT_VEC2: return T::Float2; + case GL_FLOAT_VEC3: return T::Float3; + case GL_FLOAT_VEC4: return T::Float4; + case GL_FLOAT_MAT2: return T::Float4; // does that work ? + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: return T::Invalid; + case GL_INT: return T::Int; + case GL_INT_VEC2: return T::Int2; + case GL_INT_VEC3: return T::Int3; + case GL_INT_VEC4: return T::Int4; + case GL_UNSIGNED_INT: return T::UInt; + // ES3 stuff that isn't defined yet: + //case GL_FLOAT_MAT2x3: + //case GL_FLOAT_MAT2x4: + //case GL_FLOAT_MAT3x2: + //case GL_FLOAT_MAT3x4: + //case GL_FLOAT_MAT4x2: + //case GL_FLOAT_MAT4x3: return T::Invalid; + //case GL_UNSIGNED_INT_VEC2: return T::UInt2; + //case GL_UNSIGNED_INT_VEC3: return T::UInt3; + //case GL_UNSIGNED_INT_VEC4: return T::UInt4; + //case GL_DOUBLE: return T::Float; + //case GL_DOUBLE_VEC2: return T::Float2; + //case GL_DOUBLE_VEC3: return T::Float3; + //case GL_DOUBLE_VEC4: return T::Float4; + //case GL_DOUBLE_MAT2: return T::Float4; + //case GL_DOUBLE_MAT3: + //case GL_DOUBLE_MAT4: + //case GL_DOUBLE_MAT2x3: + //case GL_DOUBLE_MAT2x4: + //case GL_DOUBLE_MAT3x2: + //case GL_DOUBLE_MAT3x4: + //case GL_DOUBLE_MAT4x2: + //case GL_DOUBLE_MAT4x3: + default: return T::Invalid; + } +} + +ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_) + : ShaderProgramBase(), + glProgram(std::move(glProgram_)) { +} + +ShaderProgramGL::ShaderProgramGL(ShaderProgramGL&& other) + : ShaderProgramBase(std::forward(other)), + glProgram(std::move(other.glProgram)) { +} + +std::shared_ptr ShaderProgramGL::create( + Context& context, + std::string_view /*name*/, + std::string_view vertexSource, + std::string_view fragmentSource) noexcept(false) { + + const auto firstAttrib = "pos"; + + // throws on compile error + auto vertProg = context.createShader(ShaderType::Vertex, std::initializer_list{vertexSource.data()}); + auto fragProg = context.createShader(ShaderType::Fragment, std::initializer_list{fragmentSource.data()}); + auto program = context.createProgram(vertProg, fragProg, firstAttrib); + + using namespace platform; + + // ES3 + //GLint numAttribs; + //glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs); + + GLint count; + GLint maxLength; + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count)); + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength)); + + auto name = std::make_unique(maxLength); + for (GLint index = 0; index < count; ++index) { + GLsizei length = 0; + GLint size = 0; + GLenum type = 0; + MBGL_CHECK_ERROR(glGetActiveUniform(program, index, maxLength, &length, &size, &type, name.get())); + } + + VertexAttributeArrayGL attrs; + + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &count)); + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength)); + for (GLint index = 0; index < count; ++index) { + GLsizei length = 0; // "number of characters actually written in name (excluding the null terminator)" + GLint size = 0; // "size of the attribute variable, in units of the type returned in type" + GLenum glType = 0; + MBGL_CHECK_ERROR(glGetActiveAttrib(program, index, maxLength, &length, &size, &glType, name.get())); + const auto elementType = mapType(glType); + if (elementType != gfx::AttributeDataType::Invalid && length > 0) { + if (auto newAttr = attrs.add(name.get(), index, elementType, size)) { + static_cast(newAttr)->setGLType(glType); + } + } + } + + return std::make_shared(std::move(program)); +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/shader_program_mtl.cpp b/src/mbgl/shaders/mtl/shader_program_mtl.cpp new file mode 100644 index 000000000..01ad8c832 --- /dev/null +++ b/src/mbgl/shaders/mtl/shader_program_mtl.cpp @@ -0,0 +1,11 @@ +#include + +namespace mbgl { +namespace mtl { + +//bool ShaderProgramMTL::compile(std::string_view vert, std::string_view frag) { +// return false; +//} + +} // namespace mtl +} // namespace mbgl diff --git a/src/mbgl/shaders/shader_program_base.cpp b/src/mbgl/shaders/shader_program_base.cpp new file mode 100644 index 000000000..ed841b21c --- /dev/null +++ b/src/mbgl/shaders/shader_program_base.cpp @@ -0,0 +1,4 @@ +#include + +#include + diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index a7012bb79..c13a8dea6 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -7,11 +7,19 @@ #include #include -#include #include +#include +#include +#include namespace mbgl { +class ChangeRequest; +class PaintParameters; + +using UniqueChangeRequest = std::unique_ptr; +using UniqueChangeRequestVec = std::vector; + namespace style { /** @@ -47,6 +55,12 @@ public: // Populates the given \a fontStack with fonts being used by the layer. virtual void populateFontStack(std::set& fontStack) const; + /// Generate any changes needed by the layer + virtual void update(UniqueChangeRequestVec&) const { } + + virtual void layerAdded(PaintParameters&, UniqueChangeRequestVec&) const { } + virtual void layerRemoved(PaintParameters&, UniqueChangeRequestVec&) const { } + std::string id; std::string source; std::string sourceLayer; diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index a59a84fbe..d641dc236 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -1,5 +1,14 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include + namespace mbgl { namespace style { @@ -7,5 +16,99 @@ bool BackgroundLayer::Impl::hasLayoutDifference(const Layer::Impl&) const { return false; } +constexpr auto shaderName = "background_generic"; + +void BackgroundLayer::Impl::layerAdded(PaintParameters& parameters, UniqueChangeRequestVec& changes) const { + // TODO: this should happen a GL-specific part of map initialization + auto &glContext = static_cast(parameters.context); + auto shader = parameters.shaders.get(shaderName); + if (!shader) { + constexpr auto vert = R"( + //#version 300 es + precision highp float; + uniform float a; + uniform int b; + uniform mat4 c; + attribute vec3 pos; //layout (location = 0) in vec3 pos; + attribute float d; + //attribute int e; + attribute mat2 f; + attribute mat4 g; + void main() { + gl_Position = vec4(a, g[0][0], f[0][0], d); + gl_Position = vec4(pos, 1.0); + })"; + constexpr auto frag = R"( + //#version 300 es + precision highp float; + //out vec4 color; + void main() { + //color = vec4(1.0,0.0,0.0,1.0); + gl_FragColor = vec4(1.0,0.0,0.0,1.0); + })"; + + try { + // Compile + shader = gl::ShaderProgramGL::create(glContext, shaderName, vert, frag); + if (shader) { + // Set default values + if (auto *attr = shader->getVertexAttributes().get("a")) { + attr->set(0, 12.3f); + } + if (auto *attr = shader->getVertexAttributes().get("b")) { + attr->set(0, 123); + } + if (auto *attr = shader->getVertexAttributes().get("f")) { + attr->set(0, gfx::VertexAttribute::matf2{ 1.0f, 2.0f, 3.0f, 4.0f }); + } + + // Add to the registry + if (!parameters.shaders.registerShader(shader, shaderName)) { + Log::Warning(Event::General, "Shader conflict - " + std::string(shaderName)); + return; + } + } else { + Log::Warning(Event::General, "Shader create failed - " + std::string(shaderName)); + return; + } + } catch (const std::runtime_error& ex) { + Log::Warning(Event::General, "Shader create exception - " + std::string(ex.what())); + return; + } + } + + buildDrawables(changes); +} + +void BackgroundLayer::Impl::layerRemoved(PaintParameters&, UniqueChangeRequestVec& changes) const { + if (drawable) { + changes.emplace_back(std::make_unique(drawable->getId())); + drawable.reset(); + } +} + +void BackgroundLayer::Impl::buildDrawables(UniqueChangeRequestVec& changes) const { + auto builder = std::make_unique(); // from GL-specific code via virtual method? + builder->setShaderID(shaderName); + builder->addTweaker(std::make_shared()); // generally shared across drawables + builder->addQuad(0, 0, util::EXTENT, util::EXTENT); + builder->flush(); + + changes.reserve(builder->getDrawables().size()); + for (auto &draw : builder->clearDrawables()) { + drawable = draw; + changes.emplace_back(std::make_unique(std::move(draw))); + } +} + +void BackgroundLayer::Impl::update(UniqueChangeRequestVec& changes) const { + if (!drawable /* && visible/enabled */) { + buildDrawables(changes); +// } else if (drawable && !visible/enabled) { +// changes.emplace_back(std::make_unique(drawable->getId())); +// drawable.reset(); + } +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 0c68610c6..09eb052a2 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -4,7 +4,16 @@ #include #include +#include + namespace mbgl { +namespace gfx { + +class Drawable; +using DrawablePtr = std::shared_ptr; + +} // namespace gfx + namespace style { class BackgroundLayer::Impl : public Layer::Impl { @@ -14,8 +23,20 @@ public: bool hasLayoutDifference(const Layer::Impl&) const override; void stringifyLayout(rapidjson::Writer&) const override; + void layerAdded(PaintParameters&, UniqueChangeRequestVec&) const override; + void layerRemoved(PaintParameters&, UniqueChangeRequestVec&) const override; + + /// Generate any changes needed by the layer + void update(UniqueChangeRequestVec& changes) const override; + +private: + void buildDrawables(UniqueChangeRequestVec&) const; + +public: BackgroundPaintProperties::Transitionable paint; + mutable gfx::DrawablePtr drawable; + DECLARE_LAYER_TYPE_INFO; }; diff --git a/src/mbgl/util/identity.cpp b/src/mbgl/util/identity.cpp new file mode 100644 index 000000000..dc8cc2913 --- /dev/null +++ b/src/mbgl/util/identity.cpp @@ -0,0 +1,23 @@ +#include + +#include + +namespace { + // This is not in the class declaration to minimize include dependencies + static std::atomic nextId = 1; +} // anonymous namespace + +namespace mbgl { +namespace util { + +const SimpleIdentity SimpleIdentity::Empty = {emptyID}; + +SimpleIdentity::SimpleIdentity() + : uniqueID(nextId++) +{ +} + + +} // namespace util +} // namespace mbgl +