SpatialSurfaceObserver :: GetObservedSurfaces () занимает много времени и блокирует рендеринг - PullRequest
0 голосов
/ 14 января 2019

У меня есть приложение Hololens, написанное на C ++ / WinRT, которое запрашивает пространственные поверхности, используя SpatialSurfaceObserver. Для этого приложение отвечает на событие ObservedSurfacesChanged и запускает функцию, которая получает список пространственных сеток с GetObservedSurfaces. Затем для каждой записи создается и визуализируется сетка.

У меня проблемы с звонками на GetObservedSurfaces. Измерения показывают, что он обычно работает в течение 120-140 миллисекунд. Первые несколько запусков после запуска приложения занимают почти 500 миллисекунд. Само по себе это может быть приемлемым. Тем не менее, кажется, что вызов блокирует все приложение до его возврата, что приводит к тому, что цикл рендеринга отбрасывает несколько кадров, разрушая пользовательский опыт. Нет блокировки, которая бы заморозила приложение во время работы MyApp::UpdateSpatialMeshes. Если я заменим вызов auto surfaces = observer.GetObservedSurfaces(); на простое ожидание продолжительностью в одну секунду (и закомментирую все в зависимости от surfaces), все будет в порядке, без потери кадров.

У кого-нибудь есть идея, почему GetObservedSurfaces блокирует мое приложение или что я могу сделать, чтобы использовать его более правильно?

ОБНОВЛЕНИЕ: Есть ок. 40 поверхностных сеток в возвращенной коллекции, содержащей ~ 100 000 треугольников.

Инициализация:

winrt::Windows::Foundation::IAsyncAction MyApp::InitSurfaceObserver()
{
  co_await winrt::resume_background();

  auto status = co_await SpatialSurfaceObserver::RequestAccessAsync();
  if (status == SpatialPerceptionAccessStatus::Allowed)
  {
    auto coordSys = m_stationaryReferenceFrame.CoordinateSystem();
    m_surfaceObserver = SpatialSurfaceObserver();
    m_surfaceObserver.ObservedSurfacesChanged([this](auto&& sender, auto&& args)
    {
      UpdateSpatialMeshes(m_surfaceObserver, coordSys); // runs in background               
    });

    SpatialBoundingBox aabb = { { 0.0f,  0.0f, 0.0f }, { 20.0f, 20.0f, 5.0f } };
    auto bounds = SpatialBoundingVolume::FromBox(coordSys, aabb);
    m_surfaceObserver.SetBoundingVolume(bounds);
  }
  // else: complain
}

Обработка:

winrt::fire_and_forget MyApp::UpdateSpatialMeshes(const SpatialCoordinateSystem& coordSys, 
const SpatialSurfaceObserver& observer)
{       
  if (coordSys /* AND no other UpdateSpatialMeshes is currently running*/)
  {   
    SpatialCoordinateSystem scs{ coordSys }; // back up the coordinate system
    co_await winrt::resume_background();
    auto surfaces = observer.GetObservedSurfaces(); // <<< FREEZES EVERYTHING

    for (auto const& pair : surfaces)
    {
      const GUID& id = pair.Key();
      auto surfaceInfo = pair.Value();
      if (!surfaceInfo) continue;
      // TryComputeLatestMeshAsync, then render
    }
  }
}
...