Skip to content

Commit

Permalink
Wire GPU selection to DXGI device for windows d3d11 video capture
Browse files Browse the repository at this point in the history
Bug: 1336546
Change-Id: I4b663881667eec0b0660e944d9a101f4d9030c75
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3706900
Reviewed-by: Joe Downing <joedow@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com>
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1018584}
  • Loading branch information
Ilya Nikolaevskiy authored and Chromium LUCI CQ committed Jun 28, 2022
1 parent 4fc8fd8 commit 65cff4a
Show file tree
Hide file tree
Showing 22 changed files with 137 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void GpuArcVideoEncodeAccelerator::GetSupportedProfiles(
GetSupportedProfilesCallback callback) {
std::move(callback).Run(
media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
gpu_preferences_, gpu_workarounds_));
gpu_preferences_, gpu_workarounds_, gpu::GPUInfo::GPUDevice()));
}

void GpuArcVideoEncodeAccelerator::Initialize(
Expand Down Expand Up @@ -129,7 +129,8 @@ GpuArcVideoEncodeAccelerator::InitializeTask(

visible_size_ = config.input_visible_size;
accelerator_ = media::GpuVideoEncodeAcceleratorFactory::CreateVEA(
config, this, gpu_preferences_, gpu_workarounds_);
config, this, gpu_preferences_, gpu_workarounds_,
gpu::GPUInfo::GPUDevice());
if (accelerator_ == nullptr) {
DLOG(ERROR) << "Failed to create a VideoEncodeAccelerator.";
return mojom::VideoEncodeAccelerator::Result::kPlatformFailureError;
Expand Down
5 changes: 3 additions & 2 deletions components/viz/service/gl/gpu_service_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ void GetVideoCapabilities(const gpu::GpuPreferences& gpu_preferences,
gpu_info->video_encode_accelerator_supported_profiles =
media::GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(
media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
gpu_preferences, gpu_workarounds,
gpu_preferences, gpu_workarounds, gpu_info->active_gpu(),
/*populate_extended_info=*/false));
#endif // BUILDFLAG(IS_ANDROID)
}
Expand Down Expand Up @@ -832,7 +832,8 @@ void GpuServiceImpl::CreateVideoEncodeAcceleratorProvider(
media::MojoVideoEncodeAcceleratorProvider::Create(
std::move(vea_provider_receiver),
base::BindRepeating(&media::GpuVideoEncodeAcceleratorFactory::CreateVEA),
gpu_preferences_, gpu_channel_manager_->gpu_driver_bug_workarounds());
gpu_preferences_, gpu_channel_manager_->gpu_driver_bug_workarounds(),
gpu_info_.active_gpu());
}

