Commit aa3f548c authored by Frank Liberato's avatar Frank Liberato Committed by Commit Bot

Handle single Texture2D video outputs for D3D11VideoDecoder

This CL causes D3D11VideoDecoder to listen to the video decoder's
config for whether it prefers one Texture2D with multiple array
slices, or multiple Texture2Ds with one array slice eacy to hold
decoded output.  Previously, we would always do the former.

Also, this CL adds a workaround to force multi-texture / one slice
mode for some Intel drivers which require it.

Bug: 971952
Change-Id: I4f12ead43aec2d35f463cc46d9a3bfc61500dc5e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2191157Reviewed-by: default avatarTed Meyer <tmathmeyer@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Commit-Queue: Frank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772409}
parent 125f00f5
......@@ -3534,7 +3534,7 @@
{
"id": 336,
"cr_bugs": [625785],
"description": "DXVA video decoder crashes on some AMD GPUs",
"description": "DXVA video decoder crashes on some AMD GPUs.",
"os": {
"type": "win"
},
......
......@@ -118,6 +118,7 @@ use_es2_for_oopr
use_gpu_driver_workaround_for_testing
use_intermediary_for_copy_texture_image
use_non_zero_size_for_client_side_stream_buffers
use_single_video_decoder_texture
use_unused_standard_shared_blocks
use_virtualized_gl_contexts
validate_multisample_buffer_allocation
......
......@@ -73,9 +73,11 @@ bool D3D11DecoderConfigurator::SupportsDevice(
ComD3D11Texture2D D3D11DecoderConfigurator::CreateOutputTexture(
ComD3D11Device device,
gfx::Size size) {
gfx::Size size,
uint32_t array_size) {
output_texture_desc_.Width = size.width();
output_texture_desc_.Height = size.height();
output_texture_desc_.ArraySize = array_size;
ComD3D11Texture2D result;
if (!SUCCEEDED(
......@@ -100,7 +102,6 @@ void D3D11DecoderConfigurator::SetUpTextureDescriptor(bool supports_swap_chain,
bool is_encrypted) {
output_texture_desc_ = {};
output_texture_desc_.MipLevels = 1;
output_texture_desc_.ArraySize = D3D11DecoderConfigurator::BUFFER_COUNT;
output_texture_desc_.Format = dxgi_format_;
output_texture_desc_.SampleDesc.Count = 1;
output_texture_desc_.Usage = D3D11_USAGE_DEFAULT;
......
......@@ -40,7 +40,9 @@ class MEDIA_GPU_EXPORT D3D11DecoderConfigurator {
bool SupportsDevice(ComD3D11VideoDevice video_device);
// Create the decoder's output texture.
ComD3D11Texture2D CreateOutputTexture(ComD3D11Device device, gfx::Size size);
ComD3D11Texture2D CreateOutputTexture(ComD3D11Device device,
gfx::Size size,
uint32_t array_size);
const D3D11_VIDEO_DECODER_DESC* DecoderDescriptor() const {
return &decoder_desc_;
......
......@@ -45,12 +45,12 @@ void AppendSubsamples(
class D3D11H264Picture : public H264Picture {
public:
D3D11H264Picture(D3D11PictureBuffer* picture)
: picture(picture), level_(picture->level()) {
: picture(picture), picture_index_(picture->picture_index()) {
picture->set_in_picture_use(true);
}
D3D11PictureBuffer* picture;
size_t level_;
size_t picture_index_;
protected:
~D3D11H264Picture() override;
......@@ -135,7 +135,7 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
D3D11H264Picture* our_ref_pic = static_cast<D3D11H264Picture*>(it->get());
if (!our_ref_pic->ref)
continue;
ref_frame_list_[i].Index7Bits = our_ref_pic->level_;
ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_;
ref_frame_list_[i].AssociatedFlag = our_ref_pic->long_term;
field_order_cnt_list_[i][0] = our_ref_pic->top_field_order_cnt;
field_order_cnt_list_[i][1] = our_ref_pic->bottom_field_order_cnt;
......@@ -281,7 +281,7 @@ void D3D11H264Accelerator::PicParamsFromSliceHeader(
void D3D11H264Accelerator::PicParamsFromPic(DXVA_PicParams_H264* pic_param,
scoped_refptr<H264Picture> pic) {
pic_param->CurrPic.Index7Bits =
static_cast<D3D11H264Picture*>(pic.get())->level_;
static_cast<D3D11H264Picture*>(pic.get())->picture_index_;
pic_param->RefPicFlag = pic->ref;
pic_param->frame_num = pic->frame_num;
......
......@@ -24,15 +24,17 @@ namespace media {
D3D11PictureBuffer::D3D11PictureBuffer(
scoped_refptr<base::SequencedTaskRunner> delete_task_runner,
ComD3D11Texture2D texture,
size_t array_slice,
std::unique_ptr<Texture2DWrapper> texture_wrapper,
gfx::Size size,
size_t level)
size_t picture_index)
: RefCountedDeleteOnSequence<D3D11PictureBuffer>(
std::move(delete_task_runner)),
texture_(std::move(texture)),
array_slice_(array_slice),
texture_wrapper_(std::move(texture_wrapper)),
size_(size),
level_(level) {}
picture_index_(picture_index) {}
D3D11PictureBuffer::~D3D11PictureBuffer() {
}
......@@ -46,7 +48,7 @@ bool D3D11PictureBuffer::Init(
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = {};
view_desc.DecodeProfile = decoder_guid;
view_desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
view_desc.Texture2D.ArraySlice = (UINT)level_;
view_desc.Texture2D.ArraySlice = array_slice_;
if (!texture_wrapper_->Init(std::move(gpu_task_runner),
std::move(get_helper_cb))) {
......@@ -69,8 +71,9 @@ bool D3D11PictureBuffer::ProcessTexture(
const gfx::ColorSpace& input_color_space,
MailboxHolderArray* mailbox_dest,
gfx::ColorSpace* output_color_space) {
return texture_wrapper_->ProcessTexture(Texture(), level_, input_color_space,
mailbox_dest, output_color_space);
return texture_wrapper_->ProcessTexture(Texture(), array_slice_,
input_color_space, mailbox_dest,
output_color_space);
}
ComD3D11Texture2D D3D11PictureBuffer::Texture() const {
......
......@@ -47,13 +47,18 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
public:
// |texture_wrapper| is responsible for controlling mailbox access to
// the ID3D11Texture2D,
// |level| is the picturebuffer index inside the Array-type ID3D11Texture2D.
// |array_slice| is the picturebuffer index inside the Array-type
// ID3D11Texture2D. |picture_index| is a unique id used to identify this
// picture to the decoder. If a texture array is used, then it might as well
// be equal to the texture array index. Otherwise, any 0-based index is
// probably okay, though sequential makes sense.
D3D11PictureBuffer(
scoped_refptr<base::SequencedTaskRunner> delete_task_runner,
ComD3D11Texture2D texture,
size_t array_slice,
std::unique_ptr<Texture2DWrapper> texture_wrapper,
gfx::Size size,
size_t level);
size_t picture_index);
bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
GetCommandBufferHelperCB get_helper_cb,
......@@ -71,7 +76,7 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
ComD3D11Texture2D Texture() const;
const gfx::Size& size() const { return size_; }
size_t level() const { return level_; }
size_t picture_index() const { return picture_index_; }
// Is this PictureBuffer backing a VideoFrame right now?
bool in_client_use() const { return in_client_use_; }
......@@ -97,11 +102,13 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
friend class base::DeleteHelper<D3D11PictureBuffer>;
ComD3D11Texture2D texture_;
uint32_t array_slice_;
std::unique_ptr<Texture2DWrapper> texture_wrapper_;
gfx::Size size_;
bool in_picture_use_ = false;
bool in_client_use_ = false;
size_t level_;
size_t picture_index_;
ComD3D11VideoDecoderOutputView output_view_;
......
......@@ -352,6 +352,23 @@ void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
return;
}
// Prefer whatever the config tells us about whether to use one Texture2D with
// multiple array slices, or multiple Texture2Ds with one slice each. If bit
// 14 is clear, then it's the former, else it's the latter.
//
// Let the workaround override array texture mode, if enabled.
//
// For more information, please see:
// https://download.microsoft.com/download/9/2/A/92A4E198-67E0-4ABD-9DB7-635D711C2752/DXVA_VPx.pdf
// https://download.microsoft.com/download/5/f/c/5fc4ec5c-bd8c-4624-8034-319c1bab7671/DXVA_H264.pdf
use_single_video_decoder_texture_ =
!!(dec_config.ConfigDecoderSpecific & (1 << 14)) ||
gpu_workarounds_.use_single_video_decoder_texture;
if (use_single_video_decoder_texture_)
MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using single textures";
else
MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using array texture";
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
hr = video_device_->CreateVideoDecoder(
decoder_configurator_->DecoderDescriptor(), &dec_config, &video_decoder);
......@@ -627,14 +644,6 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
DCHECK(texture_selector_);
gfx::Size size = accelerated_video_decoder_->GetPicSize();
// Create an input texture array.
ComD3D11Texture2D in_texture =
decoder_configurator_->CreateOutputTexture(device_, size);
if (!in_texture) {
NotifyError("Failed to create a Texture2D for PictureBuffers");
return;
}
HDRMetadata stream_metadata;
if (config_.hdr_metadata())
stream_metadata = *config_.hdr_metadata();
......@@ -653,8 +662,24 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
DCHECK(!buffer->in_picture_use());
picture_buffers_.clear();
ComD3D11Texture2D in_texture;
// Create each picture buffer.
for (size_t i = 0; i < D3D11DecoderConfigurator::BUFFER_COUNT; i++) {
// Create an input texture / texture array if we haven't already.
if (!in_texture) {
in_texture = decoder_configurator_->CreateOutputTexture(
device_, size,
use_single_video_decoder_texture_
? 1
: D3D11DecoderConfigurator::BUFFER_COUNT);
}
if (!in_texture) {
NotifyError("Failed to create a Texture2D for PictureBuffers");
return;
}
auto tex_wrapper = texture_selector_->CreateTextureWrapper(
device_, video_device_, device_context_, size);
if (!tex_wrapper) {
......@@ -662,8 +687,10 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
return;
}
picture_buffers_.push_back(new D3D11PictureBuffer(
decoder_task_runner_, in_texture, std::move(tex_wrapper), size, i));
const size_t array_slice = use_single_video_decoder_texture_ ? 0 : i;
picture_buffers_.push_back(
new D3D11PictureBuffer(decoder_task_runner_, in_texture, array_slice,
std::move(tex_wrapper), size, i /* level */));
if (!picture_buffers_[i]->Init(
gpu_task_runner_, get_helper_cb_, video_device_,
decoder_configurator_->DecoderGuid(), media_log_->Clone())) {
......@@ -671,6 +698,11 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
return;
}
// If we're using one texture per buffer, rather than an array, then clear
// the ref to it so that we allocate a new one above.
if (use_single_video_decoder_texture_)
in_texture = nullptr;
// If we have display metadata, then tell the processor. Note that the
// order of these calls is important, and we must set the display metadata
// if we set the stream metadata, else it can crash on some AMD cards.
......
......@@ -283,6 +283,10 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder,
// Should we assume that we're outputting to an HDR display?
bool is_hdr_supported_;
// Should we use multiple single textures for the decoder output (true) or one
// texture with multiple array slices (false)?
bool use_single_video_decoder_texture_ = false;
base::WeakPtrFactory<D3D11VideoDecoder> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(D3D11VideoDecoder);
......
......@@ -112,7 +112,7 @@ void D3D11VP9Accelerator::CopyFrameParams(const D3D11VP9Picture& pic,
pic_params->BitDepthMinus8Luma = pic_params->BitDepthMinus8Chroma =
pic.frame_hdr->bit_depth - 8;
pic_params->CurrPic.Index7Bits = pic.level();
pic_params->CurrPic.Index7Bits = pic.picture_index();
pic_params->frame_type = !pic.frame_hdr->IsKeyframe();
COPY_PARAM(subsampling_x);
......@@ -139,7 +139,7 @@ void D3D11VP9Accelerator::CopyReferenceFrames(
if (ref_pic) {
scoped_refptr<D3D11VP9Picture> our_ref_pic(
static_cast<D3D11VP9Picture*>(ref_pic.get()));
pic_params->ref_frame_map[i].Index7Bits = our_ref_pic->level();
pic_params->ref_frame_map[i].Index7Bits = our_ref_pic->picture_index();
pic_params->ref_frame_coded_width[i] = texture_descriptor.Width;
pic_params->ref_frame_coded_height[i] = texture_descriptor.Height;
} else {
......
......@@ -7,7 +7,8 @@
namespace media {
D3D11VP9Picture::D3D11VP9Picture(D3D11PictureBuffer* picture_buffer)
: picture_buffer_(picture_buffer), level_(picture_buffer_->level()) {
: picture_buffer_(picture_buffer),
picture_index_(picture_buffer_->picture_index()) {
picture_buffer_->set_in_picture_use(true);
}
......
......@@ -19,14 +19,14 @@ class D3D11VP9Picture : public VP9Picture {
D3D11PictureBuffer* picture_buffer() const { return picture_buffer_; }
size_t level() const { return level_; }
size_t picture_index() const { return picture_index_; }
protected:
~D3D11VP9Picture() override;
private:
D3D11PictureBuffer* picture_buffer_;
size_t level_;
size_t picture_index_;
};
} // namespace media
......
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