mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-02-21 00:39:59 +00:00
nvenc: add option to disable realtime hags
This commit is contained in:
parent
cadb45ec3d
commit
646a569210
@ -326,6 +326,7 @@ namespace config {
|
||||
}, // software
|
||||
|
||||
{}, // nv
|
||||
true, // nv_realtime_hags
|
||||
{}, // nv_legacy
|
||||
|
||||
{
|
||||
@ -924,6 +925,7 @@ namespace config {
|
||||
int_between_f(vars, "nvenc_preset", video.nv.quality_preset, { 1, 7 });
|
||||
generic_f(vars, "nvenc_twopass", video.nv.two_pass, nv::twopass_from_view);
|
||||
bool_f(vars, "nvenc_h264_cavlc", video.nv.h264_cavlc);
|
||||
bool_f(vars, "nvenc_realtime_hags", video.nv_realtime_hags);
|
||||
|
||||
#ifndef __APPLE__
|
||||
video.nv_legacy.preset = video.nv.quality_preset + 11;
|
||||
|
@ -29,6 +29,7 @@ namespace config {
|
||||
} sw;
|
||||
|
||||
nvenc::nvenc_config nv;
|
||||
bool nv_realtime_hags;
|
||||
|
||||
struct {
|
||||
int preset;
|
||||
|
@ -157,7 +157,44 @@ namespace platf::dxgi {
|
||||
D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME
|
||||
} D3DKMT_SCHEDULINGPRIORITYCLASS;
|
||||
|
||||
typedef UINT D3DKMT_HANDLE;
|
||||
|
||||
typedef struct _D3DKMT_OPENADAPTERFROMLUID {
|
||||
LUID AdapterLuid;
|
||||
D3DKMT_HANDLE hAdapter;
|
||||
} D3DKMT_OPENADAPTERFROMLUID;
|
||||
|
||||
typedef struct _D3DKMT_WDDM_2_7_CAPS {
|
||||
union {
|
||||
struct
|
||||
{
|
||||
UINT HwSchSupported : 1;
|
||||
UINT HwSchEnabled : 1;
|
||||
UINT HwSchEnabledByDefault : 1;
|
||||
UINT IndependentVidPnVSyncControl : 1;
|
||||
UINT Reserved : 28;
|
||||
};
|
||||
UINT Value;
|
||||
};
|
||||
} D3DKMT_WDDM_2_7_CAPS;
|
||||
|
||||
typedef struct _D3DKMT_QUERYADAPTERINFO {
|
||||
D3DKMT_HANDLE hAdapter;
|
||||
UINT Type;
|
||||
VOID *pPrivateDriverData;
|
||||
UINT PrivateDriverDataSize;
|
||||
} D3DKMT_QUERYADAPTERINFO;
|
||||
|
||||
const UINT KMTQAITYPE_WDDM_2_7_CAPS = 70;
|
||||
|
||||
typedef struct _D3DKMT_CLOSEADAPTER {
|
||||
D3DKMT_HANDLE hAdapter;
|
||||
} D3DKMT_CLOSEADAPTER;
|
||||
|
||||
typedef NTSTATUS(WINAPI *PD3DKMTSetProcessSchedulingPriorityClass)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS);
|
||||
typedef NTSTATUS(WINAPI *PD3DKMTOpenAdapterFromLuid)(D3DKMT_OPENADAPTERFROMLUID *);
|
||||
typedef NTSTATUS(WINAPI *PD3DKMTQueryAdapterInfo)(D3DKMT_QUERYADAPTERINFO *);
|
||||
typedef NTSTATUS(WINAPI *PD3DKMTCloseAdapter)(D3DKMT_CLOSEADAPTER *);
|
||||
|
||||
virtual bool
|
||||
is_hdr() override;
|
||||
|
@ -564,17 +564,64 @@ namespace platf::dxgi {
|
||||
|
||||
HMODULE gdi32 = GetModuleHandleA("GDI32");
|
||||
if (gdi32) {
|
||||
PD3DKMTSetProcessSchedulingPriorityClass fn =
|
||||
(PD3DKMTSetProcessSchedulingPriorityClass) GetProcAddress(gdi32, "D3DKMTSetProcessSchedulingPriorityClass");
|
||||
if (fn) {
|
||||
// Set scheduling priority to "high" for NVIDIA, or to "realtime" for other gpu vendors
|
||||
// As of 2023.07, NVIDIA driver has unfixed bug(s) where "realtime" can cause unrecoverable encoding freeze or outright driver crash
|
||||
// This issue happens more frequently with HAGS, in DX12 games or when VRAM is filled close to max capacity
|
||||
// Track OBS to see if they find better workaround or NVIDIA fixes it on their end, they seem to be in communication
|
||||
status = fn(GetCurrentProcess(), adapter_desc.VendorId == 0x10DE ? D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH : D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(warning) << "Failed to set realtime GPU priority. Please run application as administrator for optimal performance.";
|
||||
auto check_hags = [&](const LUID &adapter) -> bool {
|
||||
auto d3dkmt_open_adapter = (PD3DKMTOpenAdapterFromLuid) GetProcAddress(gdi32, "D3DKMTOpenAdapterFromLuid");
|
||||
auto d3dkmt_query_adapter_info = (PD3DKMTQueryAdapterInfo) GetProcAddress(gdi32, "D3DKMTQueryAdapterInfo");
|
||||
auto d3dkmt_close_adapter = (PD3DKMTCloseAdapter) GetProcAddress(gdi32, "D3DKMTCloseAdapter");
|
||||
if (!d3dkmt_open_adapter || !d3dkmt_query_adapter_info || !d3dkmt_close_adapter) {
|
||||
BOOST_LOG(error) << "Couldn't load d3dkmt functions from gdi32.dll to determine GPU HAGS status";
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DKMT_OPENADAPTERFROMLUID d3dkmt_adapter = { adapter };
|
||||
if (FAILED(d3dkmt_open_adapter(&d3dkmt_adapter))) {
|
||||
BOOST_LOG(error) << "D3DKMTOpenAdapterFromLuid() failed while trying to determine GPU HAGS status";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result;
|
||||
|
||||
D3DKMT_WDDM_2_7_CAPS d3dkmt_adapter_caps = {};
|
||||
D3DKMT_QUERYADAPTERINFO d3dkmt_adapter_info = {};
|
||||
d3dkmt_adapter_info.hAdapter = d3dkmt_adapter.hAdapter;
|
||||
d3dkmt_adapter_info.Type = KMTQAITYPE_WDDM_2_7_CAPS;
|
||||
d3dkmt_adapter_info.pPrivateDriverData = &d3dkmt_adapter_caps;
|
||||
d3dkmt_adapter_info.PrivateDriverDataSize = sizeof(d3dkmt_adapter_caps);
|
||||
|
||||
if (SUCCEEDED(d3dkmt_query_adapter_info(&d3dkmt_adapter_info))) {
|
||||
result = d3dkmt_adapter_caps.HwSchEnabled;
|
||||
}
|
||||
else {
|
||||
BOOST_LOG(warning) << "D3DKMTQueryAdapterInfo() failed while trying to determine GPU HAGS status";
|
||||
result = false;
|
||||
}
|
||||
|
||||
D3DKMT_CLOSEADAPTER d3dkmt_close_adapter_wrap = { d3dkmt_adapter.hAdapter };
|
||||
if (FAILED(d3dkmt_close_adapter(&d3dkmt_close_adapter_wrap))) {
|
||||
BOOST_LOG(error) << "D3DKMTCloseAdapter() failed while trying to determine GPU HAGS status";
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
auto d3dkmt_set_process_priority = (PD3DKMTSetProcessSchedulingPriorityClass) GetProcAddress(gdi32, "D3DKMTSetProcessSchedulingPriorityClass");
|
||||
if (d3dkmt_set_process_priority) {
|
||||
auto priority = D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME;
|
||||
bool hags_enabled = check_hags(adapter_desc.AdapterLuid);
|
||||
if (adapter_desc.VendorId == 0x10DE) {
|
||||
// As of 2023.07, NVIDIA driver has unfixed bug(s) where "realtime" can cause unrecoverable encoding freeze or outright driver crash
|
||||
// This issue happens more frequently with HAGS, in DX12 games or when VRAM is filled close to max capacity
|
||||
// Track OBS to see if they find better workaround or NVIDIA fixes it on their end, they seem to be in communication
|
||||
if (hags_enabled && !config::video.nv_realtime_hags) priority = D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH;
|
||||
}
|
||||
BOOST_LOG(info) << "Active GPU has HAGS " << (hags_enabled ? "enabled" : "disabled");
|
||||
BOOST_LOG(info) << "Using " << (priority == D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH ? "high" : "realtime") << " GPU priority";
|
||||
if (FAILED(d3dkmt_set_process_priority(GetCurrentProcess(), priority))) {
|
||||
BOOST_LOG(warning) << "Failed to adjust GPU priority. Please run application as administrator for optimal performance.";
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOOST_LOG(error) << "Couldn't load D3DKMTSetProcessSchedulingPriorityClass function from gdi32.dll to adjust GPU priority";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,6 +912,19 @@
|
||||
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show"
|
||||
aria-labelledby="panelsStayOpen-headingOne">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3" v-if="platform === 'windows'">
|
||||
<label for="nvenc_realtime_hags" class="form-label">Use realtime priority in hardware accelerated gpu scheduling</label>
|
||||
<select id="nvenc_realtime_hags" class="form-select" v-model="config.nvenc_realtime_hags">
|
||||
<option value="disabled">Disabled</option>
|
||||
<option value="enabled">Enabled (default)</option>
|
||||
</select>
|
||||
<div class="form-text">Currently NVIDIA drivers may freeze in encoder when
|
||||
<a href="https://devblogs.microsoft.com/directx/hardware-accelerated-gpu-scheduling/">HAGS</a>
|
||||
is enabled, realtime priority is used and VRAM utilization is close to maximum.<br>
|
||||
Disabling this option lowers the priority to high, sidestepping the freeze at the cost of reduced capture
|
||||
performance when the GPU is heavily loaded.
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="nvenc_h264_cavlc" class="form-label">Prefer CAVLC over CABAC in H.264</label>
|
||||
<select id="nvenc_h264_cavlc" class="form-select" v-model="config.nvenc_h264_cavlc">
|
||||
@ -1082,6 +1095,7 @@
|
||||
"mouse": "enabled",
|
||||
"nvenc_preset": "1",
|
||||
"nvenc_twopass": "quarter_res",
|
||||
"nvenc_realtime_hags": "enabled",
|
||||
"nvenc_h264_cavlc": "disabled",
|
||||
"origin_pin_allowed": "pc",
|
||||
"origin_web_ui_allowed": "lan",
|
||||
|
Loading…
x
Reference in New Issue
Block a user