From add281957907708c13b8ef4a97436a1cd5cc5f31 Mon Sep 17 00:00:00 2001 From: Bill Orr Date: Wed, 29 Nov 2017 04:22:14 +0000 Subject: [PATCH] OpenVRRenderLoop needs to recover from WAIT_ABANDONED If IDXGIKeyedMutex::AcquireSync fails, it may be non-recoverable, and we need to create a new texture/GpuMemoryBuffer. Change-Id: Idd90a6ad38505736606fc488705ce63c45ef6d93 Reviewed-on: https://chromium-review.googlesource.com/794023 Commit-Queue: Bill Orr Reviewed-by: Daniel Cheng Reviewed-by: Michael Thiessen Reviewed-by: Klaus Weidner Cr-Commit-Position: refs/heads/master@{#520000} --- .../browser/android/vr_shell/vr_shell_gl.cc | 2 +- device/vr/openvr/openvr_render_loop.cc | 11 +++++----- device/vr/vr_service.mojom | 21 ++++++++++++++++++- .../WebKit/Source/modules/vr/VRDisplay.cpp | 5 +++-- .../WebKit/Source/modules/vr/VRDisplay.h | 3 ++- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index a5c0cb1846147a..6ce7491faacca3 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc @@ -400,7 +400,7 @@ void VrShellGl::SubmitFrame(int16_t frame_index, } // Always notify the client that we're done with the mailbox even // if we haven't drawn it, so that it's eligible for destruction. - submit_client_->OnSubmitFrameTransferred(); + submit_client_->OnSubmitFrameTransferred(true); if (!swapped) { // We dropped without drawing, report this as completed rendering // now to unblock the client. We're not going to receive it in diff --git a/device/vr/openvr/openvr_render_loop.cc b/device/vr/openvr/openvr_render_loop.cc index 788962def80860..2b5e3ca6344957 100644 --- a/device/vr/openvr/openvr_render_loop.cc +++ b/device/vr/openvr/openvr_render_loop.cc @@ -46,7 +46,8 @@ void OpenVRRenderLoop::SubmitFrameWithTextureHandle( texture_helper_.SetSourceTexture( base::win::ScopedHandle(reinterpret_cast(platform_handle.value))); texture_helper_.AllocateBackBuffer(); - if (texture_helper_.CopyTextureToBackBuffer(true)) { + bool copy_successful = texture_helper_.CopyTextureToBackBuffer(true); + if (copy_successful) { vr::Texture_t texture; texture.handle = texture_helper_.GetBackbuffer().Get(); texture.eType = vr::TextureType_DirectX; @@ -72,11 +73,11 @@ void OpenVRRenderLoop::SubmitFrameWithTextureHandle( return; } vr_compositor_->PostPresentHandoff(); - - // Tell WebVR that we are done with the texture. - submit_client_->OnSubmitFrameTransferred(); - submit_client_->OnSubmitFrameRendered(); } + + // Tell WebVR that we are done with the texture. + submit_client_->OnSubmitFrameTransferred(copy_successful); + submit_client_->OnSubmitFrameRendered(); #endif } diff --git a/device/vr/vr_service.mojom b/device/vr/vr_service.mojom index 0ebc0422f62be5..4c17f7ac1bd48f 100644 --- a/device/vr/vr_service.mojom +++ b/device/vr/vr_service.mojom @@ -81,8 +81,27 @@ interface VRServiceClient { VRDisplayInfo display_info); }; +// After submitting a frame, the VRPresentationProvider will notify the client +// about several stages of the render pipeline. This allows pipelining +// efficiency. Following VRPresentationProvider::Submit*, the submitted frame +// will be transferred (read from, perhaps copied to another texture), and then +// rendered (submitted to the underlying VR API). +// The client lives in the render process, implemented by VRDisplay. interface VRSubmitFrameClient { - OnSubmitFrameTransferred(); + // The VRPresentationProvider calls this to indicate that the submitted frame + // has been transferred, so the backing data (mailbox or GpuMemoryBuffer) can + // be reused or discarded. Note that this is a convenience/optimization + // feature, not a security feature - if a site discards the data early we may + // drop a frame, but nothing will otherwise misbehave. + // When the frame wasn't successfully transferred, the client should create a + // new mailbox/GpuMemoryBuffer rather than reusing an existing one to recover + // for subsequent frames. + OnSubmitFrameTransferred(bool success); + + // The VRPresentationProvider calls this after the frame was handed off to the + // underlying VR API. This allows some pipelining of CPU/GPU work, while + // delaying expensive tasks for a subsequent frame until the current frame has + // completed. OnSubmitFrameRendered(); }; diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp index 5af4af9db98d1a..6e6f0f03651b2d 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp @@ -706,7 +706,7 @@ void VRDisplay::submitFrame() { if (present_image_needs_copy_) { #if defined(OS_WIN) TRACE_EVENT0("gpu", "VRDisplay::CopyImage"); - if (!frame_copier_) { + if (!frame_copier_ || !last_transfer_succeeded_) { frame_copier_ = std::make_unique(context_gl_); } auto gpu_memory_buffer = frame_copier_->CopyImage(image_ref.get()); @@ -784,9 +784,10 @@ void VRDisplay::submitFrame() { rendering_context_->MarkCompositedAndClearBackbufferIfNeeded(); } -void VRDisplay::OnSubmitFrameTransferred() { +void VRDisplay::OnSubmitFrameTransferred(bool success) { DVLOG(3) << __FUNCTION__; pending_submit_frame_ = false; + last_transfer_succeeded_ = success; } void VRDisplay::OnSubmitFrameRendered() { diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h index b0c23e609b3a6b..465b300445868a 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.h +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h @@ -133,7 +133,7 @@ class VRDisplay final : public EventTargetWithInlineData, void OnPresentChange(); // VRSubmitFrameClient - void OnSubmitFrameTransferred() override; + void OnSubmitFrameTransferred(bool success) override; void OnSubmitFrameRendered() override; // VRDisplayClient @@ -215,6 +215,7 @@ class VRDisplay final : public EventTargetWithInlineData, bool pending_previous_frame_render_ = false; bool pending_submit_frame_ = false; bool pending_present_request_ = false; + bool last_transfer_succeeded_ = false; device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_; device::mojom::blink::VRDisplayHostPtr display_;