Commit e56a64f2 authored by Klaus Weidner's avatar Klaus Weidner Committed by Commit Bot

WebXR: Tweak ARCore scheduling, add trace events

Update the ARCore scheduling to reduce latency, running GetFrameData and
ARCore's update with a delay when appropriate.

Use sliding averages to track timing for recent frames, and use that in
the heuristics.

Also add async trace events to mark Animating/Processing/Rendering
frames in the ArCoreGL timeline.

For background, see this presentation with some annotated trace events
explaining the new logic:

https://docs.google.com/presentation/d/e/2PACX-1vQTol3A0Y_LByOuMPSIb0qk-6FNQ7f5SpqO3GWfN-JY37LO7HPXTv1FrfK5e4Qerxx4CNzw9f90auCA/pub

Bug: 1136276
Change-Id: I0550ed3666c47d6f12b2708a1e5ef9a305b07f10
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2464052
Commit-Queue: Klaus Weidner <klausw@chromium.org>
Reviewed-by: default avatarPiotr Bialecki <bialpio@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816724}
parent a69328e2
...@@ -17,6 +17,10 @@ FakeArCore::FakeArCore() ...@@ -17,6 +17,10 @@ FakeArCore::FakeArCore()
FakeArCore::~FakeArCore() = default; FakeArCore::~FakeArCore() = default;
ArCore::MinMaxRange FakeArCore::GetTargetFramerateRange() {
return {30.f, 30.f};
}
bool FakeArCore::Initialize( bool FakeArCore::Initialize(
base::android::ScopedJavaLocalRef<jobject> application_context, base::android::ScopedJavaLocalRef<jobject> application_context,
const std::unordered_set<device::mojom::XRSessionFeature>& const std::unordered_set<device::mojom::XRSessionFeature>&
......
...@@ -26,6 +26,7 @@ class FakeArCore : public ArCore { ...@@ -26,6 +26,7 @@ class FakeArCore : public ArCore {
base::android::ScopedJavaLocalRef<jobject> application_context, base::android::ScopedJavaLocalRef<jobject> application_context,
const std::unordered_set<device::mojom::XRSessionFeature>& const std::unordered_set<device::mojom::XRSessionFeature>&
enabled_features) override; enabled_features) override;
MinMaxRange GetTargetFramerateRange() override;
void SetCameraTexture(uint32_t texture) override; void SetCameraTexture(uint32_t texture) override;
void SetDisplayGeometry(const gfx::Size& frame_size, void SetDisplayGeometry(const gfx::Size& frame_size,
display::Display::Rotation display_rotation) override; display::Display::Rotation display_rotation) override;
......
...@@ -25,6 +25,14 @@ class COMPONENT_EXPORT(VR_ARCORE) ArCore { ...@@ -25,6 +25,14 @@ class COMPONENT_EXPORT(VR_ARCORE) ArCore {
public: public:
virtual ~ArCore() = default; virtual ~ArCore() = default;
// Represents an inclusive range from min to max. (This is different from
// base::Interval which excludes the top end of the range, resulting in an
// empty interval if min==max.)
struct MinMaxRange {
float min;
float max;
};
// Initializes the runtime and returns whether it was successful. // Initializes the runtime and returns whether it was successful.
// If successful, the runtime must be paused when this method returns. // If successful, the runtime must be paused when this method returns.
virtual bool Initialize( virtual bool Initialize(
...@@ -32,6 +40,10 @@ class COMPONENT_EXPORT(VR_ARCORE) ArCore { ...@@ -32,6 +40,10 @@ class COMPONENT_EXPORT(VR_ARCORE) ArCore {
const std::unordered_set<device::mojom::XRSessionFeature>& const std::unordered_set<device::mojom::XRSessionFeature>&
enabled_features) = 0; enabled_features) = 0;
// Returns the target framerate range in Hz. Actual capture frame rate will
// vary within this range, i.e. lower in low light to increase exposure time.
virtual MinMaxRange GetTargetFramerateRange() = 0;
virtual void SetDisplayGeometry( virtual void SetDisplayGeometry(
const gfx::Size& frame_size, const gfx::Size& frame_size,
display::Display::Rotation display_rotation) = 0; display::Display::Rotation display_rotation) = 0;
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "device/vr/public/mojom/isolated_xr_service.mojom.h" #include "device/vr/public/mojom/isolated_xr_service.mojom.h"
#include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/public/mojom/vr_service.mojom.h"
#include "device/vr/util/fps_meter.h" #include "device/vr/util/fps_meter.h"
#include "device/vr/util/sliding_average.h"
#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h"
...@@ -180,6 +181,11 @@ class ArCoreGl : public mojom::XRFrameDataProvider, ...@@ -180,6 +181,11 @@ class ArCoreGl : public mojom::XRFrameDataProvider,
void GetRenderedFrameStats(); void GetRenderedFrameStats();
void FinishRenderingFrame(); void FinishRenderingFrame();
base::TimeDelta EstimatedArCoreFrameTime();
base::TimeDelta WaitTimeForArCoreUpdate();
base::TimeDelta WaitTimeForRenderCompletion();
void ScheduleGetFrameData();
void RunPendingGetFrameData();
bool IsFeatureEnabled(mojom::XRSessionFeature feature); bool IsFeatureEnabled(mojom::XRSessionFeature feature);
...@@ -251,6 +257,13 @@ class ArCoreGl : public mojom::XRFrameDataProvider, ...@@ -251,6 +257,13 @@ class ArCoreGl : public mojom::XRFrameDataProvider,
bool restrict_frame_data_ = false; bool restrict_frame_data_ = false;
base::TimeTicks last_arcore_update_time_;
base::TimeDelta last_arcore_frame_timestamp_;
device::SlidingTimeDeltaAverage average_animate_time_;
device::SlidingTimeDeltaAverage average_process_time_;
device::SlidingTimeDeltaAverage average_render_time_;
FPSMeter fps_meter_; FPSMeter fps_meter_;
mojo::Receiver<mojom::XRFrameDataProvider> frame_data_receiver_{this}; mojo::Receiver<mojom::XRFrameDataProvider> frame_data_receiver_{this};
......
...@@ -430,7 +430,7 @@ bool ArCoreImpl::Initialize( ...@@ -430,7 +430,7 @@ bool ArCoreImpl::Initialize(
return true; return true;
} }
bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const { bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) {
internal::ScopedArCoreObject<ArCameraConfigFilter*> camera_config_filter; internal::ScopedArCoreObject<ArCameraConfigFilter*> camera_config_filter;
ArCameraConfigFilter_create( ArCameraConfigFilter_create(
ar_session, internal::ScopedArCoreObject<ArCameraConfigFilter*>::Receiver( ar_session, internal::ScopedArCoreObject<ArCameraConfigFilter*>::Receiver(
...@@ -522,11 +522,16 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const { ...@@ -522,11 +522,16 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const {
ArCameraConfig_getDepthSensorUsage(ar_session, camera_config.get(), ArCameraConfig_getDepthSensorUsage(ar_session, camera_config.get(),
&depth_sensor_usage); &depth_sensor_usage);
int32_t min_fps, max_fps;
ArCameraConfig_getFpsRange(ar_session, camera_config.get(), &min_fps,
&max_fps);
DVLOG(3) << __func__ DVLOG(3) << __func__
<< ": matching camera config found, texture dimensions=" << ": matching camera config found, texture dimensions="
<< tex_width << "x" << tex_height << tex_width << "x" << tex_height
<< ", image dimensions= " << img_width << "x" << img_height << ", image dimensions= " << img_width << "x" << img_height
<< ", depth sensor usage=" << depth_sensor_usage; << ", depth sensor usage=" << depth_sensor_usage
<< ", min_fps=" << min_fps << ", max_fps=" << max_fps;
} }
#endif #endif
...@@ -601,6 +606,11 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const { ...@@ -601,6 +606,11 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const {
} }
}); });
int32_t fps_min, fps_max;
ArCameraConfig_getFpsRange(ar_session, best_config->get(), &fps_min,
&fps_max);
target_framerate_range_ = {fps_min, fps_max};
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
{ {
int32_t tex_width, tex_height; int32_t tex_width, tex_height;
...@@ -617,7 +627,9 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const { ...@@ -617,7 +627,9 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const {
DVLOG(3) << __func__ DVLOG(3) << __func__
<< ": selected camera config with texture dimensions=" << tex_width << ": selected camera config with texture dimensions=" << tex_width
<< "x" << tex_height << ", image dimensions=" << img_width << "x" << "x" << tex_height << ", image dimensions=" << img_width << "x"
<< img_height << ", depth sensor usage=" << depth_sensor_usage; << img_height << ", depth sensor usage=" << depth_sensor_usage
<< ", min_fps=" << target_framerate_range_.min
<< ", max_fps=" << target_framerate_range_.max;
} }
#endif #endif
...@@ -630,6 +642,10 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const { ...@@ -630,6 +642,10 @@ bool ArCoreImpl::ConfigureCamera(ArSession* ar_session) const {
return true; return true;
} }
ArCore::MinMaxRange ArCoreImpl::GetTargetFramerateRange() {
return target_framerate_range_;
}
void ArCoreImpl::SetCameraTexture(uint32_t camera_texture_id) { void ArCoreImpl::SetCameraTexture(uint32_t camera_texture_id) {
DCHECK(IsOnGlThread()); DCHECK(IsOnGlThread());
DCHECK(arcore_session_.is_valid()); DCHECK(arcore_session_.is_valid());
......
...@@ -110,6 +110,7 @@ class ArCoreImpl : public ArCore { ...@@ -110,6 +110,7 @@ class ArCoreImpl : public ArCore {
base::android::ScopedJavaLocalRef<jobject> application_context, base::android::ScopedJavaLocalRef<jobject> application_context,
const std::unordered_set<device::mojom::XRSessionFeature>& const std::unordered_set<device::mojom::XRSessionFeature>&
enabled_features) override; enabled_features) override;
MinMaxRange GetTargetFramerateRange() override;
void SetDisplayGeometry(const gfx::Size& frame_size, void SetDisplayGeometry(const gfx::Size& frame_size,
display::Display::Rotation display_rotation) override; display::Display::Rotation display_rotation) override;
void SetCameraTexture(uint32_t camera_texture_id) override; void SetCameraTexture(uint32_t camera_texture_id) override;
...@@ -190,6 +191,9 @@ class ArCoreImpl : public ArCore { ...@@ -190,6 +191,9 @@ class ArCoreImpl : public ArCore {
internal::ScopedArCoreObject<ArSession*> arcore_session_; internal::ScopedArCoreObject<ArSession*> arcore_session_;
internal::ScopedArCoreObject<ArFrame*> arcore_frame_; internal::ScopedArCoreObject<ArFrame*> arcore_frame_;
// Target framerate reflecting the current camera configuration.
MinMaxRange target_framerate_range_ = {30.f, 30.f};
// ArCore light estimation data // ArCore light estimation data
internal::ScopedArCoreObject<ArLightEstimate*> arcore_light_estimate_; internal::ScopedArCoreObject<ArLightEstimate*> arcore_light_estimate_;
...@@ -291,7 +295,7 @@ class ArCoreImpl : public ArCore { ...@@ -291,7 +295,7 @@ class ArCoreImpl : public ArCore {
// Helper, attempts to configure ArSession's camera for use. Note that this is // Helper, attempts to configure ArSession's camera for use. Note that this is
// happening during initialization, before arcore_session_ is set. // happening during initialization, before arcore_session_ is set.
// Returns true if configuration succeeded, false otherwise. // Returns true if configuration succeeded, false otherwise.
bool ConfigureCamera(ArSession* ar_session) const; bool ConfigureCamera(ArSession* ar_session);
// Must be last. // Must be last.
base::WeakPtrFactory<ArCoreImpl> weak_ptr_factory_{this}; base::WeakPtrFactory<ArCoreImpl> weak_ptr_factory_{this};
......
...@@ -31,6 +31,7 @@ namespace { ...@@ -31,6 +31,7 @@ namespace {
DO(ArCameraConfig_destroy) \ DO(ArCameraConfig_destroy) \
DO(ArCameraConfig_getDepthSensorUsage) \ DO(ArCameraConfig_getDepthSensorUsage) \
DO(ArCameraConfig_getFacingDirection) \ DO(ArCameraConfig_getFacingDirection) \
DO(ArCameraConfig_getFpsRange) \
DO(ArCameraConfig_getImageDimensions) \ DO(ArCameraConfig_getImageDimensions) \
DO(ArCameraConfig_getTextureDimensions) \ DO(ArCameraConfig_getTextureDimensions) \
DO(ArCameraConfigFilter_create) \ DO(ArCameraConfigFilter_create) \
...@@ -275,6 +276,14 @@ void ArCameraConfig_getFacingDirection( ...@@ -275,6 +276,14 @@ void ArCameraConfig_getFacingDirection(
session, camera_config, out_facing); session, camera_config, out_facing);
} }
void ArCameraConfig_getFpsRange(const ArSession* session,
const ArCameraConfig* camera_config,
int32_t* out_min_fps,
int32_t* out_max_fps) {
return g_arcore_api->impl_ArCameraConfig_getFpsRange(
session, camera_config, out_min_fps, out_max_fps);
}
void ArCameraConfig_getImageDimensions(const ArSession* session, void ArCameraConfig_getImageDimensions(const ArSession* session,
const ArCameraConfig* camera_config, const ArCameraConfig* camera_config,
int32_t* out_width, int32_t* out_width,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment