Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebased iOS Metal support branch #369

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ include(${PROJECT_SOURCE_DIR}/vendor/benchmark.cmake)

if(CMAKE_SYSTEM_NAME STREQUAL iOS)
set_target_properties(mbgl-vendor-benchmark PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}")
set_target_properties(mbgl-vendor-benchmark PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
set_target_properties(mbgl-vendor-benchmark PROPERTIES XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE bitcode)
set_target_properties(mbgl-vendor-benchmark PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
set_target_properties(mbgl-vendor-benchmark PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)

set_target_properties(mbgl-benchmark PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}")
set_target_properties(mbgl-benchmark PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
set_target_properties(mbgl-benchmark PROPERTIES XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE bitcode)
set_target_properties(mbgl-benchmark PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
set_target_properties(mbgl-benchmark PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)
endif()

Expand Down
3 changes: 1 addition & 2 deletions platform/ios/ios.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ set_target_properties(mbgl-core PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[vari

macro(initialize_ios_target target)
set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}")
set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE bitcode)
set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)
endmacro()

Expand Down
1 change: 0 additions & 1 deletion platform/ios/platform/darwin/darwin.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ OTHER_CPLUSPLUSFLAGS = $(inherited) -fvisibility=hidden -fcxx-modules
OTHER_SWIFT_FLAGS = -warnings-as-errors

// User defined
BITCODE_GENERATION_MODE = bitcode
CURRENT_COMMIT_HASH = deadbeef
CURRENT_SEMANTIC_VERSION = 0.0.0
CURRENT_SHORT_VERSION = 0.0
Expand Down
3 changes: 2 additions & 1 deletion platform/ios/platform/darwin/src/MGLOpenGLStyleLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN

@class MGLMapView;
@class MGLStyle;
@class MGLContext;

typedef struct MGLStyleLayerDrawingContext {
CGSize size;
Expand All @@ -30,7 +31,7 @@ MGL_EXPORT
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#if TARGET_OS_IPHONE
@property (nonatomic, readonly) EAGLContext *context;
@property (nonatomic, readonly) MGLContext *context;
#else
@property (nonatomic, readonly) CGLContextObj context;
#endif
Expand Down
2 changes: 1 addition & 1 deletion platform/ios/platform/darwin/src/MGLOpenGLStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ - (MGLMapView *)mapView {
}

#if TARGET_OS_IPHONE
- (EAGLContext *)context {
- (MGLContext *)context {
return self.mapView.context;
}
#else
Expand Down
2 changes: 1 addition & 1 deletion platform/ios/platform/darwin/src/MGLReachability.m
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags
- (NSString *) description
{
NSString *description = [NSString stringWithFormat:@"<%@: %p (%@)>",
NSStringFromClass([self class]), (void *) self, [self currentReachabilityFlags]];
NSStringFromClass([self class]), self, [self currentReachabilityFlags]];
return description;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ - (id)mgl_jsonExpressionObject {
}

return self.arguments.mgl_jsonExpressionObject;
} else if (op == (NSString *) [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) {
} else if ([function isEqualToString:@"colorWithRed:green:blue:alpha:"]) {
NSArray *arguments = self.arguments.mgl_jsonExpressionObject;
return [@[@"rgba"] arrayByAddingObjectsFromArray:arguments];
} else if ([function isEqualToString:@"median:"] ||
Expand Down
3 changes: 1 addition & 2 deletions platform/ios/platform/ios/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ set(USE_GLES2 ON)

macro(initialize_ios_target target)
set_xcode_property(${target} IPHONEOS_DEPLOYMENT_TARGET "9.0")
set_xcode_property(${target} ENABLE_BITCODE "YES")
set_xcode_property(${target} BITCODE_GENERATION_MODE bitcode)
set_xcode_property(${target} ENABLE_BITCODE "NO")
set_xcode_property(${target} ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)

target_compile_options(${target}
Expand Down
193 changes: 144 additions & 49 deletions platform/ios/platform/ios/ios.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions platform/ios/platform/ios/scripts/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ if [[ ${BUILD_STATIC} == true ]]; then
mkdir "${OUTPUT}/static/${NAME}.framework/Modules"
cp -pv platform/ios/framework/modulemap "${OUTPUT}/static/${NAME}.framework/Modules/module.modulemap"
fi
if [[ ${BUILD_DYNAMIC} == true && ${BUILD_FOR_DEVICE} == true ]]; then
step "Copying bitcode symbol maps…"
find "${PRODUCTS}/${BUILDTYPE}-iphoneos" -name '*.bcsymbolmap' -type f -exec cp -pv {} "${OUTPUT}/dynamic/" \;
fi
#if [[ ${BUILD_DYNAMIC} == true && ${BUILD_FOR_DEVICE} == true ]]; then
# step "Copying bitcode symbol maps…"
# find "${PRODUCTS}/${BUILDTYPE}-iphoneos" -name '*.bcsymbolmap' -type f -exec cp -pv {} "${OUTPUT}/dynamic/" \;
#fi
sed -n -e '/^## /,$p' platform/ios/CHANGELOG.md > "${OUTPUT}/CHANGELOG.md"

rm -rf /tmp/mbgl
Expand Down
4 changes: 3 additions & 1 deletion platform/ios/platform/ios/src/MGLMapView+Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#import <UIKit/UIImage.h>
#import <QuartzCore/CALayer.h>

#import <MetalANGLE/MGLContext.h>

@class MGLMapView;

class MGLMapViewImpl : public mbgl::MapObserver {
Expand All @@ -18,7 +20,7 @@ class MGLMapViewImpl : public mbgl::MapObserver {
virtual mbgl::gfx::RendererBackend& getRendererBackend() = 0;

// Returns a handle to the OpenGL context object if this view is rendered with OpenGL.
virtual EAGLContext* getEAGLContext() {
virtual MGLContext* getEAGLContext() {
return nullptr;
}

Expand Down
7 changes: 1 addition & 6 deletions platform/ios/platform/ios/src/MGLMapView+OpenGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ class MGLMapViewOpenGLImpl final : public MGLMapViewImpl,
public:
void restoreFramebufferBinding();

#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
private:
void emergencyRecreateGL();
#endif

// Implementation of mbgl::gfx::RendererBackend
public:
mbgl::gfx::Renderable& getDefaultRenderable() override {
Expand All @@ -47,7 +42,7 @@ class MGLMapViewOpenGLImpl final : public MGLMapViewImpl,
return *this;
}

EAGLContext* getEAGLContext() override;
MGLContext* getEAGLContext() override;
void setOpaque(bool) override;
void display() override;
void setPresentsWithTransaction(bool) override;
Expand Down
109 changes: 35 additions & 74 deletions platform/ios/platform/ios/src/MGLMapView+OpenGL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@

#include <mbgl/gl/renderable_resource.hpp>
Copy link

@nvanfleet nvanfleet Aug 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this file should be renamed MGLMapView+OpenGL.mm

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is still pretty much OpenGL 🤔 it's really just the overriding header files and bundled MetalANGLE doing the transition magic. I think there's a plan to rewrite the SDK in native Metal, that would be a good opportunity for changes – till that time, the SDK is formally still OpenGL.


#import <GLKit/GLKit.h>
#import <OpenGLES/EAGL.h>
#import <QuartzCore/CAEAGLLayer.h>

@interface MGLMapViewImplDelegate : NSObject <GLKViewDelegate>
@interface MGLMapViewImplDelegate : NSObject <MGLKViewDelegate>
@end

@implementation MGLMapViewImplDelegate {
Expand All @@ -22,7 +18,7 @@ - (instancetype)initWithImpl:(MGLMapViewOpenGLImpl*)impl {
return self;
}

- (void)glkView:(nonnull GLKView*)view drawInRect:(CGRect)rect {
- (void)mglkView:(MGLKView *)view drawInRect:(CGRect)rect {
_impl->render();
}

Expand Down Expand Up @@ -60,8 +56,8 @@ void bind() override {

public:
MGLMapViewImplDelegate* delegate = nil;
GLKView *glView = nil;
EAGLContext *context = nil;
MGLKView *glView = nil;
MGLContext *context = nil;
const bool atLeastiOS_12_2_0;

// We count how often the context was activated/deactivated so that we can truly deactivate it
Expand All @@ -77,8 +73,8 @@ void bind() override {

MGLMapViewOpenGLImpl::~MGLMapViewOpenGLImpl() {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
if (resource.context && [[EAGLContext currentContext] isEqual:resource.context]) {
[EAGLContext setCurrentContext:nil];
if (resource.context && [[MGLContext currentContext] isEqual:resource.context]) {
[MGLContext setCurrentContext:nil];
}
}

Expand All @@ -89,22 +85,30 @@ void bind() override {
}

void MGLMapViewOpenGLImpl::setPresentsWithTransaction(const bool value) {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
eaglLayer.presentsWithTransaction = value;
// No-op on Metal.
}

void MGLMapViewOpenGLImpl::display() {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();

// Calling `display` here directly causes the stuttering bug (if
// `presentsWithTransaction` is `YES` - see above)
// as reported in https://github.com/mapbox/mapbox-gl-native-ios/issues/350
//
// Since we use `presentsWithTransaction` to synchronize with UIView
// annotations, we now let the system handle when the view is rendered. This
// has the potential to increase latency
[resource.glView setNeedsDisplay];
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
// glClear can be blocked for 1 second. This code is an "escape hatch",
// an attempt to detect this situation and rebuild the GL views.
if (mapView.enablePresentsWithTransaction && resource.atLeastiOS_12_2_0) {
CFTimeInterval before = CACurrentMediaTime();
[resource.glView display];
CFTimeInterval after = CACurrentMediaTime();

if (after - before >= 1.0) {
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
dispatch_async(dispatch_get_main_queue(), ^{
emergencyRecreateGL();
});
#endif
}
} else {
[resource.glView display];
}
}

void MGLMapViewOpenGLImpl::createView() {
Expand All @@ -114,22 +118,21 @@ void bind() override {
}

if (!resource.context) {
resource.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
resource.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES2];
assert(resource.context);
}

resource.glView = [[GLKView alloc] initWithFrame:mapView.bounds context:resource.context];
resource.glView = [[MGLKView alloc] initWithFrame:mapView.bounds context:resource.context];
resource.glView.delegate = resource.delegate;
resource.glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
resource.glView.contentScaleFactor = contentScaleFactor();
resource.glView.contentMode = UIViewContentModeCenter;
resource.glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
resource.glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
resource.glView.drawableStencilFormat = MGLDrawableStencilFormat8;
resource.glView.drawableDepthFormat = MGLDrawableDepthFormat16;
resource.glView.opaque = mapView.opaque;
resource.glView.layer.opaque = mapView.opaque;
resource.glView.enableSetNeedsDisplay = YES;
CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
eaglLayer.presentsWithTransaction = NO;
resource.glView.layer.sublayers.firstObject.zPosition = -10;
resource.glView.enableSetNeedsDisplay = NO;

[mapView insertSubview:resource.glView atIndex:0];
}
Expand All @@ -140,51 +143,9 @@ void bind() override {
}

void MGLMapViewOpenGLImpl::deleteView() {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
[resource.glView deleteDrawable];
// No-op on Metal
}

#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
// TODO: Fix or remove
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
void MGLMapViewOpenGLImpl::emergencyRecreateGL() {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
MGLLogError(@"Rendering took too long - creating GL views");

CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
eaglLayer.presentsWithTransaction = NO;

[mapView pauseRendering:nil];

// Just performing a pauseRendering:/resumeRendering: pair isn't sufficient - in this case
// we can still get errors when calling bindDrawable. Here we completely
// recreate the GLKView

[mapView.userLocationAnnotationView removeFromSuperview];
[resource.glView removeFromSuperview];

// Recreate the view
resource.glView = nil;
createView();

if (mapView.annotationContainerView) {
[resource.glView insertSubview:mapView.annotationContainerView atIndex:0];
}

[mapView updateUserLocationAnnotationView];

// Do not bind...yet

if (mapView.window) {
[mapView resumeRendering:nil];
eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
eaglLayer.presentsWithTransaction = mapView.enablePresentsWithTransaction;
} else {
MGLLogDebug(@"No window - skipping resumeRendering");
}
}
#endif

mbgl::gl::ProcAddress MGLMapViewOpenGLImpl::getExtensionFunctionPointer(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
Expand All @@ -201,7 +162,7 @@ void bind() override {
return;
}

[EAGLContext setCurrentContext:resource.context];
[MGLContext setCurrentContext:resource.context];
}

void MGLMapViewOpenGLImpl::deactivate() {
Expand All @@ -210,7 +171,7 @@ void bind() override {
return;
}

[EAGLContext setCurrentContext:nil];
[MGLContext setCurrentContext:nil];
}

/// This function is called before we start rendering, when iOS invokes our rendering method.
Expand Down Expand Up @@ -248,7 +209,7 @@ void bind() override {
static_cast<uint32_t>(mapView.bounds.size.height * scaleFactor) };
}

EAGLContext* MGLMapViewOpenGLImpl::getEAGLContext() {
MGLContext* MGLMapViewOpenGLImpl::getEAGLContext() {
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
return resource.context;
}
Loading