diff --git a/plugins/obs-qsv11/QSV_Encoder.cpp b/plugins/obs-qsv11/QSV_Encoder.cpp index 6082f4230..e3d7873ab 100644 --- a/plugins/obs-qsv11/QSV_Encoder.cpp +++ b/plugins/obs-qsv11/QSV_Encoder.cpp @@ -63,6 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #define do_log(level, format, ...) \ blog(level, "[qsv encoder: '%s'] " format, "msdk_impl", ##__VA_ARGS__) @@ -71,6 +73,74 @@ mfxIMPL impl = MFX_IMPL_HARDWARE_ANY; mfxVersion ver = {{0, 1}}; // for backward compatibility std::atomic is_active{false}; +bool prefer_igpu_enc(int *iGPUIndex) +{ + IDXGIAdapter *pAdapter; + int adapterIndex = 0; + bool hasIGPU = false; + bool hasDGPU = false; + bool isDG1Primary = false; + + HMODULE hDXGI = LoadLibrary(L"dxgi.dll"); + if (hDXGI == NULL) { + return false; + } + + typedef HRESULT(WINAPI * LPCREATEDXGIFACTORY)(REFIID riid, + void **ppFactory); + + LPCREATEDXGIFACTORY pCreateDXGIFactory = + (LPCREATEDXGIFACTORY)GetProcAddress(hDXGI, + "CreateDXGIFactory1"); + if (pCreateDXGIFactory == NULL) { + pCreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress( + hDXGI, "CreateDXGIFactory"); + + if (pCreateDXGIFactory == NULL) { + FreeLibrary(hDXGI); + return false; + } + } + + IDXGIFactory *pFactory = NULL; + if (FAILED((*pCreateDXGIFactory)(__uuidof(IDXGIFactory), + (void **)(&pFactory)))) { + FreeLibrary(hDXGI); + return false; + } + + while (SUCCEEDED(pFactory->EnumAdapters(adapterIndex, &pAdapter))) { + DXGI_ADAPTER_DESC AdapterDesc = {}; + if (SUCCEEDED(pAdapter->GetDesc(&AdapterDesc))) { + if (AdapterDesc.VendorId == 0x8086) { + if (AdapterDesc.DedicatedVideoMemory <= + 512 * 1024 * 1024) { + hasIGPU = true; + if (iGPUIndex != NULL) { + *iGPUIndex = adapterIndex; + } + } else { + hasDGPU = true; + } + if ((AdapterDesc.DeviceId == 0x4905) || + (AdapterDesc.DeviceId == 0x4906) || + (AdapterDesc.DeviceId == 0x4907)) { + if (adapterIndex == 0) { + isDG1Primary = true; + } + } + } + } + adapterIndex++; + pAdapter->Release(); + } + + pFactory->Release(); + FreeLibrary(hDXGI); + + return hasIGPU && hasDGPU && isDG1Primary; +} + void qsv_encoder_version(unsigned short *major, unsigned short *minor) { *major = ver.Major; @@ -79,6 +149,13 @@ void qsv_encoder_version(unsigned short *major, unsigned short *minor) qsv_t *qsv_encoder_open(qsv_param_t *pParams) { + mfxIMPL impl_list[4] = {MFX_IMPL_HARDWARE, MFX_IMPL_HARDWARE2, + MFX_IMPL_HARDWARE3, MFX_IMPL_HARDWARE4}; + int igpu_index = -1; + if (prefer_igpu_enc(&igpu_index)) { + impl = impl_list[igpu_index]; + } + QSV_Encoder_Internal *pEncoder = new QSV_Encoder_Internal(impl, ver); mfxStatus sts = pEncoder->Open(pParams); if (sts != MFX_ERR_NONE) { diff --git a/plugins/obs-qsv11/QSV_Encoder.h b/plugins/obs-qsv11/QSV_Encoder.h index 9464de196..e79bda42f 100644 --- a/plugins/obs-qsv11/QSV_Encoder.h +++ b/plugins/obs-qsv11/QSV_Encoder.h @@ -136,6 +136,7 @@ int qsv_encoder_encode_tex(qsv_t *, uint64_t, uint32_t, uint64_t, uint64_t *, int qsv_encoder_headers(qsv_t *, uint8_t **pSPS, uint8_t **pPPS, uint16_t *pnSPS, uint16_t *pnPPS); enum qsv_cpu_platform qsv_get_cpu_platform(); +bool prefer_igpu_enc(int *iGPUIndex); #ifdef __cplusplus } diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index f11095820..5036f8312 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -666,6 +666,12 @@ static void *obs_qsv_create_tex(obs_data_t *settings, obs_encoder_t *encoder) return obs_encoder_create_rerouted(encoder, "obs_qsv11_soft"); } + if (prefer_igpu_enc(NULL)) { + blog(LOG_INFO, + ">>> prefer iGPU encoding, fall back to old qsv encoder"); + return obs_encoder_create_rerouted(encoder, "obs_qsv11_soft"); + } + blog(LOG_INFO, ">>> new qsv encoder"); return obs_qsv_create(settings, encoder); }