Android benchmark frame time (#1958)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Alex Cristici
2024-02-01 22:30:56 +02:00
committed by GitHub
parent b683cceb3f
commit d2feec269e
22 changed files with 191 additions and 62 deletions

View File

@@ -22,6 +22,8 @@ public:
backend.setViewport(0, 0, backend.getSize());
}
void swap() override { backend.swap(); }
private:
AndroidRendererBackend& backend;
};
@@ -62,5 +64,15 @@ void AndroidRendererBackend::markContextLost() {
}
}
void AndroidRendererBackend::setSwapBehavior(SwapBehaviour swapBehaviour_) {
swapBehaviour = swapBehaviour_;
}
void AndroidRendererBackend::swap() {
if (swapBehaviour == SwapBehaviour::Flush) {
static_cast<gl::Context&>(getContext()).finish();
}
}
} // namespace android
} // namespace mbgl

View File

@@ -19,6 +19,12 @@ public:
void resizeFramebuffer(int width, int height);
PremultipliedImage readFramebuffer();
void setSwapBehavior(SwapBehaviour swapBehaviour);
void swap();
private:
SwapBehaviour swapBehaviour = SwapBehaviour::NoFlush;
// mbgl::gfx::RendererBackend implementation
public:
mbgl::gfx::Renderable& getDefaultRenderable() override { return *this; }

View File

