Commit 4eaa4d2f authored by Sunny Sachanandani's avatar Sunny Sachanandani Committed by Commit Bot

Cache video processor output view for video swap chain

crrev.com/1318808 changed SwapChainPresenter to recreate video processor
output view on every PresentToSwapChain in addition to lazy initializing
the video device.  A power regression was noticed on internal AVA bots
around the same time.  This is a speculative fix for the power
regression by reverting to the old behavior of caching the output view.

Bug: 894675
Change-Id: I4130129951d8b9d9efa9aaeee4ba78aa1ef3f778
Reviewed-on: https://chromium-review.googlesource.com/c/1341156
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609475}
parent 75c8db0a
...@@ -461,9 +461,12 @@ class DCLayerTree::SwapChainPresenter { ...@@ -461,9 +461,12 @@ class DCLayerTree::SwapChainPresenter {
bool UploadVideoImages(gl::GLImageMemory* y_image_memory, bool UploadVideoImages(gl::GLImageMemory* y_image_memory,
gl::GLImageMemory* uv_image_memory); gl::GLImageMemory* uv_image_memory);
// Releases resources that might hold indirect references to the swap chain.
void ReleaseSwapChainResources();
// Recreate swap chain using given size. Use preferred YUV format if |yuv| is // Recreate swap chain using given size. Use preferred YUV format if |yuv| is
// true, or BGRA otherwise. Set |protected_video_type|. Returns true on // true, or BGRA otherwise. Sets flags based on |protected_video_type|.
// success. // Returns true on success.
bool ReallocateSwapChain(const gfx::Size& swap_chain_size, bool ReallocateSwapChain(const gfx::Size& swap_chain_size,
bool use_yuv_swap_chain, bool use_yuv_swap_chain,
ui::ProtectedVideoType protected_video_type); ui::ProtectedVideoType protected_video_type);
...@@ -561,6 +564,10 @@ class DCLayerTree::SwapChainPresenter { ...@@ -561,6 +564,10 @@ class DCLayerTree::SwapChainPresenter {
// chain that can be used for direct composition. // chain that can be used for direct composition.
base::win::ScopedHandle swap_chain_handle_; base::win::ScopedHandle swap_chain_handle_;
// Video processor output view created from swap chain back buffer. Must be
// cached for performance reasons.
Microsoft::WRL::ComPtr<ID3D11VideoProcessorOutputView> output_view_;
DISALLOW_COPY_AND_ASSIGN(SwapChainPresenter); DISALLOW_COPY_AND_ASSIGN(SwapChainPresenter);
}; };
...@@ -673,6 +680,9 @@ bool DCLayerTree::SwapChainPresenter::ShouldUseYUVSwapChain() { ...@@ -673,6 +680,9 @@ bool DCLayerTree::SwapChainPresenter::ShouldUseYUVSwapChain() {
if (IsProtectedVideo(protected_video_type_)) if (IsProtectedVideo(protected_video_type_))
return true; return true;
if (failed_to_create_yuv_swapchain_)
return false;
// Start out as YUV. // Start out as YUV.
if (!presentation_history_.valid()) if (!presentation_history_.valid())
return true; return true;
...@@ -960,13 +970,11 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain( ...@@ -960,13 +970,11 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain(
} }
gfx::Size swap_chain_size = CalculateSwapChainSize(params); gfx::Size swap_chain_size = CalculateSwapChainSize(params);
bool swap_chain_resized = swap_chain_size_ != swap_chain_size;
// Do not create a swap chain if swap chain size will be empty. // Do not create a swap chain if swap chain size will be empty.
if (swap_chain_size.IsEmpty()) { if (swap_chain_size.IsEmpty()) {
if (swap_chain_resized) { swap_chain_size_ = swap_chain_size;
swap_chain_size_ = swap_chain_size; if (swap_chain_) {
swap_chain_handle_.Close(); ReleaseSwapChainResources();
swap_chain_.Reset();
content_visual_->SetContent(nullptr); content_visual_->SetContent(nullptr);
*needs_commit = true; *needs_commit = true;
} }
...@@ -976,13 +984,14 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain( ...@@ -976,13 +984,14 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain(
if (UpdateVisuals(params, swap_chain_size)) if (UpdateVisuals(params, swap_chain_size))
*needs_commit = true; *needs_commit = true;
bool swap_chain_resized = swap_chain_size_ != swap_chain_size;
bool use_yuv_swap_chain = ShouldUseYUVSwapChain(); bool use_yuv_swap_chain = ShouldUseYUVSwapChain();
bool toggle_yuv_swapchain = (use_yuv_swap_chain != is_yuv_swapchain_) && bool toggle_yuv_swapchain = use_yuv_swap_chain != is_yuv_swapchain_;
!failed_to_create_yuv_swapchain_;
bool toggle_protected_video = bool toggle_protected_video =
protected_video_type_ != params.protected_video_type; protected_video_type_ != params.protected_video_type;
bool first_present = false; bool first_present = false;
if (!swap_chain_ || swap_chain_resized || toggle_yuv_swapchain || if (!swap_chain_ || swap_chain_resized || toggle_yuv_swapchain ||
toggle_protected_video) { toggle_protected_video) {
if (!ReallocateSwapChain(swap_chain_size, use_yuv_swap_chain, if (!ReallocateSwapChain(swap_chain_size, use_yuv_swap_chain,
...@@ -1172,14 +1181,14 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt( ...@@ -1172,14 +1181,14 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt(
Microsoft::WRL::ComPtr<ID3D11VideoProcessorEnumerator> Microsoft::WRL::ComPtr<ID3D11VideoProcessorEnumerator>
video_processor_enumerator = layer_tree_->video_processor_enumerator(); video_processor_enumerator = layer_tree_->video_processor_enumerator();
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_desc = {};
in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; input_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
in_desc.Texture2D.ArraySlice = input_level; input_desc.Texture2D.ArraySlice = input_level;
Microsoft::WRL::ComPtr<ID3D11VideoProcessorInputView> in_view; Microsoft::WRL::ComPtr<ID3D11VideoProcessorInputView> input_view;
HRESULT hr = video_device->CreateVideoProcessorInputView( HRESULT hr = video_device->CreateVideoProcessorInputView(
input_texture.Get(), video_processor_enumerator.Get(), &in_desc, input_texture.Get(), video_processor_enumerator.Get(), &input_desc,
in_view.GetAddressOf()); input_view.GetAddressOf());
if (FAILED(hr)) { if (FAILED(hr)) {
DLOG(ERROR) << "CreateVideoProcessorInputView failed with error 0x" DLOG(ERROR) << "CreateVideoProcessorInputView failed with error 0x"
<< std::hex << hr; << std::hex << hr;
...@@ -1192,7 +1201,7 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt( ...@@ -1192,7 +1201,7 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt(
stream.InputFrameOrField = 0; stream.InputFrameOrField = 0;
stream.PastFrames = 0; stream.PastFrames = 0;
stream.FutureFrames = 0; stream.FutureFrames = 0;
stream.pInputSurface = in_view.Get(); stream.pInputSurface = input_view.Get();
RECT dest_rect = gfx::Rect(swap_chain_size_).ToRECT(); RECT dest_rect = gfx::Rect(swap_chain_size_).ToRECT();
video_context->VideoProcessorSetOutputTargetRect(video_processor.Get(), video_context->VideoProcessorSetOutputTargetRect(video_processor.Get(),
TRUE, &dest_rect); TRUE, &dest_rect);
...@@ -1202,24 +1211,27 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt( ...@@ -1202,24 +1211,27 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt(
video_context->VideoProcessorSetStreamSourceRect(video_processor.Get(), 0, video_context->VideoProcessorSetStreamSourceRect(video_processor.Get(), 0,
TRUE, &source_rect); TRUE, &source_rect);
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture; if (!output_view_) {
swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.GetAddressOf())); Microsoft::WRL::ComPtr<ID3D11Texture2D> swap_chain_buffer;
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {}; swap_chain_->GetBuffer(0, IID_PPV_ARGS(swap_chain_buffer.GetAddressOf()));
out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
out_desc.Texture2D.MipSlice = 0; D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_desc = {};
output_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
Microsoft::WRL::ComPtr<ID3D11VideoProcessorOutputView> out_view; output_desc.Texture2D.MipSlice = 0;
hr = video_device->CreateVideoProcessorOutputView(
texture.Get(), video_processor_enumerator.Get(), &out_desc, hr = video_device->CreateVideoProcessorOutputView(
out_view.GetAddressOf()); swap_chain_buffer.Get(), video_processor_enumerator.Get(),
if (FAILED(hr)) { &output_desc, output_view_.GetAddressOf());
DLOG(ERROR) << "CreateVideoProcessorOutputView failed with error 0x" if (FAILED(hr)) {
<< std::hex << hr; DLOG(ERROR) << "CreateVideoProcessorOutputView failed with error 0x"
return false; << std::hex << hr;
return false;
}
DCHECK(output_view_);
} }
hr = video_context->VideoProcessorBlt(video_processor.Get(), out_view.Get(), hr = video_context->VideoProcessorBlt(video_processor.Get(),
0, 1, &stream); output_view_.Get(), 0, 1, &stream);
if (FAILED(hr)) { if (FAILED(hr)) {
DLOG(ERROR) << "VideoProcessorBlt failed with error 0x" << std::hex << hr; DLOG(ERROR) << "VideoProcessorBlt failed with error 0x" << std::hex << hr;
return false; return false;
...@@ -1229,15 +1241,23 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt( ...@@ -1229,15 +1241,23 @@ bool DCLayerTree::SwapChainPresenter::VideoProcessorBlt(
return true; return true;
} }
void DCLayerTree::SwapChainPresenter::ReleaseSwapChainResources() {
output_view_.Reset();
swap_chain_.Reset();
swap_chain_handle_.Close();
}
bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain( bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain(
const gfx::Size& swap_chain_size, const gfx::Size& swap_chain_size,
bool use_yuv_swap_chain, bool use_yuv_swap_chain,
ui::ProtectedVideoType protected_video_type) { ui::ProtectedVideoType protected_video_type) {
TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain"); TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain");
swap_chain_size_ = swap_chain_size;
swap_chain_.Reset(); ReleaseSwapChainResources();
swap_chain_handle_.Close();
DCHECK(!swap_chain_size.IsEmpty());
swap_chain_size_ = swap_chain_size;
protected_video_type_ = protected_video_type;
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device; Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
d3d11_device_.CopyTo(dxgi_device.GetAddressOf()); d3d11_device_.CopyTo(dxgi_device.GetAddressOf());
...@@ -1250,7 +1270,6 @@ bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain( ...@@ -1250,7 +1270,6 @@ bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain(
DCHECK(media_factory); DCHECK(media_factory);
DXGI_SWAP_CHAIN_DESC1 desc = {}; DXGI_SWAP_CHAIN_DESC1 desc = {};
DCHECK(!swap_chain_size_.IsEmpty());
desc.Width = swap_chain_size_.width(); desc.Width = swap_chain_size_.width();
desc.Height = swap_chain_size_.height(); desc.Height = swap_chain_size_.height();
desc.Format = g_overlay_dxgi_format_used; desc.Format = g_overlay_dxgi_format_used;
...@@ -1335,7 +1354,6 @@ bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain( ...@@ -1335,7 +1354,6 @@ bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain(
return false; return false;
} }
} }
protected_video_type_ = protected_video_type;
return true; return true;
} }
......
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