void GpuServiceImpl::CreateGpuMemoryBuffer(
Expand Down
1 change: 1 addition & 0 deletions media/base/win/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ component("media_foundation_util") {
"mfplat.lib",
"mfreadwrite.lib",
"dxguid.lib",
"dxgi.lib",
]

# MediaFoundation is not available on Windows N, so must be delay loaded.
Expand Down
39 changes: 31 additions & 8 deletions media/base/win/dxgi_device_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Microsoft::WRL::ComPtr<ID3D11Device> DXGIDeviceScopedHandle::GetDevice() {
return device;
}

scoped_refptr<DXGIDeviceManager> DXGIDeviceManager::Create() {
scoped_refptr<DXGIDeviceManager> DXGIDeviceManager::Create(CHROME_LUID luid) {
if (base::win::GetVersion() < base::win::Version::WIN8 ||
(!::GetModuleHandle(L"mfplat.dll") && !::LoadLibrary(L"mfplat.dll"))) {
// The MF DXGI Device manager is only supported on Win8 or later
Expand All @@ -73,7 +73,7 @@ scoped_refptr<DXGIDeviceManager> DXGIDeviceManager::Create() {
&mf_dxgi_device_manager);
RETURN_ON_HR_FAILURE(hr, "Failed to create MF DXGI device manager", nullptr);
auto dxgi_device_manager = base::WrapRefCounted(new DXGIDeviceManager(
std::move(mf_dxgi_device_manager), d3d_device_reset_token));
std::move(mf_dxgi_device_manager), d3d_device_reset_token, luid));

Microsoft::WRL::ComPtr<ID3D11Device> d3d_device;
if (dxgi_device_manager &&
Expand All @@ -87,9 +87,11 @@ scoped_refptr<DXGIDeviceManager> DXGIDeviceManager::Create() {

DXGIDeviceManager::DXGIDeviceManager(
Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> mf_dxgi_device_manager,
UINT d3d_device_reset_token)
UINT d3d_device_reset_token,
CHROME_LUID luid)
: mf_dxgi_device_manager_(std::move(mf_dxgi_device_manager)),
d3d_device_reset_token_(d3d_device_reset_token) {}
d3d_device_reset_token_(d3d_device_reset_token),
luid_(luid) {}

DXGIDeviceManager::~DXGIDeviceManager() = default;

Expand All @@ -100,10 +102,31 @@ HRESULT DXGIDeviceManager::ResetDevice(
const D3D_FEATURE_LEVEL kFeatureLevels[] = {
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0};
HRESULT hr =
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
kDeviceFlags, kFeatureLevels, std::size(kFeatureLevels),
D3D11_SDK_VERSION, &d3d_device, nullptr, nullptr);

Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;

if (luid_.HighPart || luid_.LowPart) {
Microsoft::WRL::ComPtr<IDXGIFactory1> factory;
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
RETURN_ON_HR_FAILURE(hr, "Failed to create DXGIFactory1", hr);
Microsoft::WRL::ComPtr<IDXGIAdapter> temp;
for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++) {
DXGI_ADAPTER_DESC desc;
if (SUCCEEDED(temp->GetDesc(&desc)) &&
desc.AdapterLuid.HighPart == luid_.HighPart &&
desc.AdapterLuid.LowPart == luid_.LowPart) {
adapter = temp;
break;
}
}
}
// If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN
// or D3D11CreateDevice will return E_INVALIDARG.
HRESULT hr = D3D11CreateDevice(
adapter.Get(),
adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, nullptr,
kDeviceFlags, kFeatureLevels, std::size(kFeatureLevels),
D3D11_SDK_VERSION, &d3d_device, nullptr, nullptr);
RETURN_ON_HR_FAILURE(hr, "D3D11 device creation failed", hr);
RETURN_ON_HR_FAILURE(
hr, media::SetDebugName(d3d_device.Get(), "Media_DXGIDeviceManager"), hr);
Expand Down
6 changes: 4 additions & 2 deletions media/base/win/dxgi_device_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class MF_UTIL_EXPORT DXGIDeviceManager

// Returns a DXGIDeviceManager with associated D3D device set, or nullptr on
// failure.
static scoped_refptr<DXGIDeviceManager> Create();
static scoped_refptr<DXGIDeviceManager> Create(CHROME_LUID luid);

// Associates a new D3D device with the DXGI Device Manager
// returns it in the parameter, which can't be nullptr.
Expand Down Expand Up @@ -71,11 +71,13 @@ class MF_UTIL_EXPORT DXGIDeviceManager
friend class base::RefCountedThreadSafe<DXGIDeviceManager>;
DXGIDeviceManager(
Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> mf_dxgi_device_manager,
UINT d3d_device_reset_token);
UINT d3d_device_reset_token,
CHROME_LUID luid);
virtual ~DXGIDeviceManager();

Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> mf_dxgi_device_manager_;
UINT d3d_device_reset_token_ = 0;
CHROME_LUID luid_ = {0, 0};
};

} // namespace media
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace {
class MockDXGIDeviceManager : public DXGIDeviceManager {
public:
MockDXGIDeviceManager()
: DXGIDeviceManager(nullptr, 0),
: DXGIDeviceManager(nullptr, 0, CHROME_LUID{.LowPart = 0, .HighPart = 0}),
mock_d3d_device_(new MockD3D11Device()) {}

// Associates a new D3D device with the DXGI Device Manager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace media {

VideoCaptureBufferTrackerFactoryWin::VideoCaptureBufferTrackerFactoryWin()
: dxgi_device_manager_(DXGIDeviceManager::Create()) {}
: dxgi_device_manager_(DXGIDeviceManager::Create({0, 0})) {}

VideoCaptureBufferTrackerFactoryWin::~VideoCaptureBufferTrackerFactoryWin() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ DevicesInfo VideoCaptureDeviceFactoryWin::GetDevicesInfoMediaFoundation() {
DevicesInfo devices_info;

if (use_d3d11_with_media_foundation_ && !dxgi_device_manager_) {
dxgi_device_manager_ = DXGIDeviceManager::Create();
dxgi_device_manager_ = DXGIDeviceManager::Create(luid_);
}

// Recent non-RGB (depth, IR) cameras could be marked as sensor cameras in
Expand Down
3 changes: 3 additions & 0 deletions media/capture/video/win/video_capture_device_factory_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryWin
bool use_media_foundation_;
bool use_d3d11_with_media_foundation_;

// Preferred adapter to use.
CHROME_LUID luid_ = {0, 0};

// For calling WinRT methods on a COM initiated thread.
base::Thread com_thread_;
scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1869,7 +1869,7 @@ class VideoCaptureDeviceMFWinTestWithDXGI : public VideoCaptureDeviceMFWinTest {
if (ShouldSkipD3D11Test())
GTEST_SKIP();

dxgi_device_manager_ = DXGIDeviceManager::Create();
dxgi_device_manager_ = DXGIDeviceManager::Create(CHROME_LUID{0, 0});
VideoCaptureDeviceMFWinTest::SetUp();
}
};
Expand Down
29 changes: 17 additions & 12 deletions media/gpu/gpu_video_encode_accelerator_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ std::unique_ptr<VideoEncodeAccelerator> CreateVTVEA() {
// true, VEA is limited to a subset of features that is compatible with Win 7.
std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds) {
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device) {
return base::WrapUnique<VideoEncodeAccelerator>(
new MediaFoundationVideoEncodeAccelerator(gpu_preferences,
gpu_workarounds));
new MediaFoundationVideoEncodeAccelerator(
gpu_preferences, gpu_workarounds, gpu_device.luid));
}
#endif

Expand All @@ -98,7 +99,8 @@ using VEAFactoryFunction =

std::vector<VEAFactoryFunction> GetVEAFactoryFunctions(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds) {
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device) {
// Array of VEAFactoryFunctions potentially usable on the current platform.
// This list is ordered by priority, from most to least preferred, if
// applicable. This list is composed once and then reused.
Expand Down Expand Up @@ -127,21 +129,22 @@ std::vector<VEAFactoryFunction> GetVEAFactoryFunctions(
#endif
#if BUILDFLAG(IS_WIN)
vea_factory_functions.push_back(base::BindRepeating(
&CreateMediaFoundationVEA, gpu_preferences, gpu_workarounds));
&CreateMediaFoundationVEA, gpu_preferences, gpu_workarounds, gpu_device));
#endif
return vea_factory_functions;
}

