Add Tracy instrumentation for CPU and GPU in OpenGL mode. (#2417)

This commit is contained in:
alasram
2024-06-17 10:20:14 -07:00
committed by GitHub
parent 30484d8f50
commit 4f0f3bac51
45 changed files with 1091 additions and 19 deletions

View File

@@ -14,6 +14,7 @@ option(MLN_WITH_WERROR "Make all compilation warnings errors" ON)
option(MLN_LEGACY_RENDERER "Include the legacy rendering pathway" ON)
option(MLN_DRAWABLE_RENDERER "Include the drawable rendering pathway" OFF)
option(MLN_USE_UNORDERED_DENSE "Use ankerl dense containers for performance" ON)
option(MLN_USE_TRACY "Enable Tracy instrumentation" OFF)
if (MLN_WITH_CLANG_TIDY)
find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)
@@ -409,6 +410,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/util/image.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/immutable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/util/indexed_tuple.hpp
${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/noncopyable.hpp
@@ -1105,6 +1107,7 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_custom_layer.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.hpp
${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/state.hpp
@@ -1112,6 +1115,8 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture_resource.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/timestamp_query_extension.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/timestamp_query_extension.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/types.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.hpp
@@ -1337,6 +1342,7 @@ include(${PROJECT_SOURCE_DIR}/vendor/mapbox-base.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/parsedate.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/polylabel.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/protozero.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/tracy.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/unique_resource.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/vector-tile.cmake)
include(${PROJECT_SOURCE_DIR}/vendor/wagyu.cmake)
@@ -1377,6 +1383,7 @@ target_link_libraries(
Mapbox::Base::geojson.hpp
Mapbox::Base::geometry.hpp
Mapbox::Base::variant
TracyClient
unordered_dense
)
@@ -1407,6 +1414,7 @@ export(TARGETS
mbgl-vendor-unique_resource
mbgl-vendor-vector-tile
mbgl-vendor-wagyu
TracyClient
unordered_dense
FILE MapboxCoreTargets.cmake

View File

@@ -829,6 +829,7 @@ MLN_CORE_HEADERS = [
"include/mbgl/util/image.hpp",
"include/mbgl/util/immutable.hpp",
"include/mbgl/util/indexed_tuple.hpp",
"include/mbgl/util/instrumentation.hpp",
"include/mbgl/util/interpolate.hpp",
"include/mbgl/util/logging.hpp",
"include/mbgl/util/monotonic_timer.hpp",
@@ -884,6 +885,7 @@ MLN_OPENGL_SOURCE = [
"src/mbgl/gl/program.hpp",
"src/mbgl/gl/render_pass.cpp",
"src/mbgl/gl/render_pass.hpp",
"src/mbgl/gl/renderbuffer_resource.cpp",
"src/mbgl/gl/renderbuffer_resource.hpp",
"src/mbgl/gl/renderer_backend.cpp",
"src/mbgl/gl/state.hpp",
@@ -891,6 +893,8 @@ MLN_OPENGL_SOURCE = [
"src/mbgl/gl/texture.hpp",
"src/mbgl/gl/texture_resource.cpp",
"src/mbgl/gl/texture_resource.hpp",
"src/mbgl/gl/timestamp_query_extension.cpp",
"src/mbgl/gl/timestamp_query_extension.hpp",
"src/mbgl/gl/types.hpp",
"src/mbgl/gl/uniform.cpp",
"src/mbgl/gl/uniform.hpp",

View File

@@ -14,3 +14,6 @@
- [Quickstart](./android/getting-started-guide.md)
- [Annotation: Marker](./android/annotation-guide.md)
- [Location Component](./android/location-component-guide.md)
- [Profiling applications that use MapLibre Native](./profiling/README.md)
- [Tracy profiling](./profiling/tracy-profiling.md)

View File

@@ -0,0 +1,3 @@
# MapLibre Native profiling
MabLibre Native integrates [Tracy profiler](https://github.com/wolfpld/tracy) which offers an easy way to understand and optimize your application's CPU and GPU performance

View File

@@ -0,0 +1,123 @@
# Tracy profiling
#### Introduction
MapLibre Native integrates [Tracy profiler](https://github.com/wolfpld/tracy) which offers an easy way to understand and optimize your application's CPU and GPU performance.
Tracy mainly consists in manually adding markup instrumentation in the code to log performance events. These events can then be analyzed and visualized using the [Tracy Profiler tool](https://github.com/wolfpld/tracy/tree/master/profiler).
Instrumentation is generally the first step in profiling applications that use MapLibre. Once slow inner-loop routines are identified, additional hardware vendor specific tools can be used to collect hardware counters and optimize low level CPU and GPU code.
#### Tracy client
Tracy client consists of an API to mark CPU and GPU performance zones. A zone is a code section where the start and end timestamps are recorded.
#### Tracy server
The server is the Tracy profiler that allows the analysis and visualization of the client recorded data.
The server can be downloaded from [Tracy release page](https://github.com/wolfpld/tracy/releases) or it can be easily built from [sources](https://github.com/wolfpld/tracy/tree/master/profiler) on Linux, Windows or Mac using CMake
#### Enabling instrumentation in MapLibre Native
Instrumentation is enabled by turning `ON` the CMake option `MLN_USE_TRACY`.
Tracy computational overhead is very low but by default it keeps all instrumentation events that are not consumed by the server in system memory. This can have a negative effect on platforms with low memory. To prevent high memory usage, `TRACY_ON_DEMAND` macro should defined. This way instrumentation data is only stored when the server is connected to the application.
#### Instrumentation in MapLibre
The file `include/mbgl/util/instrumentation.hpp` defines the following instrumentation macros:
##### `MLN_TRACE_ZONE(label)`
The macro records the timestamps at the start and end of the code scope. The parameter label is a user defined name for the zone. Example:
~~~
// code is not instrumented
{
MLN_TRACE_ZONE(EmptyZone); // Records from here until the end of the scope
// code here is instrumented
}
// other here not instrumented
~~~
##### `MLN_TRACE_FUNC()`
The macro is meant to be placed at the start of a function and expands to:
~~~
MLN_TRACE_ZONE(__FUNCTION__)
~~~
##### GPU instrumentation
OpenGL is also supported in MapLibre native. Tracy support is currently missing for other APIs such as Metal and need to be added separately.
##### `MLN_TRACE_GL_ZONE(label)`
This macro is similar to `MLN_TRACE_ZONE` except that [OpenGL timestamp queries](https://www.khronos.org/opengl/wiki/Query_Object) are inserted in the GPU command buffer instead of recording CPU time.
##### `MLN_TRACE_FUNC_GL(label)`
This macro is similar to `MLN_TRACE_FUNC` except that [OpenGL timestamp queries](https://www.khronos.org/opengl/wiki/Query_Object) are inserted in the GPU command buffer instead of recording CPU time.
##### Other macros
The above macros can be added inside MapLibre code and also in the application code that calls MapLibre.
The following macros should only be used if there are changes to MapLibre internals:
##### `MLN_END_FRAME()`
Mark the end of a frame.
##### `MLN_TRACE_GL_CONTEXT()`
Placed after an OpenGL context is created.
##### `MLN_TRACE_ALLOC_TEXTURE(id, size)` and `MLN_TRACE_FREE_TEXTURE(id)`
Record a read-only texture allocation and deallocation
##### `MLN_TRACE_ALLOC_RT(id, size)` and `MLN_TRACE_FREE_RT(id)`
Record a render target texture allocation and deallocation
##### `MLN_TRACE_ALLOC_VERTEX_BUFFER(id, size)` and `MLN_TRACE_FREE_VERTEX_BUFFER(id)`
Record a buffer allocation and deallocation that is intended to be used as a read-only vertex buffer
##### `MLN_TRACE_ALLOC_INDEX_BUFFER(id, size)` and `MLN_TRACE_FREE_INDEX_BUFFER(id)`
Record a buffer allocation and deallocation that is intended to be used as a read-only index buffer
##### `MLN_TRACE_ALLOC_CONST_BUFFER(id, size)` and `MLN_TRACE_FREE_CONST_BUFFER(id)`
Record a buffer allocation and deallocation that is intended to be used as a constant buffer
#### Usage example on Linux and Windows
Download or build the Tracy profiler (server) and run it.
Make sure you generate the MapLibre project with the option `MLN_USE_TRACY` enabled.
As an example, the glfw sample is used.
With CMake, in MapLibre repository root do
~~~
# generate project
cmake -B build -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMLN_WITH_CLANG_TIDY=OFF -DMLN_WITH_COVERAGE=OFF -DMLN_DRAWABLE_RENDERER=ON -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DMLN_USE_TRACY=ON
# build
cmake --build build --target mbgl-glfw -j 8
# run
./build/platform/glfw/mbgl-glfw --style https://raw.githubusercontent.com/maplibre/demotiles/gh-pages/style.json --benchmark
~~~
with Bazel
~~~
# build and run
bazel run //platform/glfw:glfw_app -- --style https://raw.githubusercontent.com/maplibre/demotiles/gh-pages/style.json --benchmark
~~~
In the Tracy Profiler hit the connect button (or select the glfw application from the list of applications that are running Tracy Client). Profile then optimize the code.
#### Connecting the profiler to a MapLibre Android application
The Android application communicates instrumentation data to the profiler (Tracy server) on the network using port 8086 by default. You can expose the port to the profiler using Android Debug Bridge by running the command:
~~~
adb forward tcp:8086 tcp:8086
~~~
#### More information and advanced usage in Tracy
[Tracy Github page](https://github.com/wolfpld/tracy/)
[Tracy user guide](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf)
[Tracy demo on Youtube](https://www.youtube.com/watch?v=fB5B46lbapc)
[Tracy CppCon presentation on Youtube](https://www.youtube.com/watch?v=ghXk3Bk5F2U&t=37s)

View File

@@ -27,6 +27,13 @@ public:
void update(const void* data, std::size_t size_) override;
private:
// unique id used for debugging and profiling purposes
// localID should not be used as unique id because a const buffer pool is managed using IBufferAllocator
// Currently unique IDs for constant buffers are only used when Tracy profiling is enabled
#ifdef MLN_TRACY_ENABLE
int64_t uniqueDebugId = -1;
#endif
// If the requested UBO size is too large for the allocator, the UBO will manage its own allocation
bool isManagedAllocation = false;
BufferID localID;

View File

@@ -0,0 +1,115 @@
#pragma once
#ifdef MLN_TRACY_ENABLE
#include <tracy/Tracy.hpp>
#include <cstddef>
template <typename GpuId>
const void* castGpuIdToTracyPtr(GpuId id) {
// Tracy functions such as TracyAllocN track resources using `const void*`
// pointers. GPU resources may use a non-pointer handles. These handles may
// be GLsizei, GLuint and Vulkan handles are guaranteed to be 64 bits:
// Check VK_USE_64_BIT_PTR_DEFINES in the spec for instance.
// For simplicity we cast to ptrdiff_t which is guaranteed to work on
// 64bits systems but the cast may drop high bits if the handle is larger
// than the pointer type
// We fail to compile if this happens. A workaround would be to map
// handles to 32 bits values if Tracy is on those systems
static_assert(sizeof(GpuId) <= sizeof(std::ptrdiff_t), "Tracy is currently not supported on 32 bits systems");
return reinterpret_cast<const void*>(static_cast<std::ptrdiff_t>(id));
}
#ifndef MLN_RENDER_BACKEND_OPENGL
#error \
"MLN_RENDER_BACKEND_OPENGL is not defined. MLN_RENDER_BACKEND_OPENGL is expected to be defined in CMake and Bazel"
#endif
#define MLN_TRACE_FUNC() ZoneScoped
#define MLN_TRACE_ZONE(label) ZoneScopedN(#label)
constexpr const char* tracyTextureMemoryLabel = "Texture Memory";
#define MLN_TRACE_ALLOC_TEXTURE(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyTextureMemoryLabel)
#define MLN_TRACE_FREE_TEXTURE(id) TracyFreeN(castGpuIdToTracyPtr(id), tracyTextureMemoryLabel)
constexpr const char* tracyRenderTargetMemoryLabel = "Render Target Memory";
#define MLN_TRACE_ALLOC_RT(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyRenderTargetMemoryLabel)
#define MLN_TRACE_FREE_RT(id) TracyFreeN(castGpuIdToTracyPtr(id), tracyRenderTargetMemoryLabel)
constexpr const char* tracyVertexMemoryLabel = "Vertex Buffer Memory";
#define MLN_TRACE_ALLOC_VERTEX_BUFFER(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyVertexMemoryLabel)
#define MLN_TRACE_FREE_VERTEX_BUFFER(id) TracyFreeN(castGpuIdToTracyPtr(id), tracyVertexMemoryLabel)
constexpr const char* tracyIndexMemoryLabel = "Index Buffer Memory";
#define MLN_TRACE_ALLOC_INDEX_BUFFER(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyIndexMemoryLabel)
#define MLN_TRACE_FREE_INDEX_BUFFER(id) TracyFreeN(castGpuIdToTracyPtr(id), tracyIndexMemoryLabel)
constexpr const char* tracyConstMemoryLabel = "Constant Buffer Memory";
#define MLN_TRACE_ALLOC_CONST_BUFFER(id, size) TracyAllocN(castGpuIdToTracyPtr(id), size, tracyConstMemoryLabel)
#define MLN_TRACE_FREE_CONST_BUFFER(id) TracyFreeN(castGpuIdToTracyPtr(id), tracyConstMemoryLabel)
// Only OpenGL is currently considered for GPU profiling
// Metal and other APIs need to be handled separately
#if MLN_RENDER_BACKEND_OPENGL
#include <mbgl/gl/timestamp_query_extension.hpp>
// TracyOpenGL.hpp assumes OpenGL functions are in the global namespace
// Temporarily expose the functions to TracyOpenGL.hpp then undef
#define glGenQueries mbgl::gl::extension::glGenQueries
#define glGetQueryiv mbgl::gl::extension::glGetQueryiv
#define glGetQueryObjectiv mbgl::gl::extension::glGetQueryObjectiv
#define glGetInteger64v mbgl::gl::extension::glGetInteger64v
#define glQueryCounter mbgl::gl::extension::glQueryCounter
#define glGetQueryObjectui64v mbgl::gl::extension::glGetQueryObjectui64v
#define GLint mbgl::platform::GLint
#include "tracy/TracyOpenGL.hpp"
#define MLN_TRACE_GL_CONTEXT() TracyGpuContext
#define MLN_TRACE_GL_ZONE(label) TracyGpuZone(#label)
#define MLN_TRACE_FUNC_GL() TracyGpuZone(__FUNCTION__)
#define MLN_END_FRAME() \
do { \
FrameMark; \
TracyGpuCollect; \
} while (0)
#undef glGenQueries
#undef glGetQueryiv
#undef glGetQueryObjectiv
#undef glGetInteger64v
#undef glQueryCounter
#undef glGetQueryObjectui64v
#undef GLint
#else // MLN_RENDER_BACKEND_OPENGL
#define MLN_TRACE_GL_CONTEXT()
#define MLN_TRACE_GL_ZONE(label)
#define MLN_TRACE_FUNC_GL()
#define MLN_END_FRAME() FrameMark
#endif // MLN_RENDER_BACKEND_OPENGL
#else // MLN_TRACY_ENABLE
#define MLN_TRACE_GL_CONTEXT()
#define MLN_TRACE_GL_ZONE(label)
#define MLN_TRACE_FUNC_GL()
#define MLN_END_FRAME()
#define MLN_TRACE_ALLOC_TEXTURE(id, size)
#define MLN_TRACE_FREE_TEXTURE(id)
#define MLN_TRACE_ALLOC_RT(id, size)
#define MLN_TRACE_FREE_RT(id)
#define MLN_TRACE_ALLOC_VERTEX_BUFFER(id, size)
#define MLN_TRACE_FREE_VERTEX_BUFFER(id)
#define MLN_TRACE_ALLOC_INDEX_BUFFER(id, size)
#define MLN_TRACE_FREE_INDEX_BUFFER(id)
#define MLN_TRACE_ALLOC_CONST_BUFFER(id, size)
#define MLN_TRACE_FREE_CONST_BUFFER(id)
#define MLN_TRACE_FUNC()
#define MLN_TRACE_ZONE(label)
#endif // MLN_TRACY_ENABLE

View File

@@ -80,3 +80,7 @@ To run the benchmarks (for Android) include the following line on a PR comment:
```
!benchmark android
```
## Profiling
[maplibre-native/docs/mdbook](https://maplibre.org/maplibre-native/docs/book/) describes how Tracy can be used for profiling.

View File

@@ -2,6 +2,7 @@
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <cassert>
#include <stdexcept>
@@ -27,7 +28,11 @@ public:
context.viewport = {0, 0, framebuffer.size};
}
void swap() override { backend.swap(); }
void swap() override {
MLN_TRACE_FUNC();
backend.swap();
}
HeadlessBackend& backend;
gl::Context& context;
@@ -44,6 +49,8 @@ HeadlessBackend::HeadlessBackend(const Size size_,
swapBehaviour(swapBehaviour_) {}
HeadlessBackend::~HeadlessBackend() {
MLN_TRACE_FUNC();
gfx::BackendScope guard{*this, gfx::BackendScope::ScopeType::Implicit};
// Some implementations require active context for GL functions to work
if (impl != nullptr && impl->glNeedsActiveContextOnDestruction()) {
@@ -66,6 +73,8 @@ gl::ProcAddress HeadlessBackend::getExtensionFunctionPointer(const char* name) {
}
void HeadlessBackend::activate() {
MLN_TRACE_FUNC();
active = true;
if (!impl) {
@@ -77,12 +86,16 @@ void HeadlessBackend::activate() {
}
void HeadlessBackend::deactivate() {
MLN_TRACE_FUNC();
assert(impl);
impl->deactivateContext();
active = false;
}
gfx::Renderable& HeadlessBackend::getDefaultRenderable() {
MLN_TRACE_FUNC();
if (!resource) {
resource = std::make_unique<HeadlessRenderableResource>(*this, static_cast<gl::Context&>(getContext()), size);
}
@@ -90,6 +103,8 @@ gfx::Renderable& HeadlessBackend::getDefaultRenderable() {
}
void HeadlessBackend::swap() {
MLN_TRACE_FUNC();
if (swapBehaviour == SwapBehaviour::Flush) static_cast<gl::Context&>(getContext()).finish();
}
@@ -98,6 +113,8 @@ void HeadlessBackend::updateAssumedState() {
}
PremultipliedImage HeadlessBackend::readStillImage() {
MLN_TRACE_FUNC();
return static_cast<gl::Context&>(getContext()).readFramebuffer<PremultipliedImage>(size);
}
@@ -112,6 +129,8 @@ namespace gfx {
template <>
std::unique_ptr<gfx::HeadlessBackend> Backend::Create<gfx::Backend::Type::OpenGL>(
const Size size, gfx::Renderable::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) {
MLN_TRACE_FUNC();
return std::make_unique<gl::HeadlessBackend>(size, swapBehavior, contextMode);
}

View File

@@ -16,6 +16,13 @@ objc_library(
],
)
filegroup(
name = "mapbox_puck_assets",
srcs = glob([
"assets/*.png",
]),
)
cc_binary(
name = "glfw_app",
srcs = glob(
@@ -36,6 +43,12 @@ cc_binary(
],
}),
copts = CPP_FLAGS + MAPLIBRE_FLAGS,
data = [
":mapbox_puck_assets",
],
defines = [
r"MAPBOX_PUCK_ASSETS_PATH=\"./platform/glfw/assets/\"",
],
linkopts = [
"-lglfw",
] + select({
@@ -53,6 +66,7 @@ cc_binary(
"@glfw",
] + select({
"@platforms//os:macos": ["metal_backend"],
"@platforms//os:linux": ["//platform/linux:impl"],
"//conditions:default": [],
}),
)

View File

@@ -2,6 +2,7 @@
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <GLFW/glfw3.h>
@@ -11,11 +12,17 @@ public:
: backend(backend_) {}
void bind() override {
MLN_TRACE_FUNC();
backend.setFramebufferBinding(0);
backend.setViewport(0, 0, backend.getSize());
}
void swap() override { backend.swap(); }
void swap() override {
MLN_TRACE_FUNC();
backend.swap();
}
private:
GLFWGLBackend& backend;
@@ -32,6 +39,8 @@ GLFWGLBackend::GLFWGLBackend(GLFWwindow* window_, const bool capFrameRate)
}(),
std::make_unique<GLFWGLRenderableResource>(*this)),
window(window_) {
MLN_TRACE_FUNC();
glfwMakeContextCurrent(window);
if (!capFrameRate) {
// Disables vsync on platforms that support it.
@@ -44,10 +53,14 @@ GLFWGLBackend::GLFWGLBackend(GLFWwindow* window_, const bool capFrameRate)
GLFWGLBackend::~GLFWGLBackend() = default;
void GLFWGLBackend::activate() {
MLN_TRACE_FUNC();
glfwMakeContextCurrent(window);
}
void GLFWGLBackend::deactivate() {
MLN_TRACE_FUNC();
glfwMakeContextCurrent(nullptr);
}
@@ -56,6 +69,8 @@ mbgl::gl::ProcAddress GLFWGLBackend::getExtensionFunctionPointer(const char* nam
}
void GLFWGLBackend::updateAssumedState() {
MLN_TRACE_FUNC();
assumeFramebufferBinding(0);
setViewport(0, 0, size);
}
@@ -69,6 +84,8 @@ void GLFWGLBackend::setSize(const mbgl::Size newSize) {
}
void GLFWGLBackend::swap() {
MLN_TRACE_FUNC();
glfwSwapBuffers(window);
}
@@ -77,6 +94,8 @@ namespace gfx {
template <>
std::unique_ptr<GLFWBackend> Backend::Create<mbgl::gfx::Backend::Type::OpenGL>(GLFWwindow* window, bool capFrameRate) {
MLN_TRACE_FUNC();
return std::make_unique<GLFWGLBackend>(window, capFrameRate);
}

View File

@@ -2,6 +2,7 @@
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/instrumentation.hpp>
GLFWRendererFrontend::GLFWRendererFrontend(std::unique_ptr<mbgl::Renderer> renderer_, GLFWView& glfwView_)
: glfwView(glfwView_),
@@ -27,6 +28,8 @@ void GLFWRendererFrontend::update(std::shared_ptr<mbgl::UpdateParameters> params
}
void GLFWRendererFrontend::render() {
MLN_TRACE_FUNC();
assert(renderer);
if (!updateParameters) return;

View File

@@ -24,6 +24,7 @@
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/platform.hpp>
#include <mbgl/util/string.hpp>
@@ -78,6 +79,8 @@ class SnapshotObserver final : public mbgl::MapSnapshotterObserver {
public:
~SnapshotObserver() override = default;
void onDidFinishLoadingStyle() override {
MLN_TRACE_FUNC();
if (didFinishLoadingStyleCallback) {
didFinishLoadingStyleCallback();
}
@@ -87,6 +90,8 @@ public:
namespace {
void addFillExtrusionLayer(mbgl::style::Style &style, bool visible) {
MLN_TRACE_FUNC();
using namespace mbgl::style;
using namespace mbgl::style::expression::dsl;
@@ -132,6 +137,8 @@ GLFWView::GLFWView(bool fullscreen_,
snapshotterObserver(std::make_unique<SnapshotObserver>()),
mapResourceOptions(resourceOptions.clone()),
mapClientOptions(clientOptions.clone()) {
MLN_TRACE_FUNC();
glfwSetErrorCallback(glfwError);
std::srand(static_cast<unsigned int>(std::time(nullptr)));
@@ -198,7 +205,8 @@ GLFWView::GLFWView(bool fullscreen_,
glfwGetWindowSize(window, &width, &height);
backend = GLFWBackend::Create(window, benchmark);
bool capFrameRate = !benchmark; // disable VSync in benchmark mode
backend = GLFWBackend::Create(window, capFrameRate);
#ifdef __APPLE__
int fbW, fbH;
@@ -270,24 +278,34 @@ GLFWView::GLFWView(bool fullscreen_,
}
GLFWView::~GLFWView() {
MLN_TRACE_FUNC();
glfwDestroyWindow(window);
glfwTerminate();
}
void GLFWView::setMap(mbgl::Map *map_) {
MLN_TRACE_FUNC();
map = map_;
map->addAnnotationImage(makeImage("default_marker", 22, 22, 1));
}
void GLFWView::setRenderFrontend(GLFWRendererFrontend *rendererFrontend_) {
MLN_TRACE_FUNC();
rendererFrontend = rendererFrontend_;
}
mbgl::gfx::RendererBackend &GLFWView::getRendererBackend() {
MLN_TRACE_FUNC();
return backend->getRendererBackend();
}
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
if (action == GLFW_RELEASE) {
@@ -588,6 +606,8 @@ struct Interpolator<mbgl::LatLng> {
} // namespace mbgl
void GLFWView::updateFreeCameraDemo() {
MLN_TRACE_FUNC();
const mbgl::LatLng trainStartPos = {60.171367, 24.941359};
const mbgl::LatLng trainEndPos = {60.185147, 24.936668};
const mbgl::LatLng cameraStartPos = {60.167443, 24.927176};
@@ -635,6 +655,8 @@ std::unique_ptr<mbgl::style::Image> GLFWView::makeImage(const std::string &id,
int width,
int height,
float pixelRatio) {
MLN_TRACE_FUNC();
const int r = static_cast<int>(255 * (static_cast<double>(std::rand()) / RAND_MAX));
const int g = static_cast<int>(255 * (static_cast<double>(std::rand()) / RAND_MAX));
const int b = static_cast<int>(255 * (static_cast<double>(std::rand()) / RAND_MAX));
@@ -680,6 +702,8 @@ void GLFWView::nextOrientation() {
}
void GLFWView::addRandomCustomPointAnnotations(int count) {
MLN_TRACE_FUNC();
for (int i = 0; i < count; i++) {
static int spriteID = 1;
const auto name = std::string{"marker-"} + mbgl::util::toString(spriteID++);
@@ -690,12 +714,16 @@ void GLFWView::addRandomCustomPointAnnotations(int count) {
}
void GLFWView::addRandomPointAnnotations(int count) {
MLN_TRACE_FUNC();
for (int i = 0; i < count; ++i) {
annotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation{makeRandomPoint(), "default_marker"}));
}
}
void GLFWView::addRandomLineAnnotations(int count) {
MLN_TRACE_FUNC();
for (int i = 0; i < count; ++i) {
mbgl::LineString<double> lineString;
for (int j = 0; j < 3; ++j) {
@@ -706,6 +734,8 @@ void GLFWView::addRandomLineAnnotations(int count) {
}
void GLFWView::addRandomShapeAnnotations(int count) {
MLN_TRACE_FUNC();
for (int i = 0; i < count; ++i) {
mbgl::Polygon<double> triangle;
triangle.push_back({makeRandomPoint(), makeRandomPoint(), makeRandomPoint()});
@@ -715,12 +745,16 @@ void GLFWView::addRandomShapeAnnotations(int count) {
}
void GLFWView::addAnimatedAnnotation() {
MLN_TRACE_FUNC();
const double started = glfwGetTime();
animatedAnnotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation{{0, 0}, "default_marker"}));
animatedAnnotationAddedTimes.push_back(started);
}
void GLFWView::updateAnimatedAnnotations() {
MLN_TRACE_FUNC();
const double time = glfwGetTime();
for (size_t i = 0; i < animatedAnnotationIDs.size(); i++) {
auto dt = time - animatedAnnotationAddedTimes[i];
@@ -752,6 +786,8 @@ void GLFWView::cycleDebugOptions() {
}
void GLFWView::clearAnnotations() {
MLN_TRACE_FUNC();
for (const auto &id : annotationIDs) {
map->removeAnnotation(id);
}
@@ -775,6 +811,8 @@ void GLFWView::popAnnotation() {
}
void GLFWView::makeSnapshot(bool withOverlay) {
MLN_TRACE_FUNC();
if (!snapshotter || snapshotter->getStyleURL() != map->getStyle().getURL()) {
snapshotter = std::make_unique<mbgl::MapSnapshotter>(map->getMapOptions().size(),
map->getMapOptions().pixelRatio(),
@@ -815,6 +853,8 @@ void GLFWView::makeSnapshot(bool withOverlay) {
}
void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
double delta = yOffset * 40;
@@ -843,6 +883,8 @@ void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset)
}
void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->width = width;
view->height = height;
@@ -856,6 +898,8 @@ void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
}
void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->backend->setSize({static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
@@ -867,6 +911,8 @@ void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
}
void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modifiers) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
if (button == GLFW_MOUSE_BUTTON_RIGHT || (button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) {
@@ -898,6 +944,8 @@ void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modi
}
void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
MLN_TRACE_FUNC();
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
if (view->tracking) {
const double dx = x - view->lastX;
@@ -958,6 +1006,8 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
}
void GLFWView::onWindowFocus(GLFWwindow *window, int focused) {
MLN_TRACE_FUNC();
if (focused == GLFW_FALSE) { // Focus lost.
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->rendererFrontend->getRenderer()->reduceMemoryUse();
@@ -965,19 +1015,35 @@ void GLFWView::onWindowFocus(GLFWwindow *window, int focused) {
}
void GLFWView::run() {
MLN_TRACE_FUNC();
auto callback = [&] {
if (glfwWindowShouldClose(window)) {
runLoop.stop();
return;
MLN_TRACE_ZONE(GLFWView_runLoop_callback);
{
MLN_TRACE_ZONE(glfwWindowShouldClose);
if (glfwWindowShouldClose(window)) {
runLoop.stop();
return;
}
}
glfwPollEvents();
{
MLN_TRACE_ZONE(glfwPollEvents);
glfwPollEvents();
}
if (dirty && rendererFrontend) {
MLN_TRACE_ZONE(ReRender);
dirty = false;
const double started = glfwGetTime();
if (animateRouteCallback) animateRouteCallback(map);
if (animateRouteCallback) {
MLN_TRACE_ZONE(animateRouteCallback);
animateRouteCallback(map);
}
updateAnimatedAnnotations();
@@ -996,7 +1062,15 @@ void GLFWView::run() {
}
};
frameTick.start(mbgl::Duration::zero(), mbgl::Milliseconds(1000 / 60), callback);
// Cap frame rate to 60hz if benchmark mode is disabled
auto tickDuration = mbgl::Milliseconds(1000 / 60);
if (benchmark) {
// frameTick.start internally uses libuv which uses milliseconds resolution
// tickDuration is set to 1ms in benchmark mode which limits FPS to 1000
// 1000 should more than enough for benchmarking purposes
tickDuration = mbgl::Milliseconds(1);
}
frameTick.start(mbgl::Duration::zero(), tickDuration, callback);
#if defined(__APPLE__)
while (!glfwWindowShouldClose(window)) runLoop.run();
#else
@@ -1013,6 +1087,8 @@ mbgl::Size GLFWView::getSize() const {
}
void GLFWView::invalidate() {
MLN_TRACE_FUNC();
dirty = true;
glfwPostEmptyEvent();
}
@@ -1041,15 +1117,21 @@ void GLFWView::setChangeStyleCallback(std::function<void()> callback) {
}
void GLFWView::setShouldClose() {
MLN_TRACE_FUNC();
glfwSetWindowShouldClose(window, true);
glfwPostEmptyEvent();
}
void GLFWView::setWindowTitle(const std::string &title) {
MLN_TRACE_FUNC();
glfwSetWindowTitle(window, (std::string{"MapLibre Native (GLFW): "} + title).c_str());
}
void GLFWView::onDidFinishLoadingStyle() {
MLN_TRACE_FUNC();
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL)
puck = nullptr;
#endif
@@ -1060,11 +1142,15 @@ void GLFWView::onDidFinishLoadingStyle() {
}
void GLFWView::toggle3DExtrusions(bool visible) {
MLN_TRACE_FUNC();
show3DExtrusions = visible;
addFillExtrusionLayer(map->getStyle(), show3DExtrusions);
}
void GLFWView::toggleCustomSource() {
MLN_TRACE_FUNC();
if (!map->getStyle().getSource("custom")) {
mbgl::style::CustomGeometrySource::Options options;
options.cancelTileFunction = [](const mbgl::CanonicalTileID &) {
@@ -1115,6 +1201,8 @@ void GLFWView::toggleCustomSource() {
}
void GLFWView::toggleLocationIndicatorLayer() {
MLN_TRACE_FUNC();
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
puck = static_cast<mbgl::style::LocationIndicatorLayer *>(map->getStyle().getLayer("puck"));
static const mbgl::LatLng puckLocation{35.683389, 139.76525}; // A location on the crossing of 4 tiles
@@ -1178,6 +1266,8 @@ void GLFWView::toggleLocationIndicatorLayer() {
using Nanoseconds = std::chrono::nanoseconds;
void GLFWView::onWillStartRenderingFrame() {
MLN_TRACE_FUNC();
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
puck = static_cast<mbgl::style::LocationIndicatorLayer *>(map->getStyle().getLayer("puck"));
if (puck) {

View File

@@ -2,6 +2,7 @@
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/layermanager/layer_manager.hpp>
@@ -25,6 +26,8 @@ void RenderAnnotationSource::update(Immutable<style::Source::Impl> baseImpl_,
const bool needsRendering,
const bool needsRelayout,
const TileParameters& parameters) {
MLN_TRACE_FUNC();
std::swap(baseImpl, baseImpl_);
enabled = needsRendering;

View File

@@ -11,10 +11,12 @@
#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/offscreen_texture.hpp>
#include <mbgl/gl/debugging_extension.hpp>
#include <mbgl/gl/timestamp_query_extension.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/thread_pool.hpp>
#if MLN_DRAWABLE_RENDERER
@@ -70,6 +72,24 @@ GLint getMaxVertexAttribs() {
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
return value;
}
// Currently renderBufferByteSize is only used when Tracy profiling is enabled
#ifdef MLN_TRACY_ENABLE
constexpr size_t renderBufferByteSize(const gfx::RenderbufferPixelType type, const Size size) noexcept {
size_t sz = size.width * size.height;
switch (type) {
case gfx::RenderbufferPixelType::RGBA:
[[fallthrough]];
case gfx::RenderbufferPixelType::DepthStencil:
sz *= 4;
break;
case gfx::RenderbufferPixelType::Depth:
sz *= 2;
break;
}
return sz;
}
#endif
} // namespace
Context::Context(RendererBackend& backend_)
@@ -93,6 +113,8 @@ Context::~Context() noexcept {
}
void Context::beginFrame() {
MLN_TRACE_FUNC();
Scheduler::GetBackground()->runRenderJobs();
#if MLN_DRAWABLE_RENDERER
@@ -111,6 +133,8 @@ void Context::beginFrame() {
}
void Context::endFrame() {
MLN_TRACE_FUNC();
#if MLN_DRAWABLE_RENDERER
if (!frameInFlightFence) {
return;
@@ -121,6 +145,8 @@ void Context::endFrame() {
}
void Context::initializeExtensions(const std::function<gl::ProcAddress(const char*)>& getProcAddress) {
MLN_TRACE_FUNC();
if (const auto* extensions = reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) {
auto fn = [&](std::initializer_list<std::pair<const char*, const char*>> probes) -> ProcAddress {
for (auto probe : probes) {
@@ -143,7 +169,13 @@ void Context::initializeExtensions(const std::function<gl::ProcAddress(const cha
if (!(renderer.find("ANGLE") != std::string::npos && renderer.find("Direct3D") != std::string::npos)) {
debugging = std::make_unique<extension::Debugging>(fn);
}
// Currently GL timestamp queries are only used when Tracy profiling is enabled
#ifdef MLN_TRACY_ENABLE
extension::loadTimeStampQueryExtension(fn);
#endif
}
MLN_TRACE_GL_CONTEXT();
}
void Context::enableDebugging() {
@@ -207,11 +239,15 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha
}
void Context::linkProgram(ProgramID program_) {
MLN_TRACE_FUNC();
MBGL_CHECK_ERROR(glLinkProgram(program_));
verifyProgramLinkage(program_);
}
void Context::verifyProgramLinkage(ProgramID program_) {
MLN_TRACE_FUNC();
GLint status;
MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_LINK_STATUS, &status));
if (status == GL_TRUE) {
@@ -230,6 +266,8 @@ void Context::verifyProgramLinkage(ProgramID program_) {
}
UniqueTexture Context::createUniqueTexture() {
MLN_TRACE_FUNC();
if (pooledTextures.empty()) {
pooledTextures.resize(TextureMax);
MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data()));
@@ -244,6 +282,8 @@ UniqueTexture Context::createUniqueTexture() {
}
VertexArray Context::createVertexArray() {
MLN_TRACE_FUNC();
VertexArrayID id = 0;
MBGL_CHECK_ERROR(glGenVertexArrays(1, &id));
// NOLINTNEXTLINE(performance-move-const-arg)
@@ -252,6 +292,8 @@ VertexArray Context::createVertexArray() {
}
UniqueFramebuffer Context::createFramebuffer() {
MLN_TRACE_FUNC();
FramebufferID id = 0;
MBGL_CHECK_ERROR(glGenFramebuffers(1, &id));
stats.numFrameBuffers++;
@@ -262,6 +304,8 @@ UniqueFramebuffer Context::createFramebuffer() {
std::unique_ptr<gfx::TextureResource> Context::createTextureResource(const Size size,
const gfx::TexturePixelType format,
const gfx::TextureChannelDataType type) {
MLN_TRACE_FUNC();
auto obj = createUniqueTexture();
int textureByteSize = gl::TextureResource::getStorageSize(size, format, type);
stats.memTextures += textureByteSize;
@@ -296,8 +340,11 @@ std::unique_ptr<gfx::TextureResource> Context::createTextureResource(const Size
std::unique_ptr<gfx::RenderbufferResource> Context::createRenderbufferResource(const gfx::RenderbufferPixelType type,
const Size size) {
MLN_TRACE_FUNC();
RenderbufferID id = 0;
MBGL_CHECK_ERROR(glGenRenderbuffers(1, &id));
MLN_TRACE_ALLOC_RT(id, renderBufferByteSize(type, size));
// NOLINTNEXTLINE(performance-move-const-arg)
UniqueRenderbuffer renderbuffer{std::move(id), {this}};
@@ -305,12 +352,16 @@ std::unique_ptr<gfx::RenderbufferResource> Context::createRenderbufferResource(c
MBGL_CHECK_ERROR(
glRenderbufferStorage(GL_RENDERBUFFER, Enum<gfx::RenderbufferPixelType>::to(type), size.width, size.height));
bindRenderbuffer = 0;
return std::make_unique<gl::RenderbufferResource>(std::move(renderbuffer));
}
std::unique_ptr<uint8_t[]> Context::readFramebuffer(const Size size,
const gfx::TexturePixelType format,
const bool flip) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
const size_t stride = size.width * (format == gfx::TexturePixelType::RGBA ? 4 : 1);
auto data = std::make_unique<uint8_t[]>(stride * size.height);
@@ -337,6 +388,8 @@ std::unique_ptr<uint8_t[]> Context::readFramebuffer(const Size size,
namespace {
void checkFramebuffer() {
MLN_TRACE_FUNC();
GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
if (status != GL_FRAMEBUFFER_COMPLETE) {
switch (status) {
@@ -368,6 +421,9 @@ void checkFramebuffer() {
}
void bindDepthStencilRenderbuffer(const gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil>& depthStencil) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
auto& depthStencilResource = depthStencil.getResource<gl::RenderbufferResource>();
#ifdef GL_DEPTH_STENCIL_ATTACHMENT
MBGL_CHECK_ERROR(glFramebufferRenderbuffer(
@@ -385,6 +441,8 @@ void bindDepthStencilRenderbuffer(const gfx::Renderbuffer<gfx::RenderbufferPixel
Framebuffer Context::createFramebuffer(
const gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA>& color,
const gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil>& depthStencil) {
MLN_TRACE_FUNC();
if (color.getSize() != depthStencil.getSize()) {
throw std::runtime_error("Renderbuffer size mismatch");
}
@@ -400,6 +458,8 @@ Framebuffer Context::createFramebuffer(
}
Framebuffer Context::createFramebuffer(const gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA>& color) {
MLN_TRACE_FUNC();
auto fbo = createFramebuffer();
bindFramebuffer = fbo;
auto& colorResource = color.getResource<gl::RenderbufferResource>();
@@ -411,6 +471,8 @@ Framebuffer Context::createFramebuffer(const gfx::Renderbuffer<gfx::Renderbuffer
Framebuffer Context::createFramebuffer(
const gfx::Texture& color, const gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil>& depthStencil) {
MLN_TRACE_FUNC();
if (color.size != depthStencil.getSize()) {
throw std::runtime_error("Renderbuffer size mismatch");
}
@@ -424,6 +486,8 @@ Framebuffer Context::createFramebuffer(
}
Framebuffer Context::createFramebuffer(const gfx::Texture& color) {
MLN_TRACE_FUNC();
auto fbo = createFramebuffer();
bindFramebuffer = fbo;
MBGL_CHECK_ERROR(glFramebufferTexture2D(
@@ -434,6 +498,7 @@ Framebuffer Context::createFramebuffer(const gfx::Texture& color) {
Framebuffer Context::createFramebuffer(const gfx::Texture& color,
const gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& depth) {
MLN_TRACE_FUNC();
if (color.size != depth.getSize()) {
throw std::runtime_error("Renderbuffer size mismatch");
}
@@ -451,14 +516,20 @@ Framebuffer Context::createFramebuffer(const gfx::Texture& color,
std::unique_ptr<gfx::OffscreenTexture> Context::createOffscreenTexture(const Size size,
const gfx::TextureChannelDataType type) {
MLN_TRACE_FUNC();
return std::make_unique<gl::OffscreenTexture>(*this, size, type);
}
std::unique_ptr<gfx::DrawScopeResource> Context::createDrawScopeResource() {
MLN_TRACE_FUNC();
return std::make_unique<gl::DrawScopeResource>(createVertexArray());
}
void Context::reset() {
MLN_TRACE_FUNC();
std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures));
pooledTextures.resize(0);
performCleanup();
@@ -466,6 +537,9 @@ void Context::reset() {
#if MLN_DRAWABLE_RENDERER
void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
// Reset GL state to a known state so the CustomLayer always has a clean slate.
bindVertexArray = value::BindVertexArray::Default;
setDepthMode(depthMode);
@@ -478,6 +552,8 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer,
const void* data,
std::size_t size,
bool persistent) {
MLN_TRACE_FUNC();
if (buffer) {
buffer->update(data, size);
return false;
@@ -488,6 +564,8 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer,
}
void Context::bindGlobalUniformBuffers(gfx::RenderPass&) const noexcept {
MLN_TRACE_FUNC();
for (size_t id = 0; id < globalUniformBuffers.allocatedSize(); id++) {
const auto& globalUniformBuffer = globalUniformBuffers.get(id);
if (!globalUniformBuffer) continue;
@@ -502,6 +580,8 @@ void Context::bindGlobalUniformBuffers(gfx::RenderPass&) const noexcept {
}
void Context::unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept {
MLN_TRACE_FUNC();
for (size_t id = 0; id < globalUniformBuffers.allocatedSize(); id++) {
const auto& globalUniformBuffer = globalUniformBuffers.get(id);
if (!globalUniformBuffer) continue;
@@ -512,6 +592,8 @@ void Context::unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept {
#endif
void Context::setDirtyState() {
MLN_TRACE_FUNC();
// Note: does not set viewport/scissorTest/bindFramebuffer to dirty
// since they are handled separately in the view object.
stencilFunc.setDirty();
@@ -550,14 +632,20 @@ void Context::setDirtyState() {
#if MLN_DRAWABLE_RENDERER
gfx::UniqueDrawableBuilder Context::createDrawableBuilder(std::string name) {
MLN_TRACE_FUNC();
return std::make_unique<gl::DrawableGLBuilder>(std::move(name));
}
gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t size, bool /*persistent*/) {
MLN_TRACE_FUNC();
return std::make_shared<gl::UniformBufferGL>(data, size, *uboAllocator);
}
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
MLN_TRACE_FUNC();
auto shaderGroup = shaders.getShaderGroup(name);
if (!shaderGroup) {
return nullptr;
@@ -566,22 +654,32 @@ gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders
}
TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {
MLN_TRACE_FUNC();
return std::make_shared<TileLayerGroupGL>(layerIndex, initialCapacity, std::move(name));
}
LayerGroupPtr Context::createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {
MLN_TRACE_FUNC();
return std::make_shared<LayerGroupGL>(layerIndex, initialCapacity, std::move(name));
}
gfx::Texture2DPtr Context::createTexture2D() {
MLN_TRACE_FUNC();
return std::make_shared<gl::Texture2D>(*this);
}
RenderTargetPtr Context::createRenderTarget(const Size size, const gfx::TextureChannelDataType type) {
MLN_TRACE_FUNC();
return std::make_shared<RenderTarget>(*this, size, type);
}
Framebuffer Context::createFramebuffer(const gfx::Texture2D& color) {
MLN_TRACE_FUNC();
auto fbo = createFramebuffer();
bindFramebuffer = fbo;
MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER,
@@ -600,6 +698,9 @@ gfx::VertexAttributeArrayPtr Context::createVertexAttributeArray() const {
#endif
void Context::clear(std::optional<mbgl::Color> color, std::optional<float> depth, std::optional<int32_t> stencil) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
GLbitfield mask = 0;
if (color) {
@@ -687,6 +788,8 @@ void Context::setColorMode(const gfx::ColorMode& color) {
}
std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
MLN_TRACE_FUNC();
backend.updateAssumedState();
if (backend.contextIsShared()) {
setDirtyState();
@@ -695,6 +798,9 @@ std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
}
void Context::finish() {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
MBGL_CHECK_ERROR(glFinish());
}
@@ -705,6 +811,9 @@ std::shared_ptr<gl::Fence> Context::getCurrentFrameFence() const {
#endif
void Context::draw(const gfx::DrawMode& drawMode, std::size_t indexOffset, std::size_t indexLength) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
switch (drawMode.type) {
case gfx::DrawModeType::Points:
break;
@@ -726,6 +835,8 @@ void Context::draw(const gfx::DrawMode& drawMode, std::size_t indexOffset, std::
}
void Context::performCleanup() {
MLN_TRACE_FUNC();
// TODO: Find a better way to unbind VAOs after we're done with them without
// introducing unnecessary bind(0)/bind(N) sequences.
{
@@ -806,6 +917,9 @@ void Context::performCleanup() {
}
void Context::reduceMemoryUsage() {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
performCleanup();
// Ensure that all pending actions are executed to ensure that they happen
@@ -824,6 +938,9 @@ void Context::visualizeDepthBuffer([[maybe_unused]] const float depthRangeSize)
#endif
void Context::clearStencilBuffer(const int32_t bits) {
MLN_TRACE_FUNC();
MLN_TRACE_FUNC_GL();
MBGL_CHECK_ERROR(glClearStencil(bits));
MBGL_CHECK_ERROR(glClear(GL_STENCIL_BUFFER_BIT));

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/platform/gl_functions.hpp>
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242

View File

@@ -1,5 +1,6 @@
#include <mbgl/gl/fence.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <cassert>
#include <stdexcept>
#include <string>
@@ -25,17 +26,23 @@ std::string glErrors() {
Fence::Fence() {}
Fence::~Fence() {
MLN_TRACE_FUNC();
if (fence) {
glDeleteSync(fence);
}
}
void Fence::insert() noexcept {
MLN_TRACE_FUNC();
assert(!fence);
fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
bool Fence::isSignaled() const {
MLN_TRACE_FUNC();
if (!fence) {
return false;
}

View File

@@ -1,10 +1,18 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/index_buffer_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace gl {
IndexBufferResource::IndexBufferResource(UniqueBuffer&& buffer_, int byteSize_)
: buffer(std::move(buffer_)),
byteSize(byteSize_) {
MLN_TRACE_ALLOC_INDEX_BUFFER(buffer.get(), byteSize);
}
IndexBufferResource::~IndexBufferResource() noexcept {
MLN_TRACE_FREE_INDEX_BUFFER(buffer.get());
auto& stats = buffer.get_deleter().context.renderingStats();
stats.memIndexBuffers -= byteSize;
assert(stats.memIndexBuffers >= 0);

View File

@@ -8,9 +8,7 @@ namespace gl {
class IndexBufferResource : public gfx::IndexBufferResource {
public:
IndexBufferResource(UniqueBuffer&& buffer_, int byteSize_)
: buffer(std::move(buffer_)),
byteSize(byteSize_) {}
IndexBufferResource(UniqueBuffer&& buffer_, int byteSize_);
~IndexBufferResource() noexcept override;
UniqueBuffer buffer;

View File

@@ -0,0 +1,13 @@
#include <mbgl/gl/renderbuffer_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace gl {
RenderbufferResource::~RenderbufferResource() noexcept {
MLN_TRACE_FREE_RT(renderbuffer.get());
}
} // namespace gl
} // namespace mbgl

View File

@@ -11,7 +11,7 @@ public:
explicit RenderbufferResource(UniqueRenderbuffer renderbuffer_)
: renderbuffer(std::move(renderbuffer_)) {}
~RenderbufferResource() noexcept override = default;
~RenderbufferResource() noexcept override;
UniqueRenderbuffer renderbuffer;
};

View File

@@ -4,6 +4,7 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/shaders/shader_manifest.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#if MLN_DRAWABLE_RENDERER
@@ -19,6 +20,8 @@ RendererBackend::RendererBackend(const gfx::ContextMode contextMode_)
: gfx::RendererBackend(contextMode_) {}
std::unique_ptr<gfx::Context> RendererBackend::createContext() {
MLN_TRACE_FUNC();
auto result = std::make_unique<gl::Context>(*this);
result->enableDebugging();
result->initializeExtensions(std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1));
@@ -26,10 +29,14 @@ std::unique_ptr<gfx::Context> RendererBackend::createContext() {
}
PremultipliedImage RendererBackend::readFramebuffer(const Size& size) {
MLN_TRACE_FUNC();
return getContext<gl::Context>().readFramebuffer<PremultipliedImage>(size);
}
void RendererBackend::assumeFramebufferBinding(const gl::FramebufferID fbo) {
MLN_TRACE_FUNC();
getContext<gl::Context>().bindFramebuffer.setCurrentValue(fbo);
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getContext<gl::Context>().bindFramebuffer.getCurrentValue());
@@ -37,20 +44,28 @@ void RendererBackend::assumeFramebufferBinding(const gl::FramebufferID fbo) {
}
void RendererBackend::assumeViewport(int32_t x, int32_t y, const Size& size) {
MLN_TRACE_FUNC();
getContext<gl::Context>().viewport.setCurrentValue({x, y, size});
assert(gl::value::Viewport::Get() == getContext<gl::Context>().viewport.getCurrentValue());
}
void RendererBackend::assumeScissorTest(bool enabled) {
MLN_TRACE_FUNC();
getContext<gl::Context>().scissorTest.setCurrentValue(enabled);
assert(gl::value::ScissorTest::Get() == getContext<gl::Context>().scissorTest.getCurrentValue());
}
bool RendererBackend::implicitFramebufferBound() {
MLN_TRACE_FUNC();
return getContext<gl::Context>().bindFramebuffer.getCurrentValue() == ImplicitFramebufferBinding;
}
void RendererBackend::setFramebufferBinding(const gl::FramebufferID fbo) {
MLN_TRACE_FUNC();
getContext<gl::Context>().bindFramebuffer = fbo;
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getContext<gl::Context>().bindFramebuffer.getCurrentValue());
@@ -58,11 +73,15 @@ void RendererBackend::setFramebufferBinding(const gl::FramebufferID fbo) {
}
void RendererBackend::setViewport(int32_t x, int32_t y, const Size& size) {
MLN_TRACE_FUNC();
getContext<gl::Context>().viewport = {x, y, size};
assert(gl::value::Viewport::Get() == getContext<gl::Context>().viewport.getCurrentValue());
}
void RendererBackend::setScissorTest(bool enabled) {
MLN_TRACE_FUNC();
getContext<gl::Context>().scissorTest = enabled;
assert(gl::value::ScissorTest::Get() == getContext<gl::Context>().scissorTest.getCurrentValue());
}
@@ -76,6 +95,8 @@ RendererBackend::~RendererBackend() = default;
/// @param programParameters ProgramParameters used to initialize each instance
template <shaders::BuiltIn... ShaderID>
void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& programParameters) {
MLN_TRACE_FUNC();
/// The following fold expression will create a shader for every type
/// in the parameter pack and register it with the shader registry.
@@ -93,6 +114,8 @@ void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& progr
}
void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramParameters& programParameters) {
MLN_TRACE_FUNC();
registerTypes<shaders::BuiltIn::BackgroundShader,
shaders::BuiltIn::BackgroundPatternShader,
shaders::BuiltIn::CircleShader,

View File

@@ -1,5 +1,6 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/texture_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace gl {
@@ -31,8 +32,15 @@ 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() noexcept {
auto& stats = texture.get_deleter().context->renderingStats();
MLN_TRACE_FREE_TEXTURE(texture.get());
stats.memTextures -= byteSize;
assert(stats.memTextures >= 0);
}

View File

@@ -8,9 +8,7 @@ namespace gl {
class TextureResource : public gfx::TextureResource {
public:
TextureResource(UniqueTexture&& texture_, int byteSize_)
: texture(std::move(texture_)),
byteSize(byteSize_) {}
TextureResource(UniqueTexture&& texture_, int byteSize_);
~TextureResource() noexcept override;
static int getStorageSize(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type);

View File

@@ -0,0 +1,118 @@
#include <mbgl/gl/timestamp_query_extension.hpp>
#include <cassert>
#include <memory>
namespace mbgl {
namespace gl {
namespace extension {
using namespace platform;
namespace {
struct TimestampQueryLoader {
TimestampQueryLoader(const GlContexsLoader &loadExtension)
: glGenQueries(loadExtension({{"GL_EXT_disjoint_timer_query", "glGenQueries"}})),
glDeleteQueries(loadExtension({{"GL_EXT_disjoint_timer_query", "glDeleteQueries"}})),
glIsQuery(loadExtension({{"GL_EXT_disjoint_timer_query", "glIsQuery"}})),
glBeginQuery(loadExtension({{"GL_EXT_disjoint_timer_query", "glBeginQuery"}})),
glEndQuery(loadExtension({{"GL_EXT_disjoint_timer_query", "glEndQuery"}})),
glQueryCounter(loadExtension({{"GL_EXT_disjoint_timer_query", "glQueryCounter"}})),
glGetQueryiv(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetQueryiv"}})),
glGetQueryObjectiv(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetQueryObjectiv"}})),
glGetQueryObjectuiv(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetQueryObjectuiv"}})),
glGetQueryObjecti64v(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetQueryObjecti64v"}})),
glGetQueryObjectui64v(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetQueryObjectui64v"}})),
glGetInteger64v(loadExtension({{"GL_EXT_disjoint_timer_query", "glGetInteger64v"}})) {}
ExtensionFunction<void(GLsizei n, GLuint *ids)> glGenQueries;
ExtensionFunction<void(GLsizei n, const GLuint *ids)> glDeleteQueries;
ExtensionFunction<GLboolean(GLuint id)> glIsQuery;
ExtensionFunction<void(GLenum target, GLuint id)> glBeginQuery;
ExtensionFunction<void(GLenum target)> glEndQuery;
ExtensionFunction<void(GLuint id, GLenum target)> glQueryCounter;
ExtensionFunction<void(GLenum target, GLenum pname, GLint *params)> glGetQueryiv;
ExtensionFunction<void(GLuint id, GLenum pname, GLint *params)> glGetQueryObjectiv;
ExtensionFunction<void(GLuint id, GLenum pname, GLuint *params)> glGetQueryObjectuiv;
ExtensionFunction<void(GLuint id, GLenum pname, GLint64 *params)> glGetQueryObjecti64v;
ExtensionFunction<void(GLuint id, GLenum pname, GLuint64 *params)> glGetQueryObjectui64v;
ExtensionFunction<void(GLenum pname, GLint64 *data)> glGetInteger64v;
};
std::unique_ptr<TimestampQueryLoader> &singleton() {
static std::unique_ptr<TimestampQueryLoader> loader;
return loader;
}
} // namespace
void glGenQueries(GLsizei n, GLuint *ids) {
assert(singleton() && singleton()->glGenQueries);
return singleton()->glGenQueries(n, ids);
}
void glDeleteQueries(GLsizei n, const GLuint *ids) {
assert(singleton() && singleton()->glDeleteQueries);
return singleton()->glDeleteQueries(n, ids);
}
GLboolean glIsQuery(GLuint id) {
assert(singleton() && singleton()->glIsQuery);
return singleton()->glIsQuery(id);
}
void glBeginQuery(GLenum target, GLuint id) {
assert(singleton() && singleton()->glBeginQuery);
return singleton()->glBeginQuery(target, id);
}
void glEndQuery(GLenum target) {
assert(singleton() && singleton()->glEndQuery);
return singleton()->glEndQuery(target);
}
void glQueryCounter(GLuint id, GLenum target) {
assert(singleton() && singleton()->glQueryCounter);
return singleton()->glQueryCounter(id, target);
}
void glGetQueryiv(GLenum target, GLenum pname, GLint *params) {
assert(singleton() && singleton()->glGetQueryiv);
return singleton()->glGetQueryiv(target, pname, params);
}
void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params) {
assert(singleton() && singleton()->glGetQueryObjectiv);
return singleton()->glGetQueryObjectiv(id, pname, params);
}
void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) {
assert(singleton() && singleton()->glGetQueryObjectuiv);
return singleton()->glGetQueryObjectuiv(id, pname, params);
}
void glGetQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params) {
assert(singleton() && singleton()->glGetQueryObjecti64v);
return singleton()->glGetQueryObjecti64v(id, pname, params);
}
void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params) {
assert(singleton() && singleton()->glGetQueryObjectui64v);
return singleton()->glGetQueryObjectui64v(id, pname, params);
}
void glGetInteger64v(GLenum pname, GLint64 *data) {
assert(singleton() && singleton()->glGetInteger64v);
return singleton()->glGetInteger64v(pname, data);
}
void loadTimeStampQueryExtension(const GlContexsLoader &loadExtension) {
auto &loader = singleton();
loader = std::make_unique<TimestampQueryLoader>(loadExtension);
}
} // namespace extension
} // namespace gl
} // namespace mbgl

View File

@@ -0,0 +1,41 @@
#pragma once
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/gl/extension.hpp>
#include <functional>
#define GL_QUERY_COUNTER_BITS 0x8864
#define GL_CURRENT_QUERY 0x8865
#define GL_QUERY_RESULT 0x8866
#define GL_QUERY_RESULT_AVAILABLE 0x8867
#define GL_TIME_ELAPSED 0x88BF
#define GL_TIMESTAMP 0x8E28
#define GL_GPU_DISJOINT 0x8FBB
namespace mbgl {
namespace gl {
namespace extension {
using namespace platform;
void glGenQueries(GLsizei n, GLuint *ids);
void glDeleteQueries(GLsizei n, const GLuint *ids);
GLboolean glIsQuery(GLuint id);
void glBeginQuery(GLenum target, GLuint id);
void glEndQuery(GLenum target);
void glQueryCounter(GLuint id, GLenum target);
void glGetQueryiv(GLenum target, GLenum pname, GLint *params);
void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params);
void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
void glGetQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
void glGetInteger64v(GLenum pname, GLint64 *data);
using GlContexsLoader = std::function<ProcAddress(std::initializer_list<std::pair<const char *, const char *>>)>;
void loadTimeStampQueryExtension(const GlContexsLoader &loadExtension);
} // namespace extension
} // namespace gl
} // namespace mbgl

View File

@@ -2,8 +2,10 @@
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/util/compression.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#include <atomic>
#include <vector>
#include <cassert>
@@ -12,9 +14,25 @@ namespace gl {
using namespace platform;
namespace {
// Currently unique IDs for constant buffers are only used when Tracy profiling is enabled
#ifdef MLN_TRACY_ENABLE
int64_t generateDebugId() noexcept {
static std::atomic_int64_t counter(0);
return ++counter;
}
#endif
} // namespace
UniformBufferGL::UniformBufferGL(const void* data_, std::size_t size_, IBufferAllocator& allocator_)
: UniformBuffer(size_),
#ifdef MLN_TRACY_ENABLE
uniqueDebugId(generateDebugId()),
#endif
managedBuffer(allocator_, this) {
MLN_TRACE_ALLOC_CONST_BUFFER(uniqueDebugId, size_);
if (size_ > managedBuffer.allocator.pageSize()) {
// Buffer is very large, won't fit in the provided allocator
MBGL_CHECK_ERROR(glGenBuffers(1, &localID));
@@ -30,15 +48,25 @@ UniformBufferGL::UniformBufferGL(const void* data_, std::size_t size_, IBufferAl
UniformBufferGL::UniformBufferGL(UniformBufferGL&& rhs) noexcept
: UniformBuffer(rhs.size),
#ifdef MLN_TRACY_ENABLE
uniqueDebugId(rhs.uniqueDebugId),
#endif
isManagedAllocation(rhs.isManagedAllocation),
localID(rhs.localID),
managedBuffer(std::move(rhs.managedBuffer)) {
managedBuffer.setOwner(this);
#ifdef MLN_TRACY_ENABLE
rhs.uniqueDebugId = -1;
#endif
}
UniformBufferGL::UniformBufferGL(const UniformBufferGL& other)
: UniformBuffer(other),
#ifdef MLN_TRACY_ENABLE
uniqueDebugId(generateDebugId()),
#endif
managedBuffer(other.managedBuffer.allocator, this) {
MLN_TRACE_ALLOC_CONST_BUFFER(uniqueDebugId, other.size);
managedBuffer.setOwner(this);
if (other.isManagedAllocation) {
managedBuffer.allocate(other.managedBuffer.getContents().data(), other.size);
@@ -52,6 +80,10 @@ UniformBufferGL::UniformBufferGL(const UniformBufferGL& other)
}
UniformBufferGL::~UniformBufferGL() {
#ifdef MLN_TRACY_ENABLE
assert(uniqueDebugId > 0);
#endif
MLN_TRACE_FREE_CONST_BUFFER(uniqueDebugId);
if (isManagedAllocation) {
return;
}

View File

@@ -1,10 +1,18 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace gl {
VertexBufferResource::VertexBufferResource(UniqueBuffer&& buffer_, int byteSize_)
: buffer(std::move(buffer_)),
byteSize(byteSize_) {
MLN_TRACE_ALLOC_VERTEX_BUFFER(buffer.get(), byteSize);
}
VertexBufferResource::~VertexBufferResource() noexcept {
MLN_TRACE_FREE_VERTEX_BUFFER(buffer.get());
auto& stats = buffer.get_deleter().context.renderingStats();
stats.memVertexBuffers -= byteSize;
assert(stats.memVertexBuffers >= 0);

View File

@@ -8,9 +8,7 @@ namespace gl {
class VertexBufferResource : public gfx::VertexBufferResource {
public:
VertexBufferResource(UniqueBuffer&& buffer_, int byteSize_)
: buffer(std::move(buffer_)),
byteSize(byteSize_) {}
VertexBufferResource(UniqueBuffer&& buffer_, int byteSize_);
~VertexBufferResource() noexcept override;
UniqueBuffer buffer;

View File

@@ -1,5 +1,6 @@
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/thread_local.hpp>
#include <cassert>
@@ -22,6 +23,8 @@ BackendScope::BackendScope(RendererBackend& backend_, ScopeType scopeType_)
nextScope(nullptr),
backend(backend_),
scopeType(scopeType_) {
MLN_TRACE_FUNC();
if (priorScope) {
assert(priorScope->nextScope == nullptr);
priorScope->nextScope = this;
@@ -34,6 +37,8 @@ BackendScope::BackendScope(RendererBackend& backend_, ScopeType scopeType_)
}
BackendScope::~BackendScope() {
MLN_TRACE_FUNC();
assert(nextScope == nullptr);
deactivate();
@@ -48,6 +53,8 @@ BackendScope::~BackendScope() {
}
void BackendScope::activate() {
MLN_TRACE_FUNC();
if (scopeType == ScopeType::Explicit && !(priorScope && this->backend == priorScope->backend) &&
!(nextScope && this->backend == nextScope->backend)) {
// Only activate when set to Explicit and

View File

@@ -26,6 +26,7 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/text/glyph_manager.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/logging.hpp>
@@ -84,6 +85,8 @@ public:
updateSymbolOpacities(updateSymbolOpacities_) {}
void prepare() override {
MLN_TRACE_FUNC();
for (auto it = layersNeedPlacement.rbegin(); it != layersNeedPlacement.rend(); ++it) {
placement->updateLayerBuckets(*it, parameters->transformParams.state, updateSymbolOpacities);
}
@@ -128,6 +131,8 @@ RenderOrchestrator::RenderOrchestrator(bool backgroundLayerAsColor_, const std::
}
RenderOrchestrator::~RenderOrchestrator() {
MLN_TRACE_FUNC();
if (contextLost) {
// Signal all RenderLayers that the context was lost
// before cleaning up. At the moment, only CustomLayer is
@@ -158,6 +163,8 @@ void RenderOrchestrator::setObserver(RendererObserver* observer_) {
std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
const std::shared_ptr<UpdateParameters>& updateParameters) {
MLN_TRACE_FUNC();
const auto startTime = util::MonotonicTimer::now().count();
const bool isMapModeContinuous = updateParameters->mode == MapMode::Continuous;
@@ -534,6 +541,8 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry,
const RenderedQueryOptions& options) const {
MLN_TRACE_FUNC();
std::unordered_map<std::string, const RenderLayer*> layers;
if (options.layerIDs) {
for (const auto& layerID : *options.layerIDs) {
@@ -554,6 +563,8 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_map<std::string, st
const ScreenLineString& geometry,
const std::unordered_map<std::string, const RenderLayer*>& layers,
const RenderedQueryOptions& options) const {
MLN_TRACE_FUNC();
const auto hasCrossTileIndex = [](const auto& pair) {
return pair.second->baseImpl->getTypeInfo()->crossTileIndex == style::LayerTypeInfo::CrossTileIndex::Required;
};
@@ -602,6 +613,8 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(
const ScreenLineString& geometry,
const RenderedQueryOptions& options,
const std::unordered_map<std::string, const RenderLayer*>& layers) const {
MLN_TRACE_FUNC();
std::unordered_set<std::string> sourceIDs;
std::unordered_map<std::string, const RenderLayer*> filteredLayers;
for (const auto& pair : layers) {
@@ -651,6 +664,8 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(
}
std::vector<Feature> RenderOrchestrator::queryShapeAnnotations(const ScreenLineString& geometry) const {
MLN_TRACE_FUNC();
assert(LayerManager::annotationsEnabled);
std::unordered_map<std::string, const RenderLayer*> shapeAnnotationLayers;
RenderedQueryOptions options;
@@ -671,6 +686,8 @@ std::vector<Feature> RenderOrchestrator::queryShapeAnnotations(const ScreenLineS
std::vector<Feature> RenderOrchestrator::querySourceFeatures(const std::string& sourceID,
const SourceQueryOptions& options) const {
MLN_TRACE_FUNC();
const RenderSource* source = getRenderSource(sourceID);
if (!source) return {};
@@ -683,6 +700,8 @@ FeatureExtensionValue RenderOrchestrator::queryFeatureExtensions(
const std::string& extension,
const std::string& extensionField,
const std::optional<std::map<std::string, Value>>& args) const {
MLN_TRACE_FUNC();
if (RenderSource* renderSource = getRenderSource(sourceID)) {
return renderSource->queryFeatureExtensions(feature, extension, extensionField, args);
}
@@ -693,6 +712,8 @@ void RenderOrchestrator::setFeatureState(const std::string& sourceID,
const std::optional<std::string>& sourceLayerID,
const std::string& featureID,
const FeatureState& state) {
MLN_TRACE_FUNC();
if (RenderSource* renderSource = getRenderSource(sourceID)) {
renderSource->setFeatureState(sourceLayerID, featureID, state);
}
@@ -702,6 +723,8 @@ void RenderOrchestrator::getFeatureState(FeatureState& state,
const std::string& sourceID,
const std::optional<std::string>& sourceLayerID,
const std::string& featureID) const {
MLN_TRACE_FUNC();
if (RenderSource* renderSource = getRenderSource(sourceID)) {
renderSource->getFeatureState(state, sourceLayerID, featureID);
}
@@ -711,12 +734,16 @@ void RenderOrchestrator::removeFeatureState(const std::string& sourceID,
const std::optional<std::string>& sourceLayerID,
const std::optional<std::string>& featureID,
const std::optional<std::string>& stateKey) {
MLN_TRACE_FUNC();
if (RenderSource* renderSource = getRenderSource(sourceID)) {
renderSource->removeFeatureState(sourceLayerID, featureID, stateKey);
}
}
void RenderOrchestrator::reduceMemoryUse() {
MLN_TRACE_FUNC();
filteredLayersForSource.shrink_to_fit();
for (const auto& entry : renderSources) {
entry.second->reduceMemoryUse();
@@ -726,6 +753,8 @@ void RenderOrchestrator::reduceMemoryUse() {
}
void RenderOrchestrator::dumpDebugLogs() {
MLN_TRACE_FUNC();
for (const auto& entry : renderSources) {
entry.second->dumpDebugLogs();
}
@@ -781,6 +810,8 @@ bool RenderOrchestrator::hasTransitions(TimePoint timePoint) const {
}
bool RenderOrchestrator::isLoaded() const {
MLN_TRACE_FUNC();
// do the simple boolean check before iterating over all the tiles in all the sources
if (!imageManager->isLoaded()) {
return false;
@@ -796,6 +827,8 @@ bool RenderOrchestrator::isLoaded() const {
}
void RenderOrchestrator::clearData() {
MLN_TRACE_FUNC();
if (!sourceImpls->empty()) sourceImpls = makeMutable<std::vector<Immutable<style::Source::Impl>>>();
if (!layerImpls->empty()) layerImpls = makeMutable<std::vector<Immutable<style::Layer::Impl>>>();
if (!imageImpls->empty()) imageImpls = makeMutable<std::vector<Immutable<style::Image::Impl>>>();
@@ -830,6 +863,8 @@ void RenderOrchestrator::addChanges(UniqueChangeRequestVec& changes) {
}
void RenderOrchestrator::updateLayerIndex(LayerGroupBasePtr layerGroup, const int32_t newIndex) {
MLN_TRACE_FUNC();
if (!layerGroup || layerGroup->getLayerIndex() == newIndex) {
return;
}
@@ -847,6 +882,8 @@ void RenderOrchestrator::updateLayerIndex(LayerGroupBasePtr layerGroup, const in
}
bool RenderOrchestrator::addLayerGroup(LayerGroupBasePtr layerGroup) {
MLN_TRACE_FUNC();
const auto index = layerGroup->getLayerIndex();
const auto range = layerGroupsByLayerIndex.equal_range(index);
bool found = false;
@@ -867,6 +904,8 @@ bool RenderOrchestrator::addLayerGroup(LayerGroupBasePtr layerGroup) {
}
bool RenderOrchestrator::removeLayerGroup(const LayerGroupBasePtr& layerGroup) {
MLN_TRACE_FUNC();
if (!layerGroup) {
return false;
}
@@ -885,6 +924,8 @@ size_t RenderOrchestrator::numLayerGroups() const noexcept {
}
int32_t RenderOrchestrator::maxLayerIndex() const {
MLN_TRACE_FUNC();
if (!layerGroupsByLayerIndex.empty()) {
assert(layerGroupsByLayerIndex.crbegin()->first == layerGroupsByLayerIndex.crbegin()->second->getLayerIndex());
return layerGroupsByLayerIndex.crbegin()->first;
@@ -897,6 +938,8 @@ void RenderOrchestrator::updateLayers(gfx::ShaderRegistry& shaders,
const TransformState& state,
const std::shared_ptr<UpdateParameters>& updateParameters,
const RenderTree& renderTree) {
MLN_TRACE_FUNC();
const bool isMapModeContinuous = updateParameters->mode == MapMode::Continuous;
const auto transitionOptions = isMapModeContinuous ? updateParameters->transitionOptions
: style::TransitionOptions();
@@ -957,6 +1000,8 @@ void RenderOrchestrator::updateDebugLayerGroups(const RenderTree& renderTree, Pa
void RenderOrchestrator::onGlyphsError(const FontStack& fontStack,
const GlyphRange& glyphRange,
std::exception_ptr error) {
MLN_TRACE_FUNC();
Log::Error(Event::Style,
"Failed to load glyph range " + std::to_string(glyphRange.first) + "-" +
std::to_string(glyphRange.second) + " for font stack " + fontStackToString(fontStack) + ": " +
@@ -965,6 +1010,8 @@ void RenderOrchestrator::onGlyphsError(const FontStack& fontStack,
}
void RenderOrchestrator::onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) {
MLN_TRACE_FUNC();
Log::Error(Event::Style,
"Failed to load tile " + util::toString(tileID) + " for source " + source.baseImpl->id + ": " +
util::toString(error));
@@ -972,14 +1019,20 @@ void RenderOrchestrator::onTileError(RenderSource& source, const OverscaledTileI
}
void RenderOrchestrator::onTileChanged(RenderSource&, const OverscaledTileID&) {
MLN_TRACE_FUNC();
observer->onInvalidate();
}
void RenderOrchestrator::onStyleImageMissing(const std::string& id, const std::function<void()>& done) {
MLN_TRACE_FUNC();
observer->onStyleImageMissing(id, done);
}
void RenderOrchestrator::onRemoveUnusedStyleImages(const std::vector<std::string>& unusedImageIDs) {
MLN_TRACE_FUNC();
observer->onRemoveUnusedStyleImages(unusedImageIDs);
}

View File

@@ -8,6 +8,7 @@
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/renderer/update_parameters.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
@@ -29,6 +30,7 @@ void Renderer::setObserver(RendererObserver* observer) {
}
void Renderer::render(const std::shared_ptr<UpdateParameters>& updateParameters) {
MLN_TRACE_FUNC();
assert(updateParameters);
if (auto renderTree = impl->orchestrator.createRenderTree(updateParameters)) {
renderTree->prepare();

View File

@@ -17,6 +17,7 @@
#include <mbgl/util/convert.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/instrumentation.hpp>
#if MLN_DRAWABLE_RENDERER
#include <mbgl/gfx/drawable_tweaker.hpp>
@@ -73,6 +74,7 @@ void Renderer::Impl::setObserver(RendererObserver* observer_) {
void Renderer::Impl::render(const RenderTree& renderTree,
[[maybe_unused]] const std::shared_ptr<UpdateParameters>& updateParameters) {
MLN_TRACE_FUNC();
auto& context = backend.getContext();
#if MLN_RENDER_BACKEND_METAL
if constexpr (EnableMetalCapture) {
@@ -539,6 +541,7 @@ void Renderer::Impl::render(const RenderTree& renderTree,
}
frameCount += 1;
MLN_END_FRAME();
}
void Renderer::Impl::reduceMemoryUse() {

View File

@@ -5,6 +5,7 @@
#include <mbgl/style/source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace style {
@@ -15,18 +16,26 @@ Style::Style(std::shared_ptr<FileSource> fileSource, float pixelRatio)
Style::~Style() = default;
void Style::loadJSON(const std::string& json) {
MLN_TRACE_FUNC();
impl->loadJSON(json);
}
void Style::loadURL(const std::string& url) {
MLN_TRACE_FUNC();
impl->loadURL(url);
}
std::string Style::getJSON() const {
MLN_TRACE_FUNC();
return impl->getJSON();
}
std::string Style::getURL() const {
MLN_TRACE_FUNC();
return impl->getURL();
}
@@ -35,14 +44,20 @@ std::string Style::getName() const {
}
CameraOptions Style::getDefaultCamera() const {
MLN_TRACE_FUNC();
return impl->getDefaultCamera();
}
TransitionOptions Style::getTransitionOptions() const {
MLN_TRACE_FUNC();
return impl->getTransitionOptions();
}
void Style::setTransitionOptions(const TransitionOptions& options) {
MLN_TRACE_FUNC();
impl->mutated = true;
impl->setTransitionOptions(options);
}
@@ -61,73 +76,103 @@ const Light* Style::getLight() const {
}
std::optional<Image> Style::getImage(const std::string& name) const {
MLN_TRACE_FUNC();
auto image = impl->getImage(name);
if (!image) return std::nullopt;
return style::Image(std::move(*image));
}
void Style::addImage(std::unique_ptr<Image> image) {
MLN_TRACE_FUNC();
impl->mutated = true;
impl->addImage(std::move(image));
}
void Style::removeImage(const std::string& name) {
MLN_TRACE_FUNC();
impl->mutated = true;
impl->removeImage(name);
}
std::vector<Source*> Style::getSources() {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->getSources();
}
std::vector<const Source*> Style::getSources() const {
MLN_TRACE_FUNC();
return const_cast<const Impl&>(*impl).getSources();
}
Source* Style::getSource(const std::string& id) {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->getSource(id);
}
const Source* Style::getSource(const std::string& id) const {
MLN_TRACE_FUNC();
return impl->getSource(id);
}
void Style::addSource(std::unique_ptr<Source> source) {
MLN_TRACE_FUNC();
impl->mutated = true;
impl->addSource(std::move(source));
}
std::unique_ptr<Source> Style::removeSource(const std::string& sourceID) {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->removeSource(sourceID);
}
std::vector<Layer*> Style::getLayers() {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->getLayers();
}
std::vector<const Layer*> Style::getLayers() const {
MLN_TRACE_FUNC();
return const_cast<const Impl&>(*impl).getLayers();
}
Layer* Style::getLayer(const std::string& layerID) {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->getLayer(layerID);
}
const Layer* Style::getLayer(const std::string& layerID) const {
MLN_TRACE_FUNC();
return impl->getLayer(layerID);
}
void Style::addLayer(std::unique_ptr<Layer> layer, const std::optional<std::string>& before) {
MLN_TRACE_FUNC();
impl->mutated = true;
impl->addLayer(std::move(layer), before);
}
std::unique_ptr<Layer> Style::removeLayer(const std::string& id) {
MLN_TRACE_FUNC();
impl->mutated = true;
return impl->removeLayer(id);
}

View File

@@ -3,7 +3,9 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/tile/geojson_tile.hpp>
#include <mbgl/tile/geojson_tile_data.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <utility>
namespace mbgl {
GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
@@ -15,6 +17,8 @@ GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
}
void GeoJSONTile::updateData(std::shared_ptr<style::GeoJSONData> data_, bool needsRelayout) {
MLN_TRACE_FUNC();
assert(data_);
data = std::move(data_);
if (needsRelayout) reset();
@@ -29,6 +33,8 @@ void GeoJSONTile::updateData(std::shared_ptr<style::GeoJSONData> data_, bool nee
}
void GeoJSONTile::querySourceFeatures(std::vector<Feature>& result, const SourceQueryOptions& options) {
MLN_TRACE_FUNC();
// Ignore the sourceLayer, there is only one
if (auto tileData = getData()) {
if (auto layer = tileData->getLayer({})) {

View File

@@ -19,6 +19,7 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/geometry_tile_worker.hpp>
#include <mbgl/tile/tile_observer.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/thread_pool.hpp>
@@ -28,6 +29,8 @@
namespace mbgl {
LayerRenderData* GeometryTile::LayoutResult::getLayerRenderData(const style::Layer::Impl& layerImpl) {
MLN_TRACE_FUNC();
auto it = layerRenderData.find(layerImpl.id);
if (it == layerRenderData.end()) {
return nullptr;
@@ -62,6 +65,8 @@ private:
using namespace style;
std::optional<ImagePosition> GeometryTileRenderData::getPattern(const std::string& pattern) const {
MLN_TRACE_FUNC();
if (layoutResult) {
const auto& iconAtlas = layoutResult->iconAtlas;
auto it = iconAtlas.patternPositions.find(pattern);
@@ -73,6 +78,8 @@ std::optional<ImagePosition> GeometryTileRenderData::getPattern(const std::strin
}
void GeometryTileRenderData::upload(gfx::UploadPass& uploadPass) {
MLN_TRACE_FUNC();
if (!layoutResult) return;
auto uploadFn = [&](Bucket& bucket) {
@@ -127,6 +134,8 @@ void GeometryTileRenderData::upload(gfx::UploadPass& uploadPass) {
}
void GeometryTileRenderData::prepare(const SourcePrepareParameters& parameters) {
MLN_TRACE_FUNC();
if (!layoutResult) return;
imagePatches = layoutResult->iconAtlas.getImagePatchesAndUpdateVersions(parameters.imageManager);
}
@@ -177,6 +186,8 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_, std::string sourceID_, c
showCollisionBoxes(parameters.debugOptions & MapDebugOptions::Collision) {}
GeometryTile::~GeometryTile() {
MLN_TRACE_FUNC();
markObsolete();
glyphManager->removeRequestor(*this);
@@ -203,6 +214,8 @@ void GeometryTile::setError(std::exception_ptr err) {
}
void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) {
MLN_TRACE_FUNC();
if (obsolete) {
return;
}
@@ -217,6 +230,8 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) {
}
void GeometryTile::reset() {
MLN_TRACE_FUNC();
// Mark the tile as pending again if it was complete before to prevent
// signaling a complete state despite pending parse operations.
pending = true;
@@ -226,10 +241,14 @@ void GeometryTile::reset() {
}
std::unique_ptr<TileRenderData> GeometryTile::createRenderData() {
MLN_TRACE_FUNC();
return std::make_unique<GeometryTileRenderData>(layoutResult, atlasTextures);
}
void GeometryTile::setLayers(const std::vector<Immutable<LayerProperties>>& layers) {
MLN_TRACE_FUNC();
// Mark the tile as pending again if it was complete before to prevent
// signaling a complete state despite pending parse operations.
pending = true;
@@ -256,6 +275,8 @@ void GeometryTile::setLayers(const std::vector<Immutable<LayerProperties>>& laye
}
void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
MLN_TRACE_FUNC();
if (showCollisionBoxes != showCollisionBoxes_) {
showCollisionBoxes = showCollisionBoxes_;
++correlationID;
@@ -264,6 +285,8 @@ void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
}
void GeometryTile::onLayout(std::shared_ptr<LayoutResult> result, const uint64_t resultCorrelationID) {
MLN_TRACE_FUNC();
loaded = true;
renderable = true;
if (resultCorrelationID == correlationID) {
@@ -287,10 +310,14 @@ void GeometryTile::onError(std::exception_ptr err, const uint64_t resultCorrelat
}
void GeometryTile::onGlyphsAvailable(GlyphMap glyphs) {
MLN_TRACE_FUNC();
worker.self().invoke(&GeometryTileWorker::onGlyphsAvailable, std::move(glyphs));
}
void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) {
MLN_TRACE_FUNC();
if (fileSource) {
glyphManager->getGlyphs(*this, std::move(glyphDependencies), *fileSource);
}
@@ -300,6 +327,8 @@ void GeometryTile::onImagesAvailable(ImageMap images,
ImageMap patterns,
ImageVersionMap versionMap,
uint64_t imageCorrelationID) {
MLN_TRACE_FUNC();
worker.self().invoke(&GeometryTileWorker::onImagesAvailable,
std::move(images),
std::move(patterns),
@@ -308,6 +337,8 @@ void GeometryTile::onImagesAvailable(ImageMap images,
}
void GeometryTile::getImages(ImageRequestPair pair) {
MLN_TRACE_FUNC();
imageManager->getImages(*this, std::move(pair));
}
@@ -316,6 +347,8 @@ std::shared_ptr<FeatureIndex> GeometryTile::getFeatureIndex() const {
}
bool GeometryTile::layerPropertiesUpdated(const Immutable<style::LayerProperties>& layerProperties) {
MLN_TRACE_FUNC();
LayerRenderData* renderData = getLayerRenderData(*layerProperties->baseImpl);
if (!renderData) {
return false;
@@ -337,10 +370,14 @@ const GeometryTileData* GeometryTile::getData() const {
}
LayerRenderData* GeometryTile::getLayerRenderData(const style::Layer::Impl& layerImpl) {
MLN_TRACE_FUNC();
return layoutResult ? layoutResult->getLayerRenderData(layerImpl) : nullptr;
}
float GeometryTile::getQueryPadding(const std::unordered_map<std::string, const RenderLayer*>& layers) {
MLN_TRACE_FUNC();
float queryPadding = 0;
for (const auto& pair : layers) {
const LayerRenderData* data = getLayerRenderData(*pair.second->baseImpl);
@@ -358,6 +395,8 @@ void GeometryTile::queryRenderedFeatures(std::unordered_map<std::string, std::ve
const RenderedQueryOptions& options,
const mat4& projMatrix,
const SourceFeatureState& featureState) {
MLN_TRACE_FUNC();
if (!getData()) return;
const float queryPadding = getQueryPadding(layers);
@@ -380,6 +419,8 @@ void GeometryTile::queryRenderedFeatures(std::unordered_map<std::string, std::ve
}
void GeometryTile::querySourceFeatures(std::vector<Feature>& result, const SourceQueryOptions& options) {
MLN_TRACE_FUNC();
// Data not yet available, or tile is empty
if (!getData()) {
return;
@@ -435,6 +476,8 @@ void GeometryTile::performedFadePlacement() {
}
void GeometryTile::setFeatureState(const LayerFeatureStates& states) {
MLN_TRACE_FUNC();
auto layers = getData();
if ((layers == nullptr) || states.empty() || !layoutResult) {
return;

View File

@@ -1,6 +1,7 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/instrumentation.hpp>
#ifdef _MSC_VER
#pragma warning(push)
@@ -28,6 +29,8 @@ static double signedArea(const GeometryCoordinates& ring) {
}
static LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
MLN_TRACE_FUNC();
LinearRing<int32_t> result;
result.reserve(ring.size());
for (const auto& p : ring) {
@@ -37,6 +40,8 @@ static LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
}
static GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipolygon) {
MLN_TRACE_FUNC();
GeometryCollection result;
for (auto& polygon : multipolygon) {
for (auto& ring : polygon) {
@@ -47,6 +52,8 @@ static GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipoly
}
GeometryCollection fixupPolygons(const GeometryCollection& rings) {
MLN_TRACE_FUNC();
using namespace mapbox::geometry::wagyu;
wagyu<int32_t> clipper;
@@ -62,6 +69,8 @@ GeometryCollection fixupPolygons(const GeometryCollection& rings) {
}
std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
MLN_TRACE_FUNC();
std::vector<GeometryCollection> polygons;
std::size_t len = rings.size();
@@ -98,6 +107,8 @@ std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
}
void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
MLN_TRACE_FUNC();
if (polygon.size() > 1 + maxHoles) {
std::nth_element(
polygon.begin() + 1, polygon.begin() + 1 + maxHoles, polygon.end(), [](const auto& a, const auto& b) {
@@ -108,6 +119,8 @@ void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
}
Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
MLN_TRACE_FUNC();
const double size = util::EXTENT * std::pow(2, tileID.z);
const double x0 = util::EXTENT * static_cast<double>(tileID.x);
const double y0 = util::EXTENT * static_cast<double>(tileID.y);
@@ -179,6 +192,8 @@ Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFe
}
GeometryCollection convertGeometry(const Feature::geometry_type& geometryTileFeature, const CanonicalTileID& tileID) {
MLN_TRACE_FUNC();
const double size = util::EXTENT * std::pow(2, tileID.z);
const double x0 = util::EXTENT * static_cast<double>(tileID.x);
const double y0 = util::EXTENT * static_cast<double>(tileID.y);
@@ -260,6 +275,8 @@ GeometryCollection convertGeometry(const Feature::geometry_type& geometryTileFea
}
Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
MLN_TRACE_FUNC();
Feature feature{convertGeometry(geometryTileFeature, tileID)};
feature.properties = geometryTileFeature.getProperties();
feature.id = geometryTileFeature.getID();

View File

@@ -14,6 +14,7 @@
#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
@@ -46,6 +47,8 @@ GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
showCollisionBoxes(showCollisionBoxes_) {}
GeometryTileWorker::~GeometryTileWorker() {
MLN_TRACE_FUNC();
Scheduler::GetBackground()->runOnRenderThread([renderData_{std::move(renderData)}]() {});
}
@@ -123,6 +126,8 @@ GeometryTileWorker::~GeometryTileWorker() {
void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
std::set<std::string> availableImages_,
uint64_t correlationID_) {
MLN_TRACE_FUNC();
try {
data = std::move(data_);
correlationID = correlationID_;
@@ -148,6 +153,8 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_,
std::set<std::string> availableImages_,
uint64_t correlationID_) {
MLN_TRACE_FUNC();
try {
layers = std::move(layers_);
correlationID = correlationID_;
@@ -189,6 +196,8 @@ void GeometryTileWorker::reset(uint64_t correlationID_) {
}
void GeometryTileWorker::setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_) {
MLN_TRACE_FUNC();
try {
showCollisionBoxes = showCollisionBoxes_;
correlationID = correlationID_;
@@ -217,6 +226,8 @@ void GeometryTileWorker::setShowCollisionBoxes(bool showCollisionBoxes_, uint64_
}
void GeometryTileWorker::symbolDependenciesChanged() {
MLN_TRACE_FUNC();
try {
switch (state) {
case Idle:
@@ -245,6 +256,8 @@ void GeometryTileWorker::symbolDependenciesChanged() {
}
void GeometryTileWorker::coalesced() {
MLN_TRACE_FUNC();
try {
switch (state) {
case Idle:
@@ -274,11 +287,15 @@ void GeometryTileWorker::coalesced() {
}
void GeometryTileWorker::coalesce() {
MLN_TRACE_FUNC();
state = Coalescing;
self.invoke(&GeometryTileWorker::coalesced);
}
void GeometryTileWorker::onGlyphsAvailable(GlyphMap newGlyphMap) {
MLN_TRACE_FUNC();
for (auto& newFontGlyphs : newGlyphMap) {
FontStackHash fontStack = newFontGlyphs.first;
Glyphs& newGlyphs = newFontGlyphs.second;
@@ -308,6 +325,8 @@ void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap,
ImageMap newPatternMap,
ImageVersionMap newVersionMap,
uint64_t imageCorrelationID_) {
MLN_TRACE_FUNC();
if (imageCorrelationID != imageCorrelationID_) {
return; // Ignore outdated image request replies.
}
@@ -319,6 +338,8 @@ void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap,
}
void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependencies) {
MLN_TRACE_FUNC();
for (auto& fontDependencies : glyphDependencies) {
auto fontGlyphs = glyphMap.find(FontStackHasher()(fontDependencies.first));
for (auto glyphID : fontDependencies.second) {
@@ -333,6 +354,8 @@ void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependen
}
void GeometryTileWorker::requestNewImages(const ImageDependencies& imageDependencies) {
MLN_TRACE_FUNC();
pendingImageDependencies = imageDependencies;
if (!pendingImageDependencies.empty()) {
@@ -341,6 +364,8 @@ void GeometryTileWorker::requestNewImages(const ImageDependencies& imageDependen
}
void GeometryTileWorker::parse() {
MLN_TRACE_FUNC();
if (!data || !layers) {
return;
}
@@ -462,6 +487,8 @@ bool GeometryTileWorker::hasPendingParseResult() const {
}
void GeometryTileWorker::finalizeLayout() {
MLN_TRACE_FUNC();
if (!data || !layers || !hasPendingParseResult() || hasPendingDependencies()) {
return;
}

View File

@@ -1,10 +1,13 @@
#include <mbgl/tile/tile_cache.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <cassert>
namespace mbgl {
void TileCache::setSize(size_t size_) {
MLN_TRACE_FUNC();
size = size_;
while (orderedKeys.size() > size) {
@@ -37,6 +40,8 @@ struct CaptureWrapper {
} // namespace
void TileCache::deferredRelease(std::unique_ptr<Tile>&& tile) {
MLN_TRACE_FUNC();
tile->cancel();
// The `std::function` must be created in a separate statement from the `schedule` call.
@@ -53,6 +58,8 @@ void TileCache::deferredRelease(std::unique_ptr<Tile>&& tile) {
}
void TileCache::add(const OverscaledTileID& key, std::unique_ptr<Tile>&& tile) {
MLN_TRACE_FUNC();
if (!tile->isRenderable() || !size) {
deferredRelease(std::move(tile));
return;

View File

@@ -1,5 +1,6 @@
#include <mbgl/tile/vector_tile_data.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <mbgl/util/logging.hpp>
namespace mbgl {
@@ -37,6 +38,8 @@ FeatureIdentifier VectorTileFeature::getID() const {
}
const GeometryCollection& VectorTileFeature::getGeometries() const {
MLN_TRACE_FUNC();
if (!lines) {
const auto scale = static_cast<float>(util::EXTENT) / feature.getExtent();
@@ -78,6 +81,8 @@ std::unique_ptr<GeometryTileData> VectorTileData::clone() const {
}
std::unique_ptr<GeometryTileLayer> VectorTileData::getLayer(const std::string& name) const {
MLN_TRACE_FUNC();
if (!parsed) {
// We're parsing this lazily so that we can construct VectorTileData
// objects on the main thread without incurring the overhead of parsing

View File

@@ -2,6 +2,7 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/instrumentation.hpp>
#ifdef _MSC_VER
#pragma warning(push)
@@ -20,6 +21,8 @@ namespace mbgl {
namespace http {
CacheControl CacheControl::parse(const std::string& value) {
MLN_TRACE_FUNC();
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
@@ -40,6 +43,8 @@ std::optional<Timestamp> CacheControl::toTimePoint() const {
std::optional<Timestamp> parseRetryHeaders(const std::optional<std::string>& retryAfter,
const std::optional<std::string>& xRateLimitReset) {
MLN_TRACE_FUNC();
if (retryAfter) {
try {
auto secs = std::chrono::seconds(std::stoi(*retryAfter));

View File

@@ -1,5 +1,6 @@
#include <mbgl/util/http_timeout.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <algorithm>
#include <cassert>
@@ -10,6 +11,8 @@ namespace http {
Duration errorRetryTimeout(Response::Error::Reason failedRequestReason,
uint32_t failedRequests,
std::optional<Timestamp> retryAfter) {
MLN_TRACE_FUNC();
if (failedRequestReason == Response::Error::Reason::Server) {
// Retry after one second three times, then start exponential backoff.
return Seconds(failedRequests <= 3 ? 1 : 1u << std::min(failedRequests - 3, 31u));

View File

@@ -1,4 +1,5 @@
#include <mbgl/util/io.hpp>
#include <mbgl/util/instrumentation.hpp>
#include <cstdio>
#include <cerrno>
@@ -21,6 +22,8 @@ IOException::IOException(int err, const std::string &msg)
code(err) {}
void write_file(const std::string &filename, const std::string &data) {
MLN_TRACE_FUNC();
FILE *fd = fopen(filename.c_str(), MBGL_FOPEN_MODE_WBE);
if (fd) {
fwrite(data.data(), sizeof(std::string::value_type), data.size(), fd);
@@ -31,6 +34,8 @@ void write_file(const std::string &filename, const std::string &data) {
}
std::string read_file(const std::string &filename) {
MLN_TRACE_FUNC();
std::ifstream file(filename, std::ios::binary);
if (file.good()) {
std::stringstream data;
@@ -42,6 +47,8 @@ std::string read_file(const std::string &filename) {
}
std::optional<std::string> readFile(const std::string &filename) {
MLN_TRACE_FUNC();
std::ifstream file(filename, std::ios::binary);
if (file.good()) {
std::stringstream data;
@@ -52,6 +59,8 @@ std::optional<std::string> readFile(const std::string &filename) {
}
void deleteFile(const std::string &filename) {
MLN_TRACE_FUNC();
const int ret = std::remove(filename.c_str());
if (ret != 0 && errno != ENOENT) {
throw IOException(errno, "Could not delete file " + filename);
@@ -59,6 +68,8 @@ void deleteFile(const std::string &filename) {
}
void copyFile(const std::string &destination, const std::string &source) {
MLN_TRACE_FUNC();
std::ifstream src(source, std::ios::binary);
if (!src.good()) {
throw IOException(errno, "Cannot read file " + source);

26
vendor/tracy.cmake vendored Normal file
View File

@@ -0,0 +1,26 @@
if (MLN_USE_TRACY)
add_definitions(-DTRACY_ENABLE)
add_definitions(-DMLN_TRACY_ENABLE)
endif()
include(FetchContent)
FetchContent_Declare(
tracy
GIT_REPOSITORY "https://github.com/wolfpld/tracy.git"
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)
set_target_properties(
TracyClient
PROPERTIES
INTERFACE_MAPBOX_NAME "Tracy profiler"
INTERFACE_MAPBOX_URL "https://github.com/wolfpld/tracy.git"
INTERFACE_MAPBOX_AUTHOR "Bartosz Taudul"
INTERFACE_MAPBOX_LICENSE ${CMAKE_CURRENT_LIST_DIR}/tracy/LICENSE
)

27
vendor/tracy/LICENSE vendored Normal file
View File

@@ -0,0 +1,27 @@
Tracy Profiler (https://github.com/wolfpld/tracy) is licensed under the
3-clause BSD license.
Copyright (c) 2017-2024, Bartosz Taudul <wolf@nereid.pl>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.