diff --git a/CMakeLists.txt b/CMakeLists.txt index d6bb697b5..292e9254f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -404,6 +404,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/util/instrumentation.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/interpolate.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/logging.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/util/lru_cache.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/noncopyable.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/platform.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/premultiply.hpp @@ -1094,6 +1095,8 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderer_backend.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/resource_pool.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/resource_pool.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/state.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index d62f246be..8f85b956e 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -830,6 +830,7 @@ MLN_CORE_HEADERS = [ "include/mbgl/util/instrumentation.hpp", "include/mbgl/util/interpolate.hpp", "include/mbgl/util/logging.hpp", + "include/mbgl/util/lru_cache.hpp", "include/mbgl/util/monotonic_timer.hpp", "include/mbgl/util/noncopyable.hpp", "include/mbgl/util/platform.hpp", @@ -886,6 +887,8 @@ MLN_OPENGL_SOURCE = [ "src/mbgl/gl/renderbuffer_resource.cpp", "src/mbgl/gl/renderbuffer_resource.hpp", "src/mbgl/gl/renderer_backend.cpp", + "src/mbgl/gl/resource_pool.cpp", + "src/mbgl/gl/resource_pool.hpp", "src/mbgl/gl/state.hpp", "src/mbgl/gl/texture.cpp", "src/mbgl/gl/texture.hpp", diff --git a/include/mbgl/gl/texture2d.hpp b/include/mbgl/gl/texture2d.hpp index 01e02035c..97984dba1 100644 --- a/include/mbgl/gl/texture2d.hpp +++ b/include/mbgl/gl/texture2d.hpp @@ -59,8 +59,8 @@ public: void unbind() noexcept; private: - void createObject() noexcept; - void createStorage(const void* data = nullptr) noexcept; + void allocateTexture() noexcept; + void updateTextureData(const void* data = nullptr) noexcept; private: gl::Context& context; diff --git a/include/mbgl/util/instrumentation.hpp b/include/mbgl/util/instrumentation.hpp index c538cbd8e..852871442 100644 --- a/include/mbgl/util/instrumentation.hpp +++ b/include/mbgl/util/instrumentation.hpp @@ -93,7 +93,7 @@ constexpr const char* tracyConstMemoryLabel = "Constant Buffer Memory"; #define MLN_TRACE_GL_CONTEXT() ((void)0) #define MLN_TRACE_GL_ZONE(label) ((void)0) #define MLN_TRACE_FUNC_GL() ((void)0) -#define MLN_END_FRAME() FrameMark; +#define MLN_END_FRAME() FrameMark #endif // MLN_RENDER_BACKEND_OPENGL diff --git a/include/mbgl/util/lru_cache.hpp b/include/mbgl/util/lru_cache.hpp new file mode 100644 index 000000000..81aa67c89 --- /dev/null +++ b/include/mbgl/util/lru_cache.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +// Simple non-thread-safe LRU cache +template > +class LRU { +public: + // Number of cached items + size_t size() const { return list.size(); } + + // Check if cache is empty + bool empty() const { return list.empty(); } + + // Access x + // If x is already cached, move it to the front (most recently used) + void touch(Item x) { + auto it = map.find(x); + if (it != map.end()) { + list.splice(list.begin(), list, it->second); + } else { + list.push_front(x); + map[std::move(x)] = list.begin(); + } + } + + // Evict the least recently used item + // If the cache is empty, throw an exception + Item evict() { + if (list.empty()) { + throw std::runtime_error("LRU::evict: empty cache"); + } + Item x = std::move(list.back()); + map.erase(x); + list.pop_back(); + return x; + } + + // Check if item exists in cache without changing its order + bool isHit(const Item& x) const { return map.find(std::move(x)) != map.end(); } + + // remove item from cache if it exists + void remove(const Item& x) { + auto it = map.find(x); + if (it != map.end()) { + list.erase(it->second); + map.erase(it); + } + } + +private: + std::list list; + std::unordered_map::iterator, Hash> map; +}; + +} // namespace mbgl diff --git a/metrics/linux-clang8-release/render-tests/line-dasharray/zoom-history/metrics.json b/metrics/linux-clang8-release/render-tests/line-dasharray/zoom-history/metrics.json index b4f03708c..0b59834ac 100644 --- a/metrics/linux-clang8-release/render-tests/line-dasharray/zoom-history/metrics.json +++ b/metrics/linux-clang8-release/render-tests/line-dasharray/zoom-history/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 147712, - 147712 + 164096, + 164096 ], [ 130, diff --git a/metrics/linux-clang8-release/render-tests/map-mode/tile-avoid-edges/metrics.json b/metrics/linux-clang8-release/render-tests/map-mode/tile-avoid-edges/metrics.json index c158d2da3..12ed06367 100644 --- a/metrics/linux-clang8-release/render-tests/map-mode/tile-avoid-edges/metrics.json +++ b/metrics/linux-clang8-release/render-tests/map-mode/tile-avoid-edges/metrics.json @@ -19,8 +19,8 @@ 51, 1, [ - 53024, - 53024 + 53032, + 53032 ], [ 43734, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json index bc237525b..7bca5d23f 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json @@ -19,8 +19,8 @@ 17, 1, [ - 125574, - 125574 + 191110, + 191110 ], [ 454, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json index bf5b94a72..c2b157771 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json @@ -19,8 +19,8 @@ 8, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json index fea6fe2e5..3420d4a3f 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 22784, - 22784 + 29184, + 29184 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json index ad0cf8a26..52ca39366 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 22784, - 22784 + 25088, + 25088 ], [ 22, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json index bb8ac8538..4bb79fe71 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 94, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json index daa3b24ba..b6bf3b9d0 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 33768, - 33768 + 50702, + 50702 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json index e85e6b42d..71ac27d9d 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 22080, - 22080 + 27776, + 27776 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json index 01b432fe2..cbd01b37e 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json index 50f1262c4..4a3aa6347 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 32768, - 32768 + 114688, + 114688 ], [ 22, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json index ecd1b9eaf..6623f4879 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json index 7da079696..857fa5f5e 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 65536, - 65536 + 81920, + 81920 ], [ 22, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json index 7f54e7480..effeefa2a 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 21264, - 21264 + 42528, + 42528 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json index 662a5ca35..6e487ce43 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json @@ -19,8 +19,8 @@ 17, 1, [ - 163840, - 163840 + 196608, + 196608 ], [ 118, diff --git a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json index 5068fa89b..1b7a2185c 100644 --- a/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json +++ b/metrics/linux-clang8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 65536, + 65536 ], [ 82, diff --git a/metrics/linux-clang8-release/render-tests/runtime-styling/image-update-icon/metrics.json b/metrics/linux-clang8-release/render-tests/runtime-styling/image-update-icon/metrics.json index 9b2e396f8..ff91a11d5 100644 --- a/metrics/linux-clang8-release/render-tests/runtime-styling/image-update-icon/metrics.json +++ b/metrics/linux-clang8-release/render-tests/runtime-styling/image-update-icon/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 24576, - 24576 + 46656, + 46656 ], [ 34, diff --git a/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json b/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json +++ b/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json b/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json +++ b/metrics/linux-clang8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json b/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json index 228731dd4..6f795d0ee 100644 --- a/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json +++ b/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 32, 4, [ - 158509, - 158509 + 321286, + 321286 ], [ 712, diff --git a/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json b/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json index e6f162de0..48f5e22ba 100644 --- a/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json +++ b/metrics/linux-clang8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 60, 4, [ - 131780, - 131780 + 230615, + 230615 ], [ 102328, diff --git a/metrics/linux-clang8-release/render-tests/text-size/zero/metrics.json b/metrics/linux-clang8-release/render-tests/text-size/zero/metrics.json index 6acd7b528..7cc4d80c9 100644 --- a/metrics/linux-clang8-release/render-tests/text-size/zero/metrics.json +++ b/metrics/linux-clang8-release/render-tests/text-size/zero/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 215688, - 215688 + 281224, + 281224 ], [ 58, diff --git a/metrics/linux-clang8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json b/metrics/linux-clang8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json index 1a348fa3e..1ca57cbe4 100644 --- a/metrics/linux-clang8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json +++ b/metrics/linux-clang8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 36, 4, [ - 143344, - 143344 + 250852, + 250852 ], [ 194056, diff --git a/metrics/linux-clang8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json b/metrics/linux-clang8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json index 22295b952..813a3d7f1 100644 --- a/metrics/linux-clang8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json +++ b/metrics/linux-clang8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 52, 4, [ - 296872, - 296872 + 685542, + 685542 ], [ 79084, diff --git a/metrics/linux-clang8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json b/metrics/linux-clang8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json index c4efa5911..2a7b3b9cd 100644 --- a/metrics/linux-clang8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json +++ b/metrics/linux-clang8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json @@ -19,8 +19,8 @@ 27, 1, [ - 150144, - 150144 + 215680, + 215680 ], [ 406, diff --git a/metrics/linux-clang8-release/render-tests/zoom-history/in/metrics.json b/metrics/linux-clang8-release/render-tests/zoom-history/in/metrics.json index ba820d16d..084056a13 100644 --- a/metrics/linux-clang8-release/render-tests/zoom-history/in/metrics.json +++ b/metrics/linux-clang8-release/render-tests/zoom-history/in/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 98816, - 98816 + 164352, + 164352 ], [ 82, diff --git a/metrics/linux-clang8-release/render-tests/zoom-history/out/metrics.json b/metrics/linux-clang8-release/render-tests/zoom-history/out/metrics.json index ba820d16d..084056a13 100644 --- a/metrics/linux-clang8-release/render-tests/zoom-history/out/metrics.json +++ b/metrics/linux-clang8-release/render-tests/zoom-history/out/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 98816, - 98816 + 164352, + 164352 ], [ 82, diff --git a/metrics/linux-clang8-release/render-tests/zoom-visibility/in-range/metrics.json b/metrics/linux-clang8-release/render-tests/zoom-visibility/in-range/metrics.json index ed4871473..a9262cad3 100644 --- a/metrics/linux-clang8-release/render-tests/zoom-visibility/in-range/metrics.json +++ b/metrics/linux-clang8-release/render-tests/zoom-visibility/in-range/metrics.json @@ -19,8 +19,8 @@ 21, 1, [ - 196608, - 196608 + 262144, + 262144 ], [ 118, diff --git a/metrics/linux-clang8-release/render-tests/zoom-visibility/out-of-range/metrics.json b/metrics/linux-clang8-release/render-tests/zoom-visibility/out-of-range/metrics.json index 8fbd5d92e..a00f95be7 100644 --- a/metrics/linux-clang8-release/render-tests/zoom-visibility/out-of-range/metrics.json +++ b/metrics/linux-clang8-release/render-tests/zoom-visibility/out-of-range/metrics.json @@ -19,8 +19,8 @@ 13, 1, [ - 131072, - 131072 + 196608, + 196608 ], [ 70, diff --git a/metrics/linux-gcc8-release/render-tests/line-dasharray/zoom-history/metrics.json b/metrics/linux-gcc8-release/render-tests/line-dasharray/zoom-history/metrics.json index b4f03708c..0b59834ac 100644 --- a/metrics/linux-gcc8-release/render-tests/line-dasharray/zoom-history/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/line-dasharray/zoom-history/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 147712, - 147712 + 164096, + 164096 ], [ 130, diff --git a/metrics/linux-gcc8-release/render-tests/map-mode/tile-avoid-edges/metrics.json b/metrics/linux-gcc8-release/render-tests/map-mode/tile-avoid-edges/metrics.json index c158d2da3..12ed06367 100644 --- a/metrics/linux-gcc8-release/render-tests/map-mode/tile-avoid-edges/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/map-mode/tile-avoid-edges/metrics.json @@ -19,8 +19,8 @@ 51, 1, [ - 53024, - 53024 + 53032, + 53032 ], [ 43734, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json index bc237525b..7bca5d23f 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3623/metrics.json @@ -19,8 +19,8 @@ 17, 1, [ - 125574, - 125574 + 191110, + 191110 ], [ 454, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#3949/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json index bf5b94a72..c2b157771 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-js#5370/metrics.json @@ -19,8 +19,8 @@ 8, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json index fea6fe2e5..3420d4a3f 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#5701/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 22784, - 22784 + 29184, + 29184 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json index ad0cf8a26..52ca39366 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6063/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 22784, - 22784 + 25088, + 25088 ], [ 22, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json index bb8ac8538..4bb79fe71 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6233/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 94, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json index daa3b24ba..b6bf3b9d0 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6820/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 33768, - 33768 + 50702, + 50702 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json index e85e6b42d..71ac27d9d 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#6903/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 22080, - 22080 + 27776, + 27776 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json index 01b432fe2..cbd01b37e 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#7241/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json index 50f1262c4..4a3aa6347 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8505/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 32768, - 32768 + 114688, + 114688 ], [ 22, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json index ecd1b9eaf..6623f4879 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8871/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json index 7da079696..857fa5f5e 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#8952/metrics.json @@ -19,8 +19,8 @@ 5, 1, [ - 65536, - 65536 + 81920, + 81920 ], [ 22, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json index 7f54e7480..effeefa2a 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9557/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 21264, - 21264 + 42528, + 42528 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json index 662a5ca35..6e487ce43 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9900/metrics.json @@ -19,8 +19,8 @@ 17, 1, [ - 163840, - 163840 + 196608, + 196608 ], [ 118, diff --git a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json index 5068fa89b..1b7a2185c 100644 --- a/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/regressions/mapbox-gl-native#9979/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 65536, + 65536 ], [ 82, diff --git a/metrics/linux-gcc8-release/render-tests/runtime-styling/image-update-icon/metrics.json b/metrics/linux-gcc8-release/render-tests/runtime-styling/image-update-icon/metrics.json index 9b2e396f8..ff91a11d5 100644 --- a/metrics/linux-gcc8-release/render-tests/runtime-styling/image-update-icon/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/runtime-styling/image-update-icon/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 24576, - 24576 + 46656, + 46656 ], [ 34, diff --git a/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json b/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-expression-to-literal/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json b/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json index b7fcd0454..cfdc9c2e2 100644 --- a/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/runtime-styling/paint-property-property-function-to-literal/metrics.json @@ -19,8 +19,8 @@ 7, 1, [ - 32768, - 32768 + 49152, + 49152 ], [ 46, diff --git a/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json b/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json index 228731dd4..6f795d0ee 100644 --- a/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-buffer-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 32, 4, [ - 158509, - 158509 + 321286, + 321286 ], [ 712, diff --git a/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json b/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json index e6f162de0..48f5e22ba 100644 --- a/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/symbol-placement/line-center-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 60, 4, [ - 131780, - 131780 + 230615, + 230615 ], [ 102328, diff --git a/metrics/linux-gcc8-release/render-tests/text-size/zero/metrics.json b/metrics/linux-gcc8-release/render-tests/text-size/zero/metrics.json index ef15ba387..7cc4d80c9 100644 --- a/metrics/linux-gcc8-release/render-tests/text-size/zero/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/text-size/zero/metrics.json @@ -19,8 +19,8 @@ 9, 1, [ - 215688, - 215688 + 281224, + 281224 ], [ 58, @@ -32,4 +32,4 @@ ] ] ] -} +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json index 1a348fa3e..1ca57cbe4 100644 --- a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/all-anchors-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 36, 4, [ - 143344, - 143344 + 250852, + 250852 ], [ 194056, diff --git a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json index 22295b952..813a3d7f1 100644 --- a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/left-top-right-bottom-offset-tile-map-mode/metrics.json @@ -19,8 +19,8 @@ 52, 4, [ - 296872, - 296872 + 685542, + 685542 ], [ 79084, diff --git a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json index c4efa5911..2a7b3b9cd 100644 --- a/metrics/linux-gcc8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/text-variable-anchor/no-animate-zoom/metrics.json @@ -19,8 +19,8 @@ 27, 1, [ - 150144, - 150144 + 215680, + 215680 ], [ 406, diff --git a/metrics/linux-gcc8-release/render-tests/zoom-history/in/metrics.json b/metrics/linux-gcc8-release/render-tests/zoom-history/in/metrics.json index ba820d16d..084056a13 100644 --- a/metrics/linux-gcc8-release/render-tests/zoom-history/in/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/zoom-history/in/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 98816, - 98816 + 164352, + 164352 ], [ 82, diff --git a/metrics/linux-gcc8-release/render-tests/zoom-history/out/metrics.json b/metrics/linux-gcc8-release/render-tests/zoom-history/out/metrics.json index ba820d16d..084056a13 100644 --- a/metrics/linux-gcc8-release/render-tests/zoom-history/out/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/zoom-history/out/metrics.json @@ -19,8 +19,8 @@ 15, 1, [ - 98816, - 98816 + 164352, + 164352 ], [ 82, diff --git a/metrics/linux-gcc8-release/render-tests/zoom-visibility/in-range/metrics.json b/metrics/linux-gcc8-release/render-tests/zoom-visibility/in-range/metrics.json index ed4871473..a9262cad3 100644 --- a/metrics/linux-gcc8-release/render-tests/zoom-visibility/in-range/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/zoom-visibility/in-range/metrics.json @@ -19,8 +19,8 @@ 21, 1, [ - 196608, - 196608 + 262144, + 262144 ], [ 118, diff --git a/metrics/linux-gcc8-release/render-tests/zoom-visibility/out-of-range/metrics.json b/metrics/linux-gcc8-release/render-tests/zoom-visibility/out-of-range/metrics.json index 8fbd5d92e..a00f95be7 100644 --- a/metrics/linux-gcc8-release/render-tests/zoom-visibility/out-of-range/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/zoom-visibility/out-of-range/metrics.json @@ -19,8 +19,8 @@ 13, 1, [ - 131072, - 131072 + 196608, + 196608 ], [ 70, diff --git a/src/mbgl/actor/mailbox.cpp b/src/mbgl/actor/mailbox.cpp index 1eb83140d..0a3946f07 100644 --- a/src/mbgl/actor/mailbox.cpp +++ b/src/mbgl/actor/mailbox.cpp @@ -88,7 +88,7 @@ void Mailbox::push(std::unique_ptr message) { }}; { - MLN_TRACE_ZONE(push_lock); + MLN_TRACE_ZONE(push lock); std::lock_guard pushingLock(pushingMutex); if (closed) { @@ -98,7 +98,7 @@ void Mailbox::push(std::unique_ptr message) { bool wasEmpty = false; { - MLN_TRACE_ZONE(queue_lock); + MLN_TRACE_ZONE(queue lock); std::lock_guard queueLock(queueMutex); wasEmpty = queue.empty(); queue.push(std::move(message)); @@ -168,4 +168,4 @@ void Mailbox::scheduleToRecieve(const std::optional& tag) } } -} // namespace mbgl +} // namespace mbgl \ No newline at end of file diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 6a34eabc9..03216eaa3 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -98,6 +98,8 @@ Context::Context(RendererBackend& backend_) #if MLN_DRAWABLE_RENDERER uboAllocator = std::make_unique(); #endif + + texturePool = std::make_unique(this); } Context::~Context() noexcept { @@ -105,6 +107,10 @@ Context::~Context() noexcept { backend.getThreadPool().runRenderJobs(true /* closeQueue */); reset(); + + // Delete all pooled resources while the context is still valid + texturePool.reset(); + #if !defined(NDEBUG) Log::Debug(Event::General, "Rendering Stats:\n" + stats.toString("\n")); #endif @@ -265,18 +271,14 @@ void Context::verifyProgramLinkage(ProgramID program_) { throw std::runtime_error("program failed to link"); } -UniqueTexture Context::createUniqueTexture() { +UniqueTexture Context::createUniqueTexture(const Size& size, + gfx::TexturePixelType format, + gfx::TextureChannelDataType type) { MLN_TRACE_FUNC(); - if (pooledTextures.empty()) { - pooledTextures.resize(TextureMax); - MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data())); - stats.numCreatedTextures += TextureMax; - } + assert(texturePool); + TextureID id = texturePool->alloc(size, format, type); - TextureID id = pooledTextures.back(); - pooledTextures.pop_back(); - stats.numActiveTextures++; // NOLINTNEXTLINE(performance-move-const-arg) return UniqueTexture{std::move(id), {this}}; } @@ -306,27 +308,13 @@ std::unique_ptr Context::createTextureResource(const Size const gfx::TextureChannelDataType type) { MLN_TRACE_FUNC(); - auto obj = createUniqueTexture(); - int textureByteSize = gl::TextureResource::getStorageSize(size, format, type); - stats.memTextures += textureByteSize; - std::unique_ptr resource = std::make_unique(std::move(obj), - textureByteSize); + auto obj = createUniqueTexture(size, format, type); + std::unique_ptr resource = std::make_unique(std::move(obj)); // Always use texture unit 0 for manipulating it. activeTextureUnit = 0; texture[0] = static_cast(*resource).texture; - // Creates an empty texture with the specified size and format. - MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, - 0, - Enum::sizedFor(format, type), - size.width, - size.height, - 0, - Enum::to(format), - Enum::to(type), - nullptr)); - // We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT // on NPOT textures. We use those when the pixelRatio isn't a power of two, // e.g. on iPhone 6 Plus. @@ -530,9 +518,10 @@ std::unique_ptr Context::createDrawScopeResource() { void Context::reset() { MLN_TRACE_FUNC(); - std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures)); - pooledTextures.resize(0); performCleanup(); + + // Delete all unused pooled resources + texturePool->shrink(); } #if MLN_DRAWABLE_RENDERER @@ -883,10 +872,8 @@ void Context::performCleanup() { binding.setDirty(); } } + texturePool->release(id); } - MBGL_CHECK_ERROR(glDeleteTextures(int(abandonedTextures.size()), abandonedTextures.data())); - stats.numCreatedTextures -= int(abandonedTextures.size()); - assert(stats.numCreatedTextures >= 0); abandonedTextures.clear(); } @@ -923,6 +910,8 @@ void Context::reduceMemoryUsage() { MLN_TRACE_FUNC_GL(); performCleanup(); + assert(texturePool); + texturePool->shrink(); // Ensure that all pending actions are executed to ensure that they happen // before the app goes to the background. @@ -949,5 +938,10 @@ void Context::clearStencilBuffer(const int32_t bits) { stats.stencilClears++; } +Texture2DPool& Context::getTexturePool() { + assert(texturePool); + return *texturePool; +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 5e8a06968..bc38dd251 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ namespace mbgl { namespace gl { -constexpr size_t TextureMax = 64; using ProcAddress = void (*)(); class RendererBackend; @@ -58,7 +58,7 @@ public: UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader, const char* location0AttribName); void verifyProgramLinkage(ProgramID); void linkProgram(ProgramID); - UniqueTexture createUniqueTexture(); + UniqueTexture createUniqueTexture(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type); Framebuffer createFramebuffer(const gfx::Renderbuffer&, const gfx::Renderbuffer&); @@ -93,18 +93,23 @@ public: // Actually remove the objects we marked as abandoned with the above methods. // Only call this while the OpenGL context is exclusive to this thread. + // Pooled textures are retained void performCleanup() override; + // Called when the app receives a memory warning and before it goes to the background. + // Calls performCleanup and destroy all pooled resources void reduceMemoryUsage() override; // Drain pools and remove abandoned objects, in preparation for destroying the store. // Only call this while the OpenGL context is exclusive to this thread. void reset(); - bool empty() const { - return pooledTextures.empty() && abandonedPrograms.empty() && abandonedShaders.empty() && - abandonedBuffers.empty() && abandonedTextures.empty() && abandonedVertexArrays.empty() && - abandonedFramebuffers.empty(); + // Returns whether there are any objects that need to be cleaned up. + // If considerPool is true, it will also check if resources are still pooled. + bool empty(bool considerPool = false) const { + return abandonedPrograms.empty() && abandonedShaders.empty() && abandonedBuffers.empty() && + abandonedTextures.empty() && abandonedVertexArrays.empty() && abandonedFramebuffers.empty() && + (considerPool ? texturePool->empty() : true); } extension::Debugging* getDebuggingExtension() const { return debugging.get(); } @@ -151,6 +156,8 @@ public: void setDirtyState() override; + Texture2DPool& getTexturePool(); + private: RendererBackend& backend; bool cleanupOnDestruction = true; @@ -230,8 +237,6 @@ private: friend detail::FramebufferDeleter; friend detail::RenderbufferDeleter; - std::vector pooledTextures; - std::vector abandonedPrograms; std::vector abandonedShaders; std::vector abandonedBuffers; @@ -240,6 +245,8 @@ private: std::vector abandonedFramebuffers; std::vector abandonedRenderbuffers; + std::unique_ptr texturePool; + public: #if !defined(NDEBUG) public: diff --git a/src/mbgl/gl/object.cpp b/src/mbgl/gl/object.cpp index c075aa8f1..78588f9a1 100644 --- a/src/mbgl/gl/object.cpp +++ b/src/mbgl/gl/object.cpp @@ -23,13 +23,10 @@ void BufferDeleter::operator()(BufferID id) const { void TextureDeleter::operator()(TextureID id) const { assert(context); - if (context->pooledTextures.size() >= TextureMax) { - context->abandonedTextures.push_back(id); - } else { - context->pooledTextures.push_back(id); - } + context->abandonedTextures.push_back(id); context->renderingStats().numActiveTextures--; assert(context->renderingStats().numActiveTextures >= 0); + assert(context->renderingStats().numActiveTextures < context->renderingStats().numCreatedTextures); } void VertexArrayDeleter::operator()(VertexArrayID id) const { diff --git a/src/mbgl/gl/resource_pool.cpp b/src/mbgl/gl/resource_pool.cpp new file mode 100644 index 000000000..9c0f4ea15 --- /dev/null +++ b/src/mbgl/gl/resource_pool.cpp @@ -0,0 +1,251 @@ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace gl { + +using namespace platform; + +namespace { + +size_t storageSize(const Texture2DDesc& desc) { + return static_cast(TextureResource::getStorageSize(desc.size, desc.pixelFormat, desc.channelType)); +} + +#if !defined(NDEBUG) +void logDebugMessage(const std::string& message) { + Log::Debug(Event::General, "Texture2DPool: " + message); +} +#else +void logDebugMessage(const std::string&) {} +#endif + +} // namespace + +std::size_t Texture2DDescHash::operator()(const Texture2DDesc& desc) const { + std::size_t seed = 0; + util::hash_combine(seed, desc.size.width); + util::hash_combine(seed, desc.size.height); + util::hash_combine(seed, std::underlying_type_t(desc.pixelFormat)); + util::hash_combine(seed, std::underlying_type_t(desc.channelType)); + return seed; +} + +Texture2DPool::Texture2DPool(Context* context_, size_t maxPoolStorage_) + : context(context_), + maxPoolStorage(maxPoolStorage_) { + assert(context); +} + +Texture2DPool::~Texture2DPool() { + assert(usedStorage() == 0); + assert(unusedStorage() == poolStorage); + shrink(); + assert(usedStorage() == 0); + assert(unusedStorage() == 0); + assert(poolStorage == 0); + assert(lru_cache.empty()); + assert(descriptions.empty()); + assert(pool.empty()); + logDebugMessage("total allocations " + util::toString(allocCount)); + logDebugMessage("total reused allocations " + util::toString(reuseCount)); + logDebugMessage("total textures released " + util::toString(releaseCount)); + logDebugMessage("total textures released and deallocated " + util::toString(freedCount)); +} + +TextureID Texture2DPool::alloc(const Texture2DDesc& desc) { + MLN_TRACE_FUNC(); + + context->renderingStats().numActiveTextures++; + + // Check if the texture is already allocated + auto set_it = pool.find(desc); + if (set_it != pool.end() && !set_it->second.free.empty()) { + // Reuse an existing texture + TextureID id = *set_it->second.free.begin(); + set_it->second.free.erase(id); + set_it->second.used.insert(id); + assert(lru_cache.isHit(id)); + lru_cache.remove(id); + ++reuseCount; + return id; + } + + // Allocate a new texture + ++allocCount; + return allocateGLMemory(desc); +} + +void Texture2DPool::release(TextureID id) { + MLN_TRACE_FUNC(); + + assert(isUsed(id)); + auto desc = descriptions.at(id); + auto set_it = pool.find(desc); + set_it->second.used.erase(id); + set_it->second.free.insert(id); + lru_cache.touch(id); + // Evict old textures if necessary + evict(); + + ++releaseCount; +} + +TextureID Texture2DPool::allocateGLMemory(const Texture2DDesc& desc) { + MLN_TRACE_FUNC(); + + // Create handle + TextureID id = 0; + MBGL_CHECK_ERROR(glGenTextures(1, &id)); + assert(id != 0); + + // Allocate memory + // Bind to TU 0 and upload + context->activeTextureUnit = 0; + context->texture[0] = id; + MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, + 0, + Enum::sizedFor(desc.pixelFormat, desc.channelType), + desc.size.width, + desc.size.height, + 0, + Enum::to(desc.pixelFormat), + Enum::to(desc.channelType), + nullptr)); + + // Update stats + context->renderingStats().numCreatedTextures++; + + // Add to descriptions + descriptions.emplace(id, desc); + + // Add to pool + pool[desc].used.insert(id); + + // Update poolStorage + auto storage = storageSize(desc); + poolStorage += storage; + context->renderingStats().memTextures += storage; + MLN_TRACE_ALLOC_TEXTURE(id, storage); + + // Evict old textures if necessary + evict(); + + return id; +} + +void Texture2DPool::freeAllocatedGLMemory(TextureID id) { + MLN_TRACE_FUNC(); + + // Remove from descriptions + auto desc_it = descriptions.find(id); + assert(desc_it != descriptions.end()); + auto desc = desc_it->second; + descriptions.erase(desc_it); + + // Remove from descriptions lru_cache if it exists + lru_cache.remove(id); + + // Remove from pool + auto set_it = pool.find(desc); + assert(set_it != pool.end()); + auto free_it = set_it->second.free.find(id); + assert(free_it != set_it->second.free.end()); + set_it->second.free.erase(free_it); + if (set_it->second.free.empty() && set_it->second.used.empty()) { + pool.erase(set_it); + } + + // Update poolStorage + auto storage = storageSize(desc); + poolStorage -= storage; + context->renderingStats().memTextures -= storage; + assert(context->renderingStats().memTextures >= 0); + MLN_TRACE_FREE_TEXTURE(id); + + // Delete the texture + MBGL_CHECK_ERROR(glDeleteTextures(1, &id)); + // Update stats + context->renderingStats().numCreatedTextures--; + + ++freedCount; +} + +void Texture2DPool::evict() { + while (poolStorage > maxPoolStorage && !lru_cache.empty()) { + TextureID id = lru_cache.evict(); + freeAllocatedGLMemory(id); + } +} + +void Texture2DPool::shrink() { + MLN_TRACE_FUNC(); + + while (!lru_cache.empty()) { + TextureID id = lru_cache.evict(); + freeAllocatedGLMemory(id); + } +} + +bool Texture2DPool::isPooled(TextureID id) const { + return descriptions.find(id) != descriptions.end(); +} + +bool Texture2DPool::isUsed(TextureID id) const { + auto desc_it = descriptions.find(id); + if (desc_it == descriptions.end()) { + return false; + } + const auto& desc = desc_it->second; + const auto& used_set = pool.at(desc).used; + return used_set.find(id) != used_set.end(); +} + +bool Texture2DPool::isUnused(TextureID id) const { + auto desc_it = descriptions.find(id); + if (desc_it == descriptions.end()) { + return false; + } + const auto& desc = desc_it->second; + const auto& free_set = pool.at(desc).free; + return free_set.find(id) != free_set.end(); +} + +size_t Texture2DPool::usedStorage() const { + size_t total = 0; + for (const auto& set : pool) { + total += storageSize(set.first) * set.second.used.size(); + } + return total; +} + +size_t Texture2DPool::unusedStorage() const { + size_t total = 0; + for (const auto& set : pool) { + total += storageSize(set.first) * set.second.free.size(); + } + return total; +} + +const Texture2DDesc& Texture2DPool::desc(TextureID id) const { + assert(descriptions.find(id) != descriptions.end()); + return descriptions.at(id); +} + +size_t Texture2DPool::storage(TextureID id) const { + assert(descriptions.find(id) != descriptions.end()); + return storageSize(descriptions.at(id)); +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/resource_pool.hpp b/src/mbgl/gl/resource_pool.hpp new file mode 100644 index 000000000..7abd62304 --- /dev/null +++ b/src/mbgl/gl/resource_pool.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mbgl { +namespace gl { + +class Context; + +struct Texture2DDesc { + Size size; + gfx::TexturePixelType pixelFormat; + gfx::TextureChannelDataType channelType; +}; + +struct Texture2DDescHash { + std::size_t operator()(const Texture2DDesc& desc) const; +}; + +inline bool operator==(const Texture2DDesc& desc1, const Texture2DDesc& desc2) { + return desc1.size == desc2.size && desc1.pixelFormat == desc2.pixelFormat && desc1.channelType == desc2.channelType; +} + +inline bool operator!=(const Texture2DDesc& desc1, const Texture2DDesc& desc2) { + return !(desc1 == desc2); +} + +class Texture2DPool { +public: + // Create a texture pool with a maximum storage size maxPoolStorage in bytes + // If maxPoolStorage is 0, pooling will disabled + Texture2DPool(Context* context, size_t maxPoolStorage = 16 * 1024 * 1024); + + // Deallocate all storage + ~Texture2DPool(); + + // Allocate a texture with the given size, pixel format, and channel type + // If the texture is already allocated in the pool, the existing texture ID will be returned + TextureID alloc(const Size& size, gfx::TexturePixelType pixelFormat, gfx::TextureChannelDataType channelType) { + return alloc({size, pixelFormat, channelType}); + } + + TextureID alloc(const Texture2DDesc& desc); + + // Release the texture but keep it in the pool + void release(TextureID id); + + // Free all unused textures + void shrink(); + + // Get the description of a texture + const Texture2DDesc& desc(TextureID id) const; + + // Get the storage size in byte of a texture + size_t storage(TextureID id) const; + + // Get the storage size in byte of all textures being used + size_t usedStorage() const; + + // Get the storage size in byte of all unused textures + size_t unusedStorage() const; + + // Get the storage size in byte of all textures in the pool + size_t storage() const { return poolStorage; } + + // Get the maximum storage size before starting to evict unused textures + size_t maxStorage() const { return maxPoolStorage; } + + bool empty() const { return poolStorage == 0; } + + // Check if a texture is pooled + bool isPooled(TextureID id) const; + + // Check if a texture is pooled and being used + bool isUsed(TextureID id) const; + + // Check if a texture is pooled but released + bool isUnused(TextureID id) const; + +private: + struct TextureSet { + std::unordered_set free; + std::unordered_set used; + }; + + // Effectively glGenTextures and glTexImage2D + TextureID allocateGLMemory(const Texture2DDesc& desc); + + // Effectively call glDeleteTextures + void freeAllocatedGLMemory(TextureID id); + + // Evict the least recently used textures until the pool storage is below maxPoolStorage + void evict(); + +private: + Context* context = nullptr; + size_t maxPoolStorage = 0; + std::size_t poolStorage = 0; + std::unordered_map pool; + std::unordered_map descriptions; + LRU lru_cache; + // stats + int64_t allocCount = 0; // total allocations + int64_t reuseCount = 0; // total reused allocations + int64_t releaseCount = 0; // total textures released + int64_t freedCount = 0; // total textures released and deallocated +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/texture2d.cpp b/src/mbgl/gl/texture2d.cpp index 537254fc4..a1c9dd957 100644 --- a/src/mbgl/gl/texture2d.cpp +++ b/src/mbgl/gl/texture2d.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -70,46 +71,30 @@ size_t Texture2D::numChannels() const noexcept { } } -void Texture2D::createObject() noexcept { +void Texture2D::allocateTexture() noexcept { + MLN_TRACE_FUNC(); + // Create a new texture object - assert(!textureResource); - auto obj = context.createUniqueTexture(); - const auto storageSize = gl::TextureResource::getStorageSize(size, pixelFormat, channelType); - context.renderingStats().memTextures += storageSize; + auto obj = context.createUniqueTexture(size, pixelFormat, channelType); // @TODO: TextureResource is still needed while we have legacy rendering pathways - textureResource = std::make_unique(std::move(obj), storageSize); + textureResource = std::make_unique(std::move(obj)); } -void Texture2D::createStorage(const void* data) noexcept { - assert(textureResource); +void Texture2D::updateTextureData(const void* data) noexcept { + MLN_TRACE_FUNC(); + if (data) { + uploadSubRegion(data, size, 0, 0); + } - // Create backing storage for our texture object - using namespace platform; - - // Bind to TU 0 and upload - context.activeTextureUnit = 0; - context.texture[0] = getTextureID(); - context.pixelStoreUnpack = {1}; - MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, - 0, - Enum::sizedFor(pixelFormat, channelType), - size.width, - size.height, - 0, - Enum::to(pixelFormat), - Enum::to(channelType), - data)); storageDirty = false; updateSamplerConfiguration(); } void Texture2D::create() noexcept { - if (!textureResource) { - createObject(); - } + allocateTexture(); if (storageDirty) { - createStorage(); + updateTextureData(); } } @@ -184,19 +169,10 @@ void Texture2D::upload(const void* pixelData, const Size& size_) noexcept { if (!textureResource || storageDirty || size_ == Size{0, 0} || size_ != size) { size = size_; - // Create the texture object if we don't already have one - if (!textureResource) { - createObject(); - } - - createStorage(pixelData); - - } else { - if (pixelData) { - // Upload to existing memory - uploadSubRegion(pixelData, size, 0, 0); - } + // Create the texture object if we don't already have one or if storage is dirty + allocateTexture(); } + updateTextureData(pixelData); } void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16_t xOffset, uint16_t yOffset) noexcept { diff --git a/src/mbgl/gl/texture_resource.cpp b/src/mbgl/gl/texture_resource.cpp index 7db1e45b0..fa8c9204d 100644 --- a/src/mbgl/gl/texture_resource.cpp +++ b/src/mbgl/gl/texture_resource.cpp @@ -32,18 +32,10 @@ static int channelStorageSize(gfx::TextureChannelDataType type) { } } -TextureResource::TextureResource(UniqueTexture&& texture_, int byteSize_) - : texture(std::move(texture_)), - byteSize(byteSize_) { - MLN_TRACE_ALLOC_TEXTURE(texture.get(), byteSize); -} +TextureResource::TextureResource(UniqueTexture&& texture_) + : texture(std::move(texture_)) {} -TextureResource::~TextureResource() noexcept { - auto& stats = texture.get_deleter().context->renderingStats(); - MLN_TRACE_FREE_TEXTURE(texture.get()); - stats.memTextures -= byteSize; - assert(stats.memTextures >= 0); -} +TextureResource::~TextureResource() noexcept {} int TextureResource::getStorageSize(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type) { return size.width * size.height * channelCount(format) * channelStorageSize(type); diff --git a/src/mbgl/gl/texture_resource.hpp b/src/mbgl/gl/texture_resource.hpp index 65d6e2dcf..d6b284b32 100644 --- a/src/mbgl/gl/texture_resource.hpp +++ b/src/mbgl/gl/texture_resource.hpp @@ -8,7 +8,7 @@ namespace gl { class TextureResource : public gfx::TextureResource { public: - TextureResource(UniqueTexture&& texture_, int byteSize_); + TextureResource(UniqueTexture&& texture_); ~TextureResource() noexcept override; static int getStorageSize(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type); @@ -18,7 +18,6 @@ public: gfx::TextureMipMapType mipmap = gfx::TextureMipMapType::No; gfx::TextureWrapType wrapX = gfx::TextureWrapType::Clamp; gfx::TextureWrapType wrapY = gfx::TextureWrapType::Clamp; - int byteSize; }; } // namespace gl diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 381f20b04..3f6f7933f 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -76,12 +76,12 @@ std::unique_ptr UploadPass::createTextureResource(const Si const void* data, gfx::TexturePixelType format, gfx::TextureChannelDataType type) { - auto obj = commandEncoder.context.createUniqueTexture(); - const int textureByteSize = gl::TextureResource::getStorageSize(size, format, type); - commandEncoder.context.renderingStats().memTextures += textureByteSize; - auto resource = std::make_unique(std::move(obj), textureByteSize); + MLN_TRACE_FUNC(); + + auto obj = commandEncoder.context.createUniqueTexture(size, format, type); + auto resource = std::make_unique(std::move(obj)); commandEncoder.context.pixelStoreUnpack = {1}; - updateTextureResource(*resource, size, data, format, type); + updateTextureResourceSub(*resource, 0, 0, size, data, format, type); // We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT // on NPOT textures. We use those when the pixelRatio isn't a power of two, // e.g. on iPhone 6 Plus. @@ -97,18 +97,9 @@ void UploadPass::updateTextureResource(gfx::TextureResource& resource, const void* data, gfx::TexturePixelType format, gfx::TextureChannelDataType type) { - // Always use texture unit 0 for manipulating it. - commandEncoder.context.activeTextureUnit = 0; - commandEncoder.context.texture[0] = static_cast(resource).texture; - MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, - 0, - Enum::to(format), - size.width, - size.height, - 0, - Enum::to(format), - Enum::to(type), - data)); + MLN_TRACE_FUNC(); + + updateTextureResourceSub(resource, 0, 0, size, data, format, type); } void UploadPass::updateTextureResourceSub(gfx::TextureResource& resource, @@ -118,9 +109,20 @@ void UploadPass::updateTextureResourceSub(gfx::TextureResource& resource, const void* data, gfx::TexturePixelType format, gfx::TextureChannelDataType type) { + MLN_TRACE_FUNC(); + + auto& ctx = commandEncoder.context; + assert(ctx.getTexturePool().isUsed(static_cast(resource).texture)); + assert(ctx.getTexturePool().desc(static_cast(resource).texture).channelType == type); + assert(ctx.getTexturePool().desc(static_cast(resource).texture).pixelFormat == format); + assert(ctx.getTexturePool().desc(static_cast(resource).texture).size.width >= + xOffset + size.width); + assert(ctx.getTexturePool().desc(static_cast(resource).texture).size.height >= + yOffset + size.height); + // Always use texture unit 0 for manipulating it. - commandEncoder.context.activeTextureUnit = 0; - commandEncoder.context.texture[0] = static_cast(resource).texture; + ctx.activeTextureUnit = 0; + ctx.texture[0] = static_cast(resource).texture; MBGL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2c0ba3f72..814b31c1d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -111,6 +111,7 @@ add_library( ${PROJECT_SOURCE_DIR}/test/util/token.test.cpp ${PROJECT_SOURCE_DIR}/test/util/url.test.cpp ${PROJECT_SOURCE_DIR}/test/util/tile_server_options.test.cpp + ${PROJECT_SOURCE_DIR}/test/util/lru_cache.test.cpp ) # MapSnapshotter uses headless backend that is rendering image on a background thread. QT / macOS adaptation for headless backend creates @@ -135,6 +136,7 @@ if(MLN_WITH_OPENGL) ${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 + ${PROJECT_SOURCE_DIR}/test/gl/resource_pool.test.cpp ${PROJECT_SOURCE_DIR}/test/renderer/backend_scope.test.cpp ${PROJECT_SOURCE_DIR}/test/util/offscreen_texture.test.cpp ) diff --git a/test/gl/object.test.cpp b/test/gl/object.test.cpp index 0567b2ed4..69ed63621 100644 --- a/test/gl/object.test.cpp +++ b/test/gl/object.test.cpp @@ -55,17 +55,22 @@ TEST(GLObject, Store) { gl::Context context{backend}; EXPECT_TRUE(context.empty()); - gl::UniqueTexture texture = context.createUniqueTexture(); + gl::UniqueTexture texture = context.createUniqueTexture( + {8, 8}, gfx::TexturePixelType::RGBA, gfx::TextureChannelDataType::UnsignedByte); EXPECT_NE(texture.get(), 0u); texture.reset(); - EXPECT_FALSE(context.empty()); + EXPECT_FALSE(context.empty(false)); + EXPECT_FALSE(context.empty(true)); context.performCleanup(); - EXPECT_FALSE(context.empty()); + EXPECT_TRUE(context.empty(false)); + EXPECT_FALSE(context.empty(true)); context.reset(); - EXPECT_TRUE(context.empty()); + EXPECT_TRUE(context.empty(false)); + EXPECT_TRUE(context.empty(true)); context.reset(); - EXPECT_TRUE(context.empty()); + EXPECT_TRUE(context.empty(false)); + EXPECT_TRUE(context.empty(true)); } #endif diff --git a/test/gl/resource_pool.test.cpp b/test/gl/resource_pool.test.cpp new file mode 100644 index 000000000..06f4ea85e --- /dev/null +++ b/test/gl/resource_pool.test.cpp @@ -0,0 +1,123 @@ +#if MLN_RENDER_BACKEND_OPENGL +#include + +#include + +#include +#include +#include +#include + +using namespace mbgl; + +namespace { + +constexpr auto oneMB = 1024 * 1024; + +constexpr gl::Texture2DDesc makeDescOneMB() { + return {{1024, 1024}, gfx::TexturePixelType::Luminance, gfx::TextureChannelDataType::UnsignedByte}; +} + +} // namespace + +TEST(ResourcePool, TexturePool) { + gl::HeadlessBackend backend{{32, 32}}; + gfx::BackendScope scope{backend}; + + gl::Context context{backend}; + EXPECT_TRUE(context.empty(true)); + + auto& pool = context.getTexturePool(); + EXPECT_LE(oneMB, pool.maxStorage()); + + EXPECT_EQ(pool.usedStorage(), 0); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), 0); + EXPECT_FALSE(pool.isUsed(3)); + EXPECT_FALSE(pool.isUnused(3)); + EXPECT_FALSE(pool.isPooled(3)); + + auto id = pool.alloc(makeDescOneMB()); + EXPECT_EQ(pool.usedStorage(), oneMB); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), oneMB); + EXPECT_TRUE(pool.isUsed(id)); + EXPECT_FALSE(pool.isUnused(id)); + EXPECT_TRUE(pool.isPooled(id)); + + pool.release(id); + EXPECT_EQ(pool.usedStorage(), 0u); + EXPECT_EQ(pool.unusedStorage(), oneMB); + EXPECT_EQ(pool.storage(), oneMB); + EXPECT_FALSE(pool.isUsed(id)); + EXPECT_TRUE(pool.isUnused(id)); + EXPECT_TRUE(pool.isPooled(id)); + + auto reused_id = pool.alloc(makeDescOneMB()); + EXPECT_EQ(reused_id, id); + EXPECT_EQ(pool.usedStorage(), oneMB); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), oneMB); + EXPECT_TRUE(pool.isUsed(id)); + EXPECT_FALSE(pool.isUnused(id)); + EXPECT_TRUE(pool.isPooled(id)); + + std::unordered_set ids = {id}; + while (pool.storage() <= pool.maxStorage()) { + auto new_id = pool.alloc(makeDescOneMB()); + EXPECT_TRUE(ids.find(new_id) == ids.end()); + ids.insert(new_id); + EXPECT_EQ(pool.usedStorage(), oneMB * ids.size()); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), pool.usedStorage()); + EXPECT_TRUE(pool.isUsed(new_id)); + EXPECT_FALSE(pool.isUnused(new_id)); + EXPECT_TRUE(pool.isPooled(new_id)); + } + + EXPECT_LE(pool.maxStorage(), pool.usedStorage()); + EXPECT_EQ(pool.usedStorage(), oneMB * ids.size()); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), pool.usedStorage()); + EXPECT_TRUE(pool.isUsed(id)); + EXPECT_FALSE(pool.isUnused(id)); + EXPECT_TRUE(pool.isPooled(id)); + + pool.release(id); + ids.erase(id); + EXPECT_GE(pool.maxStorage(), pool.usedStorage()); + EXPECT_EQ(pool.usedStorage(), oneMB * ids.size()); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), pool.usedStorage()); + EXPECT_FALSE(pool.isUsed(id)); + EXPECT_FALSE(pool.isUnused(id)); + EXPECT_FALSE(pool.isPooled(id)); + + size_t used = pool.usedStorage(); + size_t unused = 0; + while (!ids.empty()) { + auto i = *ids.begin(); + pool.release(i); + ids.erase(i); + used -= oneMB; + unused += oneMB; + EXPECT_EQ(pool.usedStorage(), used); + EXPECT_EQ(pool.unusedStorage(), unused); + EXPECT_EQ(pool.storage(), used + unused); + EXPECT_FALSE(pool.isUsed(i)); + EXPECT_TRUE(pool.isUnused(i)); + EXPECT_TRUE(pool.isPooled(i)); + } + + context.reduceMemoryUsage(); + context.renderingStats().numActiveTextures = 0; + EXPECT_EQ(pool.usedStorage(), 0); + EXPECT_EQ(pool.unusedStorage(), 0); + EXPECT_EQ(pool.storage(), 0); + EXPECT_FALSE(pool.isUsed(id)); + EXPECT_FALSE(pool.isUnused(id)); + EXPECT_FALSE(pool.isPooled(id)); + EXPECT_TRUE(context.empty(true)); +} + +#endif diff --git a/test/util/lru_cache.test.cpp b/test/util/lru_cache.test.cpp new file mode 100644 index 000000000..36cb60b3e --- /dev/null +++ b/test/util/lru_cache.test.cpp @@ -0,0 +1,38 @@ +#include + +#include + +#include + +using namespace mbgl; + +TEST(LRU, LRU) { + LRU lru; + EXPECT_TRUE(lru.empty()); + + lru.touch(1); + lru.touch(2); + lru.touch(3); + EXPECT_FALSE(lru.empty()); + EXPECT_EQ(lru.size(), 3); + + lru.remove(2); + lru.remove(77); + EXPECT_EQ(lru.evict(), 1); + EXPECT_FALSE(lru.empty()); + EXPECT_EQ(lru.size(), 1); + + lru.touch(4); + EXPECT_EQ(lru.evict(), 3); + EXPECT_FALSE(lru.empty()); + EXPECT_EQ(lru.size(), 1); + + EXPECT_FALSE(lru.isHit(3)); + EXPECT_FALSE(lru.isHit(33)); + EXPECT_TRUE(lru.isHit(4)); + + EXPECT_EQ(lru.evict(), 4); + EXPECT_TRUE(lru.empty()); + EXPECT_FALSE(lru.isHit(4)); + EXPECT_THROW(lru.evict(), std::runtime_error); +}