VideoEncodeAccelerator::SupportedProfiles GetSupportedProfilesInternal(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device,
bool populate_extended_info) {
if (gpu_preferences.disable_accelerated_video_encode)
return VideoEncodeAccelerator::SupportedProfiles();

VideoEncodeAccelerator::SupportedProfiles profiles;
for (const auto& create_vea :
GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds)) {
GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
auto vea = std::move(create_vea).Run();
if (!vea)
continue;
Expand All @@ -163,13 +166,14 @@ GpuVideoEncodeAcceleratorFactory::CreateVEA(
VideoEncodeAccelerator::Client* client,
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device,
std::unique_ptr<MediaLog> media_log) {
// NullMediaLog silently and safely does nothing.
if (!media_log)
media_log = std::make_unique<media::NullMediaLog>();

for (const auto& create_vea :
GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds)) {
GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
std::unique_ptr<VideoEncodeAccelerator> vea = create_vea.Run();
if (!vea)
continue;
Expand All @@ -188,19 +192,20 @@ MEDIA_GPU_EXPORT VideoEncodeAccelerator::SupportedProfiles
GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device,
bool populate_extended_info) {
// Cache the supported profiles so that they will not be computed more than
// once per GPU process. It is assumed that |gpu_preferences| do not change
// between calls.
VideoEncodeAccelerator::SupportedProfiles* profiles_ptr = nullptr;
if (populate_extended_info) {
static auto profiles =
GetSupportedProfilesInternal(gpu_preferences, gpu_workarounds, true);
static auto profiles = GetSupportedProfilesInternal(
gpu_preferences, gpu_workarounds, gpu_device, true);
profiles_ptr = &profiles;

} else {
static auto profiles =
GetSupportedProfilesInternal(gpu_preferences, gpu_workarounds, false);
static auto profiles = GetSupportedProfilesInternal(
gpu_preferences, gpu_workarounds, gpu_device, false);
profiles_ptr = &profiles;
}

Expand All @@ -213,7 +218,7 @@ GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
if (profiles_ptr->empty()) {
VLOGF(1) << "Supported profiles empty, querying again...";
*profiles_ptr = GetSupportedProfilesInternal(
gpu_preferences, gpu_workarounds, populate_extended_info);
gpu_preferences, gpu_workarounds, gpu_device, populate_extended_info);
}
#endif

Expand Down
3 changes: 3 additions & 0 deletions media/gpu/gpu_video_encode_accelerator_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <memory>

#include "gpu/config/gpu_info.h"
#include "media/gpu/media_gpu_export.h"
#include "media/video/video_encode_accelerator.h"

Expand All @@ -33,6 +34,7 @@ class MEDIA_GPU_EXPORT GpuVideoEncodeAcceleratorFactory {
VideoEncodeAccelerator::Client* client,
const gpu::GpuPreferences& gpu_perferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device,
std::unique_ptr<MediaLog> media_log = nullptr);

// Gets the supported codec profiles for video encoding on the platform.
Expand All @@ -41,6 +43,7 @@ class MEDIA_GPU_EXPORT GpuVideoEncodeAcceleratorFactory {
static VideoEncodeAccelerator::SupportedProfiles GetSupportedProfiles(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GPUInfo::GPUDevice& gpu_device,
bool populate_extended_info = true);
};

Expand Down
3 changes: 2 additions & 1 deletion media/gpu/test/video_encoder/video_encoder_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,8 @@ void VideoEncoderClient::CreateEncoderTask(const Video* video,
encoder_client_config_.spatial_layers);

encoder_ = GpuVideoEncodeAcceleratorFactory::CreateVEA(
config, this, gpu::GpuPreferences(), gpu::GpuDriverBugWorkarounds());
config, this, gpu::GpuPreferences(), gpu::GpuDriverBugWorkarounds(),
gpu::GPUInfo::GPUDevice());
*success = (encoder_ != nullptr);

