fangorn/sunshine-qemu
public
ref:main
/**
* @file src/nvenc/nvenc_dynamic_factory.cpp
* @brief Definitions for runtime NVENC SDK selection on Windows.
*/
#ifdef _WIN32
// this include
#include "nvenc_dynamic_factory.h"
// standard includes
#include <bit>
#include <utility>
// local includes
#include "nvenc_dynamic_factory_versions.h"
#include "src/logging.h"
namespace {
#if defined(_M_ARM64) || defined(__aarch64__)
constexpr auto nvenc_dll_name = "nvEncodeAPIa64.dll";
#elif defined(_WIN64)
constexpr auto nvenc_dll_name = "nvEncodeAPI64.dll";
#else
constexpr auto nvenc_dll_name = "nvEncodeAPI.dll";
#endif
constexpr auto minimum_driver_version = "456.71";
using get_max_supported_version_fn = std::uint32_t(WINAPI *)(std::uint32_t *);
} // namespace
namespace nvenc {
nvenc_dynamic_factory::nvenc_dynamic_factory(
shared_dll dll,
nvenc_sdk_version sdk_version,
create_encoder_fn create_native,
create_encoder_fn create_on_cuda
):
dll(std::move(dll)),
selected_sdk_version(sdk_version),
create_native(std::move(create_native)),
create_on_cuda(std::move(create_on_cuda)) {
}
std::shared_ptr<nvenc_dynamic_factory> nvenc_dynamic_factory::get() {
return get({
[]() {
return make_shared_dll(LoadLibraryEx(nvenc_dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
},
[](HMODULE dll, const char *symbol) {
return GetProcAddress(dll, symbol);
},
});
}
std::shared_ptr<nvenc_dynamic_factory> nvenc_dynamic_factory::get(const nvenc_runtime_api &runtime_api) {
auto dll = runtime_api.load_driver();
if (!dll) {
BOOST_LOG(debug) << "NvEnc: Couldn't load NvEnc library " << nvenc_dll_name;
return {};
}
const auto get_max_version = std::bit_cast<get_max_supported_version_fn>(
runtime_api.get_symbol(dll.get(), "NvEncodeAPIGetMaxSupportedVersion")
);
if (!get_max_version) {
BOOST_LOG(error) << "NvEnc: No NvEncodeAPIGetMaxSupportedVersion() in " << nvenc_dll_name;
return {};
}
std::uint32_t packed_max_version = 0;
if (get_max_version(&packed_max_version) != 0U) {
BOOST_LOG(error) << "NvEnc: NvEncodeAPIGetMaxSupportedVersion() failed";
return {};
}
const auto max_version = decode_nvenc_driver_version(packed_max_version);
const auto sdk_version = select_nvenc_sdk_version(max_version);
switch (sdk_version) {
case nvenc_sdk_version::sdk_13_1:
return std::make_shared<nvenc_dynamic_factory>(
std::move(dll),
sdk_version,
detail::create_nvenc_d3d11_native_1301,
detail::create_nvenc_d3d11_on_cuda_1301
);
case nvenc_sdk_version::sdk_13_0:
return std::make_shared<nvenc_dynamic_factory>(
std::move(dll),
sdk_version,
detail::create_nvenc_d3d11_native_1300,
detail::create_nvenc_d3d11_on_cuda_1300
);
case nvenc_sdk_version::sdk_12_0:
return std::make_shared<nvenc_dynamic_factory>(
std::move(dll),
sdk_version,
detail::create_nvenc_d3d11_native_1200,
detail::create_nvenc_d3d11_on_cuda_1200
);
case nvenc_sdk_version::sdk_11_0:
return std::make_shared<nvenc_dynamic_factory>(
std::move(dll),
sdk_version,
detail::create_nvenc_d3d11_native_1100,
detail::create_nvenc_d3d11_on_cuda_1100
);
case nvenc_sdk_version::unsupported:
default:
BOOST_LOG(error) << "NvEnc: minimum required driver version is " << minimum_driver_version;
return {};
}
}
std::unique_ptr<nvenc_d3d11_interface> nvenc_dynamic_factory::create_nvenc_d3d11_native(
ID3D11Device *d3d_device
) const {
return create_native(d3d_device, dll);
}
std::unique_ptr<nvenc_d3d11_interface> nvenc_dynamic_factory::create_nvenc_d3d11_on_cuda(
ID3D11Device *d3d_device
) const {
return create_on_cuda(d3d_device, dll);
}
nvenc_sdk_version nvenc_dynamic_factory::sdk_version() const {
return selected_sdk_version;
}
} // namespace nvenc
#endif