@@ -236,6 +236,10 @@ void MapRenderer::onSurfaceDestroyed(JNIEnv&) {
resetRenderer();
}
void MapRenderer::setSwapBehaviorFlush(JNIEnv&, jboolean flush) {
backend->setSwapBehavior(flush ? gfx::Renderable::SwapBehaviour::Flush : gfx::Renderable::SwapBehaviour::NoFlush);
}
// Static methods //
void MapRenderer::registerNative(jni::JNIEnv& env) {
@@ -256,7 +260,8 @@ void MapRenderer::registerNative(jni::JNIEnv& env) {
METHOD(&MapRenderer::onRendererReset, "nativeReset"),
METHOD(&MapRenderer::onSurfaceCreated, "nativeOnSurfaceCreated"),
METHOD(&MapRenderer::onSurfaceChanged, "nativeOnSurfaceChanged"),
METHOD(&MapRenderer::onSurfaceDestroyed, "nativeOnSurfaceDestroyed"));
METHOD(&MapRenderer::onSurfaceDestroyed, "nativeOnSurfaceDestroyed"),
METHOD(&MapRenderer::setSwapBehaviorFlush, "nativeSetSwapBehaviorFlush"));
}
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) {

View File

@@ -107,6 +107,8 @@ private:
// Called on either Main or GL thread //
void onRendererReset(JNIEnv&);
void setSwapBehaviorFlush(JNIEnv&, jboolean flush);
private:
jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer;

View File

@@ -189,11 +189,15 @@ void NativeMapView::onDidFinishRenderingFrame(MapObserver::RenderFrameStatus sta
android::UniqueEnv _env = android::AttachEnv();
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
static auto onDidFinishRenderingFrame = javaClass.GetMethod<void(jboolean)>(*_env, "onDidFinishRenderingFrame");
static auto onDidFinishRenderingFrame = javaClass.GetMethod<void(jboolean, jdouble, jdouble)>(
*_env, "onDidFinishRenderingFrame");
auto weakReference = javaPeer.get(*_env);
if (weakReference) {
weakReference.Call(
*_env, onDidFinishRenderingFrame, (jboolean)(status.mode != MapObserver::RenderMode::Partial));
weakReference.Call(*_env,
onDidFinishRenderingFrame,
(jboolean)(status.mode != MapObserver::RenderMode::Partial),
(jdouble)status.frameEncodingTime,
(jdouble)status.frameRenderingTime);
}
}

View File

@@ -135,11 +135,11 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
}
@Override
public void onDidFinishRenderingFrame(boolean fully) {
public void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime) {
try {
if (!onDidFinishRenderingFrameList.isEmpty()) {
for (MapView.OnDidFinishRenderingFrameListener listener : onDidFinishRenderingFrameList) {
listener.onDidFinishRenderingFrame(fully);
listener.onDidFinishRenderingFrame(fully, frameEncodingTime, frameRenderingTime);
}
}
} catch (Throwable err) {

View File

@@ -103,6 +103,10 @@ public final class MapLibreMap {
nativeMapView.triggerRepaint();
}
public void setSwapBehaviorFlush(boolean flush) {
nativeMapView.setSwapBehaviorFlush(flush);
}
void initialise(@NonNull Context context, @NonNull MapLibreMapOptions options) {
transform.initialise(this, options);
uiSettings.initialise(context, options);

View File

@@ -1012,7 +1012,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param fully true if all frames have been rendered, false if partially rendered
*/
void onDidFinishRenderingFrame(boolean fully);
void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime);
}
/**
@@ -1185,7 +1185,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
}
@Override
public void onDidFinishRenderingFrame(boolean fully) {
public void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime) {
if (maplibreMap != null && maplibreMap.getStyle() != null && maplibreMap.getStyle().isFullyLoaded()) {
renderCount++;
if (renderCount == 3) {
@@ -1357,7 +1357,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
}
@Override
public void onDidFinishRenderingFrame(boolean fully) {
public void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime) {
if (maplibreMap != null) {
maplibreMap.onUpdateFullyRendered();
}

View File

@@ -239,6 +239,8 @@ interface NativeMap {
void triggerRepaint();
void setSwapBehaviorFlush(boolean flush);
//
// Deprecated Annotations API
//

View File

@@ -1026,6 +1026,11 @@ final class NativeMapView implements NativeMap {
nativeTriggerRepaint();
}
@Override
public void setSwapBehaviorFlush(boolean flush) {
mapRenderer.setSwapBehaviorFlush(flush);
}
@NonNull
@Override
public RectF getDensityDependantRectangle(final RectF rectangle) {
@@ -1091,9 +1096,9 @@ final class NativeMapView implements NativeMap {
}
@Keep
private void onDidFinishRenderingFrame(boolean fully) {
private void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime) {
if (stateCallback != null) {
stateCallback.onDidFinishRenderingFrame(fully);
stateCallback.onDidFinishRenderingFrame(fully, frameEncodingTime, frameRenderingTime);
}
}
@@ -1581,7 +1586,7 @@ final class NativeMapView implements NativeMap {
void onWillStartRenderingFrame();
void onDidFinishRenderingFrame(boolean fully);
void onDidFinishRenderingFrame(boolean fully, double frameEncodingTime, double frameRenderingTime);
void onWillStartRenderingMap();

View File

@@ -102,6 +102,10 @@ public abstract class MapRenderer implements MapRendererScheduler {
}
}
public void setSwapBehaviorFlush(boolean flush) {
nativeSetSwapBehaviorFlush(flush);
}
/**
* May be called from any thread.
* <p>
@@ -134,12 +138,16 @@ public abstract class MapRenderer implements MapRendererScheduler {
private native void nativeRender();
private native void nativeSetSwapBehaviorFlush(boolean flush);
private long timeElapsed;
private void updateFps() {
long currentTime = System.nanoTime();
double fps = 1E9 / ((currentTime - timeElapsed));
onFpsChangedListener.onFpsChanged(fps);
if (timeElapsed > 0) {
double fps = 1E9 / ((currentTime - timeElapsed));
onFpsChangedListener.onFpsChanged(fps);
}
timeElapsed = currentTime;
}

View File

@@ -401,22 +401,22 @@ class MapChangeReceiverTest {
mapChangeEventManager!!.addOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(true)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true, .0, .0)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(true, .0, .0)
mapChangeEventManager!!.removeOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(true)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true, .0, .0)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(true,.0, .0)
mapChangeEventManager!!.addOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
Logger.setLoggerDefinition(loggerDefinition)
val exc: Exception = RuntimeException()
Mockito.doThrow(exc).`when`(onDidFinishRenderingFrameListener)
?.onDidFinishRenderingFrame(true)
?.onDidFinishRenderingFrame(true, .0, .0)
try {
mapChangeEventManager!!?.onDidFinishRenderingFrame(true)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true, .0, .0)
Assert.fail("The exception should've been re-thrown.")
} catch (throwable: RuntimeException) {
Mockito.verify(loggerDefinition)?.e(
@@ -427,9 +427,9 @@ class MapChangeReceiverTest {
}
val err: Error = ExecutionError("", Error())
Mockito.doThrow(err).`when`(onDidFinishRenderingFrameListener)
?.onDidFinishRenderingFrame(true)
?.onDidFinishRenderingFrame(true, .0, .0)
try {
mapChangeEventManager!!?.onDidFinishRenderingFrame(true)
mapChangeEventManager!!?.onDidFinishRenderingFrame(true, .0, .0)
Assert.fail("The exception should've been re-thrown.")
} catch (throwable: ExecutionError) {
Mockito.verify(loggerDefinition)?.e(
@@ -445,22 +445,22 @@ class MapChangeReceiverTest {
mapChangeEventManager!!.addOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(false)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false, .0, .0)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(false, .0, .0)
mapChangeEventManager!!.removeOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(false)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false, .0, .0)
Mockito.verify(onDidFinishRenderingFrameListener)?.onDidFinishRenderingFrame(false, .0, .0)
mapChangeEventManager!!.addOnDidFinishRenderingFrameListener(
onDidFinishRenderingFrameListener
)
Logger.setLoggerDefinition(loggerDefinition)
val exc: Exception = RuntimeException()
Mockito.doThrow(exc).`when`(onDidFinishRenderingFrameListener)
?.onDidFinishRenderingFrame(false)
?.onDidFinishRenderingFrame(false, .0, .0)
try {
mapChangeEventManager!!?.onDidFinishRenderingFrame(false)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false, .0, .0)
Assert.fail("The exception should've been re-thrown.")
} catch (throwable: RuntimeException) {
Mockito.verify(loggerDefinition)?.e(
@@ -471,9 +471,9 @@ class MapChangeReceiverTest {
}
val err: Error = ExecutionError("", Error())
Mockito.doThrow(err).`when`(onDidFinishRenderingFrameListener)
?.onDidFinishRenderingFrame(false)
?.onDidFinishRenderingFrame(false, .0, .0)
try {
mapChangeEventManager!!?.onDidFinishRenderingFrame(false)
mapChangeEventManager!!?.onDidFinishRenderingFrame(false, .0, .0)
Assert.fail("The exception should've been re-thrown.")
} catch (throwable: ExecutionError) {
Mockito.verify(loggerDefinition)?.e(