// Initialization is continued once the encoder notifies us of the coded size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ struct MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef {
// See bug: http://crbug.com/777659.
MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds)
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
CHROME_LUID luid)
: compatible_with_win7_(
gpu_preferences.enable_media_foundation_vea_on_windows7),
disable_dynamic_framerate_update_(
Expand All @@ -298,7 +299,8 @@ MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator(
main_client_task_runner_(base::SequencedTaskRunnerHandle::Get()),
encoder_thread_task_runner_(base::ThreadPool::CreateCOMSTATaskRunner(
{},
base::SingleThreadTaskRunnerThreadMode::DEDICATED)) {
base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
luid_(luid) {
DETACH_FROM_SEQUENCE(encode_sequence_checker_);
encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr();
}
Expand Down Expand Up @@ -530,10 +532,11 @@ void MediaFoundationVideoEncodeAccelerator::EncoderInitializeTask(
NOTIFY_RETURN_ON_HR_FAILURE(hr, "Failed to create sample", );

if (media::IsMediaFoundationD3D11VideoCaptureEnabled()) {
dxgi_device_manager_ = DXGIDeviceManager::Create();
MEDIA_LOG(INFO, media_log.get())
<< "Preferred DXGI device " << luid_.HighPart << ":" << luid_.LowPart;
dxgi_device_manager_ = DXGIDeviceManager::Create(luid_);
NOTIFY_RETURN_ON_FAILURE(!dxgi_device_manager_,
"Failed to create DXGIDeviceManager", );

auto mf_dxgi_device_manager =
dxgi_device_manager_->GetMFDXGIDeviceManager();
hr = encoder_->ProcessMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/win/shlwapi.h"
#include "base/win/windows_types.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_preferences.h"
#include "media/base/bitrate.h"
Expand All @@ -44,7 +45,8 @@ class MEDIA_GPU_EXPORT MediaFoundationVideoEncodeAccelerator
public:
explicit MediaFoundationVideoEncodeAccelerator(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds);
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
CHROME_LUID luid);

MediaFoundationVideoEncodeAccelerator(
const MediaFoundationVideoEncodeAccelerator&) = delete;
Expand Down Expand Up @@ -264,6 +266,9 @@ class MEDIA_GPU_EXPORT MediaFoundationVideoEncodeAccelerator
// DXGI device manager for handling hardware input textures
scoped_refptr<DXGIDeviceManager> dxgi_device_manager_;

// Preferred adapter for DXGIDeviceManager.
const CHROME_LUID luid_;

// A buffer used as a scratch space for I420 to NV12 conversion
std::vector<uint8_t> resize_buffer_;

Expand Down
Loading

0 comments on commit 65cff4a

Please sign in to comment.