Synchronous rendering on Metal when annotation views are visible (#2334)
This commit is contained in:
@@ -57,6 +57,10 @@ public:
|
||||
void render();
|
||||
|
||||
virtual MLNBackendResource getObject() = 0;
|
||||
|
||||
virtual void setSynchronous(bool value) {};
|
||||
virtual bool getSynchronous() const { return false; };
|
||||
|
||||
|
||||
// mbgl::MapObserver implementation
|
||||
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) override;
|
||||
|
||||
@@ -50,6 +50,9 @@ public:
|
||||
MLNBackendResource getObject() override;
|
||||
// End implementation of MLNMapViewImpl
|
||||
|
||||
void setSynchronous(bool value) override { synchronousFrame = value; };
|
||||
bool getSynchronous() const override { return synchronousFrame; };
|
||||
private:
|
||||
bool presentsWithTransaction = false;
|
||||
bool synchronousFrame = false;
|
||||
};
|
||||
|
||||
@@ -84,9 +84,15 @@ public:
|
||||
}
|
||||
[commandBuffer commit];
|
||||
|
||||
// Un-comment for synchronous, which can help troubleshoot rendering problems,
|
||||
// Synchronous rendering can help troubleshoot rendering problems,
|
||||
// particularly those related to resource tracking and multiple queued buffers.
|
||||
//[commandBuffer waitUntilCompleted];
|
||||
// The conditional logic for synchronous rendering is commanded from MLNMapView.updateAnnotationViews:
|
||||
// `_mbglView->setSynchronous(haveVisibleAnnotationViews);`
|
||||
// and fixes the desynchronization of UIView annotation when the map is rendered on the Metal backend
|
||||
// Issue: https://github.com/maplibre/maplibre-native/issues/2053
|
||||
if (backend.getSynchronous()) {
|
||||
[commandBuffer waitUntilCompleted];
|
||||
}
|
||||
|
||||
commandBuffer = nil;
|
||||
commandBufferPtr.reset();
|
||||
|
||||
@@ -6917,6 +6917,9 @@ static void *windowScreenContext = &windowScreenContext;
|
||||
NSMutableArray *offscreenAnnotations = [self.annotations mutableCopy];
|
||||
[offscreenAnnotations removeObjectsInArray:visibleAnnotations];
|
||||
|
||||
// Dynamic flag used to drive the backend's synchronous frame rendering (see comment below)
|
||||
bool haveVisibleAnnotationViews = false;
|
||||
|
||||
// Update the center of visible annotation views
|
||||
for (id<MLNAnnotation> annotation in visibleAnnotations)
|
||||
{
|
||||
@@ -6953,6 +6956,7 @@ static void *windowScreenContext = &windowScreenContext;
|
||||
if (annotationView)
|
||||
{
|
||||
annotationView.center = MLNPointRounded([self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]);
|
||||
haveVisibleAnnotationViews = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7000,6 +7004,14 @@ static void *windowScreenContext = &windowScreenContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switch synchronous frame rendering on if we have visible annotation views.
|
||||
// Only implemented on Metal, just a stub on OpenGL.
|
||||
// This logic is needed to fix the desynchronization of UIView annotations when the map is rendered on the Metal backend with asynchronous frames.
|
||||
// Root cause: the Map transform is updated immediately and the annotations are positioned on the screen using it,
|
||||
// while the map rendered surface catches up when the frame is complete.
|
||||
// Issue: https://github.com/maplibre/maplibre-native/issues/2053
|
||||
_mbglView->setSynchronous(haveVisibleAnnotationViews);
|
||||
}
|
||||
|
||||
- (BOOL)hasAnAnchoredAnnotationCalloutView
|
||||
|
||||
Reference in New Issue
Block a user