diff --git a/CMakeLists.txt b/CMakeLists.txt index f416daa4c..8756d70b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,6 +181,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/platform/thread.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/query.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_group.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_frontend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp @@ -520,6 +521,13 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager_observer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_group.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -929,6 +937,7 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/prelude.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_background.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_circle.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 9fdaa731d..57a5108ee 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -25,7 +25,6 @@ enum class DepthMaskType : bool; class DrawableTweaker; class ShaderProgramBase; using ShaderProgramBasePtr = std::shared_ptr; -using UniformBufferPtr = std::shared_ptr; using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; @@ -178,12 +177,5 @@ private: bool desc; }; -struct alignas(16) DrawableUBO { - std::array matrix; - std::array world; - std::array padding; -}; -static_assert(sizeof(DrawableUBO) % 16 == 0); - } // namespace gfx } // namespace mbgl diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index e62c560a8..7c579b019 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -25,6 +25,9 @@ using DrawablePtr = std::shared_ptr; using UniqueDrawable = std::unique_ptr; } // namespace gfx +class LayerTweaker; +using LayerTweakerPtr = std::shared_ptr; + /** A layer-like group of drawables, not a group of layers. */ @@ -54,8 +57,15 @@ public: /// Call the provided function for each drawable in undefined order, allowing ownership to be taken. virtual void observeDrawables(std::function) = 0; + /// Attach a tweaker to be run on this layer group for each frame + void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); } + + /// Get the tweaker attached to this layer group + const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } + protected: int32_t layerIndex; + LayerTweakerPtr layerTweaker; }; /** diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp new file mode 100644 index 000000000..5c1e6a6a3 --- /dev/null +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include + +namespace mbgl { + +namespace style { +class LayerProperties; +} // namespace style + +class PaintParameters; +class LayerGroup; + +/** + Base class for layer tweakers, which manipulate layer group per frame + */ +class LayerTweaker { +protected: + LayerTweaker() = delete; + LayerTweaker(Immutable properties); + +public: + virtual ~LayerTweaker() = default; + + virtual void execute(LayerGroup&, const PaintParameters&) = 0; + +protected: + Immutable evaluatedProperties; +}; + +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/drawable_background.hpp b/include/mbgl/shaders/gl/drawable_background.hpp index b049e510f..647eab21e 100644 --- a/include/mbgl/shaders/gl/drawable_background.hpp +++ b/include/mbgl/shaders/gl/drawable_background.hpp @@ -11,10 +11,8 @@ template <> struct ShaderSource { static constexpr const char* name = "BackgroundShader"; static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform BackgroundDrawableUBO { mat4 u_matrix; - vec2 u_world; - vec2 pad; }; void main() { diff --git a/include/mbgl/shaders/gl/drawable_circle.hpp b/include/mbgl/shaders/gl/drawable_circle.hpp new file mode 100644 index 000000000..aec73faf5 --- /dev/null +++ b/include/mbgl/shaders/gl/drawable_circle.hpp @@ -0,0 +1,234 @@ +// Generated code, do not modify this file! +// Generated on 2023-05-17T18:24:20.170Z by alex using shaders/generate_shader_code.js + +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "CircleShader"; + static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; +out vec3 v_data; + +layout (std140) uniform CircleDrawableUBO { + mat4 u_matrix; + vec2 u_extrude_scale; +}; + +layout (std140) uniform CirclePaintParamsUBO { + highp float u_camera_to_center_distance; + lowp float u_device_pixel_ratio; +}; + +layout (std140) uniform CircleEvaluatedPropsUBO { + highp vec4 u_color; + highp vec4 u_stroke_color; + mediump float u_radius; + lowp float u_blur; + lowp float u_opacity; + mediump float u_stroke_width; + lowp float u_stroke_opacity; + bool u_scale_with_map; + bool u_pitch_with_map; +}; + +layout (std140) uniform CircleInterpolateUBO { + lowp float u_color_t; + lowp float u_radius_t; + lowp float u_blur_t; + lowp float u_opacity_t; + lowp float u_stroke_color_t; + lowp float u_stroke_width_t; + lowp float u_stroke_opacity_t; +}; + +#ifndef HAS_UNIFORM_u_color +layout (location = 1) in highp vec4 a_color; +out highp vec4 color; +#endif +#ifndef HAS_UNIFORM_u_radius +layout (location = 2) in mediump vec2 a_radius; +out mediump float radius; +#endif +#ifndef HAS_UNIFORM_u_blur +layout (location = 3) in lowp vec2 a_blur; +out lowp float blur; +#endif +#ifndef HAS_UNIFORM_u_opacity +layout (location = 4) in lowp vec2 a_opacity; +out lowp float opacity; +#endif +#ifndef HAS_UNIFORM_u_stroke_color +layout (location = 5) in highp vec4 a_stroke_color; +out highp vec4 stroke_color; +#endif +#ifndef HAS_UNIFORM_u_stroke_width +layout (location = 6) in mediump vec2 a_stroke_width; +out mediump float stroke_width; +#endif +#ifndef HAS_UNIFORM_u_stroke_opacity +layout (location = 7) in lowp vec2 a_stroke_opacity; +out lowp float stroke_opacity; +#endif + +void main(void) { + #ifndef HAS_UNIFORM_u_color +color = unpack_mix_color(a_color, u_color_t); +#else +highp vec4 color = u_color; +#endif + #ifndef HAS_UNIFORM_u_radius +radius = unpack_mix_vec2(a_radius, u_radius_t); +#else +mediump float radius = u_radius; +#endif + #ifndef HAS_UNIFORM_u_blur +blur = unpack_mix_vec2(a_blur, u_blur_t); +#else +lowp float blur = u_blur; +#endif + #ifndef HAS_UNIFORM_u_opacity +opacity = unpack_mix_vec2(a_opacity, u_opacity_t); +#else +lowp float opacity = u_opacity; +#endif + #ifndef HAS_UNIFORM_u_stroke_color +stroke_color = unpack_mix_color(a_stroke_color, u_stroke_color_t); +#else +highp vec4 stroke_color = u_stroke_color; +#endif + #ifndef HAS_UNIFORM_u_stroke_width +stroke_width = unpack_mix_vec2(a_stroke_width, u_stroke_width_t); +#else +mediump float stroke_width = u_stroke_width; +#endif + #ifndef HAS_UNIFORM_u_stroke_opacity +stroke_opacity = unpack_mix_vec2(a_stroke_opacity, u_stroke_opacity_t); +#else +lowp float stroke_opacity = u_stroke_opacity; +#endif + + // unencode the extrusion vector that we snuck into the a_pos vector + vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); + + // multiply a_pos by 0.5, since we had it * 2 in order to sneak + // in extrusion data + vec2 circle_center = floor(a_pos * 0.5); + if (u_pitch_with_map) { + vec2 corner_position = circle_center; + if (u_scale_with_map) { + corner_position += extrude * (radius + stroke_width) * u_extrude_scale; + } else { + // Pitching the circle with the map effectively scales it with the map + // To counteract the effect for pitch-scale: viewport, we rescale the + // whole circle based on the pitch scaling effect at its central point + vec4 projected_center = u_matrix * vec4(circle_center, 0, 1); + corner_position += extrude * (radius + stroke_width) * u_extrude_scale * (projected_center.w / u_camera_to_center_distance); + } + + gl_Position = u_matrix * vec4(corner_position, 0, 1); + } else { + gl_Position = u_matrix * vec4(circle_center, 0, 1); + + if (u_scale_with_map) { + gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * u_camera_to_center_distance; + } else { + gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w; + } + } + + // This is a minimum blur distance that serves as a faux-antialiasing for + // the circle. since blur is a ratio of the circle's size and the intent is + // to keep the blur at roughly 1px, the two are inversely related. + lowp float antialiasblur = 1.0 / u_device_pixel_ratio / (radius + stroke_width); + + v_data = vec3(extrude.x, extrude.y, antialiasblur); +} +)"; + static constexpr const char* fragment = R"(in vec3 v_data; + +layout (std140) uniform CircleEvaluatedPropsUBO { + highp vec4 u_color; + highp vec4 u_stroke_color; + mediump float u_radius; + lowp float u_blur; + lowp float u_opacity; + mediump float u_stroke_width; + lowp float u_stroke_opacity; + bool u_scale_with_map; + bool u_pitch_with_map; +}; + +#ifndef HAS_UNIFORM_u_color +in highp vec4 color; +#endif +#ifndef HAS_UNIFORM_u_radius +in mediump float radius; +#endif +#ifndef HAS_UNIFORM_u_blur +in lowp float blur; +#endif +#ifndef HAS_UNIFORM_u_opacity +in lowp float opacity; +#endif +#ifndef HAS_UNIFORM_u_stroke_color +in highp vec4 stroke_color; +#endif +#ifndef HAS_UNIFORM_u_stroke_width +in mediump float stroke_width; +#endif +#ifndef HAS_UNIFORM_u_stroke_opacity +in lowp float stroke_opacity; +#endif + +void main() { + #ifdef HAS_UNIFORM_u_color +highp vec4 color = u_color; +#endif + #ifdef HAS_UNIFORM_u_radius +mediump float radius = u_radius; +#endif + #ifdef HAS_UNIFORM_u_blur +lowp float blur = u_blur; +#endif + #ifdef HAS_UNIFORM_u_opacity +lowp float opacity = u_opacity; +#endif + #ifdef HAS_UNIFORM_u_stroke_color +highp vec4 stroke_color = u_stroke_color; +#endif + #ifdef HAS_UNIFORM_u_stroke_width +mediump float stroke_width = u_stroke_width; +#endif + #ifdef HAS_UNIFORM_u_stroke_opacity +lowp float stroke_opacity = u_stroke_opacity; +#endif + + vec2 extrude = v_data.xy; + float extrude_length = length(extrude); + + lowp float antialiasblur = v_data.z; + float antialiased_blur = -max(blur, antialiasblur); + + float opacity_t = smoothstep(0.0, antialiased_blur, extrude_length - 1.0); + + float color_t = stroke_width < 0.01 ? 0.0 : smoothstep( + antialiased_blur, + 0.0, + extrude_length - radius / (radius + stroke_width) + ); + + fragColor = opacity_t * mix(color * opacity, stroke_color * stroke_opacity, color_t); + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/drawable_fill.hpp b/include/mbgl/shaders/gl/drawable_fill.hpp index b9d21aaa3..d40c8563c 100644 --- a/include/mbgl/shaders/gl/drawable_fill.hpp +++ b/include/mbgl/shaders/gl/drawable_fill.hpp @@ -12,7 +12,7 @@ struct ShaderSource { static constexpr const char* name = "FillShader"; static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform FillDrawableUBO { mat4 u_matrix; vec2 u_world; vec2 pad; diff --git a/include/mbgl/shaders/gl/drawable_fill_outline.hpp b/include/mbgl/shaders/gl/drawable_fill_outline.hpp index a32d32b2d..01d9d2ef0 100644 --- a/include/mbgl/shaders/gl/drawable_fill_outline.hpp +++ b/include/mbgl/shaders/gl/drawable_fill_outline.hpp @@ -12,7 +12,7 @@ struct ShaderSource { static constexpr const char* name = "FillOutlineShader"; static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform FillDrawableUBO { mat4 u_matrix; vec2 u_world; vec2 pad; diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index 94b7057ea..7ac3fb8b9 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -6,6 +6,7 @@ #ifdef MBGL_RENDER_BACKEND_OPENGL #include +#include #include #include #include diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index 662e7992d..a6d67a4da 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -12,6 +12,7 @@ namespace shaders { enum class BuiltIn { None, BackgroundShader, + CircleShader, FillShader, FillOutlineShader, FillPatternShader, diff --git a/shaders/drawable.background.vertex.glsl b/shaders/drawable.background.vertex.glsl index 43c2f1e9d..9038caad5 100644 --- a/shaders/drawable.background.vertex.glsl +++ b/shaders/drawable.background.vertex.glsl @@ -1,5 +1,5 @@ layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform BackgroundDrawableUBO { mat4 u_matrix; vec2 u_world; vec2 pad; diff --git a/shaders/drawable.circle.fragment.glsl b/shaders/drawable.circle.fragment.glsl new file mode 100644 index 000000000..e1fc71325 --- /dev/null +++ b/shaders/drawable.circle.fragment.glsl @@ -0,0 +1,51 @@ +in vec3 v_data; + +layout (std140) uniform CircleEvaluatedPropsUBO { + highp vec4 u_color; + mediump float u_radius; + lowp float u_blur; + lowp float u_opacity; + highp vec4 u_stroke_color; + mediump float u_stroke_width; + lowp float u_stroke_opacity; + bool u_scale_with_map; + bool u_pitch_with_map; +}; + +#pragma mapbox: define highp vec4 color +#pragma mapbox: define mediump float radius +#pragma mapbox: define lowp float blur +#pragma mapbox: define lowp float opacity +#pragma mapbox: define highp vec4 stroke_color +#pragma mapbox: define mediump float stroke_width +#pragma mapbox: define lowp float stroke_opacity + +void main() { + #pragma mapbox: initialize highp vec4 color + #pragma mapbox: initialize mediump float radius + #pragma mapbox: initialize lowp float blur + #pragma mapbox: initialize lowp float opacity + #pragma mapbox: initialize highp vec4 stroke_color + #pragma mapbox: initialize mediump float stroke_width + #pragma mapbox: initialize lowp float stroke_opacity + + vec2 extrude = v_data.xy; + float extrude_length = length(extrude); + + lowp float antialiasblur = v_data.z; + float antialiased_blur = -max(blur, antialiasblur); + + float opacity_t = smoothstep(0.0, antialiased_blur, extrude_length - 1.0); + + float color_t = stroke_width < 0.01 ? 0.0 : smoothstep( + antialiased_blur, + 0.0, + extrude_length - radius / (radius + stroke_width) + ); + + fragColor = opacity_t * mix(color * opacity, stroke_color * stroke_opacity, color_t); + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} diff --git a/shaders/drawable.circle.vertex.glsl b/shaders/drawable.circle.vertex.glsl new file mode 100644 index 000000000..6216598af --- /dev/null +++ b/shaders/drawable.circle.vertex.glsl @@ -0,0 +1,88 @@ +layout (location = 0) in vec2 a_pos; +out vec3 v_data; + +layout (std140) uniform CircleDrawableUBO { + mat4 u_matrix; + vec2 u_extrude_scale; +}; + +layout (std140) uniform CirclePaintParamsUBO { + highp float u_camera_to_center_distance; + lowp float u_device_pixel_ratio; +}; + +layout (std140) uniform CircleEvaluatedPropsUBO { + highp vec4 u_color; + highp vec4 u_stroke_color; + mediump float u_radius; + lowp float u_blur; + lowp float u_opacity; + mediump float u_stroke_width; + lowp float u_stroke_opacity; + bool u_scale_with_map; + bool u_pitch_with_map; +}; + +layout (std140) uniform CircleInterpolateUBO { + lowp float u_color_t; + lowp float u_radius_t; + lowp float u_blur_t; + lowp float u_opacity_t; + lowp float u_stroke_color_t; + lowp float u_stroke_width_t; + lowp float u_stroke_opacity_t; +}; + +#pragma mapbox: define highp vec4 color +#pragma mapbox: define mediump float radius +#pragma mapbox: define lowp float blur +#pragma mapbox: define lowp float opacity +#pragma mapbox: define highp vec4 stroke_color +#pragma mapbox: define mediump float stroke_width +#pragma mapbox: define lowp float stroke_opacity + +void main(void) { + #pragma mapbox: initialize highp vec4 color + #pragma mapbox: initialize mediump float radius + #pragma mapbox: initialize lowp float blur + #pragma mapbox: initialize lowp float opacity + #pragma mapbox: initialize highp vec4 stroke_color + #pragma mapbox: initialize mediump float stroke_width + #pragma mapbox: initialize lowp float stroke_opacity + + // unencode the extrusion vector that we snuck into the a_pos vector + vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); + + // multiply a_pos by 0.5, since we had it * 2 in order to sneak + // in extrusion data + vec2 circle_center = floor(a_pos * 0.5); + if (u_pitch_with_map) { + vec2 corner_position = circle_center; + if (u_scale_with_map) { + corner_position += extrude * (radius + stroke_width) * u_extrude_scale; + } else { + // Pitching the circle with the map effectively scales it with the map + // To counteract the effect for pitch-scale: viewport, we rescale the + // whole circle based on the pitch scaling effect at its central point + vec4 projected_center = u_matrix * vec4(circle_center, 0, 1); + corner_position += extrude * (radius + stroke_width) * u_extrude_scale * (projected_center.w / u_camera_to_center_distance); + } + + gl_Position = u_matrix * vec4(corner_position, 0, 1); + } else { + gl_Position = u_matrix * vec4(circle_center, 0, 1); + + if (u_scale_with_map) { + gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * u_camera_to_center_distance; + } else { + gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w; + } + } + + // This is a minimum blur distance that serves as a faux-antialiasing for + // the circle. since blur is a ratio of the circle's size and the intent is + // to keep the blur at roughly 1px, the two are inversely related. + lowp float antialiasblur = 1.0 / u_device_pixel_ratio / (radius + stroke_width); + + v_data = vec3(extrude.x, extrude.y, antialiasblur); +} diff --git a/shaders/drawable.fill.vertex.glsl b/shaders/drawable.fill.vertex.glsl index a3784a33e..bc4ca388c 100644 --- a/shaders/drawable.fill.vertex.glsl +++ b/shaders/drawable.fill.vertex.glsl @@ -1,6 +1,6 @@ layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform FillDrawableUBO { mat4 u_matrix; vec2 u_world; vec2 pad; diff --git a/shaders/drawable.fill_outline.vertex.glsl b/shaders/drawable.fill_outline.vertex.glsl index d30500561..16e7de16e 100644 --- a/shaders/drawable.fill_outline.vertex.glsl +++ b/shaders/drawable.fill_outline.vertex.glsl @@ -1,6 +1,6 @@ layout (location = 0) in vec2 a_pos; -layout (std140) uniform DrawableUBO { +layout (std140) uniform FillDrawableUBO { mat4 u_matrix; vec2 u_world; vec2 pad; diff --git a/shaders/manifest.json b/shaders/manifest.json index 9f0ae1580..2503588c2 100644 --- a/shaders/manifest.json +++ b/shaders/manifest.json @@ -6,6 +6,13 @@ "glsl_frag": "drawable.background.fragment.glsl", "uses_ubos": true }, + { + "name": "CircleShader", + "header": "drawable_circle", + "glsl_vert": "drawable.circle.vertex.glsl", + "glsl_frag": "drawable.circle.fragment.glsl", + "uses_ubos": true + }, { "name": "FillShader", "header": "drawable_fill", diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index d41f722e6..21c449cb7 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -81,22 +81,6 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str(); const auto debugGroup = parameters.encoder->createDebugGroup(labelPtr); - mat4 matrix = drawable.getMatrix(); - if (drawable.getTileID()) { - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); - const auto tileMat = parameters.matrixForTile(tileID); - matrix::multiply(matrix, drawable.getMatrix(), tileMat); - matrix = tileMat; - } - - const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); - - gfx::DrawableUBO drawableUBO; - drawableUBO.matrix = util::cast(matrix); - drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height}; - auto uniformBuffer = context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); - drawable.mutableUniformBuffers().addOrReplace("DrawableUBO", uniformBuffer); - drawable.draw(parameters); }); } diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 3aa639781..c2ce692a5 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -94,6 +94,7 @@ void registerTypes(gfx::ShaderRegistry& registry, gl::Context& glContext, const void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramParameters& programParameters) { registerTypes +#include + +namespace mbgl { + +LayerTweaker::LayerTweaker(Immutable properties) + : evaluatedProperties(std::move(properties)){}; + +} diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp new file mode 100644 index 000000000..71fc3f77a --- /dev/null +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +struct alignas(16) BackgroundDrawableUBO { + std::array matrix; +}; +static_assert(sizeof(BackgroundDrawableUBO) % 16 == 0); + +struct alignas(16) BackgroundLayerUBO { + Color color; + float opacity; + float padding[3]; +}; +static_assert(sizeof(BackgroundLayerUBO) % 16 == 0); + +struct alignas(16) BackgroundPatternLayerUBO { + std::array pattern_tl_a; + std::array pattern_br_a; + std::array pattern_tl_b; + std::array pattern_br_b; + std::array texsize; + std::array pattern_size_a; + std::array pattern_size_b; + std::array pixel_coord_upper; + std::array pixel_coord_lower; + float tile_units_to_pixels; + float scale_a; + float scale_b; + float mix; + float opacity; +}; +static_assert(sizeof(BackgroundPatternLayerUBO) % 16 == 0); + +void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) { + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + + if (!layerUniformBuffer) { + BackgroundLayerUBO layerUBO; + layerUBO.color = evaluated.get(); + layerUBO.opacity = evaluated.get(); + layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO)); + } + + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { + drawable.mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", layerUniformBuffer); + + if (!drawable.getTileID()) { + return; + } + mat4 matrix = drawable.getMatrix(); + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto tileMat = parameters.matrixForTile(tileID); + matrix::multiply(matrix, drawable.getMatrix(), tileMat); + matrix = tileMat; + + BackgroundDrawableUBO drawableUBO; + drawableUBO.matrix = util::cast(matrix); + auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("BackgroundDrawableUBO", drawableUniformBuffer); + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.hpp b/src/mbgl/renderer/layers/background_layer_tweaker.hpp new file mode 100644 index 000000000..8256cda9f --- /dev/null +++ b/src/mbgl/renderer/layers/background_layer_tweaker.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace mbgl { + +namespace gfx { +class UniformBuffer; +using UniformBufferPtr = std::shared_ptr; +} // namespace gfx + +/** + Background layer specific tweaker + */ +class BackgroundLayerTweaker : public LayerTweaker { +public: + BackgroundLayerTweaker(Immutable properties) + : LayerTweaker(properties){}; + +public: + ~BackgroundLayerTweaker() override = default; + + void execute(LayerGroup&, const PaintParameters&) override; + +protected: + gfx::UniformBufferPtr layerUniformBuffer = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp new file mode 100644 index 000000000..5b61893db --- /dev/null +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +struct alignas(16) CircleDrawableUBO { + std::array matrix; + std::array extrude_scale; +}; +static_assert(sizeof(CircleDrawableUBO) % 16 == 0); + +struct alignas(16) CirclePaintParamsUBO { + float camera_to_center_distance; + float device_pixel_ratio; +}; +static_assert(sizeof(CirclePaintParamsUBO) % 16 == 0); + +struct alignas(16) CircleEvaluatedPropsUBO { + Color color; + Color stroke_color; + float radius; + float blur; + float opacity; + float stroke_width; + float stroke_opacity; + int scale_with_map; + int pitch_with_map; +}; +static_assert(sizeof(CircleEvaluatedPropsUBO) % 16 == 0); + +struct alignas(16) CircleInterpolateUBO { + float color_t; + float radius_t; + float blur_t; + float opacity_t; + float stroke_color_t; + float stroke_width_t; + float stroke_opacity_t; +}; +static_assert(sizeof(CircleInterpolateUBO) % 16 == 0); + +void CircleLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) { + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + + CirclePaintParamsUBO paintParamsUBO; + paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance(); + paintParamsUBO.device_pixel_ratio = parameters.pixelRatio; + auto paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); + + const bool pitchWithMap = evaluated.get() == AlignmentType::Map; + + if (!evaluatedPropsUniformBuffer) { + CircleEvaluatedPropsUBO evaluatedPropsUBO; + evaluatedPropsUBO.color = evaluated.get().constantOr(Color()); + evaluatedPropsUBO.radius = evaluated.get().constantOr(0); + evaluatedPropsUBO.blur = evaluated.get().constantOr(0); + evaluatedPropsUBO.opacity = evaluated.get().constantOr(0); + evaluatedPropsUBO.stroke_color = evaluated.get().constantOr(Color()); + evaluatedPropsUBO.stroke_width = evaluated.get().constantOr(0); + evaluatedPropsUBO.stroke_opacity = evaluated.get().constantOr(0); + evaluatedPropsUBO.scale_with_map = evaluated.get() == CirclePitchScaleType::Map; + evaluatedPropsUBO.pitch_with_map = pitchWithMap; + evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO, + sizeof(evaluatedPropsUBO)); + } + + CircleInterpolateUBO interpolateUBO; + interpolateUBO.color_t = 0; + interpolateUBO.radius_t = 0; + interpolateUBO.blur_t = 0; + interpolateUBO.opacity_t = 0; + interpolateUBO.stroke_color_t = 0; + interpolateUBO.stroke_width_t = 0; + interpolateUBO.stroke_opacity_t = 0; + auto interpolateUniformBuffer = parameters.context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { + drawable.mutableUniformBuffers().addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer); + drawable.mutableUniformBuffers().addOrReplace("CircleEvaluatedPropsUBO", evaluatedPropsUniformBuffer); + drawable.mutableUniformBuffers().addOrReplace("CircleInterpolateUBO", interpolateUniformBuffer); + + if (!drawable.getTileID()) { + return; + } + mat4 matrix = drawable.getMatrix(); + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto tileMat = parameters.matrixForTile(tileID); + matrix::multiply(matrix, drawable.getMatrix(), tileMat); + matrix = tileMat; + + CircleDrawableUBO drawableUBO; + drawableUBO.matrix = util::cast(matrix); + drawableUBO.extrude_scale = + pitchWithMap + ? std::array{{tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), + tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom()))}} + : parameters.pixelsToGLUnits; + auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer); + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.hpp b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp new file mode 100644 index 000000000..14ab04f09 --- /dev/null +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace mbgl { + +namespace gfx { +class UniformBuffer; +using UniformBufferPtr = std::shared_ptr; +} // namespace gfx + +/** + Circle layer specific tweaker + */ +class CircleLayerTweaker : public LayerTweaker { +public: + CircleLayerTweaker(Immutable properties) + : LayerTweaker(properties){}; + +public: + ~CircleLayerTweaker() override = default; + + void execute(LayerGroup&, const PaintParameters&) override; + +protected: + gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp new file mode 100644 index 000000000..16763f8ce --- /dev/null +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +struct alignas(16) FillDrawableUBO { + std::array matrix; + std::array world; + std::array padding; +}; +static_assert(sizeof(FillDrawableUBO) % 16 == 0); + +void FillLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) { + // const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID()) { + return; + } + /*mat4 matrix = drawable.getMatrix(); + if (drawable.getTileID()) { + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto tileMat = parameters.matrixForTile(tileID); + matrix::multiply(matrix, drawable.getMatrix(), tileMat); + matrix = tileMat; + } + + const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); + + gfx::DrawableUBO drawableUBO; + drawableUBO.matrix = util::cast(matrix); + drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height}; + auto uniformBuffer = context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("DrawableUBO", uniformBuffer);*/ + + mat4 matrix = drawable.getMatrix(); + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto tileMat = parameters.matrixForTile(tileID); + matrix::multiply(matrix, drawable.getMatrix(), tileMat); + matrix = tileMat; + + const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); + + FillDrawableUBO drawableUBO; + drawableUBO.matrix = util::cast(matrix); + drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height}; + auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("FillDrawableUBO", drawableUniformBuffer); + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp new file mode 100644 index 000000000..05cff0793 --- /dev/null +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace mbgl { + +/** + Fill layer specific tweaker + */ +class FillLayerTweaker : public LayerTweaker { +public: + FillLayerTweaker(Immutable properties) + : LayerTweaker(properties){}; + +public: + ~FillLayerTweaker() override = default; + + void execute(LayerGroup&, const PaintParameters&) override; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 06ea4a717..4c575ff4a 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -1,5 +1,5 @@ #include - +#include #include #include #include @@ -62,7 +62,9 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& paramet properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); - evaluatedPropertiesChange = true; + if (tileLayerGroup) { + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + } } bool RenderBackgroundLayer::hasTransition() const { @@ -73,10 +75,16 @@ bool RenderBackgroundLayer::hasCrossfade() const { return getCrossfade(evaluatedProperties).t != 1; } +static bool enableDefaultRender = false; + void RenderBackgroundLayer::render(PaintParameters& parameters) { // Note that for bottommost layers without a pattern, the background color // is drawn with glClear rather than this method. + if (!enableDefaultRender) { + return; + } + // Ensure programs are available if (!parameters.shaders.populate(backgroundProgram)) return; if (!parameters.shaders.populate(backgroundPatternProgram)) return; @@ -210,6 +218,10 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, gfx::Context& context, const TransformState& state, UniqueChangeRequestVec& changes) { + if (enableDefaultRender) { + return; + } + std::unique_lock guard(mutex); if (!shader) { @@ -253,19 +265,12 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, return; } - if (evaluatedPropertiesChange) { - BackgroundLayerUBO backgroundLayerUBO; - backgroundLayerUBO.color = evaluated.get(); - backgroundLayerUBO.opacity = evaluated.get(); - uniformBuffer = context.createUniformBuffer(&backgroundLayerUBO, sizeof(backgroundLayerUBO)); - evaluatedPropertiesChange = false; - } - if (!tileLayerGroup) { tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); if (!tileLayerGroup) { return; } + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); } @@ -306,7 +311,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, if (tileDrawable) { // Already created, update it. - tileDrawable->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer); continue; } @@ -332,7 +336,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, if (!newDrawables.empty()) { auto& drawable = newDrawables[0]; drawable->setTileID(tileID); - drawable->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.tileDrawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index 1efd0b8ff..7b6749c8f 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -52,29 +52,4 @@ private: gfx::ShaderProgramBasePtr shader; }; -struct alignas(16) BackgroundLayerUBO { - Color color; - float opacity; - float padding[3]; -}; -static_assert(sizeof(BackgroundLayerUBO) % 16 == 0); - -struct alignas(16) BackgroundPatternLayerUBO { - std::array pattern_tl_a; - std::array pattern_br_a; - std::array pattern_tl_b; - std::array pattern_br_b; - std::array texsize; - std::array pattern_size_a; - std::array pattern_size_b; - std::array pixel_coord_upper; - std::array pixel_coord_lower; - float tile_units_to_pixels; - float scale_a; - float scale_b; - float mix; - float opacity; -}; -static_assert(sizeof(BackgroundPatternLayerUBO) % 16 == 0); - } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 58b7af4ce..3795e4bc9 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -7,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +72,9 @@ void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); + if (tileLayerGroup) { + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + } } bool RenderCircleLayer::hasTransition() const { @@ -79,8 +85,15 @@ bool RenderCircleLayer::hasCrossfade() const { return false; } +static bool enableDefaultRender = false; + void RenderCircleLayer::render(PaintParameters& parameters) { assert(renderTiles); + + if (!enableDefaultRender) { + return; + } + if (parameters.pass == RenderPass::Opaque) { return; } @@ -236,4 +249,214 @@ bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryG return false; } +void RenderCircleLayer::layerRemoved(UniqueChangeRequestVec& changes) { + // Remove everything + if (tileLayerGroup) { + changes.emplace_back(std::make_unique(tileLayerGroup->getLayerIndex())); + tileLayerGroup.reset(); + } +} + +void RenderCircleLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); +} + +void RenderCircleLayer::update(const int32_t layerIndex, + gfx::ShaderRegistry& shaders, + gfx::Context& context, + const TransformState& /*state*/, + UniqueChangeRequestVec& changes) { + if (enableDefaultRender) { + return; + } + + std::unique_lock guard(mutex); + + if (!renderTiles || renderTiles->empty()) { + if (tileLayerGroup) { + stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount(); + tileLayerGroup->clearDrawables(); + } + return; + } + + // Set up a layer group + if (!tileLayerGroup) { + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); + if (!tileLayerGroup) { + return; + } + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); + } + + if (!circleShader) { + circleShader = context.getGenericShader(shaders, "CircleShader"); + } + + std::unordered_set newTileIDs(renderTiles->size()); + std::transform(renderTiles->begin(), + renderTiles->end(), + std::inserter(newTileIDs, newTileIDs.begin()), + [](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); }); + + std::unique_ptr circleBuilder; + std::vector newTiles; + gfx::VertexAttributeArray circleVertexAttrs; + auto renderPass = RenderPass::Translucent; + + if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { + return; + } + + tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { + const auto tileID = drawable->getTileID(); + if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) { + // remove it + drawable.reset(); + ++stats.tileDrawablesRemoved; + } + }); + + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + auto& tileDrawable = tileLayerGroup->getDrawable(renderPass, tileID); + if (tileDrawable) { + continue; + } + + const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass); + if (!renderData) { + removeTile(renderPass, tileID); + continue; + } + + auto& bucket = static_cast(*renderData->bucket); + + std::vector> rawVerts; + const auto buildVertices = [&]() { + const std::vector>>::Vertex>& + verts = bucket.vertices.vector(); + if (rawVerts.size() < verts.size()) { + rawVerts.resize(verts.size()); + std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); + } + }; + + circleVertexAttrs.clear(); + + const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); + + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_color")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& packedColor = static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set( + i, {packedColor[0], packedColor[1], packedColor[0], packedColor[1]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_radius")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& radius = static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set(i, {radius[0], radius[0]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_blur")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& blur = static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set(i, {blur[0], blur[0]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_opacity")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& opacity = static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set(i, {opacity[0], opacity[0]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_color")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& packedStrokeColor = + static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set( + i, {packedStrokeColor[0], packedStrokeColor[1], packedStrokeColor[0], packedStrokeColor[1]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_width")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& strokeWidth = static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set(i, {strokeWidth[0], strokeWidth[0]}); + } + } + } + if (auto& binder = paintPropertyBinders.get()) { + const auto count = binder->getVertexCount(); + if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_opacity")) { + for (std::size_t i = 0; i < count; ++i) { + const auto& strokeOpacity = + static_cast>*>( + binder->getVertexValue(i)) + ->a1; + attr->set(i, {strokeOpacity[0], strokeOpacity[0]}); + } + } + } + + circleBuilder = context.createDrawableBuilder("circle"); + circleBuilder->setShader(circleShader); + circleBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); + circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite + : gfx::DepthMaskType::ReadOnly); + circleBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); + circleBuilder->setLayerIndex(layerIndex); + + circleBuilder->setRenderPass(renderPass); + circleBuilder->setVertexAttributes(circleVertexAttrs); + + buildVertices(); + circleBuilder->addVertices(rawVerts, 0, rawVerts.size()); + + for (const auto& seg : bucket.segments) { + circleBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength); + } + + circleBuilder->flush(); + + for (auto& drawable : circleBuilder->clearDrawables()) { + drawable->setTileID(tileID); + + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); + ++stats.tileDrawablesAdded; + } + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index ccf4d40b7..a34ab1baa 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -13,6 +13,15 @@ public: explicit RenderCircleLayer(Immutable); ~RenderCircleLayer() final = default; + void layerRemoved(UniqueChangeRequestVec&) override; + + /// Generate any changes needed by the layer + void update(int32_t layerIndex, + gfx::ShaderRegistry&, + gfx::Context&, + const TransformState&, + UniqueChangeRequestVec&) override; + private: void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; @@ -28,11 +37,16 @@ private: const mat4&, const FeatureState&) const override; + /// Remove all drawables for the tile from the layer group + void removeTile(RenderPass, const OverscaledTileID&); + // Paint properties style::CirclePaintProperties::Unevaluated unevaluated; // Programs std::shared_ptr circleProgram; + + gfx::ShaderProgramBasePtr circleShader; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index c911bde5c..673246ff6 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,9 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { } properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); - - evaluatedPropertiesChange = true; + if (tileLayerGroup) { + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + } } bool RenderFillLayer::hasTransition() const { @@ -287,6 +289,10 @@ void RenderFillLayer::update(const int32_t layerIndex, gfx::Context& context, const TransformState& /*state*/, UniqueChangeRequestVec& changes) { + if (enableDefaultRender) { + return; + } + std::unique_lock guard(mutex); if (!renderTiles || renderTiles->empty()) { @@ -303,6 +309,7 @@ void RenderFillLayer::update(const int32_t layerIndex, if (!tileLayerGroup) { return; } + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); } @@ -442,16 +449,7 @@ void RenderFillLayer::update(const int32_t layerIndex, } } - if (evaluatedPropertiesChange) { - // FillLayerUBO fillLayerUBO; - // fillLayerUBO.color = evaluated.get(); - // fillLayerUBO.opacity = evaluated.get(); - // uniformBuffer = context.createUniformBuffer(&fillLayerUBO, sizeof(fillLayerUBO)); - evaluatedPropertiesChange = false; - } - if (tileDrawable) { - // tileDrawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer); continue; } diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index b28123908..6d367da9d 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -169,8 +169,6 @@ protected: TileLayerGroupPtr tileLayerGroup; std::mutex mutex; - bool evaluatedPropertiesChange = false; - gfx::UniformBufferPtr uniformBuffer = nullptr; struct Stats { size_t propertyEvaluations = 0; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 4169b26ee..a50a6853f 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,13 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } } + // Run layer tweakers to update any dynamic elements + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { + if (layerGroup.getLayerTweaker()) { + layerGroup.getLayerTweaker()->execute(layerGroup, parameters); + } + }); + // Give the layers a chance to do setup orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters); }); @@ -200,9 +208,6 @@ void Renderer::Impl::render(const RenderTree& renderTree) { for (auto it = layerRenderItems.rbegin(); it != layerRenderItems.rend(); ++it, ++i) { parameters.currentLayer = i; const RenderItem& renderItem = it->get(); - if (renderItem.getName() == "background") { - continue; - } if (renderItem.hasRenderPass(parameters.pass)) { const auto layerDebugGroup(parameters.renderPass->createDebugGroup(renderItem.getName().c_str())); renderItem.render(parameters);