From e183d9b236605ca5370914c714406566ca8698e1 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Tue, 26 Sep 2023 18:46:47 +0200 Subject: [PATCH 01/19] Run on group instead of label (#1691) --- .github/actionlint.yaml | 8 -------- .github/workflows/android-ci.yml | 18 ++---------------- .github/workflows/linux-ci.yml | 3 ++- 3 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml deleted file mode 100644 index dcab400b9..000000000 --- a/.github/actionlint.yaml +++ /dev/null @@ -1,8 +0,0 @@ -self-hosted-runner: - # Labels of self-hosted runner in array of strings. - labels: - - MapLibre_Native_Large_Runner -# Configuration variables in array of strings defined in your repository or -# organization. `null` means disabling configuration variables check. -# Empty array means no configuration variable is allowed. -config-variables: null diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 0ec90f904..83ee3c198 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -44,7 +44,8 @@ jobs: "!**/*.md"] android-build: - runs-on: MapLibre_Native_Large_Runner + runs-on: + group: maplibre-native needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' @@ -57,21 +58,6 @@ jobs: IS_LOCAL_DEVELOPMENT: false MLN_ANDROID_STL: c++_static steps: - - name: Update Apt Package Cache - run: sudo apt-get update - working-directory: . - - - name: Free Disk Space (Ubuntu) - uses: jlumbroso/free-disk-space@main - with: - tool-cache: false - android: false - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: false - - uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 93713e05a..457e5a54f 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -46,7 +46,8 @@ jobs: fail-fast: false matrix: renderer: [legacy, drawable] - runs-on: MapLibre_Native_Large_Runner + runs-on: + group: maplibre-native steps: - uses: actions/checkout@v4 with: From 2d8cde8abf0e67b5fc3c2e13ebb9b4b2b6ef1930 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Wed, 27 Sep 2023 12:02:15 +0200 Subject: [PATCH 02/19] Update Boost to 1.83, replace Boost Locale with deprecated codecvt STL (#1660) Co-authored-by: mwilsnd --- .github/actionlint.yaml | 8 +++++ .github/workflows/android-ci.yml | 3 +- .github/workflows/linux-ci.yml | 3 +- .gitmodules | 6 ++-- BUILD.bazel | 36 +++++++++++----------- include/mbgl/gfx/renderer_backend.hpp | 2 +- include/mbgl/map/mode.hpp | 10 +++--- include/mbgl/util/bitmask_operations.hpp | 8 ++--- include/mbgl/util/convert.hpp | 4 +-- include/mbgl/util/util.hpp | 7 ----- platform/default/src/mbgl/util/utf.cpp | 16 ++++++++-- scripts/update-boost.sh | 21 ++----------- scripts/vendor/icu.sh | 25 +++------------ src/mbgl/annotation/annotation_manager.cpp | 2 +- src/mbgl/text/language_tag.cpp | 4 +-- src/mbgl/util/http_header.cpp | 4 +-- vendor/BUILD.bazel | 5 ++- vendor/boost | 2 +- 18 files changed, 72 insertions(+), 94 deletions(-) create mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 000000000..2ef1c46f4 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,8 @@ +self-hosted-runner: + # Labels of self-hosted runner in array of strings. + labels: + - MapLibre_Native_Linux_16_core +# Configuration variables in array of strings defined in your repository or +# organization. `null` means disabling configuration variables check. +# Empty array means no configuration variable is allowed. +config-variables: null diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 83ee3c198..a9e03feca 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -44,8 +44,7 @@ jobs: "!**/*.md"] android-build: - runs-on: - group: maplibre-native + runs-on: MapLibre_Native_Linux_16_core needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 457e5a54f..7e136b531 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -46,8 +46,7 @@ jobs: fail-fast: false matrix: renderer: [legacy, drawable] - runs-on: - group: maplibre-native + runs-on: MapLibre_Native_Linux_16_core steps: - uses: actions/checkout@v4 with: diff --git a/.gitmodules b/.gitmodules index 9cf14d70e..c6895bebd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,9 +16,6 @@ [submodule "vendor/unique_resource"] path = vendor/unique_resource url = https://github.com/okdshin/unique_resource.git -[submodule "vendor/boost"] - path = vendor/boost - url = https://github.com/maplibre/maplibre-gl-native-boost.git [submodule "vendor/benchmark"] path = vendor/benchmark url = https://github.com/google/benchmark.git @@ -49,3 +46,6 @@ [submodule "platform/windows/vendor/vcpkg"] path = platform/windows/vendor/vcpkg url = https://github.com/microsoft/vcpkg.git +[submodule "vendor/boost"] + path = vendor/boost + url = https://github.com/maplibre/maplibre-gl-native-boost.git diff --git a/BUILD.bazel b/BUILD.bazel index 383030a5d..5fed687fb 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -3,14 +3,14 @@ load( "//bazel:core.bzl", "MLN_CORE_HEADERS", "MLN_CORE_SOURCE", - "MLN_DRAWABLES_HEADERS", - "MLN_DRAWABLES_SOURCE", "MLN_DRAWABLES_GL_HEADERS", "MLN_DRAWABLES_GL_SOURCE", + "MLN_DRAWABLES_HEADERS", "MLN_DRAWABLES_MTL_HEADERS", "MLN_DRAWABLES_MTL_SOURCE", - "MLN_GENERATED_SHADER_HEADERS", + "MLN_DRAWABLES_SOURCE", "MLN_GENERATED_OPENGL_SHADER_HEADERS", + "MLN_GENERATED_SHADER_HEADERS", "MLN_GENERATED_STYLE_SOURCE", "MLN_OPENGL_HEADERS", "MLN_OPENGL_SOURCE", @@ -90,17 +90,17 @@ cc_library( name = "mbgl-core", srcs = MLN_CORE_SOURCE + MLN_GENERATED_STYLE_SOURCE + select({ - ":drawable_renderer": MLN_OPENGL_SOURCE + MLN_DRAWABLES_SOURCE + MLN_DRAWABLES_GL_SOURCE, - ":legacy_renderer": MLN_OPENGL_SOURCE, - ":metal_renderer": MLN_DRAWABLES_SOURCE + MLN_DRAWABLES_MTL_SOURCE, - "//conditions:default": [], - }), + ":drawable_renderer": MLN_OPENGL_SOURCE + MLN_DRAWABLES_SOURCE + MLN_DRAWABLES_GL_SOURCE, + ":legacy_renderer": MLN_OPENGL_SOURCE, + ":metal_renderer": MLN_DRAWABLES_SOURCE + MLN_DRAWABLES_MTL_SOURCE, + "//conditions:default": [], + }), hdrs = MLN_CORE_HEADERS + select({ - ":drawable_renderer": MLN_OPENGL_HEADERS + MLN_DRAWABLES_HEADERS + MLN_DRAWABLES_GL_HEADERS, - ":legacy_renderer": MLN_OPENGL_HEADERS, - ":metal_renderer": MLN_DRAWABLES_HEADERS + MLN_DRAWABLES_MTL_HEADERS, - "//conditions:default": [], - }), + ":drawable_renderer": MLN_OPENGL_HEADERS + MLN_DRAWABLES_HEADERS + MLN_DRAWABLES_GL_HEADERS, + ":legacy_renderer": MLN_OPENGL_HEADERS, + ":metal_renderer": MLN_DRAWABLES_HEADERS + MLN_DRAWABLES_MTL_HEADERS, + "//conditions:default": [], + }), copts = CPP_FLAGS + MAPLIBRE_FLAGS, defines = select({ ":legacy_renderer": [ @@ -209,11 +209,11 @@ config_setting( string_flag( name = "renderer", build_setting_default = "legacy", - values=[ + values = [ "legacy", "drawable", - "metal" - ] + "metal", + ], ) config_setting( @@ -233,8 +233,8 @@ config_setting( config_setting( name = "metal_renderer", flag_values = { - ":renderer": "metal" - } + ":renderer": "metal", + }, ) exports_files( diff --git a/include/mbgl/gfx/renderer_backend.hpp b/include/mbgl/gfx/renderer_backend.hpp index 9530d9069..5d8b74f00 100644 --- a/include/mbgl/gfx/renderer_backend.hpp +++ b/include/mbgl/gfx/renderer_backend.hpp @@ -74,7 +74,7 @@ protected: friend class BackendScope; }; -MBGL_CONSTEXPR bool operator==(const RendererBackend& a, const RendererBackend& b) { +constexpr bool operator==(const RendererBackend& a, const RendererBackend& b) { return &a == &b; } diff --git a/include/mbgl/map/mode.hpp b/include/mbgl/map/mode.hpp index b16026bd1..5835cf8df 100644 --- a/include/mbgl/map/mode.hpp +++ b/include/mbgl/map/mode.hpp @@ -45,23 +45,23 @@ enum class MapDebugOptions : EnumType { DepthBuffer = 1 << 7, }; -MBGL_CONSTEXPR MapDebugOptions operator|(MapDebugOptions lhs, MapDebugOptions rhs) { +constexpr MapDebugOptions operator|(MapDebugOptions lhs, MapDebugOptions rhs) { return MapDebugOptions(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs)); } -MBGL_CONSTEXPR MapDebugOptions& operator|=(MapDebugOptions& lhs, MapDebugOptions rhs) { +constexpr MapDebugOptions& operator|=(MapDebugOptions& lhs, MapDebugOptions rhs) { return (lhs = MapDebugOptions(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs))); } -MBGL_CONSTEXPR bool operator&(MapDebugOptions lhs, MapDebugOptions rhs) { +constexpr bool operator&(MapDebugOptions lhs, MapDebugOptions rhs) { return mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs); } -MBGL_CONSTEXPR MapDebugOptions& operator&=(MapDebugOptions& lhs, MapDebugOptions rhs) { +constexpr MapDebugOptions& operator&=(MapDebugOptions& lhs, MapDebugOptions rhs) { return (lhs = MapDebugOptions(mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs))); } -MBGL_CONSTEXPR MapDebugOptions operator~(MapDebugOptions value) { +constexpr MapDebugOptions operator~(MapDebugOptions value) { return MapDebugOptions(~mbgl::underlying_type(value)); } diff --git a/include/mbgl/util/bitmask_operations.hpp b/include/mbgl/util/bitmask_operations.hpp index b22eb58c2..e2c64de8d 100644 --- a/include/mbgl/util/bitmask_operations.hpp +++ b/include/mbgl/util/bitmask_operations.hpp @@ -6,25 +6,25 @@ namespace mbgl { template -MBGL_CONSTEXPR Enum operator|(Enum a, Enum b) { +constexpr Enum operator|(Enum a, Enum b) { static_assert(std::is_enum::value, "Enum must be an enum type"); return Enum(mbgl::underlying_type(a) | mbgl::underlying_type(b)); } template -MBGL_CONSTEXPR Enum& operator|=(Enum& a, Enum b) { +constexpr Enum& operator|=(Enum& a, Enum b) { static_assert(std::is_enum::value, "Enum must be an enum type"); return (a = a | b); } template -MBGL_CONSTEXPR bool operator&(Enum a, Enum b) { +constexpr bool operator&(Enum a, Enum b) { static_assert(std::is_enum::value, "Enum must be an enum type"); return bool(mbgl::underlying_type(a) & mbgl::underlying_type(b)); } template -MBGL_CONSTEXPR Enum operator~(Enum value) { +constexpr Enum operator~(Enum value) { static_assert(std::is_enum::value, "Enum must be an enum type"); return Enum(~mbgl::underlying_type(value)); } diff --git a/include/mbgl/util/convert.hpp b/include/mbgl/util/convert.hpp index 8bda38143..1ddf5bc99 100644 --- a/include/mbgl/util/convert.hpp +++ b/include/mbgl/util/convert.hpp @@ -11,14 +11,14 @@ namespace mbgl { namespace util { template >> -MBGL_CONSTEXPR std::array convert(const std::array& from) { +constexpr std::array convert(const std::array& from) { std::array to{{}}; std::copy(std::begin(from), std::end(from), std::begin(to)); return to; } template >> -MBGL_CONSTEXPR std::array cast(const std::array& from) { +constexpr std::array cast(const std::array& from) { std::array to{{}}; std::transform(std::begin(from), std::end(from), std::begin(to), [](From x) { return static_cast(x); }); return to; diff --git a/include/mbgl/util/util.hpp b/include/mbgl/util/util.hpp index 52d9ad85b..2ae898171 100644 --- a/include/mbgl/util/util.hpp +++ b/include/mbgl/util/util.hpp @@ -13,13 +13,6 @@ #endif -// GCC 4.9 compatibility -#if !defined(__GNUC__) || __GNUC__ >= 5 -#define MBGL_CONSTEXPR constexpr -#else -#define MBGL_CONSTEXPR inline -#endif - // Compiler defines for making symbols visible, otherwise they // will be defined as hidden by default. diff --git a/platform/default/src/mbgl/util/utf.cpp b/platform/default/src/mbgl/util/utf.cpp index f0f9d3e67..859cf9b12 100644 --- a/platform/default/src/mbgl/util/utf.cpp +++ b/platform/default/src/mbgl/util/utf.cpp @@ -1,17 +1,27 @@ #include -#include +#include +#include namespace mbgl { namespace util { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + std::u16string convertUTF8ToUTF16(const std::string& str) { - return boost::locale::conv::utf_to_utf(str); + std::wstring_convert, char16_t> conv; + + return conv.from_bytes(str); } std::string convertUTF16ToUTF8(const std::u16string& str) { - return boost::locale::conv::utf_to_utf(str); + std::wstring_convert, char16_t> conv; + + return conv.to_bytes(str); } +#pragma GCC diagnostic pop + } // namespace util } // namespace mbgl diff --git a/scripts/update-boost.sh b/scripts/update-boost.sh index 2c411d9ea..68e39089c 100755 --- a/scripts/update-boost.sh +++ b/scripts/update-boost.sh @@ -2,30 +2,13 @@ set -eu -pushd "$BOOST" -if [ ! -f dist/bin/bcp ]; then - # Build bcp - ./bootstrap.sh - ./b2 tools/bcp -fi -popd - # Extract boost modules that we need rm -rf vendor/boost/include mkdir -p vendor/boost/include -"$BOOST/dist/bin/bcp" --boost="$BOOST" --scan $(find {src,include,test,platform,bin} -name "*.cpp" -o -name "*.hpp") vendor/boost/include +bcp --boost="$BOOST" --scan $(find {src,include,test,platform,bin,render-test} -name "*.cpp" -o -name "*.hpp") vendor/boost/include pushd vendor/boost VERSION=$(sed -n 's/^#define BOOST_LIB_VERSION "\([^"]*\)"$/\1/p' include/boost/version.hpp) -echo "libboost ${VERSION/_/.} for Mapbox GL Native" > README.md +echo "libboost ${VERSION/_/.} for MapLibre Native" > README.md git add README.md include popd - -echo "If everything works, run:" -echo "" -echo " git -C vendor/boost checkout main" -echo " git -C vendor/boost commit -m \"update boost to ${VERSION/_/.}\"" -echo " git -C vendor/boost push" -echo " git add vendor/boost" -echo "" -echo "and commit." diff --git a/scripts/vendor/icu.sh b/scripts/vendor/icu.sh index 7a2c63508..5a5c1e7c7 100755 --- a/scripts/vendor/icu.sh +++ b/scripts/vendor/icu.sh @@ -2,10 +2,11 @@ source "$(dirname "${BASH_SOURCE[0]}")/common.sh" NAME=icu -VERSION=61.1 +VERSION=73.2 ROOT=icu/source -download "http://download.icu-project.org/files/icu4c/$VERSION/icu4c-${VERSION//./_}-src.tgz" +VERSION_=${VERSION//./_} +download "https://github.com/unicode-org/icu/releases/download/release-${VERSION//./-}/icu4c-${VERSION_}-src.tgz" init STRIP_COMPONENTS=2 extract_gzip "${ROOT}/common/*.h" "${ROOT}/common/*.cpp" STRIP_COMPONENTS=1 extract_gzip "icu/LICENSE" @@ -33,7 +34,7 @@ FILES=( echo ">> Finding dependencies..." ALL=() for FILE in "${FILES[@]}"; do - ALL+=($(cd "common" && $CXX -std=c++14 -I. -c "$FILE" -M | sed -e 's/^[a-z0-9._-]*: *//;s/ *\\$//')) + ALL+=($(cd "common" && $CXX -std=c++17 -I. -c "$FILE" -M | sed -e 's/^[a-z0-9._-]*: *//;s/ *\\$//')) done # Remove duplicates @@ -49,24 +50,6 @@ for FILE in "${ALL[@]}"; do sed 's/^#include \"\(unicode\/[^\"]\{1,\}\)\"/#include <\1>/' "common/$FILE" > "$DIR/$FILE" done -# Apply patch from https://github.com/LibreOffice/core/blob/master/external/icu/icu4c-ubsan.patch.1 -# Shifting signed int to a number greater than can be represented is undefined behavior -patch -p0 << PATCH ---- src/ubidiimp.h -+++ src/ubidiimp.h -@@ -198,8 +198,8 @@ - /* in a Run, logicalStart will get this bit set if the run level is odd */ - #define INDEX_ODD_BIT (1UL<<31) - --#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)(level)<<31)) -+#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((uint32_t)(level)<<31)) --#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)(level)<<31)) -+#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((uint32_t)(level)<<31)) - #define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT) - - #define GET_INDEX(x) ((x)&~INDEX_ODD_BIT) -PATCH - rm -rf common file_list include src -name "*.h" -o -name "*.cpp" diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 1121a24ef..381680a9c 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include // Note: LayerManager::annotationsEnabled is defined // at compile time, so that linker (with LTO on) is able diff --git a/src/mbgl/text/language_tag.cpp b/src/mbgl/text/language_tag.cpp index 05851d18b..4fdd0c658 100644 --- a/src/mbgl/text/language_tag.cpp +++ b/src/mbgl/text/language_tag.cpp @@ -6,8 +6,8 @@ #endif #include -#include -#include +#include +#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/mbgl/util/http_header.cpp b/src/mbgl/util/http_header.cpp index dbff7a275..ceb4bcf08 100644 --- a/src/mbgl/util/http_header.cpp +++ b/src/mbgl/util/http_header.cpp @@ -9,8 +9,8 @@ #endif #include -#include -#include +#include +#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/vendor/BUILD.bazel b/vendor/BUILD.bazel index c950e3a3c..b822d9eea 100644 --- a/vendor/BUILD.bazel +++ b/vendor/BUILD.bazel @@ -178,7 +178,10 @@ cc_library( # vendor/metal-cpp.json cc_library( name = "metal-cpp", - hdrs = glob(["metal-cpp/**/*.hpp"], allow_empty = False), + hdrs = glob( + ["metal-cpp/**/*.hpp"], + allow_empty = False, + ), copts = CPP_FLAGS, includes = ["metal-cpp"], visibility = ["//visibility:public"], diff --git a/vendor/boost b/vendor/boost index 5140cf182..805bc2ee7 160000 --- a/vendor/boost +++ b/vendor/boost @@ -1 +1 @@ -Subproject commit 5140cf182b904138ba7f9848633fde9460df857a +Subproject commit 805bc2ee74cc06d7159ec9ac9bf56072c16a2389 From 810be67fa23afeb8112037b9cd43bca5462c1728 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Thu, 28 Sep 2023 11:18:42 -0700 Subject: [PATCH 03/19] Issue/1687 (#1697) Co-authored-by: Bart Louwers Co-authored-by: mwilsnd --- bazel/core.bzl | 17 ++ include/mbgl/gfx/drawable.hpp | 8 + include/mbgl/gfx/drawable_builder.hpp | 5 + include/mbgl/gfx/shader_group.hpp | 14 +- include/mbgl/gfx/vertex_attribute.hpp | 29 ++- include/mbgl/renderer/layer_group.hpp | 12 +- include/mbgl/renderer/layer_tweaker.hpp | 37 ++- include/mbgl/shaders/gl/shader_group_gl.hpp | 61 +++-- include/mbgl/shaders/layer_ubo.hpp | 2 - include/mbgl/shaders/mtl/background.hpp | 11 +- .../mbgl/shaders/mtl/background_pattern.hpp | 6 +- include/mbgl/shaders/mtl/circle.hpp | 22 +- include/mbgl/shaders/mtl/clipping_mask.hpp | 10 +- include/mbgl/shaders/mtl/common.hpp | 3 - include/mbgl/shaders/mtl/fill.hpp | 82 +------ include/mbgl/shaders/mtl/fill_extrusion.hpp | 18 +- .../shaders/mtl/fill_extrusion_pattern.hpp | 6 +- include/mbgl/shaders/mtl/heatmap.hpp | 16 +- include/mbgl/shaders/mtl/heatmap_texture.hpp | 14 +- include/mbgl/shaders/mtl/hillshade.hpp | 14 +- .../mbgl/shaders/mtl/hillshade_prepare.hpp | 14 +- include/mbgl/shaders/mtl/line.hpp | 46 +--- include/mbgl/shaders/mtl/line_gradient.hpp | 22 +- include/mbgl/shaders/mtl/raster.hpp | 15 +- include/mbgl/shaders/mtl/shader_group.hpp | 18 +- include/mbgl/shaders/mtl/shader_program.hpp | 6 + include/mbgl/shaders/mtl/symbol_icon.hpp | 25 +- include/mbgl/shaders/mtl/symbol_sdf.hpp | 29 +-- .../mbgl/shaders/mtl/symbol_text_and_icon.hpp | 29 +-- include/mbgl/util/string_indexer.hpp | 2 +- src/mbgl/gfx/vertex_attribute.cpp | 3 +- src/mbgl/gl/context.cpp | 3 +- src/mbgl/gl/drawable_gl.cpp | 6 +- src/mbgl/gl/drawable_gl_builder.cpp | 1 + src/mbgl/gl/layer_group_gl.cpp | 3 +- src/mbgl/mtl/context.cpp | 9 +- src/mbgl/mtl/drawable.cpp | 6 +- src/mbgl/mtl/drawable_builder.cpp | 1 + src/mbgl/renderer/layer_group.cpp | 13 ++ src/mbgl/renderer/layer_tweaker.cpp | 34 +-- .../layers/background_layer_tweaker.cpp | 3 + .../renderer/layers/circle_layer_tweaker.cpp | 31 ++- .../layers/collision_layer_tweaker.cpp | 2 +- .../layers/fill_extrusion_layer_tweaker.cpp | 18 +- .../renderer/layers/fill_layer_tweaker.cpp | 46 ++-- .../renderer/layers/heatmap_layer_tweaker.cpp | 19 +- .../layers/heatmap_texture_layer_tweaker.cpp | 4 + .../layers/hillshade_layer_tweaker.cpp | 8 +- .../hillshade_prepare_layer_tweaker.cpp | 4 +- .../renderer/layers/line_layer_tweaker.cpp | 19 +- .../renderer/layers/raster_layer_tweaker.cpp | 4 + .../layers/render_background_layer.cpp | 13 +- .../renderer/layers/render_circle_layer.cpp | 68 +++--- .../renderer/layers/render_circle_layer.hpp | 11 - .../layers/render_fill_extrusion_layer.cpp | 38 ++- .../renderer/layers/render_fill_layer.cpp | 82 +++---- .../renderer/layers/render_fill_layer.hpp | 11 - .../renderer/layers/render_heatmap_layer.cpp | 109 ++++----- .../renderer/layers/render_heatmap_layer.hpp | 21 +- .../layers/render_hillshade_layer.cpp | 112 +++++---- .../layers/render_hillshade_layer.hpp | 3 +- .../renderer/layers/render_line_layer.cpp | 171 ++++++-------- .../renderer/layers/render_line_layer.hpp | 10 - .../renderer/layers/render_raster_layer.cpp | 216 +++++++++--------- .../renderer/layers/render_raster_layer.hpp | 14 +- .../renderer/layers/render_symbol_layer.cpp | 116 ++++++---- .../renderer/layers/render_symbol_layer.hpp | 12 +- .../renderer/layers/symbol_layer_tweaker.cpp | 24 +- .../renderer/layers/symbol_layer_tweaker.hpp | 3 + src/mbgl/renderer/render_layer.cpp | 44 +++- src/mbgl/renderer/render_layer.hpp | 14 +- src/mbgl/renderer/render_target.cpp | 7 +- src/mbgl/renderer/renderer_impl.cpp | 7 +- src/mbgl/shaders/mtl/background.cpp | 17 ++ src/mbgl/shaders/mtl/background_pattern.cpp | 14 ++ src/mbgl/shaders/mtl/circle.cpp | 27 +++ src/mbgl/shaders/mtl/clipping_mask.cpp | 16 ++ src/mbgl/shaders/mtl/fill.cpp | 82 +++++++ src/mbgl/shaders/mtl/fill_extrusion.cpp | 24 ++ .../shaders/mtl/fill_extrusion_pattern.cpp | 14 ++ src/mbgl/shaders/mtl/heatmap.cpp | 21 ++ src/mbgl/shaders/mtl/heatmap_texture.cpp | 20 ++ src/mbgl/shaders/mtl/hillshade.cpp | 19 ++ src/mbgl/shaders/mtl/hillshade_prepare.cpp | 20 ++ src/mbgl/shaders/mtl/line.cpp | 49 ++++ src/mbgl/shaders/mtl/line_gradient.cpp | 27 +++ src/mbgl/shaders/mtl/raster.cpp | 19 ++ src/mbgl/shaders/mtl/shader_program.cpp | 26 ++- src/mbgl/shaders/mtl/symbol_icon.cpp | 30 +++ src/mbgl/shaders/mtl/symbol_sdf.cpp | 36 +++ src/mbgl/shaders/mtl/symbol_text_and_icon.cpp | 36 +++ src/mbgl/util/hash.hpp | 20 ++ test/CMakeLists.txt | 3 +- test/util/hash.test.cpp | 54 +++++ 94 files changed, 1467 insertions(+), 1043 deletions(-) create mode 100644 src/mbgl/shaders/mtl/background.cpp create mode 100644 src/mbgl/shaders/mtl/background_pattern.cpp create mode 100644 src/mbgl/shaders/mtl/circle.cpp create mode 100644 src/mbgl/shaders/mtl/clipping_mask.cpp create mode 100644 src/mbgl/shaders/mtl/fill.cpp create mode 100644 src/mbgl/shaders/mtl/fill_extrusion.cpp create mode 100644 src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp create mode 100644 src/mbgl/shaders/mtl/heatmap.cpp create mode 100644 src/mbgl/shaders/mtl/heatmap_texture.cpp create mode 100644 src/mbgl/shaders/mtl/hillshade.cpp create mode 100644 src/mbgl/shaders/mtl/hillshade_prepare.cpp create mode 100644 src/mbgl/shaders/mtl/line.cpp create mode 100644 src/mbgl/shaders/mtl/line_gradient.cpp create mode 100644 src/mbgl/shaders/mtl/raster.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_icon.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_sdf.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_text_and_icon.cpp create mode 100644 test/util/hash.test.cpp diff --git a/bazel/core.bzl b/bazel/core.bzl index 6329df8eb..e59e7c4a9 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -1019,6 +1019,23 @@ MLN_DRAWABLES_MTL_SOURCE = [ "src/mbgl/mtl/upload_pass.cpp", "src/mbgl/mtl/vertex_attribute.cpp", "src/mbgl/shaders/mtl/shader_program.cpp", + "src/mbgl/shaders/mtl/background.cpp", + "src/mbgl/shaders/mtl/background_pattern.cpp", + "src/mbgl/shaders/mtl/circle.cpp", + "src/mbgl/shaders/mtl/clipping_mask.cpp", + "src/mbgl/shaders/mtl/fill.cpp", + "src/mbgl/shaders/mtl/fill_extrusion.cpp", + "src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp", + "src/mbgl/shaders/mtl/heatmap.cpp", + "src/mbgl/shaders/mtl/heatmap_texture.cpp", + "src/mbgl/shaders/mtl/hillshade.cpp", + "src/mbgl/shaders/mtl/hillshade_prepare.cpp", + "src/mbgl/shaders/mtl/line.cpp", + "src/mbgl/shaders/mtl/line_gradient.cpp", + "src/mbgl/shaders/mtl/raster.cpp", + "src/mbgl/shaders/mtl/symbol_icon.cpp", + "src/mbgl/shaders/mtl/symbol_sdf.cpp", + "src/mbgl/shaders/mtl/symbol_text_and_icon.cpp", ] MLN_DRAWABLES_MTL_HEADERS = [ diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index b13a93b75..13feb6e59 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -18,8 +18,11 @@ namespace mbgl { class Color; class PaintParameters; +class LayerTweaker; enum class RenderPass : uint8_t; +using LayerTweakerPtr = std::shared_ptr; + namespace gfx { class ColorMode; @@ -234,6 +237,10 @@ public: /// Get drawable user-defined type size_t getType() const { return type; } + /// Associate the drawable with a layer tweaker. This is used to manage the lifetime of the tweaker. + void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); } + const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } + protected: bool enabled = true; bool enableColor = true; @@ -257,6 +264,7 @@ protected: Textures textures; std::vector tweakers; + LayerTweakerPtr layerTweaker; std::size_t type = 0; }; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index b13249425..bc5fd59f0 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -145,6 +145,9 @@ public: /// @param location A sampler location in the shader being used. void setTexture(const gfx::Texture2DPtr&, int32_t location); + /// Direct access to the current texture set + const gfx::Drawable::Textures& getTextures() const { return textures; } + /// Add a tweaker to emitted drawable void addTweaker(DrawableTweakerPtr value) { tweakers.emplace_back(std::move(value)); } @@ -225,5 +228,7 @@ protected: std::unique_ptr impl; }; +using UniqueDrawableBuilder = std::unique_ptr; + } // namespace gfx } // namespace mbgl diff --git a/include/mbgl/gfx/shader_group.hpp b/include/mbgl/gfx/shader_group.hpp index cf1fd9b27..3aa8760dd 100644 --- a/include/mbgl/gfx/shader_group.hpp +++ b/include/mbgl/gfx/shader_group.hpp @@ -6,9 +6,12 @@ #include #include #include -#include +#include namespace mbgl { + +using StringIdentity = std::size_t; + namespace gfx { class Context; @@ -138,12 +141,13 @@ public: /// @brief Get a shader from the group by its set of data driven properties as uniforms. /// if no shader is found, create and register the shader. - /// @param propertiesAsUniforms Vector of data driven properties as uniforms. + /// @param propertiesAsUniforms Set of data driven properties as uniforms. /// @param firstAttribName Name of the first attribute /// @return A `gfx::ShaderPtr` - virtual gfx::ShaderPtr getOrCreateShader(gfx::Context&, - [[maybe_unused]] const std::vector& propertiesAsUniforms, - [[maybe_unused]] std::string_view firstAttribName = "a_pos") { + virtual gfx::ShaderPtr getOrCreateShader( + gfx::Context&, + [[maybe_unused]] const std::unordered_set& propertiesAsUniforms, + [[maybe_unused]] std::string_view firstAttribName = "a_pos") { return {}; } diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 17c0c53e4..4ce7dc0d9 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -364,9 +365,15 @@ public: } /// Specialized DataDrivenPaintProperty reader + /// @param binders Property binders for the target shader + /// @param evaluated Evaluated properties + /// @param propertiesAsUniforms [out] A set of string identities for the properties which will be constant, not + /// attributes. + /// @details The property name IDs refer to the "a\_" prefixed values to match the shader definitions. template - std::vector readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) { - std::vector propertiesAsUniforms; + void readDataDrivenPaintProperties(const Binders& binders, + const Evaluated& evaluated, + std::unordered_set& propertiesAsUniforms) { propertiesAsUniforms.reserve(sizeof...(DataDrivenPaintProperty)); ( [&](const auto& attributeNames) { @@ -377,15 +384,14 @@ public: using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType using InterpType = ZoomInterpolatedAttributeType; + auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex]; + if (!attributeNameID) { + attributeNameID = StringIndexer::get(attributePrefix + attributeName.data()); + } + const auto vertexCount = binder->getVertexCount(); const auto isConstant = evaluated.template get().isConstant(); if (vertexCount > 0 && !isConstant) { - auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex]; - if (!attributeNameID) { - static const std::string attributePrefix = "a_"; - attributeNameID = StringIndexer::get(attributePrefix + attributeName.data()); - } - if (auto& attr = getOrAdd(*attributeNameID)) { if (const auto& sharedVector = binder->getSharedVertexVector()) { const auto rawSize = static_cast(sharedVector->getRawSize()); @@ -402,15 +408,13 @@ public: } } } - propertiesAsUniforms.emplace_back(std::string()); } else { - propertiesAsUniforms.emplace_back(attributeName); + propertiesAsUniforms.emplace(*attributeNameID); } } } }(DataDrivenPaintProperty::AttributeNames), ...); - return propertiesAsUniforms; } /// Copy another collection into this one @@ -435,7 +439,8 @@ protected: protected: AttributeMap attrs; - static std::unique_ptr nullref; + static const std::unique_ptr nullref; + static const std::string attributePrefix; }; } // namespace gfx diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index dd708f8ea..8780ba8d3 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -13,6 +13,7 @@ namespace mbgl { class LayerGroupBase; class PaintParameters; class RenderOrchestrator; +class RenderTree; class TileLayerGroup; using LayerGroupBasePtr = std::shared_ptr; @@ -28,6 +29,7 @@ using UniqueDrawable = std::unique_ptr; class LayerTweaker; using LayerTweakerPtr = std::shared_ptr; +using LayerTweakerWeakPtr = std::weak_ptr; /** A layer-like group of drawables, not a group of layers. @@ -86,16 +88,16 @@ public: /// @return The number of items removed virtual std::size_t removeDrawablesIf(const std::function&& f) = 0; - /// Attach a tweaker to be run on this layer group for each frame - void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); } + /// Attach a tweaker to be run on this layer group for each frame. + /// Tweaker lifetime is controlled by the render layer and drawables, the layer group retains a weak reference. + void addLayerTweaker(const LayerTweakerPtr& tweaker) { layerTweakers.emplace_back(tweaker); } - /// Get the tweaker attached to this layer group - const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } + void runTweakers(const RenderTree&, PaintParameters&); protected: bool enabled = true; int32_t layerIndex; - LayerTweakerPtr layerTweaker; + std::vector layerTweakers; std::string name; }; diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 2b81f1746..403746419 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -1,25 +1,31 @@ #pragma once +#include #include #include #include #include -#include +#include namespace mbgl { + namespace gfx { +class Drawable; class UniformBuffer; using UniformBufferPtr = std::shared_ptr; } // namespace gfx + namespace shaders { enum class AttributeSource : int32_t; struct ExpressionInputsUBO; } // namespace shaders + namespace style { class LayerProperties; enum class TranslateAnchorType : bool; } // namespace style + class TransformState; class LayerGroupBase; class PaintParameters; @@ -27,6 +33,7 @@ class RenderTree; class UnwrappedTileID; using mat4 = std::array; +using StringIdentity = std::size_t; /** Base class for layer tweakers, which manipulate layer group per frame @@ -45,16 +52,20 @@ public: /// Build the common expression inupts UBO static shaders::ExpressionInputsUBO buildExpressionUBO(double zoom, uint64_t frameCount); + /// @brief Check whether a property name exists within the previously set collection. + bool hasPropertyAsUniform(StringIdentity) const; + shaders::AttributeSource getAttributeSource(StringIdentity) const; + + template + shaders::AttributeSource getAttributeSource(size_t index) { + using ShaderClass = shaders::ShaderSource; + return getAttributeSource(ShaderClass::attributes[index].nameID); + } +#endif // MLN_RENDER_BACKEND_METAL + /// @brief Set the collection of attribute names which will be provided at uniform values rather than per-vertex /// attributes. - /// @details These values should not have "a_" prefixes, as produced by `readDataDrivenPaintProperties`. - void setPropertiesAsUniforms(std::vector); - - /// @brief Check whether a property name exists within the previously set collection. - /// @details The string value provided is expected to have the "a_" prefix, as defined in the shader classes. - bool hasPropertyAsUniform(std::string_view) const; - shaders::AttributeSource getAttributeSource(const std::string_view& attribName) const; -#endif // MLN_RENDER_BACKEND_METAL + void setPropertiesAsUniforms(const std::unordered_set&); void enableOverdrawInspector(bool); @@ -63,6 +74,9 @@ public: void updateProperties(Immutable); protected: + /// Determine whether this tweaker should apply to the given drawable + bool checkTweakDrawable(const gfx::Drawable&) const; + /// Calculate matrices for this tile. /// @param nearClipped If true, the near plane is moved further to enhance depth buffer precision. /// @param inViewportPixelUnits If false, the translation is scaled based on the current zoom. @@ -78,14 +92,15 @@ protected: protected: std::string id; Immutable evaluatedProperties; - bool propertiesUpdated = true; #if MLN_RENDER_BACKEND_METAL // For Metal, whether a property is provided through attribtues or uniforms is specified in // a uniform buffer rather than by a shader compiled with different preprocessor definitions. - std::vector propertiesAsUniforms; + std::unordered_set propertiesAsUniforms; #endif // MLN_RENDER_BACKEND_METAL + bool propertiesUpdated = true; + bool propertiesChanged = true; bool overdrawInspector = false; }; diff --git a/include/mbgl/shaders/gl/shader_group_gl.hpp b/include/mbgl/shaders/gl/shader_group_gl.hpp index cec5740f7..9c54ed5ea 100644 --- a/include/mbgl/shaders/gl/shader_group_gl.hpp +++ b/include/mbgl/shaders/gl/shader_group_gl.hpp @@ -4,6 +4,10 @@ #include #include #include +#include + +#include +#include namespace mbgl { namespace gl { @@ -13,40 +17,61 @@ class ShaderGroupGL final : public gfx::ShaderGroup { public: ShaderGroupGL(const ProgramParameters& programParameters_) : ShaderGroup(), - programParameters(programParameters_){}; + programParameters(programParameters_) {} ~ShaderGroupGL() noexcept override = default; gfx::ShaderPtr getOrCreateShader(gfx::Context& context, - const std::vector& propertiesAsUniforms, + const std::unordered_set& propertiesAsUniforms, std::string_view firstAttribName) override { - constexpr auto& name = shaders::ShaderSource::name; constexpr auto& vert = shaders::ShaderSource::vertex; constexpr auto& frag = shaders::ShaderSource::fragment; - uint32_t key = 0; + // Generate a map key for the specified combination of properties + const size_t key = util::order_independent_hash(propertiesAsUniforms.begin(), propertiesAsUniforms.end()); + + // We could cache these by key here to avoid creating a string key each time, but we + // would need another mutex. We could also push string IDs down into `ShaderGroup`. + const std::string shaderName = getShaderName(key); + auto shader = get(shaderName); + if (shader) { + return shader; + } + + // No match, we need to create the shader. std::string additionalDefines; - for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) { - if (propertiesAsUniforms[i].empty()) { - continue; + additionalDefines.reserve(propertiesAsUniforms.size() * 48); + for (const auto nameID : propertiesAsUniforms) { + // We expect the names to be prefixed by "a_", but we need just the base here. + const auto prefixedAttrName = StringIndexer::get(nameID); + const auto* prefix = prefixedAttrName.data(); + if (prefix[0] == 'a' && prefix[1] == '_') { + prefix += 2; } - key |= 1 << i; + additionalDefines += "#define HAS_UNIFORM_u_"; - additionalDefines += propertiesAsUniforms[i]; + additionalDefines += prefix; additionalDefines += "\n"; } - const std::string shaderName = std::string(name) + "#" + std::to_string(key); - auto shader = get(shaderName); - if (!shader) { - auto& glContext = static_cast(context); - shader = ShaderProgramGL::create( - glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines); - if (!shader || !registerShader(shader, shaderName)) { - throw std::runtime_error("Failed to register " + shaderName + " with shader group!"); - } + + auto& glContext = static_cast(context); + shader = ShaderProgramGL::create( + glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines); + if (!shader || !registerShader(shader, shaderName)) { + throw std::runtime_error("Failed to register " + shaderName + " with shader group!"); } return shader; } +protected: + std::string getShaderName(std::size_t key) { + constexpr auto& name = shaders::ShaderSource::name; + + // This could be more efficient. + std::ostringstream stream; + stream << name << '#' << key; + return stream.str(); + } + private: ProgramParameters programParameters; }; diff --git a/include/mbgl/shaders/layer_ubo.hpp b/include/mbgl/shaders/layer_ubo.hpp index 7caac8f20..ea69aa070 100644 --- a/include/mbgl/shaders/layer_ubo.hpp +++ b/include/mbgl/shaders/layer_ubo.hpp @@ -5,8 +5,6 @@ #include #include -#define MLN_STRINGIZE(X) #X - namespace mbgl { namespace shaders { diff --git a/include/mbgl/shaders/mtl/background.hpp b/include/mbgl/shaders/mtl/background.hpp index b5e799fca..5dc954ebe 100644 --- a/include/mbgl/shaders/mtl/background.hpp +++ b/include/mbgl/shaders/mtl/background.hpp @@ -14,14 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Float3, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, true, BackgroundLayerUBO), - MLN_MTL_UNIFORM_BLOCK(2, true, false, BackgroundDrawableUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #include diff --git a/include/mbgl/shaders/mtl/background_pattern.hpp b/include/mbgl/shaders/mtl/background_pattern.hpp index 428fb855a..8cbd69f68 100644 --- a/include/mbgl/shaders/mtl/background_pattern.hpp +++ b/include/mbgl/shaders/mtl/background_pattern.hpp @@ -9,11 +9,7 @@ template <> struct ShaderSource : public ShaderSource { static constexpr auto name = "BackgroundPatternShader"; - static constexpr UniformBlockInfo uniforms[] = { - {1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"}, - {2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"}, - {3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"}, - }; + static const std::array uniforms; }; } // namespace shaders diff --git a/include/mbgl/shaders/mtl/circle.hpp b/include/mbgl/shaders/mtl/circle.hpp index 42eb9fc18..fc049990c 100644 --- a/include/mbgl/shaders/mtl/circle.hpp +++ b/include/mbgl/shaders/mtl/circle.hpp @@ -14,25 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_radius"}, - {3, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"}, - {6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"}, - {7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, false, CircleDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, true, CirclePaintParamsUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, true, CircleEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, CircleInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, CirclePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/clipping_mask.hpp b/include/mbgl/shaders/mtl/clipping_mask.hpp index 5c62c52a7..e86707dfe 100644 --- a/include/mbgl/shaders/mtl/clipping_mask.hpp +++ b/include/mbgl/shaders/mtl/clipping_mask.hpp @@ -20,13 +20,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Float3, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, false, ClipUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #include diff --git a/include/mbgl/shaders/mtl/common.hpp b/include/mbgl/shaders/mtl/common.hpp index 04257e9d6..de61c8a0c 100644 --- a/include/mbgl/shaders/mtl/common.hpp +++ b/include/mbgl/shaders/mtl/common.hpp @@ -1,8 +1,5 @@ #pragma once -#define MLN_MTL_UNIFORM_BLOCK(idx, vert, frag, struc) \ - { idx, vert, frag, sizeof(struc), MLN_STRINGIZE(struc) } - namespace mbgl { namespace shaders { diff --git a/include/mbgl/shaders/mtl/fill.hpp b/include/mbgl/shaders/mtl/fill.hpp index 472e579b0..e16881ac9 100644 --- a/include/mbgl/shaders/mtl/fill.hpp +++ b/include/mbgl/shaders/mtl/fill.hpp @@ -14,24 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - - // This shader doesn't use it, but we need this so that the layer can assign the same - // attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it, - // this can be removed. - {8, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, FillDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -104,22 +89,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - - // See `a_outline_color` in FillShader - {8, gfx::AttributeDataType::Float2, 1, "a_color"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, FillOutlineDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillOutlineEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillOutlineInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillOutlinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -203,24 +175,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, - {2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillPatternDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillPatternTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPatternEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, FillPatternInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, true, FillPatternPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO), - }; - - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -341,24 +298,9 @@ struct ShaderSource attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/fill_extrusion.hpp b/include/mbgl/shaders/mtl/fill_extrusion.hpp index 22a751df0..da20b28cf 100644 --- a/include/mbgl/shaders/mtl/fill_extrusion.hpp +++ b/include/mbgl/shaders/mtl/fill_extrusion.hpp @@ -14,21 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"}, - {2, gfx::AttributeDataType::Float4, 1, "a_color"}, - {3, gfx::AttributeDataType::Float, 1, "a_base"}, - {4, gfx::AttributeDataType::Float, 1, "a_height"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillExtrusionDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, false, FillExtrusionDrawablePropsUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, FillExtrusionInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, false, FillExtrusionPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct alignas(16) FillExtrusionInterpolateUBO { diff --git a/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp b/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp index ec96161af..20904c7fa 100644 --- a/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp +++ b/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp @@ -14,9 +14,9 @@ struct ShaderSource attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( )"; diff --git a/include/mbgl/shaders/mtl/heatmap.hpp b/include/mbgl/shaders/mtl/heatmap.hpp index 9aef72564..8ea16d229 100644 --- a/include/mbgl/shaders/mtl/heatmap.hpp +++ b/include/mbgl/shaders/mtl/heatmap.hpp @@ -14,19 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_weight"}, - {2, gfx::AttributeDataType::Float2, 1, "a_radius"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, HeatmapDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, HeatmapEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, HeatmapInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, HeatmapPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/heatmap_texture.hpp b/include/mbgl/shaders/mtl/heatmap_texture.hpp index 3c4873f8f..d9a621489 100644 --- a/include/mbgl/shaders/mtl/heatmap_texture.hpp +++ b/include/mbgl/shaders/mtl/heatmap_texture.hpp @@ -14,16 +14,10 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, true, HeatmapTextureDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - {1, "u_color_ramp"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/hillshade.hpp b/include/mbgl/shaders/mtl/hillshade.hpp index 1fa97b3b8..4248ce134 100644 --- a/include/mbgl/shaders/mtl/hillshade.hpp +++ b/include/mbgl/shaders/mtl/hillshade.hpp @@ -14,17 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadeDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(3, false, true, HillshadeEvaluatedPropsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/hillshade_prepare.hpp b/include/mbgl/shaders/mtl/hillshade_prepare.hpp index be57aef91..532f9f579 100644 --- a/include/mbgl/shaders/mtl/hillshade_prepare.hpp +++ b/include/mbgl/shaders/mtl/hillshade_prepare.hpp @@ -14,16 +14,10 @@ struct ShaderSource static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadePrepareDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/line.hpp b/include/mbgl/shaders/mtl/line.hpp index 9fed89140..e5b44db07 100644 --- a/include/mbgl/shaders/mtl/line.hpp +++ b/include/mbgl/shaders/mtl/line.hpp @@ -14,24 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float4, 1, "a_color"}, - {3, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {6, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {7, gfx::AttributeDataType::Float2, 1, "a_width"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, true, LineUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, LinePropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, LineInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -143,28 +128,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {5, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {6, gfx::AttributeDataType::Float2, 1, "a_width"}, - {7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, - {8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(9, true, true, LinePatternUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, LinePatternPropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, LinePatternInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, LinePatternTilePropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/line_gradient.hpp b/include/mbgl/shaders/mtl/line_gradient.hpp index 6d2b90416..ca718159c 100644 --- a/include/mbgl/shaders/mtl/line_gradient.hpp +++ b/include/mbgl/shaders/mtl/line_gradient.hpp @@ -14,25 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {5, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {6, gfx::AttributeDataType::Float2, 1, "a_width"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(7, true, true, LineGradientUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, false, LineGradientPropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, LineGradientInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/raster.hpp b/include/mbgl/shaders/mtl/raster.hpp index ca9f6b3a1..4b9022991 100644 --- a/include/mbgl/shaders/mtl/raster.hpp +++ b/include/mbgl/shaders/mtl/raster.hpp @@ -14,17 +14,10 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, RasterDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image0"}, - {1, "u_image1"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/shader_group.hpp b/include/mbgl/shaders/mtl/shader_group.hpp index 05a402a85..40aa8a977 100644 --- a/include/mbgl/shaders/mtl/shader_group.hpp +++ b/include/mbgl/shaders/mtl/shader_group.hpp @@ -22,32 +22,20 @@ public: ~ShaderGroup() noexcept override = default; gfx::ShaderPtr getOrCreateShader(gfx::Context& gfxContext, - const std::vector& propertiesAsUniforms, + const std::unordered_set& propertiesAsUniforms, std::string_view /*firstAttribName*/) override { constexpr auto& name = shaders::ShaderSource::name; constexpr auto& source = shaders::ShaderSource::source; constexpr auto& vertMain = shaders::ShaderSource::vertexMainFunction; constexpr auto& fragMain = shaders::ShaderSource::fragmentMainFunction; - uint32_t key = 0; - assert(propertiesAsUniforms.size() < 32); - std::unordered_map additionalDefines(propertiesAsUniforms.size()); - for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) { - if (!propertiesAsUniforms[i].empty()) { - key |= 1U << i; - auto name = std::string("HAS_UNIFORM_u_") + propertiesAsUniforms[i]; - additionalDefines.insert(std::make_pair(std::move(name), "1")); - } - } - - const std::string shaderName = std::string(name); // + "#" + std::to_string(key); + const std::string shaderName = std::string(name); const auto shaderSource = std::string(shaders::prelude) + source; auto shader = get(shaderName); if (!shader) { auto& context = static_cast(gfxContext); - shader = context.createProgram( - shaderName, shaderSource, vertMain, fragMain, programParameters, additionalDefines); + shader = context.createProgram(shaderName, shaderSource, vertMain, fragMain, programParameters, {}); assert(shader); if (!shader || !registerShader(shader, shaderName)) { assert(false); diff --git a/include/mbgl/shaders/mtl/shader_program.hpp b/include/mbgl/shaders/mtl/shader_program.hpp index 11ea96bc4..772f1dc2d 100644 --- a/include/mbgl/shaders/mtl/shader_program.hpp +++ b/include/mbgl/shaders/mtl/shader_program.hpp @@ -15,21 +15,27 @@ namespace mbgl { namespace shaders { struct AttributeInfo { + AttributeInfo(std::size_t index, gfx::AttributeDataType dataType, std::size_t count, std::string_view name); std::size_t index; gfx::AttributeDataType dataType; std::size_t count; std::string_view name; + StringIdentity nameID; }; struct UniformBlockInfo { + UniformBlockInfo(std::size_t index, bool vertex, bool fragment, std::size_t size, std::string_view name); std::size_t index; bool vertex; bool fragment; std::size_t size; std::string_view name; + StringIdentity nameID; }; struct TextureInfo { + TextureInfo(std::size_t index, std::string_view name); std::size_t index; std::string_view name; + StringIdentity nameID; }; } // namespace shaders namespace mtl { diff --git a/include/mbgl/shaders/mtl/symbol_icon.hpp b/include/mbgl/shaders/mtl/symbol_icon.hpp index 5f307c164..0cd4ada77 100644 --- a/include/mbgl/shaders/mtl/symbol_icon.hpp +++ b/include/mbgl/shaders/mtl/symbol_icon.hpp @@ -14,28 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, - {3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {5, gfx::AttributeDataType::Float, 1, "a_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/symbol_sdf.hpp b/include/mbgl/shaders/mtl/symbol_sdf.hpp index c1e8db6ee..c9858636b 100644 --- a/include/mbgl/shaders/mtl/symbol_sdf.hpp +++ b/include/mbgl/shaders/mtl/symbol_sdf.hpp @@ -14,32 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, - {3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {5, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, - {6, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, - {7, gfx::AttributeDataType::Float, 1, "a_opacity"}, - {8, gfx::AttributeDataType::Float, 1, "a_halo_width"}, - {9, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(10, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(15, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp index b9d7bdfb7..afd4dd4b8 100644 --- a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp +++ b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp @@ -14,32 +14,9 @@ struct ShaderSource static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {4, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, - {5, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, - {6, gfx::AttributeDataType::Float, 1, "a_opacity"}, - {7, gfx::AttributeDataType::Float, 1, "a_halo_width"}, - {8, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, true, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - {1, "u_texture_icon"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #define SDF 1.0 diff --git a/include/mbgl/util/string_indexer.hpp b/include/mbgl/util/string_indexer.hpp index 8cd5afbd3..cf4f5b6c7 100644 --- a/include/mbgl/util/string_indexer.hpp +++ b/include/mbgl/util/string_indexer.hpp @@ -11,7 +11,7 @@ namespace mbgl { -using StringIdentity = size_t; +using StringIdentity = std::size_t; class StringIndexer { public: diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index a1862fef9..b1e6c3c5d 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -17,7 +17,8 @@ std::size_t VertexAttribute::getCount() const { return sharedRawData ? sharedRawData->getRawCount() : items.size(); } -std::unique_ptr VertexAttributeArray::nullref = nullptr; +const std::unique_ptr VertexAttributeArray::nullref; +const std::string VertexAttributeArray::attributePrefix = "a_"; VertexAttributeArray::VertexAttributeArray(VertexAttributeArray&& other) : attrs(std::move(other.attrs)) {} diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 82cef14a2..1eecdd458 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -489,12 +489,11 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t } gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { - std::vector emptyProperties(0); auto shaderGroup = shaders.getShaderGroup(name); if (!shaderGroup) { return nullptr; } - return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, emptyProperties)); + return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, {})); } TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index f9adc544e..314243ff0 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -122,9 +122,11 @@ void DrawableGL::bindUniformBuffers() const { const auto& uniformBuffer = getUniformBuffers().get(element.first); if (!uniformBuffer) { using namespace std::string_literals; + const auto tileID = getTileID() ? util::toString(*getTileID()) : ""; Log::Error(Event::General, - "DrawableGL::bindUniformBuffers: UBO "s + std::string(StringIndexer::get(element.first)) + - " not found. skipping."); + "bindUniformBuffers: UBO "s + std::string(StringIndexer::get(element.first)) + + " not found for " + util::toString(getID()) + " / " + getName() + " / " + tileID + + ". skipping."); assert(false); continue; } diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index 6b1a55134..caa3afdb9 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -43,6 +43,7 @@ void DrawableGLBuilder::init() { impl->buildIndexes.clear(); impl->segments.clear(); impl->vertices.clear(); + textures.clear(); } } // namespace gl diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index d8df4c621..0ce9a50e6 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -103,7 +103,8 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) #if !defined(NDEBUG) std::string label_tile; if (const auto& tileID = drawable.getTileID()) { - label_tile = drawable.getName() + "/" + util::toString(*tileID); + label_tile = util::toString(drawable.getID().id()) + "/" + drawable.getName() + "/" + + util::toString(*tileID); } const auto labelPtr = (label_tile.empty() ? drawable.getName() : label_tile).c_str(); const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr); diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index b92adf543..1100e34d3 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -151,12 +151,9 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t } gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { - std::vector emptyProperties(0); - auto shaderGroup = shaders.getShaderGroup(name); - if (!shaderGroup) { - return nullptr; - } - return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, emptyProperties)); + const auto shaderGroup = shaders.getShaderGroup(name); + auto shader = shaderGroup ? shaderGroup->getOrCreateShader(*this, {}) : gfx::ShaderProgramBasePtr{}; + return std::static_pointer_cast(std::move(shader)); } TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 2caaaf3b6..57d9c1fc9 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -377,9 +377,11 @@ void Drawable::bindUniformBuffers(const RenderPass& renderPass) const { const auto& uniformBuffer = getUniformBuffers().get(element.first); if (!uniformBuffer) { using namespace std::string_literals; + const auto tileID = getTileID() ? util::toString(*getTileID()) : ""; + const auto tileLabel = util::toString(getID()) + "/" + getName() + "/" + tileID; Log::Error(Event::General, - "Drawable::bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + - " not found. skipping."); + "bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + " not found on " + + tileLabel + ". skipping."); assert(false); continue; } diff --git a/src/mbgl/mtl/drawable_builder.cpp b/src/mbgl/mtl/drawable_builder.cpp index ec436fbc7..fe2454472 100644 --- a/src/mbgl/mtl/drawable_builder.cpp +++ b/src/mbgl/mtl/drawable_builder.cpp @@ -43,6 +43,7 @@ void DrawableBuilder::init() { impl->buildIndexes.clear(); impl->segments.clear(); impl->vertices.clear(); + textures.clear(); } } // namespace mtl diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index cc9ffdb97..48c423d6a 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include #include @@ -16,6 +18,17 @@ void LayerGroupBase::addDrawable(gfx::UniqueDrawable& drawable) { } } +void LayerGroupBase::runTweakers(const RenderTree& renderTree, PaintParameters& parameters) { + for (auto it = layerTweakers.begin(); it != layerTweakers.end();) { + if (auto tweaker = it->lock()) { + tweaker->execute(*this, renderTree, parameters); + ++it; + } else { + it = layerTweakers.erase(it); + } + } +} + struct LayerGroup::Impl { using DrawableCollection = std::set; DrawableCollection drawables; diff --git a/src/mbgl/renderer/layer_tweaker.cpp b/src/mbgl/renderer/layer_tweaker.cpp index b982f2978..01e0a2761 100644 --- a/src/mbgl/renderer/layer_tweaker.cpp +++ b/src/mbgl/renderer/layer_tweaker.cpp @@ -19,6 +19,12 @@ LayerTweaker::LayerTweaker(std::string id_, Immutable pr : id(std::move(id_)), evaluatedProperties(std::move(properties)) {} +bool LayerTweaker::checkTweakDrawable(const gfx::Drawable& drawable) const { + // Apply to a drawable if it references us, or if doesn't reference anything. + const auto& tweaker = drawable.getLayerTweaker(); + return !tweaker || tweaker.get() == this; +} + mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID, const RenderTree& renderTree, const TransformState& state, @@ -60,27 +66,25 @@ shaders::ExpressionInputsUBO LayerTweaker::buildExpressionUBO(double zoom, uint6 0}; } -void LayerTweaker::setPropertiesAsUniforms(std::vector props) { - if (props != propertiesAsUniforms) { - propertiesAsUniforms = std::move(props); - propertiesChanged = true; - } -} -bool LayerTweaker::hasPropertyAsUniform(const std::string_view attrName) const { - // `attrName` is expected to have the "a_" prefix, while the values in `propertiesAsUniforms` - // do not. Search for the former within the latter without allocating temporary strings. - return propertiesAsUniforms.end() != - std::find_if(propertiesAsUniforms.begin(), propertiesAsUniforms.end(), [&](const auto& name) { - return name.size() + 2 == attrName.size() && 0 == std::strcmp(name.data(), attrName.data() + 2); - }); +bool LayerTweaker::hasPropertyAsUniform(const StringIdentity attrNameID) const { + return propertiesAsUniforms.find(attrNameID) != propertiesAsUniforms.end(); } using namespace shaders; -AttributeSource LayerTweaker::getAttributeSource(const std::string_view& attribName) const { - return hasPropertyAsUniform(attribName) ? AttributeSource::Constant : AttributeSource::PerVertex; +AttributeSource LayerTweaker::getAttributeSource(const StringIdentity attribNameID) const { + return hasPropertyAsUniform(attribNameID) ? AttributeSource::Constant : AttributeSource::PerVertex; } #endif // MLN_RENDER_BACKEND_METAL +void LayerTweaker::setPropertiesAsUniforms([[maybe_unused]] const std::unordered_set& props) { +#if MLN_RENDER_BACKEND_METAL + if (props != propertiesAsUniforms) { + propertiesAsUniforms = props; + propertiesChanged = true; + } +#endif +} + void LayerTweaker::enableOverdrawInspector(bool value) { if (overdrawInspector != value) { overdrawInspector = value; diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index ceb875b3f..d4ee0b033 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -54,6 +54,9 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre std::optional samplerLocation{}; layerGroup.visitDrawables([&](gfx::Drawable& drawable) { assert(drawable.getTileID()); + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } // We assume that drawables don't change between pattern and non-pattern. const auto& shader = drawable.getShader(); diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 9d1500127..090ad72cb 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -60,20 +60,15 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); #if MLN_RENDER_BACKEND_METAL - using ShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const CirclePermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .blur = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[4].name), /*.expression=*/{}}, - /* .stroke_color = */ {/*.source=*/source(ShaderClass::attributes[5].name), /*.expression=*/{}}, - /* .stroke_width = */ {/*.source=*/source(ShaderClass::attributes[6].name), /*.expression=*/{}}, - /* .stroke_opacity = */ {/*.source=*/source(ShaderClass::attributes[7].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .radius = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .blur = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, + /* .stroke_color = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .stroke_width = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .stroke_opacity = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -114,16 +109,16 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace(idCirclePaintParamsUBOName, paintParamsUniformBuffer); - uniforms.addOrReplace(idCircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - - if (!drawable.getTileID()) { - assert(!"Circles only render with tiles"); + assert(drawable.getTileID() || !"Circles only render with tiles"); + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(idCirclePaintParamsUBOName, paintParamsUniformBuffer); + uniforms.addOrReplace(idCircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp index 5e8d0bd9a..508f16888 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp @@ -50,7 +50,7 @@ void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID() || !drawable.getData()) { + if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index deb0c8ab9..8ac8bf6f6 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -16,6 +16,10 @@ #include #include +#if MLN_RENDER_BACKEND_METAL +#include +#endif + namespace mbgl { using namespace shaders; @@ -79,9 +83,9 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); if (propertiesChanged) { const FillExtrusionPermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/getAttributeSource("a_color"), /*.expression=*/{}}, - /* .base = */ {/*.source=*/getAttributeSource("a_base"), /*.expression=*/{}}, - /* .height = */ {/*.source=*/getAttributeSource("a_height"), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .base = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .height = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -102,15 +106,15 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace(idFillExtrusionDrawablePropsUBOName, propsBuffer); - - if (!drawable.getTileID()) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(idFillExtrusionDrawablePropsUBOName, propsBuffer); + const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index ebd33424f..14ded51d4 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -77,12 +77,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif -#if MLN_RENDER_BACKEND_METAL - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; -#endif - bool fillUniformBufferUpdated = false; bool fillOutlineUniformBufferUpdated = false; bool fillPatternUniformBufferUpdated = false; @@ -92,11 +86,10 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillPermutationUniformBuffer) { const FillPermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -131,11 +124,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillOutlineUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillOutlinePermutationUniformBuffer) { const FillOutlinePermutationUBO permutationUBO = { - /* .outline_color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .outline_color = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -172,12 +165,14 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillPatternUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillPatternPermutationUniformBuffer) { const FillPatternPermutationUBO permutationUBO = { - /* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .pattern_to = */ + {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .opacity = */ + {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -211,12 +206,14 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillOutlinePatternUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; - if (propertiesChanged || !fillOutlinePermutationUniformBuffer) { + if (propertiesChanged || !fillOutlinePatternPermutationUniformBuffer) { const FillOutlinePatternPermutationUBO permutationUBO = { - /* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .pattern_to = */ + {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .opacity = */ + {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -255,6 +252,10 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); // auto& drawableType = drawable.getShader()->typeName(); @@ -287,9 +288,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, } } } - if (!drawable.getTileID()) { - return; - } if (uniforms.get(idFillInterpolateUBOName)) { UpdateFillUniformBuffers(); diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index 4fa4f5699..6cfc4a57a 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -43,15 +43,10 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); #if MLN_RENDER_BACKEND_METAL - using ShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const HeatmapPermutationUBO permutationUBO = { - /* .weight = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .weight = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .radius = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad1/2/3 = */ 0, 0, @@ -85,13 +80,15 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.addOrReplace(idHeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - if (!drawable.getTileID()) { - return; - } - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); constexpr bool nearClipped = false; constexpr bool inViewportPixelUnits = false; const auto matrix = getTileMatrix(tileID, diff --git a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp index 2331c6846..d7542bbbd 100644 --- a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp @@ -33,6 +33,10 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!checkTweakDrawable(drawable)) { + return; + } + const auto& size = parameters.staticData.backendSize; mat4 viewportMat; matrix::ortho(viewportMat, 0, size.width, size.height, 0, -1, 1); diff --git a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp index 088785304..7e030ba36 100644 --- a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp @@ -55,12 +55,14 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - - if (!drawable.getTileID()) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + + drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + const auto matrix = getTileMatrix( tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, true); HillshadeDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix), diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index dfd33efe5..d8971b00a 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -42,7 +42,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID() || !drawable.getData()) { + if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); @@ -52,7 +52,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, matrix::ortho(matrix, 0, util::EXTENT, -util::EXTENT, 0, -1, 1); matrix::translate(matrix, matrix, 0, -util::EXTENT, 0); - HillshadePrepareDrawableUBO drawableUBO = { + const HillshadePrepareDrawableUBO drawableUBO = { /* .matrix = */ util::cast(matrix), /* .unpack = */ getUnpackVector(drawableData.encoding), /* .dimension = */ {static_cast(drawableData.stride), static_cast(drawableData.stride)}, diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index a0275e54b..cef597f7c 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -112,19 +112,14 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, }; #if MLN_RENDER_BACKEND_METAL - using LineShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const LinePermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(LineShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .blur = */ {/*.source=*/source(LineShaderClass::attributes[3].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(LineShaderClass::attributes[4].name), /*.expression=*/{}}, - /* .gapwidth = */ {/*.source=*/source(LineShaderClass::attributes[5].name), /*.expression=*/{}}, - /* .offset = */ {/*.source=*/source(LineShaderClass::attributes[6].name), /*.expression=*/{}}, - /* .width = */ {/*.source=*/source(LineShaderClass::attributes[7].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .blur = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, + /* .gapwidth = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .offset = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .width = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, /* .floorwidth = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, /* .pattern_from = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, /* .pattern_to = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, @@ -149,7 +144,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, layerGroup.visitDrawables([&](gfx::Drawable& drawable) { const auto shader = drawable.getShader(); - if (!drawable.getTileID() || !shader) { + if (!drawable.getTileID() || !shader || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index 945309f8c..2854f82dd 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -25,6 +25,10 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, const auto& evaluated = static_cast(*evaluatedProperties).evaluated; layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!checkTweakDrawable(drawable)) { + return; + } + const auto spinWeights = [](float spin) -> std::array { spin = util::deg2radf(spin); const float s = std::sin(spin); diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index b13b44914..6f50db3d4 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -67,7 +66,8 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& paramet #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } #endif } @@ -250,12 +250,18 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + if (!hasPattern && !plainShader) { plainShader = context.getGenericShader(shaders, std::string(BackgroundPlainShaderName)); } @@ -312,6 +318,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); tileLayerGroup->addDrawable(drawPasses, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index b3c704d95..f2e83ea1e 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -93,7 +93,10 @@ void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } #endif // MLN_DRAWABLE_RENDERER } @@ -276,19 +279,6 @@ static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos"); using namespace shaders; -#if MLN_DRAWABLE_RENDERER -void RenderCircleLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -305,12 +295,19 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!circleShaderGroup) { circleShaderGroup = shaders.getShaderGroup(CircleShaderGroupName); } @@ -319,14 +316,6 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - std::unique_ptr circleBuilder; constexpr auto renderPass = RenderPass::Translucent; @@ -338,6 +327,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -375,6 +365,11 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, // If there are already drawables for this tile, update their UBOs and move on to the next tile. auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate(idCircleInterpolateUBOName, &interpolateUBO, context); }; @@ -384,30 +379,28 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + propertiesAsUniforms.clear(); gfx::VertexAttributeArray circleVertexAttrs; - auto propertiesAsUniforms_ = circleVertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); + circleVertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); if (!circleShaderGroup) { continue; } - const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!circleShader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL if (const auto& attr = circleVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, @@ -434,6 +427,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : circleBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto& uniforms = drawable->mutableUniformBuffers(); uniforms.addOrReplace(idCircleInterpolateUBOName, interpBuffer); diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index 43ed687c3..da8c50dbb 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -49,10 +49,6 @@ private: void render(PaintParameters&) override; #endif // MLN_LEGACY_RENDERER -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - private: // Paint properties style::CirclePaintProperties::Unevaluated unevaluated; @@ -64,13 +60,6 @@ private: #if MLN_DRAWABLE_RENDERER gfx::ShaderGroupPtr circleShaderGroup; - - CircleLayerTweakerPtr tweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index d0364ac7b..f60ac813f 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #endif // MLN_DRAWABLE_RENDERER @@ -75,7 +76,8 @@ void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& para #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } #endif // MLN_DRAWABLE_RENDERER } @@ -275,7 +277,7 @@ bool RenderFillExtrusionLayer::queryIntersectsFeature(const GeometryCoordinates& void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, const RenderTree& /*renderTree*/, UniqueChangeRequestVec& changes) { if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { @@ -286,11 +288,19 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!fillExtrusionGroup) { fillExtrusionGroup = shaders.getShaderGroup("FillExtrusionShader"); } @@ -331,6 +341,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, return; } + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -388,6 +399,11 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, if (tileLayerGroup->getDrawableCount(drawPass, tileID) > 0) { // Just update the drawables we already created tileLayerGroup->visitDrawables(drawPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate( FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context); @@ -398,20 +414,25 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } gfx::VertexAttributeArray vertexAttrs; - const auto uniformProps = vertexAttrs.readDataDrivenPaintProperties(binders, evaluated); + propertiesAsUniforms.clear(); + vertexAttrs.readDataDrivenPaintProperties(binders, evaluated, propertiesAsUniforms); if (!shaderGroup) { continue; } const auto shader = std::static_pointer_cast( - shaderGroup->getOrCreateShader(context, uniformProps)); + shaderGroup->getOrCreateShader(context, propertiesAsUniforms)); if (!shader) { continue; } + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); + } + // The non-pattern path in `render()` only uses two-pass rendering if there's translucency. // The pattern path always uses two passes. const auto doDepthPass = (!opaque || hasPattern); @@ -501,6 +522,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate( diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index fcba89c00..d2627b4b5 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -104,9 +104,9 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } - updateLayerTweaker(); #endif } @@ -308,17 +308,6 @@ bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeo #if MLN_DRAWABLE_RENDERER -void RenderFillLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} - void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -332,24 +321,22 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!fillShaderGroup) { fillShaderGroup = shaders.getShaderGroup(std::string(FillShaderName)); } @@ -373,7 +360,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, std::unique_ptr outlinePatternBuilder; const auto layerPrefix = getID() + "/"; - const auto renderPass = RenderPass::Translucent; + constexpr auto renderPass = RenderPass::Translucent; const auto commonInit = [&](gfx::DrawableBuilder& builder) { builder.setCullFaceMode(gfx::CullFaceMode::disabled()); @@ -383,12 +370,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, stats.drawablesRemoved += tileLayerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) { // If the render pass has changed or the tile has dropped out of the cover set, remove it. const auto& tileID = drawable.getTileID(); - if (tileID && !hasRenderTile(*tileID)) { - return true; - } - return false; + return tileID && !hasRenderTile(*tileID); }); + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -519,9 +504,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // `Fill*Program` all use `style::FillPaintProperties` gfx::VertexAttributeArray vertexAttrs; - const auto propertiesAsUniforms_ = - vertexAttrs.readDataDrivenPaintProperties(binders, - evaluated); + propertiesAsUniforms.clear(); + vertexAttrs.readDataDrivenPaintProperties( + binders, evaluated, propertiesAsUniforms); + + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); + } const auto vertexCount = bucket.vertices.elements(); if (const auto& attr = vertexAttrs.add(idPosAttribName)) { @@ -534,6 +523,11 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // If we already have drawables for this tile, update them. auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); if (uniforms.get(FillLayerTweaker::idFillInterpolateUBOName)) { uniforms.createOrUpdate(FillLayerTweaker::idFillInterpolateUBOName, &getFillInterpolateUBO(), context); @@ -566,19 +560,12 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, continue; } const auto fillShader = std::static_pointer_cast( - fillShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)); + fillShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); const auto outlineShader = doOutline ? std::static_pointer_cast( - outlineShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)) + outlineShaderGroup->getOrCreateShader(context, propertiesAsUniforms)) : nullptr; -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); - } -#endif // MLN_RENDER_BACKEND_METAL - if (!fillBuilder && fillShader) { if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) { commonInit(*builder); @@ -610,6 +597,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate(interpolateUBONameId, &interpolateUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -653,19 +642,12 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } const auto fillShader = std::static_pointer_cast( - patternShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)); + patternShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); const auto outlineShader = doOutline ? std::static_pointer_cast( outlinePatternShaderGroup->getOrCreateShader( - context, propertiesAsUniforms_)) + context, propertiesAsUniforms)) : nullptr; -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); - } -#endif // MLN_RENDER_BACKEND_METAL - if (!patternBuilder) { if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) { commonInit(*builder); @@ -708,6 +690,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate(interpolateNameId, &interpolateUBO, context); uniforms.createOrUpdate(tileUBONameId, &tileUBO, context); diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index c077d926f..9ba69f8e3 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -46,10 +46,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, float, @@ -73,13 +69,6 @@ private: gfx::ShaderGroupPtr outlineShaderGroup; gfx::ShaderGroupPtr patternShaderGroup; gfx::ShaderGroupPtr outlinePatternShaderGroup; - - FillLayerTweakerPtr tweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - bool overdrawInspector = false; - #endif }; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index e980da01e..9e7bc96cf 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -70,8 +70,17 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); - updateLayerTextureTweaker(); + if (layerGroup) { + auto newTextureTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(textureTweaker, std::move(newTextureTweaker), {layerGroup}); + } + + if (renderTarget) { + if (auto tileLayerGroup = renderTarget->getLayerGroup(0)) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {std::move(tileLayerGroup)}); + } + } #endif } @@ -247,17 +256,24 @@ void RenderHeatmapLayer::markLayerRenderable(bool willRender, UniqueChangeReques activateRenderTarget(renderTarget, willRender, changes); } -void RenderHeatmapLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { - auto* tileLayerGroup = static_cast(renderTarget->getLayerGroup(0).get()); - stats.drawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); +std::size_t RenderHeatmapLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + if (auto* tileLayerGroup = static_cast(renderTarget->getLayerGroup(0).get())) { + const auto count = tileLayerGroup->removeDrawables(renderPass, tileID).size(); + stats.drawablesRemoved += count; + return count; + } + return 0; } -void RenderHeatmapLayer::removeAllDrawables() { - RenderLayer::removeAllDrawables(); +std::size_t RenderHeatmapLayer::removeAllDrawables() { + auto removed = RenderLayer::removeAllDrawables(); if (renderTarget) { - stats.drawablesRemoved += renderTarget->getLayerGroup(0)->getDrawableCount(); + const auto count = renderTarget->getLayerGroup(0)->getDrawableCount(); + removed += count; + stats.drawablesRemoved += count; renderTarget->getLayerGroup(0)->clearDrawables(); } + return removed; } namespace { @@ -273,27 +289,6 @@ static const StringIdentity idTexColorRampName = StringIndexer::get("u_color_ram using namespace shaders; -#if MLN_DRAWABLE_RENDERER -void RenderHeatmapLayer::updateLayerTweaker() { - if (renderTarget) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - renderTarget->getLayerGroup(0)->setLayerTweaker(tweaker); - } -} - -void RenderHeatmapLayer::updateLayerTextureTweaker() { - if (layerGroup) { - textureTweaker = std::make_shared(getID(), evaluatedProperties); - textureTweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(textureTweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -324,7 +319,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return; } renderTarget->addLayerGroup(tileLayerGroup, /*replace=*/true); - updateLayerTweaker(); + textureTweaker.reset(); } if (renderTarget->getTexture()->getSize() != size) { @@ -341,14 +336,11 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - textureTweaker->enableOverdrawInspector(overdrawInspector); - } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + tileLayerGroup->addLayerTweaker(layerTweaker); } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); std::unique_ptr heatmapBuilder; constexpr auto renderPass = RenderPass::Translucent; @@ -361,6 +353,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -389,6 +382,10 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, /* .padding = */ {0}}; tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } drawable.mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); }); @@ -397,25 +394,18 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } gfx::VertexAttributeArray heatmapVertexAttrs; + propertiesAsUniforms.clear(); + heatmapVertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); - const auto propertiesAsUniforms_ = - heatmapVertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - - if (!heatmapShaderGroup) { - continue; - } - const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!heatmapShader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL if (const auto& attr = heatmapVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, @@ -441,6 +431,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : heatmapBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + drawable->mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -450,13 +442,20 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, // Set up texture layer group if (!layerGroup) { - auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID()); - if (!layerGroup_) { + if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { + if (textureTweaker) { + layerGroup_->addLayerTweaker(textureTweaker); + } + setLayerGroup(std::move(layerGroup_), changes); + } else { return; } - setLayerGroup(std::move(layerGroup_), changes); - updateLayerTextureTweaker(); } + if (!textureTweaker) { + textureTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(textureTweaker); + } + textureTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); if (!heatmapTextureShader) { heatmapTextureShader = context.getGenericShader(shaders, HeatmapTextureShaderGroupName); @@ -467,6 +466,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } auto* textureLayerGroup = static_cast(layerGroup.get()); + // TODO: Don't rebuild drawables every time textureLayerGroup->clearDrawables(); std::unique_ptr heatmapTextureBuilder; @@ -516,6 +516,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, heatmapTextureBuilder->flush(); for (auto& drawable : heatmapTextureBuilder->clearDrawables()) { + drawable->setLayerTweaker(textureTweaker); textureLayerGroup->addDrawable(std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 4d259fc06..d5c499f11 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -47,11 +47,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); - void updateLayerTextureTweaker(); -#endif // MLN_DRAWABLE_RENDERER - bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, float, @@ -63,10 +58,12 @@ private: #if MLN_DRAWABLE_RENDERER /// Remove all drawables for the tile from the layer group - void removeTile(RenderPass, const OverscaledTileID&) override; + /// @return The number of drawables actually removed. + std::size_t removeTile(RenderPass, const OverscaledTileID&) override; /// Remove all the drawables for tiles - void removeAllDrawables() override; + /// @return The number of drawables actually removed. + std::size_t removeAllDrawables() override; #endif // Paint properties @@ -90,13 +87,9 @@ private: using TextureVertexVector = gfx::VertexVector; std::shared_ptr sharedTextureVertices; - HeatmapLayerTweakerPtr tweaker; - HeatmapTextureLayerTweakerPtr textureTweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; + // This is the layer tweaker for applying the off-screen texture to the framebuffer. + // The inherited layer tweaker is for applying tiles to the off-screen texture. + LayerTweakerPtr textureTweaker; #endif }; diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 04297439c..fbbefb52c 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -73,7 +73,26 @@ void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& paramete properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } + + if (!activatedRenderTargets.empty()) { + auto newTweaker2 = std::make_shared(getID(), evaluatedProperties); + + std::vector groups; + for (const auto& target : activatedRenderTargets) { + if (const auto& group = target->getLayerGroup(0)) { + groups.push_back(group); + } + } + if (groups.empty()) { + prepareLayerTweaker = newTweaker2; + } else { + replaceTweaker(prepareLayerTweaker, std::move(newTweaker2), groups); + } + } #endif } @@ -284,16 +303,6 @@ static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_texture_pos"); static const StringIdentity idTexImageName = StringIndexer::get("u_image"); -#if MLN_DRAWABLE_RENDERER -void RenderHillshadeLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, [[maybe_unused]] const TransformState& state, @@ -309,16 +318,21 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { - auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); - if (!layerGroup_) { + if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { + setLayerGroup(std::move(layerGroup_), changes); + } else { return; } - setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!hillshadePrepareShader) { hillshadePrepareShader = context.getGenericShader(shaders, HillshadePrepareShaderGroupName); } @@ -330,14 +344,6 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - auto renderPass = RenderPass::Translucent; if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { return; @@ -389,11 +395,13 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, if (!singleTileLayerGroup) { return; } - const auto prepareTweaker = std::make_shared(getID(), evaluatedProperties); - prepareTweaker->enableOverdrawInspector(overdrawInspector); - singleTileLayerGroup->setLayerTweaker(prepareTweaker); renderTarget->addLayerGroup(singleTileLayerGroup, /*replace=*/true); + if (!prepareLayerTweaker) { + prepareLayerTweaker = std::make_shared(getID(), evaluatedProperties); + } + singleTileLayerGroup->addLayerTweaker(prepareLayerTweaker); + gfx::VertexAttributeArray hillshadePrepareVertexAttrs; if (const auto& attr = hillshadePrepareVertexAttrs.add(idPosAttribName)) { @@ -437,6 +445,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : hillshadePrepareBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(prepareLayerTweaker); drawable->setData(std::make_unique( bucket.getDEMData().stride, bucket.getDEMData().encoding, maxzoom)); singleTileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -474,31 +483,34 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadeBuilder = context.createDrawableBuilder("hillshade"); - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { - tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - drawable.setVertexAttributes(std::move(hillshadeVertexAttrs)); - drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); + const auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + return; + } + drawable.setVertexAttributes(std::move(hillshadeVertexAttrs)); + drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); - std::vector> drawSegments; - for (std::size_t i = 0; i < segments->size(); ++i) { - const auto& seg = segments->data()[i]; - auto segCopy = SegmentBase{ - // no copy constructor - seg.vertexOffset, - seg.indexOffset, - seg.vertexLength, - seg.indexLength, - seg.sortKey, - }; - drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy))); - } - drawable.setIndexData(indices->vector(), std::move(drawSegments)); + std::vector> drawSegments; + for (std::size_t i = 0; i < segments->size(); ++i) { + const auto& seg = segments->data()[i]; + auto segCopy = SegmentBase{ + // no copy constructor + seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.sortKey, + }; + drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy))); + } + drawable.setIndexData(indices->vector(), std::move(drawSegments)); - auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); - if (imageLocation.has_value()) { - drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); - } - }); + auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); + if (imageLocation.has_value()) { + drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); + } + }; + if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, updateExisting)) { continue; } @@ -521,6 +533,8 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : hillshadeBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp index 050ce023a..97a74b25d 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.hpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp @@ -75,8 +75,7 @@ private: using HillshadeVertexVector = gfx::VertexVector; std::shared_ptr staticDataSharedVertices; - HillshadeLayerTweakerPtr tweaker; - bool overdrawInspector = false; + LayerTweakerPtr prepareLayerTweaker; #endif }; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 2f79b0f76..9da26fd14 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -21,16 +21,6 @@ #include #include -#if MLN_DRAWABLE_RENDERER -#include -#include -#include -#include -#include -#include -#include -#endif - #if MLN_DRAWABLE_RENDERER #include #include @@ -40,6 +30,7 @@ #include #include #include +#include #endif namespace mbgl { @@ -90,7 +81,10 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } #endif } @@ -364,16 +358,6 @@ static const StringIdentity idLineSDFInterpolationUBOName = StringIndexer::get(" /// Evaluated properties that depend on the tile static const StringIdentity idLinePatternTilePropertiesUBOName = StringIndexer::get("LinePatternTilePropertiesUBO"); -void RenderLineLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} static const StringIdentity idLineImageUniformName = StringIndexer::get("u_image"); @@ -390,23 +374,22 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!lineShaderGroup) { lineShaderGroup = shaders.getShaderGroup("LineShader"); } @@ -476,6 +459,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, builder->setSegments(gfx::Triangles(), bucket.sharedTriangles, bucket.segments.data(), bucket.segments.size()); }; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -546,6 +530,11 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // update existing drawables tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + const auto& shader = drawable.getShader(); const auto& shaderUniforms = shader->getUniformBlocks(); auto& drawableUniforms = drawable.mutableUniformBuffers(); @@ -579,31 +568,30 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } if (!evaluated.get().from.empty()) { - // dash array line (SDF) - gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - if (!lineSDFShaderGroup) { continue; } - auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // dash array line (SDF) + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("lineSDF", std::move(shader)); @@ -618,6 +606,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::SDF)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->setData(std::make_unique(cap)); drawable->mutableUniformBuffers().createOrUpdate( idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context); @@ -626,31 +615,27 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, ++stats.drawablesAdded; } } else if (!unevaluated.get().isUndefined()) { - // pattern line - gfx::VertexAttributeArray vertexAttrs; - paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); - auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - if (!linePatternShaderGroup) { continue; } - auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // pattern line + paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); + + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs + .readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("linePattern", std::move(shader)); @@ -679,6 +664,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Pattern)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLinePatternInterpolationUBOName, &linePatternInterpolationUBO, context); drawable->mutableUniformBuffers().createOrUpdate( @@ -689,26 +675,24 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } } } else if (!unevaluated.get().getValue().isUndefined()) { - // gradient line - gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms_ = - vertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); - if (!lineGradientShaderGroup) { continue; } - auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // gradient line + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("lineGradient", std::move(shader)); @@ -736,6 +720,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Gradient)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLineGradientInterpolationUBOName, &lineGradientInterpolationUBO, context); @@ -744,37 +729,26 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } } } - } else { - // simple line - gfx::VertexAttributeArray vertexAttrs; - const auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); - - assert(6 == propertiesAsUniforms_.size()); - assert(vertexAttrs.size() == (size_t)std::count_if(propertiesAsUniforms_.begin(), - propertiesAsUniforms_.end(), - [](const auto& s) { return s.empty(); })); - if (!lineShaderGroup) { continue; } - auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // simple line + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs + .readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("line", std::move(shader)); @@ -787,6 +761,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Simple)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLineInterpolationUBOName, &lineInterpolationUBO, context); diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 78424ff52..7b147bdc1 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -58,9 +58,6 @@ private: #if MLN_LEGACY_RENDERER void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, @@ -97,13 +94,6 @@ private: gfx::ShaderGroupPtr linePatternShaderGroup; gfx::DrawableTweakerPtr iconTweaker; - LineLayerTweakerPtr tweaker; - -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index a3022b59c..a32240fc1 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -53,7 +53,10 @@ void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup, imageLayerGroup}); + } #endif } @@ -247,19 +250,6 @@ static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_textu static const StringIdentity idTexImage0Name = StringIndexer::get("u_image0"); static const StringIdentity idTexImage1Name = StringIndexer::get("u_image1"); -void RenderRasterLayer::updateLayerTweaker() { - if (layerGroup || imageLayerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); - tweaker->enableOverdrawInspector(overdrawInspector); - if (layerGroup) { - layerGroup->setLayerTweaker(tweaker); - } - if (imageLayerGroup) { - imageLayerGroup->setLayerTweaker(tweaker); - } - } -} - void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& /*state*/, @@ -278,22 +268,28 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, return; } - auto renderPass = RenderPass::Translucent; + constexpr auto renderPass = RenderPass::Translucent; if (!rasterShader) { rasterShader = context.getGenericShader(shaders, "RasterShader"); if (!rasterShader) { return; } + rasterSampler0 = rasterShader->getSamplerLocation(idTexImage0Name); + rasterSampler1 = rasterShader->getSamplerLocation(idTexImage1Name); } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + + if (layerGroup) { + layerGroup->addLayerTweaker(layerTweaker); + } + if (imageLayerGroup) { + imageLayerGroup->addLayerTweaker(layerTweaker); } } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); if (!staticDataVertices) { staticDataVertices = std::make_shared(RenderStaticData::rasterVertices()); @@ -305,61 +301,47 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, staticDataSegments = std::make_shared(RenderStaticData::rasterSegments()); } - const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - RasterProgram::Binders paintAttributeData{evaluated, 0}; - - const gfx::TextureFilterType filter = evaluated.get() == RasterResamplingType::Nearest - ? gfx::TextureFilterType::Nearest - : gfx::TextureFilterType::Linear; - - auto createBuilder = [&context, &renderPass, this]() -> std::unique_ptr { - std::unique_ptr builder{context.createDrawableBuilder("raster")}; + const auto createBuilder = [&] { + auto builder = context.createDrawableBuilder("raster"); builder->setShader(rasterShader); builder->setRenderPass(renderPass); builder->setSubLayerIndex(0); - builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setVertexAttrNameId(idPosAttribName); - return builder; }; - auto setTextures = [&context, &filter, this](std::unique_ptr& builder, - const RasterBucket& bucket) { - // textures - auto location0 = rasterShader->getSamplerLocation(idTexImage0Name); - if (location0.has_value()) { - std::shared_ptr tex0 = context.createTexture2D(); - tex0->setImage(bucket.image); - tex0->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - builder->setTexture(tex0, location0.value()); - } - auto location1 = rasterShader->getSamplerLocation(idTexImage1Name); - if (location1.has_value()) { - std::shared_ptr tex1 = context.createTexture2D(); - tex1->setImage(bucket.image); - tex1->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - builder->setTexture(tex1, location1.value()); + const auto setTextures = [&](gfx::UniqueDrawableBuilder& builder, const RasterBucket& bucket) { + if (bucket.image && (rasterSampler0 || rasterSampler1)) { + if (auto tex = context.createTexture2D()) { + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + const bool nearest = evaluated.get() == RasterResamplingType::Nearest; + const auto filter = nearest ? gfx::TextureFilterType::Nearest : gfx::TextureFilterType::Linear; + + tex->setImage(bucket.image); + tex->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + + if (rasterSampler0) { + builder->setTexture(tex, *rasterSampler0); + } + if (rasterSampler1) { + builder->setTexture(std::move(tex), *rasterSampler1); + } + } } }; - auto buildVertexData = [this](std::unique_ptr& builder, const RasterBucket& bucket) { - RasterVertexVectorPtr vertices = staticDataVertices; - TriangleIndexVectorPtr indices = staticDataIndices; - const RasterSegmentVector* segments = staticDataSegments.get(); + // Build vertex attributes and apply them to a drawable or a builder + const auto buildVertexData = + [this](const gfx::UniqueDrawableBuilder& builder, gfx::Drawable* drawable, const RasterBucket& bucket) { + const bool shared = (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()); + const auto& vertices = shared ? bucket.sharedVertices : staticDataVertices; + const auto& indices = shared ? bucket.sharedTriangles : staticDataIndices; + const auto* segments = shared ? &bucket.segments : staticDataSegments.get(); - if (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()) { - vertices = bucket.sharedVertices; - indices = bucket.sharedTriangles; - segments = &bucket.segments; - } - - // attributes - { gfx::VertexAttributeArray vertexAttrs; - if (auto& attr = vertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(vertices, offsetof(RasterLayoutVertex, a1), @@ -376,76 +358,74 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } - builder->setVertexAttributes(std::move(vertexAttrs)); + if (drawable) { + drawable->setVertexAttributes(std::move(vertexAttrs)); + } else if (builder) { + builder->setVertexAttributes(std::move(vertexAttrs)); + builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); + builder->setSegments(gfx::Triangles(), indices, segments->data(), segments->size()); + } + }; + + gfx::UniqueDrawableBuilder builder; + if (imageData) { + // TODO: Can we avoid rebuilding drawables each time in this case as well? + if (imageLayerGroup) { + stats.drawablesRemoved += imageLayerGroup->clearDrawables(); } - builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); - builder->setSegments(gfx::Triangles(), indices, segments->data(), segments->size()); - }; - - auto buildDrawables = [&setTextures, &buildVertexData](std::unique_ptr& builder, - const RasterBucket& bucket) { - buildVertexData(builder, bucket); - setTextures(builder, bucket); - }; - - auto updateTileDrawables = [&](std::unique_ptr& builder, - auto* tileLayerGroup, - const auto& tileID, - const RasterBucket& bucket) { - // TODO: check for oportunity to skip - - buildVertexData(builder, bucket); - tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - for (auto& tex : drawable.getTextures()) { - builder->setTexture(tex.second, tex.first); - } - }); - }; - - if (imageData) { RasterBucket& bucket = *imageData->bucket; if (!bucket.vertices.empty()) { - if (imageLayerGroup) { - stats.drawablesRemoved += imageLayerGroup->clearDrawables(); - } else { + if (!imageLayerGroup) { // Set up a layer group imageLayerGroup = context.createLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); + imageLayerGroup->addLayerTweaker(layerTweaker); activateLayerGroup(imageLayerGroup, isRenderable, changes); - updateLayerTweaker(); } - auto builder = createBuilder(); + // Create a drawable for each transformation + // TODO: Share textures + builder = createBuilder(); for (const auto& matrix_ : imageData->matrices) { - buildDrawables(builder, bucket); + buildVertexData(builder, /*drawable=*/nullptr, bucket); + setTextures(builder, bucket); // finish builder->flush(); for (auto& drawable : builder->clearDrawables()) { drawable->setData(std::make_unique(matrix_)); + drawable->setLayerTweaker(layerTweaker); imageLayerGroup->addDrawable(std::move(drawable)); ++stats.drawablesAdded; } } } } else if (renderTiles) { - if (layerGroup) { - stats.drawablesRemoved += layerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) { - // Has this tile dropped out of the cover set? - return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); + // Update existing drawables, returns the number of drawables found for the tile + const auto updateTileDrawables = [&](auto* tileLayerGroup, const auto& tileID, const RasterBucket& bucket) { + return tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() == layerTweaker) { + gfx::UniqueDrawableBuilder none; + buildVertexData(none, &drawable, bucket); + } }); + }; + + // Remove existing drawables that are no longer in the cover set + if (layerGroup) { + stats.drawablesRemoved += layerGroup->removeDrawablesIf( + [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); } else { // Set up a tile layer group if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { + layerGroup_->addLayerTweaker(layerTweaker); setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); } } auto* tileLayerGroup = static_cast(layerGroup.get()); - auto builder = createBuilder(); for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -455,30 +435,44 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, continue; } + bool cleared = false; const auto& bucket = static_cast(*bucket_); - const auto prevBucketID = getRenderTileBucketID(tileID); - if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { - // This tile was previously set up from a different bucket, drop and re-create any drawables for it. + // If the bucket data has changed, rebuild the drawables. + const bool bucketSharedData = (!bucket.vertices.empty() && !bucket.indices.empty() && + !bucket.segments.empty()); + const bool bucketDirty = bucketSharedData && (bucket.vertices.getDirty() || bucket.indices.getDirty()); + if (bucketDirty) { + // Note, vertex/index dirty flags will be reset when those buffers are uploaded. removeTile(renderPass, tileID); + cleared = true; + } else if (setRenderTileBucketID(tileID, bucket.getID())) { + // Bucket ID changed, we need to rebuild the drawables + removeTile(renderPass, tileID); + cleared = true; } - setRenderTileBucketID(tileID, bucket.getID()); - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { - // re-create drawable geometry and pass texture - updateTileDrawables(builder, tileLayerGroup, tileID, bucket); + // If there are any drawables left for this tile, update them. + if (!cleared && 0 < updateTileDrawables(tileLayerGroup, tileID, bucket)) { + continue; + } - // erase current drawable - removeTile(renderPass, tileID); - } else if (bucket.image) { - // build new drawable for this tile - buildDrawables(builder, bucket); + // Otherwise, create new ones. + if (!builder) { + builder = createBuilder(); + } + + if (bucket.image && builder->getTextures().size() == 0) { + setTextures(builder, bucket); }; + buildVertexData(builder, /*drawable=*/nullptr, bucket); + // finish builder->flush(); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp index 849a3dbc1..361392d82 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.hpp +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -8,11 +8,6 @@ namespace mbgl { -#if MLN_DRAWABLE_RENDERER -class RasterLayerTweaker; -using RasterLayerTweakerPtr = std::shared_ptr; -#endif // MLN_DRAWABLE_RENDERER - class ImageSourceRenderData; class RasterProgram; @@ -60,10 +55,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - // Paint properties style::RasterPaintProperties::Unevaluated unevaluated; const ImageSourceRenderData* imageData = nullptr; @@ -75,6 +66,8 @@ private: #if MLN_DRAWABLE_RENDERER gfx::ShaderProgramBasePtr rasterShader; + std::optional rasterSampler0; + std::optional rasterSampler1; LayerGroupPtr imageLayerGroup; using RasterVertexVector = gfx::VertexVector; @@ -88,9 +81,6 @@ private: using RasterSegmentVector = SegmentVector; using RasterSegmentVectorPtr = std::shared_ptr; std::shared_ptr staticDataSegments; - - RasterLayerTweakerPtr tweaker; - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 3a06160ef..bc8437218 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -379,11 +380,10 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - if (layerGroup && layerGroup->getLayerTweaker()) { -#if MLN_RENDER_BACKEND_METAL - layerGroup->getLayerTweaker()->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - layerGroup->getLayerTweaker()->updateProperties(evaluatedProperties); + // The symbol tweaker supports updating properties. + // When the style changes, it will be replaced in `RenderLayer::layerChanged` + if (layerTweaker) { + layerTweaker->updateProperties(evaluatedProperties); } #endif // MLN_DRAWABLE_RENDERER } @@ -749,19 +749,21 @@ SymbolDrawableTilePropsUBO buildTileUBO(const SymbolBucket& bucket, }; } -static const StringIdentity idDataAttibName = StringIndexer::get("a_data"); -static const StringIdentity idPosOffsetAttribName = StringIndexer::get("a_pos_offset"); -static const StringIdentity idPixOffsetAttribName = StringIndexer::get("a_pixeloffset"); -static const StringIdentity idProjPosAttribName = StringIndexer::get("a_projected_pos"); -static const StringIdentity idFadeOpacityAttribName = StringIndexer::get("a_fade_opacity"); -static const StringIdentity idTexUniformName = StringIndexer::get("u_texture"); -static const StringIdentity idTexIconUniformName = StringIndexer::get("u_texture_icon"); +static const auto idDataAttibName = StringIndexer::get("a_data"); +static const auto posOffsetAttribName = "a_pos_offset"; +static const auto idPosOffsetAttribName = StringIndexer::get(posOffsetAttribName); +static const auto idPixOffsetAttribName = StringIndexer::get("a_pixeloffset"); +static const auto idProjPosAttribName = StringIndexer::get("a_projected_pos"); +static const auto idFadeOpacityAttribName = StringIndexer::get("a_fade_opacity"); +static const auto idTexUniformName = StringIndexer::get("u_texture"); +static const auto idTexIconUniformName = StringIndexer::get("u_texture_icon"); -std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer, - const bool isText, - const SymbolBucket::PaintProperties& paintProps, - const SymbolPaintProperties::PossiblyEvaluated& evaluated, - gfx::VertexAttributeArray& attribs) { +void updateTileAttributes(const SymbolBucket::Buffer& buffer, + const bool isText, + const SymbolBucket::PaintProperties& paintProps, + const SymbolPaintProperties::PossiblyEvaluated& evaluated, + gfx::VertexAttributeArray& attribs, + std::unordered_set& propertiesAsUniforms) { if (const auto& attr = attribs.getOrAdd(idPosOffsetAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a1), @@ -801,13 +803,13 @@ std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer gfx::AttributeDataType::Float); } - return isText - ? attribs - .readDataDrivenPaintProperties( - paintProps.textBinders, evaluated) - : attribs - .readDataDrivenPaintProperties( - paintProps.iconBinders, evaluated); + if (isText) { + attribs.readDataDrivenPaintProperties( + paintProps.textBinders, evaluated, propertiesAsUniforms); + } else { + attribs.readDataDrivenPaintProperties( + paintProps.iconBinders, evaluated, propertiesAsUniforms); + } } void updateTileDrawable(gfx::Drawable& drawable, @@ -817,7 +819,8 @@ void updateTileDrawable(gfx::Drawable& drawable, const SymbolPaintProperties::PossiblyEvaluated& evaluated, const TransformState& state, gfx::UniformBufferPtr& textInterpUBO, - gfx::UniformBufferPtr& iconInterpUBO) { + gfx::UniformBufferPtr& iconInterpUBO, + std::unordered_set& propertiesAsUniforms) { if (!drawable.getData()) { return; } @@ -859,7 +862,7 @@ void updateTileDrawable(gfx::Drawable& drawable, // See `Placement::updateBucketDynamicVertices` gfx::VertexAttributeArray attribs; - updateTileAttributes(buffer, isText, paintProps, evaluated, attribs); + updateTileAttributes(buffer, isText, paintProps, evaluated, attribs, propertiesAsUniforms); drawable.setVertexAttributes(std::move(attribs)); } @@ -970,16 +973,19 @@ void RenderSymbolLayer::layerIndexChanged(int32_t newLayerIndex, UniqueChangeReq changeLayerIndex(collisionTileLayerGroup, newLayerIndex, changes); } -void RenderSymbolLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { +std::size_t RenderSymbolLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + const auto oldValue = stats.drawablesRemoved; if (const auto tileGroup = static_cast(layerGroup.get())) { stats.drawablesRemoved += tileGroup->removeDrawables(renderPass, tileID).size(); } if (collisionTileLayerGroup) { stats.drawablesRemoved += collisionTileLayerGroup->removeDrawables(renderPass, tileID).size(); } + return stats.drawablesRemoved - oldValue; } -void RenderSymbolLayer::removeAllDrawables() { +std::size_t RenderSymbolLayer::removeAllDrawables() { + const auto oldValue = stats.drawablesRemoved; if (layerGroup) { stats.drawablesRemoved += layerGroup->getDrawableCount(); layerGroup->clearDrawables(); @@ -988,12 +994,13 @@ void RenderSymbolLayer::removeAllDrawables() { stats.drawablesRemoved += collisionTileLayerGroup->getDrawableCount(); collisionTileLayerGroup->clearDrawables(); } + return stats.drawablesRemoved - oldValue; } void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, const RenderTree& /*renderTree*/, UniqueChangeRequestVec& changes) { if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { @@ -1004,24 +1011,27 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - layerGroup_->setLayerTweaker(tweaker); setLayerGroup(std::move(layerGroup_), changes); } } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + const auto& getCollisionTileLayerGroup = [&] { if (!collisionTileLayerGroup) { if ((collisionTileLayerGroup = context.createTileLayerGroup( layerIndex, /*initialCapacity=*/64, getID() + "-collision"))) { - collisionTileLayerGroup->setLayerTweaker( - std::make_shared(getID(), evaluatedProperties)); activateLayerGroup(collisionTileLayerGroup, true, changes); } } + if (!collisionLayerTweaker) { + collisionLayerTweaker = std::make_shared(getID(), evaluatedProperties); + collisionTileLayerGroup->addLayerTweaker(collisionLayerTweaker); + } return collisionTileLayerGroup; }; @@ -1079,6 +1089,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, collisionBuilder->setColorMode(gfx::ColorMode::alphaBlended()); collisionBuilder->setVertexAttrNameId(idCollisionPosAttribName); + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -1168,6 +1179,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // add drawables to layer group for (auto& drawable : collisionBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(collisionLayerTweaker); + auto drawData = std::make_unique(values.translate, values.translateAnchor); drawable->setData(std::move(drawData)); group->addDrawable(passes, tileID, std::move(drawable)); @@ -1181,9 +1194,22 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // Just update the drawables we already created tileLayerGroup->visitDrawables(passes, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + const auto& evaluated = getEvaluated(renderData.layerProperties); - updateTileDrawable( - drawable, context, bucket, bucketPaintProperties, evaluated, state, textInterpUBO, iconInterpUBO); + propertiesAsUniforms.clear(); + updateTileDrawable(drawable, + context, + bucket, + bucketPaintProperties, + evaluated, + state, + textInterpUBO, + iconInterpUBO, + propertiesAsUniforms); }); // re-create collision drawables @@ -1263,15 +1289,12 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto vertexCount = buffer.vertices().elements(); + propertiesAsUniforms.clear(); gfx::VertexAttributeArray attribs; - const auto uniformProps = updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs); - -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = uniformProps; - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs, propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL const auto textHalo = evaluated.get().constantOr(Color::black()).a > 0.0f && evaluated.get().constantOr(1); @@ -1341,7 +1364,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, return; } const auto shader = std::static_pointer_cast( - shaderGroup->getOrCreateShader(context, uniformProps, StringIndexer::get(idPosOffsetAttribName))); + shaderGroup->getOrCreateShader(context, propertiesAsUniforms, posOffsetAttribName)); if (!shader) { return; } @@ -1359,6 +1382,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto drawData = std::make_unique( /*.isHalo=*/isHalo, diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp index c391d266b..a1e483313 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.hpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -118,10 +118,10 @@ protected: void layerRemoved(UniqueChangeRequestVec&) override; /// Remove all drawables for the tile from the layer group - void removeTile(RenderPass, const OverscaledTileID&) override; + std::size_t removeTile(RenderPass, const OverscaledTileID&) override; /// Remove all the drawables for tiles - void removeAllDrawables() override; + std::size_t removeAllDrawables() override; #endif // MLN_DRAWABLE_RENDERER private: @@ -151,8 +151,6 @@ private: #endif // MLN_LEGACY_RENDERER #if MLN_DRAWABLE_RENDERER - SymbolLayerTweakerPtr tweaker; - gfx::ShaderGroupPtr symbolIconGroup; gfx::ShaderGroupPtr symbolSDFGroup; gfx::ShaderGroupPtr symbolTextAndIconGroup; @@ -160,11 +158,9 @@ private: gfx::ShaderGroupPtr collisionBoxGroup; gfx::ShaderGroupPtr collisionCircleGroup; std::shared_ptr collisionTileLayerGroup; -#endif // MLN_DRAWABLE_RENDERER -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL + LayerTweakerPtr collisionLayerTweaker; +#endif // MLN_DRAWABLE_RENDERER }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index a7b7f16bf..204cffe58 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -19,6 +19,7 @@ #if MLN_RENDER_BACKEND_METAL #include +#include #endif // MLN_RENDER_BACKEND_METAL namespace mbgl { @@ -92,11 +93,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, #if MLN_RENDER_BACKEND_METAL if (propertiesChanged) { const SymbolPermutationUBO permutationUBO = { - /* .fill_color = */ {/*.source=*/getAttributeSource("a_fill_color"), /*.expression=*/{}}, - /* .halo_color = */ {/*.source=*/getAttributeSource("a_halo_color"), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/getAttributeSource("a_opacity"), /*.expression=*/{}}, - /* .halo_width = */ {/*.source=*/getAttributeSource("a_halo_width"), /*.expression=*/{}}, - /* .halo_blur = */ {/*.source=*/getAttributeSource("a_halo_blur"), /*.expression=*/{}}, + /* .fill_color = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .halo_color = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, + /* .halo_width = */ {/*.source=*/getAttributeSource(8), /*.expression=*/{}}, + /* .halo_blur = */ {/*.source=*/getAttributeSource(9), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -116,6 +117,12 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, } #endif + if (propertiesUpdated) { + textPropertiesUpdated = true; + iconPropertiesUpdated = true; + propertiesUpdated = false; + } + layerGroup.visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !drawable.getData()) { return; @@ -125,14 +132,15 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& symbolData = static_cast(*drawable.getData()); const auto isText = (symbolData.symbolType == SymbolType::Text); - if (isText && (!textPaintBuffer || propertiesUpdated)) { + if (isText && (textPaintBuffer || textPropertiesUpdated)) { const auto props = buildPaintUBO(true, evaluated); textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); - } else if (!isText && (!iconPaintBuffer || propertiesUpdated)) { + textPropertiesUpdated = false; + } else if (!isText && (!iconPaintBuffer || iconPropertiesUpdated)) { const auto props = buildPaintUBO(false, evaluated); iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); + iconPropertiesUpdated = false; } - propertiesUpdated = false; // from RenderTile::translatedMatrix const auto translate = isText ? evaluated.get() : evaluated.get(); diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp index 97098d99f..a632da3ff 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp @@ -30,6 +30,9 @@ private: gfx::UniformBufferPtr textPaintBuffer; gfx::UniformBufferPtr iconPaintBuffer; + bool textPropertiesUpdated = false; + bool iconPropertiesUpdated = false; + #if MLN_RENDER_BACKEND_METAL gfx::UniformBufferPtr permutationUniformBuffer; gfx::UniformBufferPtr expressionUniformBuffer; diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index ea974117b..4311bcb11 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -70,11 +70,41 @@ std::optional RenderLayer::getSolidBackground() const { } #if MLN_DRAWABLE_RENDERER +void RenderLayer::replaceTweaker(LayerTweakerPtr& curTweaker, + LayerTweakerPtr newTweaker, + const std::vector& layerGroups) { + const auto prevTweaker = curTweaker; + + // We need to re-create the tweaker because it doesn't yet support modifying evaluated + // properties, but we don't want to stop updating drawables (as in the `layerChanged` case) + // so we need to update the tweaker reference on the outstanding drawables so that they + // pass the check in `updateExisting`. + // TODO: Once the tweaker doesn't need to be re-created on each property evaluation, this won't be needed. + for (const auto& group : layerGroups) { + if (group) { + group->addLayerTweaker(newTweaker); + + group->visitDrawables([&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() == prevTweaker) { + drawable.setLayerTweaker(curTweaker); + } + }); + } + } + + curTweaker = std::move(newTweaker); +} + void RenderLayer::layerChanged(const TransitionParameters&, const Immutable&, UniqueChangeRequestVec&) { // When a layer changes, the bucket won't be replaced until the new source(s) load. // If we remove the drawables here, they will just be re-created based on the current data. + + // Detach the layer tweaker, if any. This keeps the existing tiles up-to-date with the + // most recent evaluated properties, while a new one will be created along with new drawables + // when tiles are loaded and new buckets are available. + layerTweaker.reset(); } void RenderLayer::layerRemoved(UniqueChangeRequestVec& changes) { @@ -136,17 +166,23 @@ const LayerRenderData* RenderLayer::getRenderDataForPass(const RenderTile& tile, } #if MLN_DRAWABLE_RENDERER -void RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { +std::size_t RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { if (const auto tileGroup = static_cast(layerGroup.get())) { - stats.drawablesRemoved += tileGroup->removeDrawables(renderPass, tileID).size(); + const auto n = tileGroup->removeDrawables(renderPass, tileID).size(); + stats.drawablesRemoved += n; + return n; } + return 0; } -void RenderLayer::removeAllDrawables() { +std::size_t RenderLayer::removeAllDrawables() { if (layerGroup) { - stats.drawablesRemoved += layerGroup->getDrawableCount(); + const auto count = layerGroup->getDrawableCount(); + stats.drawablesRemoved += count; layerGroup->clearDrawables(); + return count; } + return 0; } void RenderLayer::updateRenderTileIDs() { diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 020576462..6ad7b0b02 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -211,10 +211,11 @@ protected: void changeLayerIndex(const LayerGroupBasePtr&, int32_t newLayerIndex, UniqueChangeRequestVec&); /// Remove all drawables for the tile from the layer group - virtual void removeTile(RenderPass, const OverscaledTileID&); + /// @return The number of drawables actually removed. + virtual std::size_t removeTile(RenderPass, const OverscaledTileID&); /// Remove all the drawables for tiles - virtual void removeAllDrawables(); + virtual std::size_t removeAllDrawables(); /// Update `renderTileIDs` from `renderTiles` void updateRenderTileIDs(); @@ -233,6 +234,12 @@ protected: /// @return true if updated, false if the tile ID is not present in the set of tiles to be rendered or the ID is /// unchanged bool setRenderTileBucketID(const OverscaledTileID&, util::SimpleIdentity bucketID); + + /// Update the layer tweaker and drawables which reference it + static void replaceTweaker(LayerTweakerPtr& toReplace, + LayerTweakerPtr newTweaker, + const std::vector&); + #endif // MLN_DRAWABLE_RENDERER static bool applyColorRamp(const style::ColorRampPropertyValue&, PremultipliedImage&); @@ -251,6 +258,9 @@ protected: // will need to be overriden to handle their activation. LayerGroupBasePtr layerGroup; + // An optional tweaker that will update drawables + LayerTweakerPtr layerTweaker; + // The set of Tile IDs in `renderTiles`, along with the // identity of the bucket from which they were built. std::unordered_map renderTileIDs; diff --git a/src/mbgl/renderer/render_target.cpp b/src/mbgl/renderer/render_target.cpp index 924dae958..4d707d13e 100644 --- a/src/mbgl/renderer/render_target.cpp +++ b/src/mbgl/renderer/render_target.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mbgl { @@ -84,11 +85,7 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re "render target", {*offscreenTexture, Color{0.0f, 0.0f, 0.0f, 1.0f}, {}, {}}); // Run layer tweakers to update any dynamic elements - visitLayerGroups([&](LayerGroupBase& layerGroup) { - if (layerGroup.getLayerTweaker()) { - layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters); - } - }); + visitLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); // draw layer groups, opaque pass parameters.pass = RenderPass::Opaque; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index bf6c2df29..c917bdf69 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -152,11 +152,8 @@ void Renderer::Impl::render(const RenderTree& renderTree, #endif // Tweakers are run in the upload pass so they can set up uniforms. - orchestrator.visitLayerGroups([&](LayerGroupBase& layerGroup) { - if (layerGroup.getLayerTweaker()) { - layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters); - } - }); + orchestrator.visitLayerGroups( + [&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); } // Update the debug layer groups diff --git a/src/mbgl/shaders/mtl/background.cpp b/src/mbgl/shaders/mtl/background.cpp new file mode 100644 index 000000000..9eec3d3c1 --- /dev/null +++ b/src/mbgl/shaders/mtl/background.cpp @@ -0,0 +1,17 @@ +#include +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{1, true, true, sizeof(BackgroundLayerUBO), "BackgroundLayerUBO"}, + UniformBlockInfo{2, true, false, sizeof(BackgroundDrawableUBO), "BackgroundDrawableUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/background_pattern.cpp b/src/mbgl/shaders/mtl/background_pattern.cpp new file mode 100644 index 000000000..fa173422d --- /dev/null +++ b/src/mbgl/shaders/mtl/background_pattern.cpp @@ -0,0 +1,14 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"}, + UniformBlockInfo{2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"}, + UniformBlockInfo{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/circle.cpp b/src/mbgl/shaders/mtl/circle.cpp new file mode 100644 index 000000000..cdf6c06cf --- /dev/null +++ b/src/mbgl/shaders/mtl/circle.cpp @@ -0,0 +1,27 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"}, + AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, false, sizeof(CircleDrawableUBO), "CircleDrawableUBO"}, + UniformBlockInfo{9, true, true, sizeof(CirclePaintParamsUBO), "CirclePaintParamsUBO"}, + UniformBlockInfo{10, true, true, sizeof(CircleEvaluatedPropsUBO), "CircleEvaluatedPropsUBO"}, + UniformBlockInfo{11, true, false, sizeof(CircleInterpolateUBO), "CircleInterpolateUBO"}, + UniformBlockInfo{12, true, true, sizeof(CirclePermutationUBO), "CirclePermutationUBO"}, + UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/clipping_mask.cpp b/src/mbgl/shaders/mtl/clipping_mask.cpp new file mode 100644 index 000000000..9cd391a1e --- /dev/null +++ b/src/mbgl/shaders/mtl/clipping_mask.cpp @@ -0,0 +1,16 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{1, true, false, sizeof(ClipUBO), "ClipUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill.cpp b/src/mbgl/shaders/mtl/fill.cpp new file mode 100644 index 000000000..448a8786d --- /dev/null +++ b/src/mbgl/shaders/mtl/fill.cpp @@ -0,0 +1,82 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + + // This shader doesn't use it, but we need this so that the layer can assign the same + // attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it, + // this can be removed. + AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(FillDrawableUBO), "FillDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(FillEvaluatedPropsUBO), "FillEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillInterpolateUBO), "FillInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillPermutationUBO), "FillPermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + + // See `a_outline_color` in FillShader + AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_color"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(FillOutlineDrawableUBO), "FillOutlineDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(FillOutlineEvaluatedPropsUBO), "FillOutlineEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillOutlineInterpolateUBO), "FillOutlineInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillOutlinePermutationUBO), "FillOutlinePermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{4, true, true, sizeof(FillPatternDrawableUBO), "FillPatternDrawableUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillPatternTilePropsUBO), "FillPatternTilePropsUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillPatternEvaluatedPropsUBO), "FillPatternEvaluatedPropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillPatternInterpolateUBO), "FillPatternInterpolateUBO"}, + UniformBlockInfo{8, true, true, sizeof(FillPatternPermutationUBO), "FillPatternPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +const std::array + ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{4, true, true, sizeof(FillOutlinePatternDrawableUBO), "FillOutlinePatternDrawableUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillOutlinePatternTilePropsUBO), "FillOutlinePatternTilePropsUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillOutlinePatternEvaluatedPropsUBO), "FillOutlinePatternEvaluatedPropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillOutlinePatternInterpolateUBO), "FillOutlinePatternInterpolateUBO"}, + UniformBlockInfo{8, true, true, sizeof(FillOutlinePatternPermutationUBO), "FillOutlinePatternPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = + { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill_extrusion.cpp b/src/mbgl/shaders/mtl/fill_extrusion.cpp new file mode 100644 index 000000000..a320f95e8 --- /dev/null +++ b/src/mbgl/shaders/mtl/fill_extrusion.cpp @@ -0,0 +1,24 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"}, + AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"}, + AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_base"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_height"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{5, true, false, sizeof(FillExtrusionDrawableUBO), "FillExtrusionDrawableUBO"}, + UniformBlockInfo{6, true, false, sizeof(FillExtrusionDrawablePropsUBO), "FillExtrusionDrawablePropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillExtrusionInterpolateUBO), "FillExtrusionInterpolateUBO"}, + UniformBlockInfo{8, true, false, sizeof(FillExtrusionPermutationUBO), "FillExtrusionPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp b/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp new file mode 100644 index 000000000..70e90f5f9 --- /dev/null +++ b/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp @@ -0,0 +1,14 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = {}; +const std::array + ShaderSource::uniforms = {}; +const std::array + ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/heatmap.cpp b/src/mbgl/shaders/mtl/heatmap.cpp new file mode 100644 index 000000000..b6a42f3f4 --- /dev/null +++ b/src/mbgl/shaders/mtl/heatmap.cpp @@ -0,0 +1,21 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_weight"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(HeatmapDrawableUBO), "HeatmapDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(HeatmapEvaluatedPropsUBO), "HeatmapEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(HeatmapInterpolateUBO), "HeatmapInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(HeatmapPermutationUBO), "HeatmapPermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/heatmap_texture.cpp b/src/mbgl/shaders/mtl/heatmap_texture.cpp new file mode 100644 index 000000000..6d9546363 --- /dev/null +++ b/src/mbgl/shaders/mtl/heatmap_texture.cpp @@ -0,0 +1,20 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = + { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{1, true, true, sizeof(HeatmapTextureDrawableUBO), "HeatmapTextureDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, + TextureInfo{1, "u_color_ramp"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/hillshade.cpp b/src/mbgl/shaders/mtl/hillshade.cpp new file mode 100644 index 000000000..a7b0f32a5 --- /dev/null +++ b/src/mbgl/shaders/mtl/hillshade.cpp @@ -0,0 +1,19 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(HillshadeDrawableUBO), "HillshadeDrawableUBO"}, + UniformBlockInfo{3, false, true, sizeof(HillshadeEvaluatedPropsUBO), "HillshadeEvaluatedPropsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/hillshade_prepare.cpp b/src/mbgl/shaders/mtl/hillshade_prepare.cpp new file mode 100644 index 000000000..6ae470498 --- /dev/null +++ b/src/mbgl/shaders/mtl/hillshade_prepare.cpp @@ -0,0 +1,20 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(HillshadePrepareDrawableUBO), "HillshadePrepareDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/line.cpp b/src/mbgl/shaders/mtl/line.cpp new file mode 100644 index 000000000..514cf2f55 --- /dev/null +++ b/src/mbgl/shaders/mtl/line.cpp @@ -0,0 +1,49 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_width"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, true, sizeof(LineUBO), "LineUBO"}, + UniformBlockInfo{9, true, false, sizeof(LinePropertiesUBO), "LinePropertiesUBO"}, + UniformBlockInfo{10, true, false, sizeof(LineInterpolationUBO), "LineInterpolationUBO"}, + UniformBlockInfo{11, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{12, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"}, + AttributeInfo{7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{9, true, true, sizeof(LinePatternUBO), "LinePatternUBO"}, + UniformBlockInfo{10, true, false, sizeof(LinePatternPropertiesUBO), "LinePatternPropertiesUBO"}, + UniformBlockInfo{11, true, false, sizeof(LinePatternInterpolationUBO), "LinePatternInterpolationUBO"}, + UniformBlockInfo{12, true, false, sizeof(LinePatternTilePropertiesUBO), "LinePatternTilePropertiesUBO"}, + UniformBlockInfo{13, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/line_gradient.cpp b/src/mbgl/shaders/mtl/line_gradient.cpp new file mode 100644 index 000000000..fc980003e --- /dev/null +++ b/src/mbgl/shaders/mtl/line_gradient.cpp @@ -0,0 +1,27 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{7, true, true, sizeof(LineGradientUBO), "LineGradientUBO"}, + UniformBlockInfo{8, true, false, sizeof(LineGradientPropertiesUBO), "LineGradientPropertiesUBO"}, + UniformBlockInfo{9, true, false, sizeof(LineGradientInterpolationUBO), "LineGradientInterpolationUBO"}, + UniformBlockInfo{10, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{11, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/raster.cpp b/src/mbgl/shaders/mtl/raster.cpp new file mode 100644 index 000000000..c0ba80422 --- /dev/null +++ b/src/mbgl/shaders/mtl/raster.cpp @@ -0,0 +1,19 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(RasterDrawableUBO), "RasterDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image0"}, + TextureInfo{1, "u_image1"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/shader_program.cpp b/src/mbgl/shaders/mtl/shader_program.cpp index bb07378ae..545b9c75e 100644 --- a/src/mbgl/shaders/mtl/shader_program.cpp +++ b/src/mbgl/shaders/mtl/shader_program.cpp @@ -22,8 +22,32 @@ using namespace std::string_literals; namespace mbgl { -namespace mtl { +shaders::AttributeInfo::AttributeInfo(std::size_t index_, + gfx::AttributeDataType dataType_, + std::size_t count_, + std::string_view name_) + : index(index_), + dataType(dataType_), + count(count_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +shaders::UniformBlockInfo::UniformBlockInfo( + std::size_t index_, bool vertex_, bool fragment_, std::size_t size_, std::string_view name_) + : index(index_), + vertex(vertex_), + fragment(fragment_), + size(size_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +shaders::TextureInfo::TextureInfo(std::size_t index_, std::string_view name_) + : index(index_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +namespace mtl { namespace { MTL::BlendOperation metalBlendOperation(const gfx::ColorBlendEquationType& colorBlend) { switch (colorBlend) { diff --git a/src/mbgl/shaders/mtl/symbol_icon.cpp b/src/mbgl/shaders/mtl/symbol_icon.cpp new file mode 100644 index 000000000..7a2b8242e --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_icon.cpp @@ -0,0 +1,30 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, + AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{5, gfx::AttributeDataType::Float, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{9, true, true, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{10, true, false, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{11, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{12, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/symbol_sdf.cpp b/src/mbgl/shaders/mtl/symbol_sdf.cpp new file mode 100644 index 000000000..b1cf6d428 --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_sdf.cpp @@ -0,0 +1,36 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = + { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, + AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, + AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_opacity"}, + AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_width"}, + AttributeInfo{9, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{10, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{11, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{12, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{13, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{14, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{15, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp b/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp new file mode 100644 index 000000000..d735e1862 --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp @@ -0,0 +1,36 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{4, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float, 1, "a_opacity"}, + AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_halo_width"}, + AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{9, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{10, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{11, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{12, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{13, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, + TextureInfo{1, "u_texture_icon"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/util/hash.hpp b/src/mbgl/util/hash.hpp index cb92fe9be..299d018dd 100644 --- a/src/mbgl/util/hash.hpp +++ b/src/mbgl/util/hash.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace mbgl { namespace util { @@ -19,5 +20,24 @@ std::size_t hash(Args&&... args) { return seed; } +namespace detail { +template +using TIterVal = std::enable_if_t::value, typename TIter::value_type>; +} // namespace detail + +/// Generate a hash key from a collection of integer values which doesn't depend on their order. +/// Adapted from https://stackoverflow.com/a/76993810/135138 +/// Default factor prime value from 64-bit FNV hash. +template , TKey factor = 1099511628211LL> +TKey order_independent_hash(TIter cur, const TIter end) { + detail::TIterVal sum = 0, product = 1; + for (; cur != end; ++cur) { + const auto& value = *cur; + sum += value; + product *= (1 + value) * factor; + } + return sum ^ product; +} + } // namespace util } // namespace mbgl diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c12e11f13..bad61b04c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -88,6 +88,7 @@ add_library( ${PROJECT_SOURCE_DIR}/test/util/dtoa.test.cpp ${PROJECT_SOURCE_DIR}/test/util/geo.test.cpp ${PROJECT_SOURCE_DIR}/test/util/grid_index.test.cpp + ${PROJECT_SOURCE_DIR}/test/util/hash.test.cpp ${PROJECT_SOURCE_DIR}/test/util/http_timeout.test.cpp ${PROJECT_SOURCE_DIR}/test/util/image.test.cpp ${PROJECT_SOURCE_DIR}/test/util/mapbox.test.cpp @@ -236,4 +237,4 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux) mbgl-test PRIVATE USE_CPP_TEST_SERVER ) -endif() \ No newline at end of file +endif() diff --git a/test/util/hash.test.cpp b/test/util/hash.test.cpp new file mode 100644 index 000000000..203dacd39 --- /dev/null +++ b/test/util/hash.test.cpp @@ -0,0 +1,54 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace mbgl; + +TEST(OrderIndependentHash, Permutations) { + // Try collections of up to this many elements + constexpr int maxSize = 6; + // Try this many different sets of values for each size + constexpr int iterations = 10; + // Use values up to this large + constexpr size_t maxVal = 10; + + std::seed_seq seed{0xf00dLL}; + std::default_random_engine engine(seed); + std::uniform_int_distribution distribution(0, maxVal); + + for (int curSize = 1; curSize <= maxSize; ++curSize) { + for (int ii = 0; ii < iterations; ++ii) { + // Generate `curSize` random values + std::vector values; + for (int jj = 0; jj < curSize; ++jj) { + values.push_back(distribution(engine)); + } + + // Generate the hash for each permutation, comparing subsequent values to the first one. + bool isFirst = true; + size_t initialValue = 0; + do { + const auto curValue = util::order_independent_hash(values.begin(), values.end()); + if (isFirst || curValue != initialValue) { + for (auto v : values) { + std::cout << v << ","; + } + std::cout << " - " << std::hex << curValue << std::endl; + } + if (isFirst) { + initialValue = curValue; + isFirst = false; + } else { + EXPECT_EQ(initialValue, curValue); + } + } while (std::next_permutation(values.begin(), values.end())); + } + } +} From a671de64de1def4580c82910d852b3f11d6ef456 Mon Sep 17 00:00:00 2001 From: Stefan Karschti Date: Fri, 29 Sep 2023 16:56:40 +0300 Subject: [PATCH 04/19] Add 10x Test Shapes (annotations) + MBXFrameTimeGraphView update (#1689) --- platform/ios/app/MBXFrameTimeGraphView.m | 24 +-- platform/ios/app/MBXViewController.m | 200 ++++++++++++----------- 2 files changed, 117 insertions(+), 107 deletions(-) diff --git a/platform/ios/app/MBXFrameTimeGraphView.m b/platform/ios/app/MBXFrameTimeGraphView.m index e881eb9f4..4efb1d542 100644 --- a/platform/ios/app/MBXFrameTimeGraphView.m +++ b/platform/ios/app/MBXFrameTimeGraphView.m @@ -1,6 +1,6 @@ #import "MBXFrameTimeGraphView.h" -const CGFloat MBXFrameTimeExaggeration = 4.f * 1000.f; +const CGFloat MBXFrameTimeExaggeration = 10.f; const CGFloat MBXFrameTimeBarWidth = 4.f; @interface MBXFrameTimeGraphView () @@ -58,7 +58,7 @@ const CGFloat MBXFrameTimeBarWidth = 4.f; if (!CGRectEqualToRect(self.scrollLayer.frame, self.bounds)) { self.scrollLayer.frame = self.bounds; - CGRect thresholdLineRect = CGRectMake(0, self.frame.size.height - [self renderDurationTargetMilliseconds], self.frame.size.width, 1); + CGRect thresholdLineRect = CGRectMake(0, self.frame.size.height - self.frame.size.height * MBXFrameTimeExaggeration * [self renderDurationTargetMilliseconds], self.frame.size.width, 1); { CGPathRef path = CGPathCreateWithRect(thresholdLineRect, nil); @@ -96,8 +96,8 @@ const CGFloat MBXFrameTimeBarWidth = 4.f; maximumFramesPerSecond = 60; } - CGFloat target = (1.0 / maximumFramesPerSecond) * MBXFrameTimeExaggeration; - return [self roundedFloat:target]; + CGFloat target = (1.0 / maximumFramesPerSecond); + return target; } - (CGFloat)roundedFloat:(CGFloat)f { @@ -112,7 +112,7 @@ const CGFloat MBXFrameTimeBarWidth = 4.f; - (CAShapeLayer *)barWithFrameDuration:(CFTimeInterval)frameDuration { CAShapeLayer *bar = [CAShapeLayer layer]; - CGRect barRect = CGRectMake(0, 0, MBXFrameTimeBarWidth, -(fminf(frameDuration * MBXFrameTimeExaggeration, self.frame.size.height))); + CGRect barRect = CGRectMake(0, 0, MBXFrameTimeBarWidth, -(fminf(frameDuration * MBXFrameTimeExaggeration * self.frame.size.height, self.frame.size.height))); UIBezierPath *barPath = [UIBezierPath bezierPathWithRect:barRect]; bar.path = barPath.CGPath; bar.fillColor = [self colorForFrameDuration:frameDuration].CGColor; @@ -121,15 +121,15 @@ const CGFloat MBXFrameTimeBarWidth = 4.f; } - (UIColor *)colorForFrameDuration:(CFTimeInterval)frameDuration { - CGFloat renderDurationTargetMilliseconds = [self renderDurationTargetMilliseconds]; - frameDuration *= MBXFrameTimeExaggeration; + const double greenLevel = [self renderDurationTargetMilliseconds]; + const double yellowLevel = greenLevel * 3.0; - if (frameDuration < renderDurationTargetMilliseconds && frameDuration > (renderDurationTargetMilliseconds * 0.75)) { - return self.warningColor; - } else if (frameDuration > renderDurationTargetMilliseconds) { - return self.dangerColor; - } else { + if (frameDuration <= greenLevel) { return self.safeColor; + } else if (frameDuration <= yellowLevel) { + return self.warningColor; + } else { + return self.dangerColor; } } diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 0b57ed0de..9ec99f894 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -69,6 +69,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsAnnotationsRows) { MBXSettingsAnnotations10000Sprites, MBXSettingsAnnotationAnimation, MBXSettingsAnnotationsTestShapes, + MBXSettingsAnnotationsManyTestShapes, MBXSettingsAnnotationsCustomCallout, MBXSettingsAnnotationsQueryAnnotations, MBXSettingsAnnotationsCustomUserDot, @@ -400,6 +401,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { @"Add 10,000 Sprites", @"Animate an Annotation View", @"Add Test Shapes", + @"Add 10x Test Shapes", @"Add Point With Custom Callout", @"Query Annotations", [NSString stringWithFormat:@"%@ Custom User Dot", (_customUserLocationAnnnotationEnabled ? @"Disable" : @"Enable")], @@ -548,7 +550,10 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { [self animateAnnotationView]; break; case MBXSettingsAnnotationsTestShapes: - [self addTestShapes]; + [self addTestShapes:1]; + break; + case MBXSettingsAnnotationsManyTestShapes: + [self addTestShapes:10]; break; case MBXSettingsAnnotationsCustomCallout: [self addAnnotationWithCustomCallout]; @@ -881,102 +886,107 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { }); }; -- (void)addTestShapes +- (void)addTestShapes:(NSUInteger)featuresCount { - // Pacific Northwest triangle - // - CLLocationCoordinate2D triangleCoordinates[3] = - { - CLLocationCoordinate2DMake(44, -122), - CLLocationCoordinate2DMake(46, -122), - CLLocationCoordinate2DMake(46, -121) - }; - - MLNPolygon *triangle = [MLNPolygon polygonWithCoordinates:triangleCoordinates count:3]; - - [self.mapView addAnnotation:triangle]; - - // West coast polyline - // - CLLocationCoordinate2D lineCoordinates[4] = { - CLLocationCoordinate2DMake(47.6025, -122.3327), - CLLocationCoordinate2DMake(45.5189, -122.6726), - CLLocationCoordinate2DMake(37.7790, -122.4177), - CLLocationCoordinate2DMake(34.0532, -118.2349) - }; - MLNPolyline *line = [MLNPolyline polylineWithCoordinates:lineCoordinates count:4]; - [self.mapView addAnnotation:line]; - - // Orcas Island, WA hike polyline - // - NSDictionary *hike = [NSJSONSerialization JSONObjectWithData: - [NSData dataWithContentsOfFile: - [[NSBundle mainBundle] pathForResource:@"polyline" ofType:@"geojson"]] - options:0 - error:nil]; - - NSArray *hikeCoordinatePairs = hike[@"features"][0][@"geometry"][@"coordinates"]; - - CLLocationCoordinate2D *polylineCoordinates = (CLLocationCoordinate2D *)malloc([hikeCoordinatePairs count] * sizeof(CLLocationCoordinate2D)); - - for (NSUInteger i = 0; i < [hikeCoordinatePairs count]; i++) - { - polylineCoordinates[i] = CLLocationCoordinate2DMake([hikeCoordinatePairs[i][1] doubleValue], [hikeCoordinatePairs[i][0] doubleValue]); - } - - MLNPolyline *polyline = [MLNPolyline polylineWithCoordinates:polylineCoordinates - count:[hikeCoordinatePairs count]]; - - [self.mapView addAnnotation:polyline]; - - free(polylineCoordinates); - - // PA/NJ/DE polygons - // - NSDictionary *threestates = [NSJSONSerialization JSONObjectWithData: - [NSData dataWithContentsOfFile: - [[NSBundle mainBundle] pathForResource:@"threestates" ofType:@"geojson"]] - options:0 - error:nil]; - - for (NSDictionary *feature in threestates[@"features"]) - { - NSArray *stateCoordinatePairs = feature[@"geometry"][@"coordinates"]; - - while ([stateCoordinatePairs count] == 1) stateCoordinatePairs = stateCoordinatePairs[0]; - - CLLocationCoordinate2D *polygonCoordinates = (CLLocationCoordinate2D *)malloc([stateCoordinatePairs count] * sizeof(CLLocationCoordinate2D)); - - for (NSUInteger i = 0; i < [stateCoordinatePairs count]; i++) + for (int featureIndex = 0; featureIndex < featuresCount; ++featureIndex) { + double deltaLongitude = featureIndex * 0.01; + double deltaLatitude = -featureIndex * 0.01; + + // Pacific Northwest triangle + // + CLLocationCoordinate2D triangleCoordinates[3] = { - polygonCoordinates[i] = CLLocationCoordinate2DMake([stateCoordinatePairs[i][1] doubleValue], [stateCoordinatePairs[i][0] doubleValue]); + CLLocationCoordinate2DMake(44 + deltaLatitude, -122 + deltaLongitude), + CLLocationCoordinate2DMake(46 + deltaLatitude, -122 + deltaLongitude), + CLLocationCoordinate2DMake(46 + deltaLatitude, -121 + deltaLongitude) + }; + + MLNPolygon *triangle = [MLNPolygon polygonWithCoordinates:triangleCoordinates count:3]; + + [self.mapView addAnnotation:triangle]; + + // West coast polyline + // + CLLocationCoordinate2D lineCoordinates[4] = { + CLLocationCoordinate2DMake(47.6025 + deltaLatitude, -122.3327 + deltaLongitude), + CLLocationCoordinate2DMake(45.5189 + deltaLatitude, -122.6726 + deltaLongitude), + CLLocationCoordinate2DMake(37.7790 + deltaLatitude, -122.4177 + deltaLongitude), + CLLocationCoordinate2DMake(34.0532 + deltaLatitude, -118.2349 + deltaLongitude) + }; + MLNPolyline *line = [MLNPolyline polylineWithCoordinates:lineCoordinates count:4]; + [self.mapView addAnnotation:line]; + + // Orcas Island, WA hike polyline + // + NSDictionary *hike = [NSJSONSerialization JSONObjectWithData: + [NSData dataWithContentsOfFile: + [[NSBundle mainBundle] pathForResource:@"polyline" ofType:@"geojson"]] + options:0 + error:nil]; + + NSArray *hikeCoordinatePairs = hike[@"features"][0][@"geometry"][@"coordinates"]; + + CLLocationCoordinate2D *polylineCoordinates = (CLLocationCoordinate2D *)malloc([hikeCoordinatePairs count] * sizeof(CLLocationCoordinate2D)); + + for (NSUInteger i = 0; i < [hikeCoordinatePairs count]; i++) + { + polylineCoordinates[i] = CLLocationCoordinate2DMake([hikeCoordinatePairs[i][1] doubleValue] + deltaLatitude, [hikeCoordinatePairs[i][0] doubleValue] + deltaLongitude); } - - MLNPolygon *polygon = [MLNPolygon polygonWithCoordinates:polygonCoordinates count:[stateCoordinatePairs count]]; - polygon.title = feature[@"properties"][@"NAME"]; - - [self.mapView addAnnotation:polygon]; - - free(polygonCoordinates); + + MLNPolyline *polyline = [MLNPolyline polylineWithCoordinates:polylineCoordinates + count:[hikeCoordinatePairs count]]; + + [self.mapView addAnnotation:polyline]; + + free(polylineCoordinates); + + // PA/NJ/DE polygons + // + NSDictionary *threestates = [NSJSONSerialization JSONObjectWithData: + [NSData dataWithContentsOfFile: + [[NSBundle mainBundle] pathForResource:@"threestates" ofType:@"geojson"]] + options:0 + error:nil]; + + for (NSDictionary *feature in threestates[@"features"]) + { + NSArray *stateCoordinatePairs = feature[@"geometry"][@"coordinates"]; + + while ([stateCoordinatePairs count] == 1) stateCoordinatePairs = stateCoordinatePairs[0]; + + CLLocationCoordinate2D *polygonCoordinates = (CLLocationCoordinate2D *)malloc([stateCoordinatePairs count] * sizeof(CLLocationCoordinate2D)); + + for (NSUInteger i = 0; i < [stateCoordinatePairs count]; i++) + { + polygonCoordinates[i] = CLLocationCoordinate2DMake([stateCoordinatePairs[i][1] doubleValue] + deltaLatitude, [stateCoordinatePairs[i][0] doubleValue] + deltaLongitude); + } + + MLNPolygon *polygon = [MLNPolygon polygonWithCoordinates:polygonCoordinates count:[stateCoordinatePairs count]]; + polygon.title = feature[@"properties"][@"NAME"]; + + [self.mapView addAnnotation:polygon]; + + free(polygonCoordinates); + } + + // Null Island polygon with an interior hole + // + CLLocationCoordinate2D innerCoordinates[] = { + CLLocationCoordinate2DMake(-5 + deltaLatitude, -5 + deltaLongitude), + CLLocationCoordinate2DMake(-5 + deltaLatitude, 5 + deltaLongitude), + CLLocationCoordinate2DMake(5 + deltaLatitude, 5 + deltaLongitude), + CLLocationCoordinate2DMake(5 + deltaLatitude, -5 + deltaLongitude), + }; + MLNPolygon *innerPolygon = [MLNPolygon polygonWithCoordinates:innerCoordinates count:sizeof(innerCoordinates) / sizeof(innerCoordinates[0])]; + CLLocationCoordinate2D outerCoordinates[] = { + CLLocationCoordinate2DMake(-10 + deltaLatitude, -10 + deltaLongitude), + CLLocationCoordinate2DMake(-10 + deltaLatitude, 10 + deltaLongitude), + CLLocationCoordinate2DMake(10 + deltaLatitude, 10 + deltaLongitude), + CLLocationCoordinate2DMake(10 + deltaLatitude, -10 + deltaLongitude), + }; + MLNPolygon *outerPolygon = [MLNPolygon polygonWithCoordinates:outerCoordinates count:sizeof(outerCoordinates) / sizeof(outerCoordinates[0]) interiorPolygons:@[innerPolygon]]; + [self.mapView addAnnotation:outerPolygon]; } - - // Null Island polygon with an interior hole - // - CLLocationCoordinate2D innerCoordinates[] = { - CLLocationCoordinate2DMake(-5, -5), - CLLocationCoordinate2DMake(-5, 5), - CLLocationCoordinate2DMake(5, 5), - CLLocationCoordinate2DMake(5, -5), - }; - MLNPolygon *innerPolygon = [MLNPolygon polygonWithCoordinates:innerCoordinates count:sizeof(innerCoordinates) / sizeof(innerCoordinates[0])]; - CLLocationCoordinate2D outerCoordinates[] = { - CLLocationCoordinate2DMake(-10, -10), - CLLocationCoordinate2DMake(-10, 10), - CLLocationCoordinate2DMake(10, 10), - CLLocationCoordinate2DMake(10, -10), - }; - MLNPolygon *outerPolygon = [MLNPolygon polygonWithCoordinates:outerCoordinates count:sizeof(outerCoordinates) / sizeof(outerCoordinates[0]) interiorPolygons:@[innerPolygon]]; - [self.mapView addAnnotation:outerPolygon]; } - (void)addAnnotationWithCustomCallout @@ -2439,9 +2449,9 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { return features; } -- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered { +- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered frameTime:(double)frameTime { if (self.frameTimeGraphEnabled) { - [self.frameTimeGraphView updatePathWithFrameDuration:mapView.frameTime]; + [self.frameTimeGraphView updatePathWithFrameDuration:frameTime]; } } From 3f1807a11a732beb32177ecad0369e7ba12a610d Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Mon, 2 Oct 2023 18:21:59 +0300 Subject: [PATCH 05/19] Metal headless backend (#1690) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CMakeLists.txt | 22 ++++ bazel/core.bzl | 5 + include/mbgl/gfx/backend.hpp | 6 +- include/mbgl/gfx/types.hpp | 1 + include/mbgl/mtl/context.hpp | 2 + include/mbgl/mtl/offscreen_texture.hpp | 2 +- include/mbgl/shaders/collision_layer_ubo.hpp | 18 +++ include/mbgl/shaders/mtl/collision_box.hpp | 91 +++++++++++++++ include/mbgl/shaders/mtl/collision_circle.hpp | 110 ++++++++++++++++++ .../mbgl/shaders/mtl/symbol_text_and_icon.hpp | 4 +- platform/default/BUILD.bazel | 4 +- .../include/mbgl/gfx/headless_backend.hpp | 4 - .../include/mbgl/mtl/headless_backend.hpp | 33 ++++++ .../default/src/mbgl/mtl/headless_backend.cpp | 107 +++++++++++++++++ src/mbgl/mtl/context.cpp | 9 +- src/mbgl/mtl/offscreen_texture.cpp | 85 +++++++++++--- src/mbgl/mtl/renderer_backend.cpp | 4 + src/mbgl/mtl/texture2d.cpp | 20 ++++ .../layers/collision_layer_tweaker.cpp | 14 +-- src/mbgl/renderer/renderer_impl.cpp | 5 +- src/mbgl/shaders/mtl/background_pattern.cpp | 2 +- src/mbgl/shaders/mtl/collision_box.cpp | 19 +++ src/mbgl/shaders/mtl/collision_circle.cpp | 20 ++++ 23 files changed, 540 insertions(+), 47 deletions(-) create mode 100644 include/mbgl/shaders/collision_layer_ubo.hpp create mode 100644 include/mbgl/shaders/mtl/collision_box.hpp create mode 100644 include/mbgl/shaders/mtl/collision_circle.hpp create mode 100644 platform/default/include/mbgl/mtl/headless_backend.hpp create mode 100644 platform/default/src/mbgl/mtl/headless_backend.cpp create mode 100644 src/mbgl/shaders/mtl/collision_box.cpp create mode 100644 src/mbgl/shaders/mtl/collision_circle.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f35ec847..d67f539df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1110,6 +1110,7 @@ if(MLN_WITH_OPENGL) list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/background_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/circle_layer_ubo.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/collision_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_extrusion_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp @@ -1174,6 +1175,8 @@ if(MBGL_WITH_METAL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/circle.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/clipping_mask.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/common.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_box.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_circle.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp @@ -1210,6 +1213,25 @@ if(MBGL_WITH_METAL) ${PROJECT_SOURCE_DIR}/src/mbgl/mtl/upload_pass.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_attribute.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background_pattern.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/circle.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_box.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_circle.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/clipping_mask.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill_extrusion.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/heatmap.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/heatmap_texture.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/hillshade.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/hillshade_prepare.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/line.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/line_gradient.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/raster.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_icon.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_sdf.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_text_and_icon.cpp ] ) endif() diff --git a/bazel/core.bzl b/bazel/core.bzl index e59e7c4a9..9a13789fa 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -961,6 +961,7 @@ MLN_DRAWABLES_HEADERS = [ "include/mbgl/renderer/render_target.hpp", "include/mbgl/shaders/background_layer_ubo.hpp", "include/mbgl/shaders/circle_layer_ubo.hpp", + "include/mbgl/shaders/collision_layer_ubo.hpp", "include/mbgl/shaders/fill_layer_ubo.hpp", "include/mbgl/shaders/fill_extrusion_layer_ubo.hpp", "include/mbgl/shaders/heatmap_layer_ubo.hpp", @@ -1022,6 +1023,8 @@ MLN_DRAWABLES_MTL_SOURCE = [ "src/mbgl/shaders/mtl/background.cpp", "src/mbgl/shaders/mtl/background_pattern.cpp", "src/mbgl/shaders/mtl/circle.cpp", + "src/mbgl/shaders/mtl/collision_box.cpp", + "src/mbgl/shaders/mtl/collision_circle.cpp", "src/mbgl/shaders/mtl/clipping_mask.cpp", "src/mbgl/shaders/mtl/fill.cpp", "src/mbgl/shaders/mtl/fill_extrusion.cpp", @@ -1062,6 +1065,8 @@ MLN_DRAWABLES_MTL_HEADERS = [ "include/mbgl/shaders/mtl/background_pattern.hpp", "include/mbgl/shaders/mtl/circle.hpp", "include/mbgl/shaders/mtl/clipping_mask.hpp", + "include/mbgl/shaders/mtl/collision_box.hpp", + "include/mbgl/shaders/mtl/collision_circle.hpp", "include/mbgl/shaders/mtl/common.hpp", "include/mbgl/shaders/mtl/fill.hpp", "include/mbgl/shaders/mtl/fill_extrusion.hpp", diff --git a/include/mbgl/gfx/backend.hpp b/include/mbgl/gfx/backend.hpp index bc79032b7..859bc5f23 100644 --- a/include/mbgl/gfx/backend.hpp +++ b/include/mbgl/gfx/backend.hpp @@ -19,7 +19,7 @@ public: #if MLN_RENDER_BACKEND_METAL static constexpr Type DefaultType = Type::Metal; -#else // assume MLN_RENDER_BACKEND_METAL +#else // assume MLN_RENDER_BACKEND_OPENGL static constexpr Type DefaultType = Type::OpenGL; #endif @@ -33,7 +33,11 @@ public: template static std::unique_ptr Create(Args... args) { +#if MLN_RENDER_BACKEND_METAL + return Create(std::forward(args)...); +#else // assume MLN_RENDER_BACKEND_OPENGL return Create(std::forward(args)...); +#endif } private: diff --git a/include/mbgl/gfx/types.hpp b/include/mbgl/gfx/types.hpp index 7d77fe014..0dabb1619 100644 --- a/include/mbgl/gfx/types.hpp +++ b/include/mbgl/gfx/types.hpp @@ -113,6 +113,7 @@ enum class TexturePixelType : uint8_t { enum class TextureChannelDataType : uint8_t { UnsignedByte, ///< 8 bit unsigned byte HalfFloat, ///< 16 bit "half-float" + Float, ///< 32 bit float }; /// Texture mip map type diff --git a/include/mbgl/mtl/context.hpp b/include/mbgl/mtl/context.hpp index 7e47a7695..2b6129339 100644 --- a/include/mbgl/mtl/context.hpp +++ b/include/mbgl/mtl/context.hpp @@ -78,6 +78,8 @@ public: void setDirtyState() override; + std::unique_ptr createOffscreenTexture(Size, gfx::TextureChannelDataType, bool, bool); + std::unique_ptr createOffscreenTexture(Size, gfx::TextureChannelDataType) override; std::unique_ptr createTextureResource(Size, diff --git a/include/mbgl/mtl/offscreen_texture.hpp b/include/mbgl/mtl/offscreen_texture.hpp index c131838b9..f291a7a90 100644 --- a/include/mbgl/mtl/offscreen_texture.hpp +++ b/include/mbgl/mtl/offscreen_texture.hpp @@ -11,7 +11,7 @@ class Texture2D; class OffscreenTexture final : public gfx::OffscreenTexture { public: - OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte); + OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type, bool depth, bool stencil); bool isRenderable() override; diff --git a/include/mbgl/shaders/collision_layer_ubo.hpp b/include/mbgl/shaders/collision_layer_ubo.hpp new file mode 100644 index 000000000..ac7d762d0 --- /dev/null +++ b/include/mbgl/shaders/collision_layer_ubo.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace mbgl { +namespace shaders { + +struct alignas(16) CollisionUBO { + std::array matrix; + std::array extrude_scale; + float camera_to_center_distance; + float overscale_factor; +}; +static_assert(sizeof(CollisionUBO) % 16 == 0); +static_assert(sizeof(CollisionUBO) == 80); + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/collision_box.hpp b/include/mbgl/shaders/mtl/collision_box.hpp new file mode 100644 index 000000000..a26249fcd --- /dev/null +++ b/include/mbgl/shaders/mtl/collision_box.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr auto name = "CollisionBoxShader"; + static constexpr auto vertexMainFunction = "vertexMain"; + static constexpr auto fragmentMainFunction = "fragmentMain"; + + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + + static constexpr auto source = R"( + +struct VertexStage { + short2 pos [[attribute(0)]]; + short2 anchor_pos [[attribute(1)]]; + short2 extrude [[attribute(2)]]; + uchar2 placed [[attribute(3)]]; + float2 shift [[attribute(4)]]; +}; + +struct FragmentStage { + float4 position [[position, invariant]]; + float placed; + float notUsed; +}; + +struct alignas(16) CollisionBoxUBO { + float4x4 matrix; + float2 extrude_scale; + float camera_to_center_distance; + float pad1; +}; + +FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], + device const CollisionBoxUBO& drawable [[buffer(5)]]) { + + float4 projectedPoint = drawable.matrix * float4(float2(vertx.anchor_pos), 0, 1); + float camera_to_anchor_distance = projectedPoint.w; + float collision_perspective_ratio = clamp( + 0.5 + 0.5 * (drawable.camera_to_center_distance / camera_to_anchor_distance), + 0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles + 4.0); + + float4 position = drawable.matrix * float4(float2(vertx.pos), 0.0, 1.0); + position.xy += (float2(vertx.extrude) + vertx.shift) * drawable.extrude_scale * position.w * collision_perspective_ratio; + + float placed = float(vertx.placed.x); + float notUsed = float(vertx.placed.y); + + return { + .position = position, + .placed = placed, + .notUsed = notUsed, + }; +} + +half4 fragment fragmentMain(FragmentStage in [[stage_in]], + device const CollisionBoxUBO& drawable [[buffer(5)]]) { + + float alpha = 0.5; + + // Red = collision, hide label + float4 color = float4(1.0, 0.0, 0.0, 1.0) * alpha; + + // Blue = no collision, label is showing + if (in.placed > 0.5) { + color = float4(0.0, 0.0, 1.0, 0.5) * alpha; + } + + if (in.notUsed > 0.5) { + // This box not used, fade it out + color *= 0.1; + } + + return half4(color); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/collision_circle.hpp b/include/mbgl/shaders/mtl/collision_circle.hpp new file mode 100644 index 000000000..39822a7bb --- /dev/null +++ b/include/mbgl/shaders/mtl/collision_circle.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr auto name = "CollisionCircleShader"; + static constexpr auto vertexMainFunction = "vertexMain"; + static constexpr auto fragmentMainFunction = "fragmentMain"; + + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + + static constexpr auto source = R"( + +struct VertexStage { + short2 pos [[attribute(0)]]; + short2 anchor_pos [[attribute(1)]]; + short2 extrude [[attribute(2)]]; + uchar2 placed [[attribute(3)]]; +}; + +struct FragmentStage { + float4 position [[position, invariant]]; + float placed; + float notUsed; + float radius; + float2 extrude; + float2 extrude_scale; +}; + +struct alignas(16) CollisionCircleUBO { + float4x4 matrix; + float2 extrude_scale; + float camera_to_center_distance; + float overscale_factor; +}; + +FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], + device const CollisionCircleUBO& drawable [[buffer(4)]]) { + + float4 projectedPoint = drawable.matrix * float4(float2(vertx.anchor_pos), 0, 1); + float camera_to_anchor_distance = projectedPoint.w; + float collision_perspective_ratio = clamp( + 0.5 + 0.5 * (drawable.camera_to_center_distance / camera_to_anchor_distance), + 0.0, // Prevents oversized near-field circles in pitched/overzoomed tiles + 4.0); + + float4 position = drawable.matrix * float4(float2(vertx.pos), 0.0, 1.0); + + float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur + position.xy += float2(vertx.extrude) * drawable.extrude_scale * padding_factor * position.w * collision_perspective_ratio; + + float placed = float(vertx.placed.x); + float notUsed = float(vertx.placed.y); + float radius = abs(float(vertx.extrude.y)); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius + + float2 extrude = float2(vertx.extrude) * padding_factor; + float2 extrude_scale = drawable.extrude_scale * drawable.camera_to_center_distance * collision_perspective_ratio; + + return { + .position = position, + .placed = placed, + .notUsed = notUsed, + .radius = radius, + .extrude = extrude, + .extrude_scale = extrude_scale, + }; +} + +half4 fragment fragmentMain(FragmentStage in [[stage_in]], + device const CollisionCircleUBO& drawable [[buffer(4)]]) { + + float alpha = 0.5; + + // Red = collision, hide label + float4 color = float4(1.0, 0.0, 0.0, 1.0) * alpha; + + // Blue = no collision, label is showing + if (in.placed > 0.5) { + color = float4(0.0, 0.0, 1.0, 0.5) * alpha; + } + + if (in.notUsed > 0.5) { + // This box not used, fade it out + color *= 0.2; + } + + float extrude_scale_length = length(in.extrude_scale); + float extrude_length = length(in.extrude) * extrude_scale_length; + float stroke_width = 15.0 * extrude_scale_length / drawable.overscale_factor; + float radius = in.radius * extrude_scale_length; + + float distance_to_edge = abs(extrude_length - radius); + float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge); + + return half4(opacity_t * color); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp index afd4dd4b8..f0d68a52f 100644 --- a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp +++ b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp @@ -118,7 +118,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos); const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0); - const float2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset; + const float2 pos_rot = a_offset / 32.0 * fontScale; const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot; const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0); const float gamma_scale = position.w; @@ -155,7 +155,7 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]], if (in.data1.w == ICON) { const float2 tex_icon = in.data0.zw; - const float alpha = opacity * fade_opacity; + const float alpha = in.opacity * fade_opacity; return half4(icon_image.sample(icon_sampler, tex_icon) * alpha); } diff --git a/platform/default/BUILD.bazel b/platform/default/BUILD.bazel index b76d6f17c..2d3cd2ad7 100644 --- a/platform/default/BUILD.bazel +++ b/platform/default/BUILD.bazel @@ -55,7 +55,7 @@ cc_library( "src/mbgl/util/thread_local.cpp", "src/mbgl/util/utf.cpp", ] + select({ - "//:metal_renderer": [], + "//:metal_renderer": ["src/mbgl/mtl/headless_backend.cpp"], "//conditions:default": ["src/mbgl/gl/headless_backend.cpp"], }) + select({ "//:linux": [ @@ -89,7 +89,7 @@ cc_library( "include/mbgl/storage/sqlite3.hpp", "include/mbgl/text/unaccent.hpp", ] + select({ - "//:metal_renderer": [], + "//:metal_renderer": ["include/mbgl/mtl/headless_backend.hpp"], "//conditions:default": ["include/mbgl/gl/headless_backend.hpp"], }), copts = CPP_FLAGS + MAPLIBRE_FLAGS, diff --git a/platform/default/include/mbgl/gfx/headless_backend.hpp b/platform/default/include/mbgl/gfx/headless_backend.hpp index a2656c431..1dc775531 100644 --- a/platform/default/include/mbgl/gfx/headless_backend.hpp +++ b/platform/default/include/mbgl/gfx/headless_backend.hpp @@ -24,11 +24,7 @@ public: static std::unique_ptr Create(const Size size = {256, 256}, SwapBehaviour swapBehavior = SwapBehaviour::NoFlush, const gfx::ContextMode contextMode = gfx::ContextMode::Unique) { -#if MLN_RENDER_BACKEND_METAL - throw std::runtime_error("Not yet implemented"); -#else // MLN_RENDER_BACKEND_OPENGL return Backend::Create(size, swapBehavior, contextMode); -#endif } virtual PremultipliedImage readStillImage() = 0; diff --git a/platform/default/include/mbgl/mtl/headless_backend.hpp b/platform/default/include/mbgl/mtl/headless_backend.hpp new file mode 100644 index 000000000..af7d1aa7e --- /dev/null +++ b/platform/default/include/mbgl/mtl/headless_backend.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace mtl { + +class HeadlessBackend final : public mtl::RendererBackend, public gfx::HeadlessBackend { +public: + HeadlessBackend(Size = {256, 256}, + SwapBehaviour = SwapBehaviour::NoFlush, + gfx::ContextMode = gfx::ContextMode::Unique); + ~HeadlessBackend() override; + void updateAssumedState() override; + gfx::Renderable& getDefaultRenderable() override; + PremultipliedImage readStillImage() override; + RendererBackend* getRendererBackend() override; + SwapBehaviour getSwapBehaviour(); + +private: + void activate() override; + void deactivate() override; + +private: + bool active = false; + SwapBehaviour swapBehaviour = SwapBehaviour::NoFlush; +}; + +} // namespace mtl +} // namespace mbgl diff --git a/platform/default/src/mbgl/mtl/headless_backend.cpp b/platform/default/src/mbgl/mtl/headless_backend.cpp new file mode 100644 index 000000000..f2dc98112 --- /dev/null +++ b/platform/default/src/mbgl/mtl/headless_backend.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mbgl { +namespace mtl { + +class HeadlessRenderableResource final : public mtl::RenderableResource { +public: + HeadlessRenderableResource(HeadlessBackend& backend_, mtl::Context& context_, Size size) + : backend(backend_), + context(context_) { + offscreenTexture = context.createOffscreenTexture(size, gfx::TextureChannelDataType::UnsignedByte, true, true); + } + + ~HeadlessRenderableResource() noexcept override = default; + + void bind() override { offscreenTexture->getResource().bind(); } + + void swap() override { offscreenTexture->getResource().swap(); } + + PremultipliedImage readStillImage() { return offscreenTexture->readStillImage(); } + + const RendererBackend& getBackend() const override { return context.getBackend(); } + + const MTLCommandBufferPtr& getCommandBuffer() const override { + return offscreenTexture->getResource().getCommandBuffer(); + } + + MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override { + return offscreenTexture->getResource().getUploadPassDescriptor(); + } + + MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override { + return offscreenTexture->getResource().getRenderPassDescriptor(); + } + + HeadlessBackend& backend; + Context& context; + std::unique_ptr offscreenTexture; +}; + +HeadlessBackend::HeadlessBackend(const Size size_, + gfx::HeadlessBackend::SwapBehaviour swapBehaviour_, + const gfx::ContextMode contextMode_) + : mbgl::mtl::RendererBackend(contextMode_), + mbgl::gfx::HeadlessBackend(size_), + swapBehaviour(swapBehaviour_) {} + +HeadlessBackend::~HeadlessBackend() { + gfx::BackendScope guard{*this, gfx::BackendScope::ScopeType::Implicit}; + // Explicitly reset the renderable resource + resource.reset(); + // Explicitly reset the context + context.reset(); +} + +void HeadlessBackend::activate() { + active = true; +} + +void HeadlessBackend::deactivate() { + active = false; +} + +gfx::Renderable& HeadlessBackend::getDefaultRenderable() { + if (!resource) { + resource = std::make_unique(*this, static_cast(getContext()), size); + } + return *this; +} + +void HeadlessBackend::updateAssumedState() { + // no-op +} + +PremultipliedImage HeadlessBackend::readStillImage() { + return getResource().readStillImage(); +} + +RendererBackend* HeadlessBackend::getRendererBackend() { + return this; +} + +HeadlessBackend::SwapBehaviour HeadlessBackend::getSwapBehaviour() { + return swapBehaviour; +} + +} // namespace mtl + +namespace gfx { + +template <> +std::unique_ptr Backend::Create( + const Size size, gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) { + return std::make_unique(size, swapBehavior, contextMode); +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index 1100e34d3..186079043 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -186,8 +186,15 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, const void Context::setDirtyState() {} +std::unique_ptr Context::createOffscreenTexture(Size size, + gfx::TextureChannelDataType type, + bool depth, + bool stencil) { + return std::make_unique(*this, size, type, depth, stencil); +} + std::unique_ptr Context::createOffscreenTexture(Size size, gfx::TextureChannelDataType type) { - return std::make_unique(*this, size, type); + return createOffscreenTexture(size, type, false, false); } std::unique_ptr Context::createTextureResource(Size, diff --git a/src/mbgl/mtl/offscreen_texture.cpp b/src/mbgl/mtl/offscreen_texture.cpp index 11895f807..42bb5fa8f 100644 --- a/src/mbgl/mtl/offscreen_texture.cpp +++ b/src/mbgl/mtl/offscreen_texture.cpp @@ -11,18 +11,39 @@ namespace mtl { class OffscreenTextureResource final : public RenderableResource { public: - OffscreenTextureResource(Context& context_, const Size size_, const gfx::TextureChannelDataType type_) + OffscreenTextureResource( + Context& context_, const Size size_, const gfx::TextureChannelDataType type_, bool depth, bool stencil) : context(context_), size(size_), type(type_) { assert(!size.isEmpty()); - texture = context.createTexture2D(); - texture->setSize(size); - texture->setFormat(gfx::TexturePixelType::RGBA, type); - texture->setSamplerConfiguration( + colorTexture = context.createTexture2D(); + colorTexture->setSize(size); + colorTexture->setFormat(gfx::TexturePixelType::RGBA, type); + colorTexture->setSamplerConfiguration( {gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - static_cast(texture.get()) + static_cast(colorTexture.get()) ->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget); + + if (depth) { + depthTexture = context.createTexture2D(); + depthTexture->setSize(size); + depthTexture->setFormat(gfx::TexturePixelType::Depth, gfx::TextureChannelDataType::Float); + depthTexture->setSamplerConfiguration( + {gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + static_cast(depthTexture.get()) + ->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget); + } + + if (stencil) { + stencilTexture = context.createTexture2D(); + stencilTexture->setSize(size); + stencilTexture->setFormat(gfx::TexturePixelType::Stencil, gfx::TextureChannelDataType::UnsignedByte); + stencilTexture->setSamplerConfiguration( + {gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + static_cast(stencilTexture.get()) + ->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget); + } } ~OffscreenTextureResource() noexcept override = default; @@ -30,7 +51,25 @@ public: void bind() override { assert(context.getBackend().getCommandQueue()); commandBuffer = NS::RetainPtr(context.getBackend().getCommandQueue()->commandBuffer()); - texture->create(); + colorTexture->create(); + + renderPassDescriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init()); + if (auto* colorTarget = renderPassDescriptor->colorAttachments()->object(0)) { + colorTarget->setTexture(static_cast(colorTexture.get())->getMetalTexture()); + } + + if (depthTexture) { + depthTexture->create(); + if (auto* depthTarget = renderPassDescriptor->depthAttachment()) { + depthTarget->setTexture(static_cast(depthTexture.get())->getMetalTexture()); + } + } + if (stencilTexture) { + stencilTexture->create(); + if (auto* stencilTarget = renderPassDescriptor->stencilAttachment()) { + stencilTarget->setTexture(static_cast(stencilTexture.get())->getMetalTexture()); + } + } } void swap() override { @@ -38,16 +77,24 @@ public: commandBuffer->commit(); commandBuffer->waitUntilCompleted(); commandBuffer.reset(); + renderPassDescriptor.reset(); } PremultipliedImage readStillImage() { - assert(false); - return PremultipliedImage(); + assert(static_cast(colorTexture.get())->getMetalTexture()); + + auto data = std::make_unique(colorTexture->getDataSize()); + MTL::Region region = MTL::Region::Make2D(0, 0, size.width, size.height); + NS::UInteger bytesPerRow = size.width * colorTexture->getPixelStride(); + + static_cast(colorTexture.get())->getMetalTexture()->getBytes(data.get(), bytesPerRow, region, 0); + + return {size, std::move(data)}; } gfx::Texture2DPtr& getTexture() { - assert(texture); - return texture; + assert(colorTexture); + return colorTexture; } const RendererBackend& getBackend() const override { return context.getBackend(); } @@ -55,15 +102,11 @@ public: const MTLCommandBufferPtr& getCommandBuffer() const override { return commandBuffer; } MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override { - assert(false); return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init()); } MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override { - auto renderPassDescriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init()); - if (auto* colorTarget = renderPassDescriptor->colorAttachments()->object(0)) { - colorTarget->setTexture(static_cast(texture.get())->getMetalTexture()); - } + assert(renderPassDescriptor); return renderPassDescriptor; } @@ -71,12 +114,16 @@ private: Context& context; const Size size; const gfx::TextureChannelDataType type; - gfx::Texture2DPtr texture; + gfx::Texture2DPtr colorTexture; + gfx::Texture2DPtr depthTexture; + gfx::Texture2DPtr stencilTexture; MTLCommandBufferPtr commandBuffer; + MTLRenderPassDescriptorPtr renderPassDescriptor; }; -OffscreenTexture::OffscreenTexture(Context& context, const Size size_, const gfx::TextureChannelDataType type) - : gfx::OffscreenTexture(size, std::make_unique(context, size_, type)) {} +OffscreenTexture::OffscreenTexture( + Context& context, const Size size_, const gfx::TextureChannelDataType type, bool depth, bool stencil) + : gfx::OffscreenTexture(size, std::make_unique(context, size_, type, depth, stencil)) {} bool OffscreenTexture::isRenderable() { assert(false); diff --git a/src/mbgl/mtl/renderer_backend.cpp b/src/mbgl/mtl/renderer_backend.cpp index b290e605a..deb9cc781 100644 --- a/src/mbgl/mtl/renderer_backend.cpp +++ b/src/mbgl/mtl/renderer_backend.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -124,6 +126,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::BackgroundPatternShader, shaders::BuiltIn::CircleShader, shaders::BuiltIn::ClippingMaskProgram, + shaders::BuiltIn::CollisionBoxShader, + shaders::BuiltIn::CollisionCircleShader, shaders::BuiltIn::FillShader, shaders::BuiltIn::FillOutlineShader, shaders::BuiltIn::FillOutlinePatternShader, diff --git a/src/mbgl/mtl/texture2d.cpp b/src/mbgl/mtl/texture2d.cpp index fe0e541d2..6abdfc1bb 100644 --- a/src/mbgl/mtl/texture2d.cpp +++ b/src/mbgl/mtl/texture2d.cpp @@ -56,6 +56,8 @@ size_t Texture2D::getPixelStride() const noexcept { return 1 * numChannels(); case gfx::TextureChannelDataType::HalfFloat: return 2 * numChannels(); + case gfx::TextureChannelDataType::Float: + return 4 * numChannels(); } } @@ -65,6 +67,10 @@ size_t Texture2D::numChannels() const noexcept { return 4; case gfx::TexturePixelType::Alpha: return 1; + case gfx::TexturePixelType::Stencil: + return 1; + case gfx::TexturePixelType::Depth: + return 1; default: return 0; } @@ -78,6 +84,8 @@ MTL::PixelFormat Texture2D::getMetalPixelFormat() const noexcept { return MTL::PixelFormat::PixelFormatRGBA8Unorm; case gfx::TexturePixelType::Alpha: return MTL::PixelFormat::PixelFormatA8Unorm; + case gfx::TexturePixelType::Stencil: + return MTL::PixelFormat::PixelFormatStencil8; default: assert(false); return MTL::PixelFormat::PixelFormatInvalid; @@ -92,6 +100,18 @@ MTL::PixelFormat Texture2D::getMetalPixelFormat() const noexcept { assert(false); return MTL::PixelFormat::PixelFormatInvalid; } + case gfx::TextureChannelDataType::Float: + switch (pixelFormat) { + case gfx::TexturePixelType::RGBA: + return MTL::PixelFormat::PixelFormatRGBA32Float; + case gfx::TexturePixelType::Alpha: + return MTL::PixelFormat::PixelFormatR32Float; + case gfx::TexturePixelType::Depth: + return MTL::PixelFormat::PixelFormatDepth32Float; + default: + assert(false); + return MTL::PixelFormat::PixelFormatInvalid; + } default: assert(false); return MTL::PixelFormat::PixelFormatInvalid; diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp index 508f16888..d46a60aae 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,18 +19,7 @@ namespace mbgl { using namespace style; - -namespace { - -struct alignas(16) CollisionUBO { - std::array matrix; - std::array extrude_scale; - float camera_to_center_distance; - float overscale_factor; -}; -static_assert(sizeof(CollisionUBO) == 20 * 4); - -} // namespace +using namespace shaders; const StringIdentity CollisionLayerTweaker::idCollisionCircleUBOName = StringIndexer::get(CollisionCircleUBOName); const StringIdentity CollisionLayerTweaker::idCollisionBoxUBOName = StringIndexer::get(CollisionBoxUBOName); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index c917bdf69..33bdca101 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -392,10 +392,7 @@ void Renderer::Impl::render(const RenderTree& renderTree, // Ends the RenderPass parameters.renderPass.reset(); - const bool isMapModeContinuous = renderTreeParameters.mapMode == MapMode::Continuous; - if (isMapModeContinuous) { - parameters.encoder->present(parameters.backend.getDefaultRenderable()); - } + parameters.encoder->present(parameters.backend.getDefaultRenderable()); // CommandEncoder destructor submits render commands. parameters.encoder.reset(); diff --git a/src/mbgl/shaders/mtl/background_pattern.cpp b/src/mbgl/shaders/mtl/background_pattern.cpp index fa173422d..88aff4809 100644 --- a/src/mbgl/shaders/mtl/background_pattern.cpp +++ b/src/mbgl/shaders/mtl/background_pattern.cpp @@ -7,7 +7,7 @@ const std::array ShaderSource::uniforms = { UniformBlockInfo{1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"}, UniformBlockInfo{2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"}, - UniformBlockInfo{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"}, + UniformBlockInfo{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundLayerUBO"}, }; } // namespace shaders diff --git a/src/mbgl/shaders/mtl/collision_box.cpp b/src/mbgl/shaders/mtl/collision_box.cpp new file mode 100644 index 000000000..66cbbef9a --- /dev/null +++ b/src/mbgl/shaders/mtl/collision_box.cpp @@ -0,0 +1,19 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_anchor_pos"}, + AttributeInfo{2, gfx::AttributeDataType::Short2, 1, "a_extrude"}, + AttributeInfo{3, gfx::AttributeDataType::UByte2, 1, "a_placed"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_shift"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{5, true, true, sizeof(CollisionUBO), "CollisionBoxUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/collision_circle.cpp b/src/mbgl/shaders/mtl/collision_circle.cpp new file mode 100644 index 000000000..9eb6934ab --- /dev/null +++ b/src/mbgl/shaders/mtl/collision_circle.cpp @@ -0,0 +1,20 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = + { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_anchor_pos"}, + AttributeInfo{2, gfx::AttributeDataType::Short2, 1, "a_extrude"}, + AttributeInfo{3, gfx::AttributeDataType::UByte2, 1, "a_placed"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{5, true, true, sizeof(CollisionUBO), "CollisionCircleUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl From 59a5edb1ea14978aa1e28d0809a62aa8a095548f Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 2 Oct 2023 08:29:57 -0700 Subject: [PATCH 06/19] Handle updated evaluated properties in the fill layer tweaker instead of replacing it on every update (#1707) --- .../renderer/layers/fill_layer_tweaker.cpp | 105 +++++++----------- .../renderer/layers/render_fill_layer.cpp | 5 +- 2 files changed, 42 insertions(+), 68 deletions(-) diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 14ded51d4..4949e8547 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -77,13 +77,15 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif + // Only run each update function once bool fillUniformBufferUpdated = false; bool fillOutlineUniformBufferUpdated = false; bool fillPatternUniformBufferUpdated = false; bool fillOutlinePatternUniformBufferUpdated = false; - auto UpdateFillUniformBuffers = [&]() { + const auto UpdateFillUniformBuffers = [&]() { if (fillUniformBufferUpdated) return; + fillUniformBufferUpdated = true; #if MLN_RENDER_BACKEND_METAL if (propertiesChanged || !fillPermutationUniformBuffer) { @@ -99,16 +101,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, }; - if (fillPermutationUniformBuffer) { - fillPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO)); - } else { - fillPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO, sizeof(permutationUBO)); - } - fillUniformBufferUpdated = true; + context.emplaceOrUpdateUniformBuffer(fillPermutationUniformBuffer, &permutationUBO); } #endif - if (!fillPropsUniformBuffer) { + if (!fillPropsUniformBuffer || propertiesUpdated) { const FillEvaluatedPropsUBO paramsUBO = { /* .color = */ evaluated.get().constantOr(FillColor::defaultValue()), /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), @@ -116,12 +113,13 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0, }; - fillPropsUniformBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + context.emplaceOrUpdateUniformBuffer(fillPropsUniformBuffer, ¶msUBO); } }; - auto UpdateFillOutlineUniformBuffers = [&]() { + const auto UpdateFillOutlineUniformBuffers = [&]() { if (fillOutlineUniformBufferUpdated) return; + fillOutlineUniformBufferUpdated = true; #if MLN_RENDER_BACKEND_METAL if (propertiesChanged || !fillOutlinePermutationUniformBuffer) { @@ -137,17 +135,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0, }; - - if (fillOutlinePermutationUniformBuffer) { - fillOutlinePermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO)); - } else { - fillOutlinePermutationUniformBuffer = context.createUniformBuffer(&permutationUBO, - sizeof(permutationUBO)); - } + context.emplaceOrUpdateUniformBuffer(fillOutlinePermutationUniformBuffer, &permutationUBO); } #endif - if (!fillOutlinePropsUniformBuffer) { + if (!fillOutlinePropsUniformBuffer || propertiesUpdated) { const FillOutlineEvaluatedPropsUBO paramsUBO = { /* .outline_color = */ evaluated.get().constantOr(FillOutlineColor::defaultValue()), /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), @@ -155,55 +147,47 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0, }; - fillOutlinePropsUniformBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + context.emplaceOrUpdateUniformBuffer(fillOutlinePropsUniformBuffer, ¶msUBO); } - - fillOutlineUniformBufferUpdated = true; }; - auto UpdateFillPatternUniformBuffers = [&]() { + const auto UpdateFillPatternUniformBuffers = [&]() { if (fillPatternUniformBufferUpdated) return; + fillPatternUniformBufferUpdated = true; #if MLN_RENDER_BACKEND_METAL if (propertiesChanged || !fillPatternPermutationUniformBuffer) { const FillPatternPermutationUBO permutationUBO = { - /* .pattern_from = */ {/*.source=*/getAttributeSource(1), + /* .pattern_from = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, /* .pattern_to = */ - {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .opacity = */ - {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, 0, 0, }; - - if (fillPatternPermutationUniformBuffer) { - fillPatternPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO)); - } else { - fillPatternPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO, - sizeof(permutationUBO)); - } + context.emplaceOrUpdateUniformBuffer(fillPatternPermutationUniformBuffer, &permutationUBO); } #endif - if (!fillPatternPropsUniformBuffer) { + if (!fillPatternPropsUniformBuffer || propertiesUpdated) { const FillPatternEvaluatedPropsUBO paramsUBO = { /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), /* .fade = */ crossfade.t, 0, 0, }; - fillPatternPropsUniformBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + context.emplaceOrUpdateUniformBuffer(fillPatternPropsUniformBuffer, ¶msUBO); } - - fillPatternUniformBufferUpdated = true; }; - auto UpdateFillOutlinePatternUniformBuffers = [&]() { + const auto UpdateFillOutlinePatternUniformBuffers = [&]() { if (fillOutlinePatternUniformBufferUpdated) return; + fillOutlinePatternUniformBufferUpdated = true; #if MLN_RENDER_BACKEND_METAL if (propertiesChanged || !fillOutlinePatternPermutationUniformBuffer) { @@ -220,57 +204,47 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0, }; - - if (fillOutlinePatternPermutationUniformBuffer) { - fillOutlinePatternPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO)); - } else { - fillOutlinePatternPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO, - sizeof(permutationUBO)); - } + context.emplaceOrUpdateUniformBuffer(fillOutlinePatternPermutationUniformBuffer, &permutationUBO); } #endif - if (!fillOutlinePatternPropsUniformBuffer) { + if (!fillOutlinePatternPropsUniformBuffer || propertiesUpdated) { const FillOutlinePatternEvaluatedPropsUBO paramsUBO = { /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), /* .fade = */ crossfade.t, 0, 0, }; - fillOutlinePatternPropsUniformBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + context.emplaceOrUpdateUniformBuffer(fillOutlinePatternPropsUniformBuffer, ¶msUBO); } - - fillOutlinePatternUniformBufferUpdated = true; }; #if MLN_RENDER_BACKEND_METAL - if (!expressionUniformBuffer) { - const auto zoom = parameters.state.getZoom(); - const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount); - expressionUniformBuffer = context.createUniformBuffer(&expressionUBO, sizeof(expressionUBO)); - } + const auto zoom = parameters.state.getZoom(); + const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount); + context.emplaceOrUpdateUniformBuffer(expressionUniformBuffer, &expressionUBO); #endif + const auto& translation = evaluated.get(); + const auto anchor = evaluated.get(); + + const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); + const auto intZoom = parameters.state.getIntegerZoom(); + const auto pixelRatio = parameters.pixelRatio; + layerGroup.visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } - auto& uniforms = drawable.mutableUniformBuffers(); - // auto& drawableType = drawable.getShader()->typeName(); - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); - const auto& translation = evaluated.get(); - const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix constexpr bool nearClipped = false; const auto matrix = getTileMatrix( tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); // from FillPatternProgram::layoutUniformValues - const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); - const auto intZoom = parameters.state.getIntegerZoom(); const auto tileRatio = 1.0f / tileID.pixelsToTileUnits(1.0f, intZoom); const int32_t tileSizeAtNearestZoom = static_cast( util::tileSize_D * parameters.state.zoomScale(intZoom - tileID.canonical.z)); @@ -278,7 +252,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * parameters.state.zoomScale(tileID.canonical.z))); const int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y; - const auto pixelRatio = parameters.pixelRatio; Size textureSize = {0, 0}; if (const auto shader = drawable.getShader()) { @@ -289,12 +262,13 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, } } + auto& uniforms = drawable.mutableUniformBuffers(); if (uniforms.get(idFillInterpolateUBOName)) { UpdateFillUniformBuffers(); uniforms.addOrReplace(idFillEvaluatedPropsUBOName, fillPropsUniformBuffer); - const FillDrawableUBO drawableUBO = {/*.matrix=*/util::cast(matrix)}; + const FillDrawableUBO drawableUBO = {/*.matrix=*/util::cast(matrix)}; uniforms.createOrUpdate(idFillDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL @@ -304,12 +278,12 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, UpdateFillOutlineUniformBuffers(); uniforms.addOrReplace(idFillOutlineEvaluatedPropsUBOName, fillOutlinePropsUniformBuffer); + const FillOutlineDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.world=*/{(float)renderableSize.width, (float)renderableSize.height}, /* pad1 */ 0, /* pad2 */ 0}; - uniforms.createOrUpdate(idFillOutlineDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL @@ -319,6 +293,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, UpdateFillPatternUniformBuffers(); uniforms.addOrReplace(idFillPatternEvaluatedPropsUBOName, fillPatternPropsUniformBuffer); + const FillPatternDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, @@ -328,7 +303,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0, }; - uniforms.createOrUpdate(idFillPatternDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL @@ -338,6 +312,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, UpdateFillOutlinePatternUniformBuffers(); uniforms.addOrReplace(idFillOutlinePatternEvaluatedPropsUBOName, fillOutlinePatternPropsUniformBuffer); + const FillOutlinePatternDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, @@ -346,7 +321,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, /*.pixel_coord_lower=*/{static_cast(pixelX & 0xFFFF), static_cast(pixelY & 0xFFFF)}, /*.texsize=*/{static_cast(textureSize.width), static_cast(textureSize.height)}, }; - uniforms.createOrUpdate(idFillOutlinePatternDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL @@ -360,6 +334,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, }); propertiesChanged = false; + propertiesUpdated = false; } } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index d2627b4b5..4063c23c4 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -103,9 +103,8 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - if (layerGroup) { - auto newTweaker = std::make_shared(getID(), evaluatedProperties); - replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + if (layerTweaker) { + layerTweaker->updateProperties(evaluatedProperties); } #endif } From 44b5af7c4aa8eb08152858d1bd1eece697465cb3 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 2 Oct 2023 09:47:17 -0700 Subject: [PATCH 07/19] Topic/metal cache (#1704) --- include/mbgl/gfx/drawable.hpp | 8 +- include/mbgl/mtl/drawable.hpp | 13 ++- include/mbgl/mtl/renderable_resource.hpp | 2 +- platform/ios/src/MLNMapView+Metal.mm | 11 ++- src/mbgl/mtl/drawable.cpp | 104 ++++++++++++++--------- src/mbgl/mtl/drawable_impl.hpp | 10 +++ src/mbgl/renderer/paint_parameters.cpp | 45 +++++----- 7 files changed, 112 insertions(+), 81 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 13feb6e59..56a140b3f 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -134,7 +134,7 @@ public: bool getEnableStencil() const { return enableStencil; } /// Set stencil usage - void setEnableStencil(bool value) { enableStencil = value; } + virtual void setEnableStencil(bool value) { enableStencil = value; } /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } @@ -142,19 +142,19 @@ public: /// Whether to enable depth testing bool getEnableDepth() { return enableDepth; } - void setEnableDepth(bool value) { enableDepth = value; } + virtual void setEnableDepth(bool value) { enableDepth = value; } /// Determines depth range within the layer for 2D drawables int32_t getSubLayerIndex() const { return subLayerIndex; } /// Set sub-layer index - void setSubLayerIndex(int32_t value) { subLayerIndex = value; } + virtual void setSubLayerIndex(int32_t value) { subLayerIndex = value; } /// Depth writability for 2D drawables DepthMaskType getDepthType() const { return depthType; } /// Set depth type - void setDepthType(DepthMaskType value) { depthType = value; } + virtual void setDepthType(DepthMaskType value) { depthType = value; } /// Uses 3D depth mode bool getIs3D() const { return is3D; } diff --git a/include/mbgl/mtl/drawable.hpp b/include/mbgl/mtl/drawable.hpp index c2e96608d..2d0fb7118 100644 --- a/include/mbgl/mtl/drawable.hpp +++ b/include/mbgl/mtl/drawable.hpp @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include @@ -59,6 +57,11 @@ public: void setShader(gfx::ShaderProgramBasePtr) override; + void setEnableStencil(bool) override; + void setEnableDepth(bool) override; + void setSubLayerIndex(int32_t) override; + void setDepthType(gfx::DepthMaskType) override; + protected: // For testing only. Drawable(std::unique_ptr); @@ -76,12 +79,6 @@ protected: class Impl; const std::unique_ptr impl; - - gfx::AttributeBindingArray attributeBindings; - - mutable MTLRenderPipelineStatePtr pipelineState; - - mutable std::optional renderPassDescriptor; }; } // namespace mtl diff --git a/include/mbgl/mtl/renderable_resource.hpp b/include/mbgl/mtl/renderable_resource.hpp index f469f0a34..d8620d636 100644 --- a/include/mbgl/mtl/renderable_resource.hpp +++ b/include/mbgl/mtl/renderable_resource.hpp @@ -23,7 +23,7 @@ public: virtual const mbgl::mtl::RendererBackend& getBackend() const = 0; virtual const mbgl::mtl::MTLCommandBufferPtr& getCommandBuffer() const = 0; virtual mbgl::mtl::MTLBlitPassDescriptorPtr getUploadPassDescriptor() const = 0; - virtual mbgl::mtl::MTLRenderPassDescriptorPtr getRenderPassDescriptor() const = 0; + virtual const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const = 0; }; } // namespace mtl diff --git a/platform/ios/src/MLNMapView+Metal.mm b/platform/ios/src/MLNMapView+Metal.mm index 8ae82c32f..d8614c920 100644 --- a/platform/ios/src/MLNMapView+Metal.mm +++ b/platform/ios/src/MLNMapView+Metal.mm @@ -69,8 +69,12 @@ public: return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init()); } - mbgl::mtl::MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override { - return NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlView.currentRenderPassDescriptor); + const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override { + if (!cachedRenderPassDescriptor) { + auto* mtlDesc = mtlView.currentRenderPassDescriptor; + cachedRenderPassDescriptor = NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlDesc); + } + return cachedRenderPassDescriptor; } void swap() override { @@ -83,6 +87,8 @@ public: commandBuffer = nil; commandBufferPtr.reset(); + + cachedRenderPassDescriptor.reset(); } mbgl::Size framebufferSize() { @@ -94,6 +100,7 @@ public: private: MLNMapViewMetalImpl& backend; mbgl::mtl::MTLCommandBufferPtr commandBufferPtr; + mutable mbgl::mtl::MTLRenderPassDescriptorPtr cachedRenderPassDescriptor; public: MLNMapViewImplDelegate* delegate = nil; diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 57d9c1fc9..b0c638d68 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -123,12 +123,32 @@ MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) { } // namespace void Drawable::setColorMode(const gfx::ColorMode& value) { - pipelineState.reset(); + impl->pipelineState.reset(); gfx::Drawable::setColorMode(value); } +void Drawable::setEnableStencil(bool value) { + gfx::Drawable::setEnableStencil(value); + impl->depthStencilState.reset(); +} + +void Drawable::setEnableDepth(bool value) { + gfx::Drawable::setEnableDepth(value); + impl->depthStencilState.reset(); +} + +void Drawable::setSubLayerIndex(int32_t value) { + gfx::Drawable::setSubLayerIndex(value); + impl->depthStencilState.reset(); +} + +void Drawable::setDepthType(gfx::DepthMaskType value) { + gfx::Drawable::setDepthType(value); + impl->depthStencilState.reset(); +} + void Drawable::setShader(gfx::ShaderProgramBasePtr value) { - pipelineState.reset(); + impl->pipelineState.reset(); gfx::Drawable::setShader(value); } @@ -151,13 +171,12 @@ void Drawable::draw(PaintParameters& parameters) const { return; } - if (renderPassDescriptor.has_value() && renderPass.getDescriptor() != renderPassDescriptor.value()) { - pipelineState.reset(); + const auto& descriptor = renderPass.getDescriptor(); + if (impl->renderPassDescriptor && descriptor != *impl->renderPassDescriptor) { + impl->pipelineState.reset(); } - renderPassDescriptor.emplace(gfx::RenderPassDescriptor{renderPass.getDescriptor().renderable, - renderPass.getDescriptor().clearColor, - renderPass.getDescriptor().clearDepth, - renderPass.getDescriptor().clearStencil}); + impl->renderPassDescriptor.emplace(gfx::RenderPassDescriptor{ + descriptor.renderable, descriptor.clearColor, descriptor.clearDepth, descriptor.clearStencil}); const auto& shaderMTL = static_cast(*shader); @@ -165,23 +184,6 @@ void Drawable::draw(PaintParameters& parameters) const { const auto debugGroup = parameters.encoder->createDebugGroup(debugLabel(*this)); #endif - /* - context.setDepthMode(getIs3D() ? parameters.depthModeFor3D() - : parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType())); - - // force disable depth test for debugging - // context.setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}}); - - // For 3D mode, stenciling is handled by the layer group - if (!is3D) { - context.setStencilMode(makeStencilMode(parameters)); - } - - context.setColorMode(getColorMode()); - context.setCullFaceMode(getCullFaceMode()); - - */ - bindAttributes(renderPass); bindUniformBuffers(renderPass); bindTextures(renderPass); @@ -207,11 +209,11 @@ void Drawable::draw(PaintParameters& parameters) const { encoder->setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone); encoder->setFrontFacingWinding(mapWindingMode(cullMode.winding)); - if (!pipelineState) { - pipelineState = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode()); + if (!impl->pipelineState) { + impl->pipelineState = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode()); } - if (pipelineState) { - encoder->setRenderPipelineState(pipelineState.get()); + if (impl->pipelineState) { + encoder->setRenderPipelineState(impl->pipelineState.get()); } else { assert(!"Failed to create render pipeline state"); return; @@ -219,12 +221,30 @@ void Drawable::draw(PaintParameters& parameters) const { // For 3D mode, stenciling is handled by the layer group if (!is3D) { - const auto depthMode = parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType()); - const auto stencilMode = enableStencil ? parameters.stencilModeForClipping(tileID->toUnwrapped()) - : gfx::StencilMode::disabled(); - if (auto depthStencilState = context.makeDepthStencilState(depthMode, stencilMode, renderPass)) { - encoder->setDepthStencilState(depthStencilState.get()); - encoder->setStencilReferenceValue(stencilMode.ref); + std::optional newStencilMode; + + // If we have a stencil state, we may be able to reuse it, if the tile masks haven't changed. + // We assume that only the reference value needs to be compared. + if (impl->depthStencilState && enableStencil) { + newStencilMode = parameters.stencilModeForClipping(tileID->toUnwrapped()); + if (newStencilMode->ref != impl->previousStencilMode.ref) { + // No, need to rebuild it + impl->depthStencilState.reset(); + } + } + if (!impl->depthStencilState) { + if (enableStencil && !newStencilMode) { + newStencilMode = parameters.stencilModeForClipping(tileID->toUnwrapped()); + } + const auto depthMode = parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType()); + const auto stencilMode = enableStencil ? parameters.stencilModeForClipping(tileID->toUnwrapped()) + : gfx::StencilMode::disabled(); + impl->depthStencilState = context.makeDepthStencilState(depthMode, stencilMode, renderPass); + impl->previousStencilMode = *newStencilMode; + } + if (impl->depthStencilState) { + encoder->setDepthStencilState(impl->depthStencilState.get()); + encoder->setStencilReferenceValue(impl->previousStencilMode.ref); } } @@ -266,7 +286,7 @@ void Drawable::draw(PaintParameters& parameters) const { assert(mlSegment.indexOffset + mlSegment.indexLength <= indexBufferLength); assert(static_cast(maxIndex) < mlSegment.vertexLength); - for (const auto& binding : attributeBindings) { + for (const auto& binding : impl->attributeBindings) { if (binding) { if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) { assert((maxIndex + mlSegment.vertexOffset) * binding->vertexStride <= buffer->length()); @@ -348,7 +368,7 @@ void Drawable::bindAttributes(const RenderPass& renderPass) const { const auto& encoder = renderPass.getMetalEncoder(); NS::UInteger attributeIndex = 0; - for (const auto& binding : attributeBindings) { + for (const auto& binding : impl->attributeBindings) { if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) { assert(binding->vertexStride * impl->vertexCount <= getBufferSize(binding->vertexBufferResource)); encoder->setVertexBuffer(buffer, /*offset=*/0, attributeIndex); @@ -363,7 +383,7 @@ void Drawable::unbindAttributes(const RenderPass& renderPass) const { const auto& encoder = renderPass.getMetalEncoder(); NS::UInteger attributeIndex = 0; - for (const auto& binding : attributeBindings) { + for (const auto& binding : impl->attributeBindings) { encoder->setVertexBuffer(nullptr, /*offset=*/0, attributeIndex); attributeIndex += 1; } @@ -558,14 +578,14 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { impl->vertexAttributes.visitAttributes( [](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); }); - if (attributeBindings != attributeBindings_) { - attributeBindings = attributeBindings_; + if (impl->attributeBindings != attributeBindings_) { + impl->attributeBindings = attributeBindings_; // Create a layout descriptor for each attribute auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor()); NS::UInteger index = 0; - for (auto& binding : attributeBindings) { + for (auto& binding : impl->attributeBindings) { if (!binding) { assert("Missing attribute binding"); continue; @@ -595,7 +615,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } impl->vertexDesc = std::move(vertDesc); - pipelineState.reset(); + impl->pipelineState.reset(); } } diff --git a/src/mbgl/mtl/drawable_impl.hpp b/src/mbgl/mtl/drawable_impl.hpp index ef386fe44..a0face522 100644 --- a/src/mbgl/mtl/drawable_impl.hpp +++ b/src/mbgl/mtl/drawable_impl.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,15 @@ public: StringIdentity idVertexAttrName = StringIndexer::get("a_pos"); gfx::UniqueVertexBufferResource noBindingBuffer; + + gfx::AttributeBindingArray attributeBindings; + + MTLRenderPipelineStatePtr pipelineState; + + std::optional renderPassDescriptor; + + MTLDepthStencilStatePtr depthStencilState; + gfx::StencilMode previousStencilMode; }; struct Drawable::DrawSegment final : public gfx::Drawable::DrawSegment { diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 1b2a14615..0badb071c 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -157,6 +157,22 @@ void PaintParameters::clearTileClippingMasks() { } } +namespace { +const auto clipMaskStencilMode = gfx::StencilMode{ + /*.test=*/gfx::StencilMode::Always(), + /*.ref=*/0, + /*.mask=*/0b11111111, + /*.fail=*/gfx::StencilOpType::Keep, + /*.depthFail=*/gfx::StencilOpType::Keep, + /*.pass=*/gfx::StencilOpType::Replace, +}; +const auto clipMaskDepthMode = gfx::DepthMode{ + .func = gfx::DepthFunctionType::Always, + .mask = gfx::DepthMaskType::ReadOnly, + .range = {0, 1}, +}; +} // namespace + template void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc&& f, bool clear) { if (tileIDsIdentical(beg, end, f, tileClippingMaskIDs)) { @@ -238,32 +254,13 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun // gfx::CullFaceMode::disabled(); encoder->setCullMode(MTL::CullModeNone); - auto stencilDescriptor = NS::TransferPtr(MTL::StencilDescriptor::alloc()->init()); - if (!stencilDescriptor) { + if (auto depthStencilState = mtlContext.makeDepthStencilState( + clipMaskDepthMode, clipMaskStencilMode, mtlRenderPass)) { + encoder->setDepthStencilState(depthStencilState.get()); + } else { + assert(!"Failed to create depth-stencil state"); return; } - stencilDescriptor->setStencilCompareFunction(MTL::CompareFunction::CompareFunctionAlways); - stencilDescriptor->setStencilFailureOperation(MTL::StencilOperation::StencilOperationKeep); - stencilDescriptor->setDepthFailureOperation(MTL::StencilOperation::StencilOperationKeep); - stencilDescriptor->setDepthStencilPassOperation(MTL::StencilOperation::StencilOperationReplace); - stencilDescriptor->setReadMask(0); - stencilDescriptor->setWriteMask(0b11111111); - - auto depthStencilDescriptor = NS::TransferPtr(MTL::DepthStencilDescriptor::alloc()->init()); - if (!depthStencilDescriptor) { - return; - } - depthStencilDescriptor->setDepthCompareFunction(MTL::CompareFunction::CompareFunctionAlways); - depthStencilDescriptor->setDepthWriteEnabled(false); - depthStencilDescriptor->setFrontFaceStencil(stencilDescriptor.get()); - depthStencilDescriptor->setBackFaceStencil(stencilDescriptor.get()); - - auto& device = mtlContext.getBackend().getDevice(); - auto depthStencilState = NS::TransferPtr(device->newDepthStencilState(depthStencilDescriptor.get())); - if (!depthStencilState) { - return; - } - encoder->setDepthStencilState(depthStencilState.get()); // Create a render pipeline state, telling Metal how to render the primitives const auto& renderPassDescriptor = mtlRenderPass.getDescriptor(); From 4e65763bc126b48cd70470d25c3a3efd2e32bed5 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Mon, 2 Oct 2023 21:20:30 +0300 Subject: [PATCH 08/19] OpenGL float support (#1717) --- src/mbgl/gl/enum.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mbgl/gl/enum.cpp b/src/mbgl/gl/enum.cpp index 060435e28..58dc1e656 100644 --- a/src/mbgl/gl/enum.cpp +++ b/src/mbgl/gl/enum.cpp @@ -398,6 +398,14 @@ platform::GLenum Enum::sizedFor<>(const gfx::TexturePixel break; } } + case gfx::TextureChannelDataType::Float: { + switch (value) { + case gfx::TexturePixelType::RGBA: + return GL_RGBA32F; + default: + break; + } + } } return GL_INVALID_ENUM; @@ -410,6 +418,8 @@ gfx::TextureChannelDataType Enum::from(const platfo return gfx::TextureChannelDataType::UnsignedByte; case GL_HALF_FLOAT: return gfx::TextureChannelDataType::HalfFloat; + case GL_FLOAT: + return gfx::TextureChannelDataType::Float; } return {}; } @@ -421,6 +431,8 @@ platform::GLenum Enum::to(const gfx::TextureChannel return GL_UNSIGNED_BYTE; case gfx::TextureChannelDataType::HalfFloat: return GL_HALF_FLOAT; + case gfx::TextureChannelDataType::Float: + return GL_FLOAT; } return GL_INVALID_ENUM; } From ef351964a144595336c02189760204aa1a8355f6 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Mon, 2 Oct 2023 22:02:47 +0300 Subject: [PATCH 09/19] Metal sep25 - Fixed compilation error (#1718) --- platform/default/src/mbgl/mtl/headless_backend.cpp | 2 +- src/mbgl/mtl/offscreen_texture.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/default/src/mbgl/mtl/headless_backend.cpp b/platform/default/src/mbgl/mtl/headless_backend.cpp index f2dc98112..2f83829aa 100644 --- a/platform/default/src/mbgl/mtl/headless_backend.cpp +++ b/platform/default/src/mbgl/mtl/headless_backend.cpp @@ -38,7 +38,7 @@ public: return offscreenTexture->getResource().getUploadPassDescriptor(); } - MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override { + const MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override { return offscreenTexture->getResource().getRenderPassDescriptor(); } diff --git a/src/mbgl/mtl/offscreen_texture.cpp b/src/mbgl/mtl/offscreen_texture.cpp index 42bb5fa8f..03e52915c 100644 --- a/src/mbgl/mtl/offscreen_texture.cpp +++ b/src/mbgl/mtl/offscreen_texture.cpp @@ -105,7 +105,7 @@ public: return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init()); } - MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override { + const MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override { assert(renderPassDescriptor); return renderPassDescriptor; } From a9ead54d737b883eeec0141cdaefd4fb08d542c9 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 3 Oct 2023 14:15:59 -0700 Subject: [PATCH 10/19] Fix line properties on Metal --- include/mbgl/renderer/layer_tweaker.hpp | 13 +++++++------ src/mbgl/renderer/layer_tweaker.cpp | 14 ++++++++++++++ src/mbgl/renderer/layers/render_line_layer.cpp | 8 ++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 31d6868eb..06c388c57 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -41,32 +41,33 @@ using StringIdentity = std::size_t; class LayerTweaker { protected: LayerTweaker(std::string id, Immutable properties); - + public: LayerTweaker() = delete; virtual ~LayerTweaker() = default; - + const std::string& getID() const { return id; } - + #if MLN_RENDER_BACKEND_METAL /// Build the common expression inupts UBO static shaders::ExpressionInputsUBO buildExpressionUBO(double zoom, uint64_t frameCount); - + /// @brief Check whether a property name exists within the previously set collection. bool hasPropertyAsUniform(StringIdentity) const; shaders::AttributeSource getAttributeSource(StringIdentity) const; - + template shaders::AttributeSource getAttributeSource(size_t index) { using ShaderClass = shaders::ShaderSource; return getAttributeSource(ShaderClass::attributes[index].nameID); } #endif // MLN_RENDER_BACKEND_METAL - + /// @brief Set the collection of attribute names which will be provided at uniform values rather than per-vertex /// attributes. /// @details These values should not have "a_" prefixes, as produced by `readDataDrivenPaintProperties`. void setPropertiesAsUniforms(const std::unordered_set&); + const std::unordered_set& getPropertiesAsUniforms() const; void enableOverdrawInspector(bool); diff --git a/src/mbgl/renderer/layer_tweaker.cpp b/src/mbgl/renderer/layer_tweaker.cpp index 1fbb1d574..682445df7 100644 --- a/src/mbgl/renderer/layer_tweaker.cpp +++ b/src/mbgl/renderer/layer_tweaker.cpp @@ -85,6 +85,20 @@ void LayerTweaker::setPropertiesAsUniforms([[maybe_unused]] const std::unordered #endif } +#if !MLN_RENDER_BACKEND_METAL +namespace { +const std::unordered_set emptyIDSet; +} +#endif + +const std::unordered_set& LayerTweaker::getPropertiesAsUniforms() const { +#if MLN_RENDER_BACKEND_METAL + return propertiesAsUniforms; +#else + return emptyIDSet; +#endif +} + void LayerTweaker::enableOverdrawInspector(bool value) { if (overdrawInspector != value) { overdrawInspector = value; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index aae15c80d..ee8f692ff 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -83,6 +83,12 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { #if MLN_DRAWABLE_RENDERER if (layerGroup) { auto newTweaker = std::make_shared(getID(), evaluatedProperties); + + // propertiesAsUniforms isn't recalculated every update, so carry it over + if (layerTweaker) { + newTweaker->setPropertiesAsUniforms(layerTweaker->getPropertiesAsUniforms()); + } + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } #endif @@ -566,6 +572,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, else if (shaderUniforms.get(idLineSDFInterpolationUBOName)) { drawableUniforms.createOrUpdate(idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context); } + + // TODO: vertex attributes or `propertiesAsUniforms` updated, is that needed? }); if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { From bdf043b91391a35d5d2db81b7ba3a6773c0771b8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 21:47:35 +0000 Subject: [PATCH 11/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/mbgl/renderer/layer_tweaker.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 06c388c57..1f00a8b6f 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -41,28 +41,28 @@ using StringIdentity = std::size_t; class LayerTweaker { protected: LayerTweaker(std::string id, Immutable properties); - + public: LayerTweaker() = delete; virtual ~LayerTweaker() = default; - + const std::string& getID() const { return id; } - + #if MLN_RENDER_BACKEND_METAL /// Build the common expression inupts UBO static shaders::ExpressionInputsUBO buildExpressionUBO(double zoom, uint64_t frameCount); - + /// @brief Check whether a property name exists within the previously set collection. bool hasPropertyAsUniform(StringIdentity) const; shaders::AttributeSource getAttributeSource(StringIdentity) const; - + template shaders::AttributeSource getAttributeSource(size_t index) { using ShaderClass = shaders::ShaderSource; return getAttributeSource(ShaderClass::attributes[index].nameID); } #endif // MLN_RENDER_BACKEND_METAL - + /// @brief Set the collection of attribute names which will be provided at uniform values rather than per-vertex /// attributes. /// @details These values should not have "a_" prefixes, as produced by `readDataDrivenPaintProperties`. From ec3f927f8350e65c958340022b54242ecce2f381 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 3 Oct 2023 22:24:45 +0000 Subject: [PATCH 12/19] Fix Linux build issues --- src/mbgl/gl/drawable_gl.cpp | 4 ++-- src/mbgl/gl/enum.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 314243ff0..fdc9e3f39 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -122,10 +122,10 @@ void DrawableGL::bindUniformBuffers() const { const auto& uniformBuffer = getUniformBuffers().get(element.first); if (!uniformBuffer) { using namespace std::string_literals; - const auto tileID = getTileID() ? util::toString(*getTileID()) : ""; + const auto tileIDStr = getTileID() ? util::toString(*getTileID()) : ""; Log::Error(Event::General, "bindUniformBuffers: UBO "s + std::string(StringIndexer::get(element.first)) + - " not found for " + util::toString(getID()) + " / " + getName() + " / " + tileID + + " not found for " + util::toString(getID()) + " / " + getName() + " / " + tileIDStr + ". skipping."); assert(false); continue; diff --git a/src/mbgl/gl/enum.cpp b/src/mbgl/gl/enum.cpp index 58dc1e656..d59306c4f 100644 --- a/src/mbgl/gl/enum.cpp +++ b/src/mbgl/gl/enum.cpp @@ -397,6 +397,7 @@ platform::GLenum Enum::sizedFor<>(const gfx::TexturePixel default: break; } + break; } case gfx::TextureChannelDataType::Float: { switch (value) { From a8f6a3b6afdd1823f598a0a5967487de06e59538 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 3 Oct 2023 22:34:55 +0000 Subject: [PATCH 13/19] More build issues --- src/mbgl/renderer/paint_parameters.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 0badb071c..65d404368 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -157,6 +157,7 @@ void PaintParameters::clearTileClippingMasks() { } } +#if MLN_RENDER_BACKEND_METAL namespace { const auto clipMaskStencilMode = gfx::StencilMode{ /*.test=*/gfx::StencilMode::Always(), @@ -167,11 +168,12 @@ const auto clipMaskStencilMode = gfx::StencilMode{ /*.pass=*/gfx::StencilOpType::Replace, }; const auto clipMaskDepthMode = gfx::DepthMode{ - .func = gfx::DepthFunctionType::Always, - .mask = gfx::DepthMaskType::ReadOnly, - .range = {0, 1}, + /*.func=*/gfx::DepthFunctionType::Always, + /*.mask=*/gfx::DepthMaskType::ReadOnly, + /*.range=*/{0, 1}, }; } // namespace +#endif // MLN_RENDER_BACKEND_METAL template void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc&& f, bool clear) { From 501125ba4b4a31e92b7f893b00953caa928a0aa7 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Wed, 4 Oct 2023 09:05:22 -0700 Subject: [PATCH 14/19] Add checks for enum conversions and `reduceMemoryUse` to improve coverage --- test/CMakeLists.txt | 1 + test/gl/context.test.cpp | 5 ++ test/gl/enum.test.cpp | 160 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 test/gl/enum.test.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bad61b04c..a11b58587 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -129,6 +129,7 @@ if(MLN_WITH_OPENGL) PRIVATE ${PROJECT_SOURCE_DIR}/test/api/custom_layer.test.cpp ${PROJECT_SOURCE_DIR}/test/gl/bucket.test.cpp + ${PROJECT_SOURCE_DIR}/test/gl/enum.test.cpp ${PROJECT_SOURCE_DIR}/test/gl/context.test.cpp ${PROJECT_SOURCE_DIR}/test/gl/gl_functions.test.cpp ${PROJECT_SOURCE_DIR}/test/gl/object.test.cpp diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp index c8bc88fd6..85311a9c8 100644 --- a/test/gl/context.test.cpp +++ b/test/gl/context.test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,11 @@ TEST(GLContextMode, Shared) { MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos)); MBGL_CHECK_ERROR(glVertexAttribPointer(paintShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3)); + + frontend.getRenderer()->reduceMemoryUse(); + ASSERT_TRUE(static_cast(frontend.getBackend()->getContext()).empty()); } test::checkImage("test/fixtures/shared_context", frontend.render(map).image, 0.5, 0.1); } + diff --git a/test/gl/enum.test.cpp b/test/gl/enum.test.cpp new file mode 100644 index 000000000..d4802232e --- /dev/null +++ b/test/gl/enum.test.cpp @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include + +using namespace mbgl; +using namespace mbgl::gfx; +using namespace mbgl::gl; + +TEST(GL, DrawModeType) { + ASSERT_EQ(GL_POINTS, Enum::to(DrawModeType::Points)); + ASSERT_EQ(GL_LINES, Enum::to(DrawModeType::Lines)); + ASSERT_EQ(GL_LINE_LOOP, Enum::to(DrawModeType::LineLoop)); + ASSERT_EQ(GL_LINE_STRIP, Enum::to(DrawModeType::LineStrip)); + ASSERT_EQ(GL_TRIANGLES, Enum::to(DrawModeType::Triangles)); + ASSERT_EQ(GL_TRIANGLE_STRIP, Enum::to(DrawModeType::TriangleStrip)); + ASSERT_EQ(GL_TRIANGLE_FAN, Enum::to(DrawModeType::TriangleFan)); + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); +} + +namespace { +template +auto enumIdentity(T x) { return Enum::from(Enum::to(x)); } +} + +TEST(GL, ColorBlendEquationType) { + //const auto identity = [](auto x){ return Enum::from(Enum::to(x)); }; + ASSERT_EQ(ColorBlendEquationType::Add, enumIdentity(ColorBlendEquationType::Add)); + ASSERT_EQ(ColorBlendEquationType::Subtract, enumIdentity(ColorBlendEquationType::Subtract)); + ASSERT_EQ(ColorBlendEquationType::ReverseSubtract, enumIdentity(ColorBlendEquationType::ReverseSubtract)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(ColorBlendEquationType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, ColorBlendFactorType) { + ASSERT_EQ(ColorBlendFactorType::Zero, enumIdentity(ColorBlendFactorType::Zero)); + ASSERT_EQ(ColorBlendFactorType::One, enumIdentity(ColorBlendFactorType::One)); + ASSERT_EQ(ColorBlendFactorType::SrcColor, enumIdentity(ColorBlendFactorType::SrcColor)); + ASSERT_EQ(ColorBlendFactorType::OneMinusSrcColor, enumIdentity(ColorBlendFactorType::OneMinusSrcColor)); + ASSERT_EQ(ColorBlendFactorType::DstColor, enumIdentity(ColorBlendFactorType::DstColor)); + ASSERT_EQ(ColorBlendFactorType::OneMinusDstColor, enumIdentity(ColorBlendFactorType::OneMinusDstColor)); + ASSERT_EQ(ColorBlendFactorType::SrcAlpha, enumIdentity(ColorBlendFactorType::SrcAlpha)); + ASSERT_EQ(ColorBlendFactorType::OneMinusSrcAlpha, enumIdentity(ColorBlendFactorType::OneMinusSrcAlpha)); + ASSERT_EQ(ColorBlendFactorType::DstAlpha, enumIdentity(ColorBlendFactorType::DstAlpha)); + ASSERT_EQ(ColorBlendFactorType::OneMinusDstAlpha, enumIdentity(ColorBlendFactorType::OneMinusDstAlpha)); + ASSERT_EQ(ColorBlendFactorType::ConstantColor, enumIdentity(ColorBlendFactorType::ConstantColor)); + ASSERT_EQ(ColorBlendFactorType::OneMinusConstantColor, enumIdentity(ColorBlendFactorType::OneMinusConstantColor)); + ASSERT_EQ(ColorBlendFactorType::ConstantAlpha, enumIdentity(ColorBlendFactorType::ConstantAlpha)); + ASSERT_EQ(ColorBlendFactorType::OneMinusConstantAlpha, enumIdentity(ColorBlendFactorType::OneMinusConstantAlpha)); + ASSERT_EQ(ColorBlendFactorType::SrcAlphaSaturate, enumIdentity(ColorBlendFactorType::SrcAlphaSaturate)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(ColorBlendFactorType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, DepthFunctionType) { + ASSERT_EQ(DepthFunctionType::Never, enumIdentity(DepthFunctionType::Never)); + ASSERT_EQ(DepthFunctionType::Less, enumIdentity(DepthFunctionType::Less)); + ASSERT_EQ(DepthFunctionType::Equal, enumIdentity(DepthFunctionType::Equal)); + ASSERT_EQ(DepthFunctionType::LessEqual, enumIdentity(DepthFunctionType::LessEqual)); + ASSERT_EQ(DepthFunctionType::Greater, enumIdentity(DepthFunctionType::Greater)); + ASSERT_EQ(DepthFunctionType::NotEqual, enumIdentity(DepthFunctionType::NotEqual)); + ASSERT_EQ(DepthFunctionType::GreaterEqual, enumIdentity(DepthFunctionType::GreaterEqual)); + ASSERT_EQ(DepthFunctionType::Always, enumIdentity(DepthFunctionType::Always)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(DepthFunctionType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, DepthMaskType) { + ASSERT_EQ(DepthMaskType::ReadOnly, enumIdentity(DepthMaskType::ReadOnly)); + ASSERT_EQ(DepthMaskType::ReadWrite, enumIdentity(DepthMaskType::ReadWrite)); + + // anything non-zero is true, there's no way to represent invalid + ASSERT_EQ(GL_TRUE, Enum::to(static_cast(-1))); +} + +TEST(GL, StencilFunctionType) { + ASSERT_EQ(StencilFunctionType::Never, enumIdentity(StencilFunctionType::Never)); + ASSERT_EQ(StencilFunctionType::Less, enumIdentity(StencilFunctionType::Less)); + ASSERT_EQ(StencilFunctionType::Equal, enumIdentity(StencilFunctionType::Equal)); + ASSERT_EQ(StencilFunctionType::LessEqual, enumIdentity(StencilFunctionType::LessEqual)); + ASSERT_EQ(StencilFunctionType::Greater, enumIdentity(StencilFunctionType::Greater)); + ASSERT_EQ(StencilFunctionType::NotEqual, enumIdentity(StencilFunctionType::NotEqual)); + ASSERT_EQ(StencilFunctionType::GreaterEqual, enumIdentity(StencilFunctionType::GreaterEqual)); + ASSERT_EQ(StencilFunctionType::Always, enumIdentity(StencilFunctionType::Always)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(StencilFunctionType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, StencilOpType) { + ASSERT_EQ(StencilOpType::Keep, enumIdentity(StencilOpType::Keep)); + ASSERT_EQ(StencilOpType::Zero, enumIdentity(StencilOpType::Zero)); + ASSERT_EQ(StencilOpType::Replace, enumIdentity(StencilOpType::Replace)); + ASSERT_EQ(StencilOpType::Increment, enumIdentity(StencilOpType::Increment)); + ASSERT_EQ(StencilOpType::IncrementWrap, enumIdentity(StencilOpType::IncrementWrap)); + ASSERT_EQ(StencilOpType::Decrement, enumIdentity(StencilOpType::Decrement)); + ASSERT_EQ(StencilOpType::DecrementWrap, enumIdentity(StencilOpType::DecrementWrap)); + ASSERT_EQ(StencilOpType::Invert, enumIdentity(StencilOpType::Invert)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(StencilOpType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, CullFaceSideType) { + ASSERT_EQ(CullFaceSideType::Front, enumIdentity(CullFaceSideType::Front)); + ASSERT_EQ(CullFaceSideType::Back, enumIdentity(CullFaceSideType::Back)); + ASSERT_EQ(CullFaceSideType::FrontAndBack, enumIdentity(CullFaceSideType::FrontAndBack)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(CullFaceSideType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, CullFaceWindingType) { + ASSERT_EQ(CullFaceWindingType::Clockwise, enumIdentity(CullFaceWindingType::Clockwise)); + ASSERT_EQ(CullFaceWindingType::CounterClockwise, enumIdentity(CullFaceWindingType::CounterClockwise)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(CullFaceWindingType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, BufferUsageType) { + ASSERT_EQ(BufferUsageType::StreamDraw, enumIdentity(BufferUsageType::StreamDraw)); + ASSERT_EQ(BufferUsageType::StaticDraw, enumIdentity(BufferUsageType::StaticDraw)); + ASSERT_EQ(BufferUsageType::DynamicDraw, enumIdentity(BufferUsageType::DynamicDraw)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(BufferUsageType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, TexturePixelType) { + ASSERT_EQ(TexturePixelType::RGBA, enumIdentity(TexturePixelType::RGBA)); + ASSERT_EQ(TexturePixelType::Alpha, enumIdentity(TexturePixelType::Alpha)); + ASSERT_EQ(TexturePixelType::Stencil, enumIdentity(TexturePixelType::Stencil)); + ASSERT_EQ(TexturePixelType::Depth, enumIdentity(TexturePixelType::Depth)); + ASSERT_EQ(TexturePixelType::Luminance, enumIdentity(TexturePixelType::Luminance)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(TexturePixelType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, TextureChannelDataType) { + ASSERT_EQ(TextureChannelDataType::UnsignedByte, enumIdentity(TextureChannelDataType::UnsignedByte)); + ASSERT_EQ(TextureChannelDataType::HalfFloat, enumIdentity(TextureChannelDataType::HalfFloat)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(TextureChannelDataType{}, Enum::from(GL_RGBA8)); +} + +TEST(GL, RenderbufferPixelType) { + ASSERT_EQ(RenderbufferPixelType::RGBA, enumIdentity(RenderbufferPixelType::RGBA)); + ASSERT_EQ(RenderbufferPixelType::Depth, enumIdentity(RenderbufferPixelType::Depth)); + ASSERT_EQ(RenderbufferPixelType::DepthStencil, enumIdentity(RenderbufferPixelType::DepthStencil)); + + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); + ASSERT_EQ(RenderbufferPixelType{}, Enum::from(GL_RGBA8)); +} From afb2062b61ab98537e8911422e184db057c15e54 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:05:46 +0000 Subject: [PATCH 15/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test/gl/context.test.cpp | 1 - test/gl/enum.test.cpp | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp index 85311a9c8..e04d08f3b 100644 --- a/test/gl/context.test.cpp +++ b/test/gl/context.test.cpp @@ -122,4 +122,3 @@ TEST(GLContextMode, Shared) { test::checkImage("test/fixtures/shared_context", frontend.render(map).image, 0.5, 0.1); } - diff --git a/test/gl/enum.test.cpp b/test/gl/enum.test.cpp index d4802232e..6cc13d0e2 100644 --- a/test/gl/enum.test.cpp +++ b/test/gl/enum.test.cpp @@ -21,11 +21,14 @@ TEST(GL, DrawModeType) { namespace { template -auto enumIdentity(T x) { return Enum::from(Enum::to(x)); } +auto enumIdentity(T x) { + return Enum::from(Enum::to(x)); } +} // namespace TEST(GL, ColorBlendEquationType) { - //const auto identity = [](auto x){ return Enum::from(Enum::to(x)); }; + // const auto identity = [](auto x){ return Enum::from(Enum::to(x)); + // }; ASSERT_EQ(ColorBlendEquationType::Add, enumIdentity(ColorBlendEquationType::Add)); ASSERT_EQ(ColorBlendEquationType::Subtract, enumIdentity(ColorBlendEquationType::Subtract)); ASSERT_EQ(ColorBlendEquationType::ReverseSubtract, enumIdentity(ColorBlendEquationType::ReverseSubtract)); @@ -50,7 +53,7 @@ TEST(GL, ColorBlendFactorType) { ASSERT_EQ(ColorBlendFactorType::ConstantAlpha, enumIdentity(ColorBlendFactorType::ConstantAlpha)); ASSERT_EQ(ColorBlendFactorType::OneMinusConstantAlpha, enumIdentity(ColorBlendFactorType::OneMinusConstantAlpha)); ASSERT_EQ(ColorBlendFactorType::SrcAlphaSaturate, enumIdentity(ColorBlendFactorType::SrcAlphaSaturate)); - + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); ASSERT_EQ(ColorBlendFactorType{}, Enum::from(GL_RGBA8)); } @@ -64,7 +67,7 @@ TEST(GL, DepthFunctionType) { ASSERT_EQ(DepthFunctionType::NotEqual, enumIdentity(DepthFunctionType::NotEqual)); ASSERT_EQ(DepthFunctionType::GreaterEqual, enumIdentity(DepthFunctionType::GreaterEqual)); ASSERT_EQ(DepthFunctionType::Always, enumIdentity(DepthFunctionType::Always)); - + ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); ASSERT_EQ(DepthFunctionType{}, Enum::from(GL_RGBA8)); } From 4001b1bb4d54f1885fcd90650ec1f817adfe1117 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Wed, 4 Oct 2023 19:12:38 +0300 Subject: [PATCH 16/19] Fixed offscreen unit tests (#1723) --- .../renderer/sources/render_image_source.cpp | 2 ++ test/renderer/shader_registry.test.cpp | 12 ++++++++++ test/util/offscreen_texture.test.cpp | 24 ++++++++++--------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 5fd73e490..6c23c386c 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -24,11 +24,13 @@ void ImageSourceRenderData::upload(gfx::UploadPass& uploadPass) const { bucket->upload(uploadPass); } +#if MLN_LEGACY_RENDERER if (!debugTexture) { std::array data{{0, 0, 0, 0}}; static const PremultipliedImage emptyImage{Size(1, 1), data.data(), data.size()}; debugTexture = uploadPass.createTexture(emptyImage); } +#endif } void ImageSourceRenderData::render(PaintParameters& parameters) const { diff --git a/test/renderer/shader_registry.test.cpp b/test/renderer/shader_registry.test.cpp index ee362370a..d9ecd1ee3 100644 --- a/test/renderer/shader_registry.test.cpp +++ b/test/renderer/shader_registry.test.cpp @@ -207,7 +207,11 @@ TEST(ShaderRegistry, NamedReplace) { } // Test replacing an actual program instance with a similar instance +#if MLN_LEGACY_RENDERER TEST(ShaderRegistry, GLSLReplacement_NoOp) { +#else +TEST(ShaderRegistry, DISABLED_GLSLReplacement_NoOp) { +#endif MapInstance::ShaderAndStyleObserver observer; util::RunLoop runLoop; auto map = MapInstance(1.0f, observer); @@ -233,7 +237,11 @@ TEST(ShaderRegistry, GLSLReplacement_NoOp) { // Test replacing an actual program with a similar instance using a different // fragment shader +#if MLN_LEGACY_RENDERER TEST(ShaderRegistry, GLSLReplacement1) { +#else +TEST(ShaderRegistry, DISABLED_GLSLReplacement1) { +#endif MapInstance::ShaderAndStyleObserver observer; util::RunLoop runLoop; auto map = MapInstance(1.0f, observer); @@ -267,7 +275,11 @@ void main() { // Test replacing an actual program with a similar instance using a different // fragment shader +#if MLN_LEGACY_RENDERER TEST(ShaderRegistry, GLSLReplacement2) { +#else +TEST(ShaderRegistry, DISABLED_GLSLReplacement2) { +#endif MapInstance::ShaderAndStyleObserver observer; util::RunLoop runLoop; auto map = MapInstance(1.0f, observer); diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp index adf3f3dce..282579101 100644 --- a/test/util/offscreen_texture.test.cpp +++ b/test/util/offscreen_texture.test.cpp @@ -4,12 +4,17 @@ #include #include #include -#include #include #include #include #include +#if MLN_LEGACY_RENDERER +#include +#else +#include +#endif + using namespace mbgl; using namespace mbgl::platform; @@ -75,11 +80,7 @@ struct Buffer { GLuint buffer = 0; }; -#if MLN_LEGACY_RENDERER TEST(OffscreenTexture, RenderToTexture) { -#else -TEST(OffscreenTexture, DISABLED_RenderToTexture) { -#endif if (gfx::Backend::GetType() != gfx::Backend::Type::OpenGL) { return; } @@ -145,13 +146,13 @@ void main() { // Then, create a texture, bind it, and render yellow to that texture. This // should not affect the originally bound FBO. - gl::OffscreenTexture texture(context, {128, 128}); + gl::OffscreenTexture offscreenTexture(context, {128, 128}); // Scissor test shouldn't leak after OffscreenTexture::bind(). MBGL_CHECK_ERROR(glScissor(32, 32, 64, 64)); context.scissorTest.setCurrentValue(true); - texture.getResource().bind(); + offscreenTexture.getResource().bind(); context.clear(Color(), {}, {}); @@ -161,7 +162,7 @@ void main() { MBGL_CHECK_ERROR(glVertexAttribPointer(paintShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3)); - auto image = texture.readStillImage(); + auto image = offscreenTexture.readStillImage(); test::checkImage("test/fixtures/offscreen_texture/render-to-texture", image, 0, 0); // Now reset the FBO back to normal and retrieve the original (restored) framebuffer. @@ -172,12 +173,13 @@ void main() { // Now, composite the Framebuffer texture we've rendered to onto the main FBO. #if MLN_LEGACY_RENDERER - gl::bindTexture(context, 0, {texture.getTexture().getResource(), gfx::TextureFilterType::Linear}); + gl::bindTexture(context, 0, {offscreenTexture.getTexture().getResource(), gfx::TextureFilterType::Linear}); + MBGL_CHECK_ERROR(glUniform1i(u_texture, 0)); #else - // TODO: Implement based on gfx::Texture2D + offscreenTexture.getTexture()->setSamplerConfiguration({gfx::TextureFilterType::Linear}); + std::static_pointer_cast(offscreenTexture.getTexture())->bind(u_texture, 0); #endif MBGL_CHECK_ERROR(glUseProgram(compositeShader.program)); - MBGL_CHECK_ERROR(glUniform1i(u_texture, 0)); MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, viewportBuffer.buffer)); MBGL_CHECK_ERROR(glEnableVertexAttribArray(compositeShader.a_pos)); MBGL_CHECK_ERROR(glVertexAttribPointer(compositeShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); From 60b07656bf6f42ba0c85cf88bf5c6e9f2f2d678a Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Wed, 4 Oct 2023 10:12:47 -0700 Subject: [PATCH 17/19] more test coverage --- test/gl/enum.test.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/gl/enum.test.cpp b/test/gl/enum.test.cpp index 6cc13d0e2..ffda174fd 100644 --- a/test/gl/enum.test.cpp +++ b/test/gl/enum.test.cpp @@ -148,6 +148,7 @@ TEST(GL, TexturePixelType) { TEST(GL, TextureChannelDataType) { ASSERT_EQ(TextureChannelDataType::UnsignedByte, enumIdentity(TextureChannelDataType::UnsignedByte)); ASSERT_EQ(TextureChannelDataType::HalfFloat, enumIdentity(TextureChannelDataType::HalfFloat)); + ASSERT_EQ(TextureChannelDataType::Float, enumIdentity(TextureChannelDataType::Float)); ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); ASSERT_EQ(TextureChannelDataType{}, Enum::from(GL_RGBA8)); @@ -161,3 +162,12 @@ TEST(GL, RenderbufferPixelType) { ASSERT_EQ(GL_INVALID_ENUM, Enum::to(static_cast(-1))); ASSERT_EQ(RenderbufferPixelType{}, Enum::from(GL_RGBA8)); } + +TEST(GL, sizedFor) { + ASSERT_EQ(GL_RGBA, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::UnsignedByte)); + ASSERT_EQ(GL_RGBA16F, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::HalfFloat)); + ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::HalfFloat)); + ASSERT_EQ(GL_RGBA32F, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::Float)); + ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::Float)); + ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::RGBA, static_cast(-1))); +} From c67bc3b18abe0de51d9940e5120fec61504f4ea7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:14:22 +0000 Subject: [PATCH 18/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test/gl/enum.test.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/gl/enum.test.cpp b/test/gl/enum.test.cpp index ffda174fd..ab4a95153 100644 --- a/test/gl/enum.test.cpp +++ b/test/gl/enum.test.cpp @@ -164,10 +164,15 @@ TEST(GL, RenderbufferPixelType) { } TEST(GL, sizedFor) { - ASSERT_EQ(GL_RGBA, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::UnsignedByte)); - ASSERT_EQ(GL_RGBA16F, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::HalfFloat)); - ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::HalfFloat)); + ASSERT_EQ(GL_RGBA, + Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::UnsignedByte)); + ASSERT_EQ(GL_RGBA16F, + Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::HalfFloat)); + ASSERT_EQ(GL_INVALID_ENUM, + Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::HalfFloat)); ASSERT_EQ(GL_RGBA32F, Enum::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::Float)); - ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::Float)); - ASSERT_EQ(GL_INVALID_ENUM, Enum::sizedFor(TexturePixelType::RGBA, static_cast(-1))); + ASSERT_EQ(GL_INVALID_ENUM, + Enum::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::Float)); + ASSERT_EQ(GL_INVALID_ENUM, + Enum::sizedFor(TexturePixelType::RGBA, static_cast(-1))); } From db798459882e04a1a0e6513744133af4e71e042f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 19:20:33 +0000 Subject: [PATCH 19/19] chore(deps): update dependency rules_xcodeproj to v1.12.0 --- WORKSPACE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 47bb88527..401e01c58 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -10,8 +10,8 @@ http_archive( http_archive( name = "rules_xcodeproj", - sha256 = "4886d10566dade9048a0b239fc43c21c29bb0ba03fb611a997f7b786d6e859b6", - url = "https://github.com/MobileNativeFoundation/rules_xcodeproj/releases/download/1.11.0/release.tar.gz", + sha256 = "d25a6af62c0b9ad781a824f6c1e866f8106531019cb7a172bd17eb9cc805a6f7", + url = "https://github.com/MobileNativeFoundation/rules_xcodeproj/releases/download/1.12.0/release.tar.gz", ) load(