mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-15 22:02:29 +00:00
Try all available GPUs in D3D11VA decoder
This commit is contained in:
parent
b12724db02
commit
d3a542bac4
2 changed files with 109 additions and 41 deletions
|
@ -144,6 +144,95 @@ D3D11VARenderer::~D3D11VARenderer()
|
||||||
SAFE_COM_RELEASE(m_Factory);
|
SAFE_COM_RELEASE(m_Factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool D3D11VARenderer::createDeviceByAdapterIndex(int adapterIndex, bool* indexWasInvalid)
|
||||||
|
{
|
||||||
|
IDXGIAdapter1* adapter;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
SDL_assert(m_Device == nullptr);
|
||||||
|
SDL_assert(m_DeviceContext == nullptr);
|
||||||
|
|
||||||
|
// If we fail in EnumAdapters(), assume it was an invalid index.
|
||||||
|
// Even if it wasn't, there's a good chance it will result in an
|
||||||
|
// infinite loop if we don't treat it like one anyway.
|
||||||
|
if (indexWasInvalid != nullptr) {
|
||||||
|
*indexWasInvalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = m_Factory->EnumAdapters1(adapterIndex, &adapter);
|
||||||
|
if (hr == DXGI_ERROR_NOT_FOUND) {
|
||||||
|
// Expected at the end of enumeration
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"IDXGIFactory::EnumAdapters1() failed: %x",
|
||||||
|
hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From now on, we know the adapter was valid
|
||||||
|
if (indexWasInvalid != nullptr) {
|
||||||
|
*indexWasInvalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||||
|
hr = adapter->GetDesc1(&adapterDesc);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"IDXGIAdapter::GetDesc() failed: %x",
|
||||||
|
hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||||
|
// Skip the WARP device
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Detected GPU %d: %S (%x:%x)",
|
||||||
|
adapterIndex,
|
||||||
|
adapterDesc.Description,
|
||||||
|
adapterDesc.VendorId,
|
||||||
|
adapterDesc.DeviceId);
|
||||||
|
|
||||||
|
hr = D3D11CreateDevice(adapter,
|
||||||
|
D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
nullptr,
|
||||||
|
D3D11_CREATE_DEVICE_VIDEO_SUPPORT
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
| D3D11_CREATE_DEVICE_DEBUG
|
||||||
|
#endif
|
||||||
|
,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
D3D11_SDK_VERSION,
|
||||||
|
&m_Device,
|
||||||
|
nullptr,
|
||||||
|
&m_DeviceContext);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"D3D11CreateDevice() failed: %x",
|
||||||
|
hr);
|
||||||
|
adapter->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkDecoderSupport(adapter)) {
|
||||||
|
m_DeviceContext->Release();
|
||||||
|
m_DeviceContext = nullptr;
|
||||||
|
m_Device->Release();
|
||||||
|
m_Device = nullptr;
|
||||||
|
|
||||||
|
adapter->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter->Release();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
{
|
{
|
||||||
int adapterIndex, outputIndex;
|
int adapterIndex, outputIndex;
|
||||||
|
@ -175,44 +264,28 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDXGIAdapter* adapter;
|
// First try the adapter corresponding to the display where our window resides.
|
||||||
hr = m_Factory->EnumAdapters(adapterIndex, &adapter);
|
// This will let us avoid a copy if the display GPU has the required decoder.
|
||||||
if (FAILED(hr)) {
|
if (!createDeviceByAdapterIndex(adapterIndex)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
// If that didn't work, we'll try all GPUs in order until we find one
|
||||||
"IDXGIFactory::EnumAdapters() failed: %x",
|
// or run out of GPUs (DXGI_ERROR_NOT_FOUND from EnumAdapters())
|
||||||
hr);
|
bool invalidIndex = false;
|
||||||
return false;
|
for (int i = 0; !invalidIndex; i++) {
|
||||||
|
if (i == adapterIndex) {
|
||||||
|
// Don't try the same GPU again
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = D3D11CreateDevice(adapter,
|
if (createDeviceByAdapterIndex(i, &invalidIndex)) {
|
||||||
D3D_DRIVER_TYPE_UNKNOWN,
|
// This GPU worked! Continue initialization.
|
||||||
nullptr,
|
break;
|
||||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT
|
}
|
||||||
#ifdef QT_DEBUG
|
|
||||||
| D3D11_CREATE_DEVICE_DEBUG
|
|
||||||
#endif
|
|
||||||
,
|
|
||||||
nullptr,
|
|
||||||
0,
|
|
||||||
D3D11_SDK_VERSION,
|
|
||||||
&m_Device,
|
|
||||||
nullptr,
|
|
||||||
&m_DeviceContext);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"D3D11CreateDevice() failed: %x",
|
|
||||||
hr);
|
|
||||||
adapter->Release();
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkDecoderSupport(adapter)) {
|
if (invalidIndex) {
|
||||||
adapter->Release();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
adapter->Release();
|
|
||||||
adapter = nullptr;
|
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||||
swapChainDesc.Stereo = FALSE;
|
swapChainDesc.Stereo = FALSE;
|
||||||
|
@ -913,12 +986,6 @@ bool D3D11VARenderer::checkDecoderSupport(IDXGIAdapter* adapter)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Detected GPU: %S (%x:%x)",
|
|
||||||
adapterDesc.Description,
|
|
||||||
adapterDesc.VendorId,
|
|
||||||
adapterDesc.DeviceId);
|
|
||||||
|
|
||||||
if (DXUtil::isFormatHybridDecodedByHardware(m_DecoderParams.videoFormat, adapterDesc.VendorId, adapterDesc.DeviceId)) {
|
if (DXUtil::isFormatHybridDecodedByHardware(m_DecoderParams.videoFormat, adapterDesc.VendorId, adapterDesc.DeviceId)) {
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"GPU decoding for format %x is blocked due to hardware limitations",
|
"GPU decoding for format %x is blocked due to hardware limitations",
|
||||||
|
|
|
@ -33,6 +33,7 @@ private:
|
||||||
void bindColorConversion(AVFrame* frame);
|
void bindColorConversion(AVFrame* frame);
|
||||||
void renderVideo(AVFrame* frame);
|
void renderVideo(AVFrame* frame);
|
||||||
bool checkDecoderSupport(IDXGIAdapter* adapter);
|
bool checkDecoderSupport(IDXGIAdapter* adapter);
|
||||||
|
bool createDeviceByAdapterIndex(int adapterIndex, bool* indexWasInvalid = nullptr);
|
||||||
|
|
||||||
IDXGIFactory5* m_Factory;
|
IDXGIFactory5* m_Factory;
|
||||||
ID3D11Device* m_Device;
|
ID3D11Device* m_Device;
|
||||||
|
|
Loading…
Reference in a new issue