mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
style: adjust clang-format rules (#2186)
Co-authored-by: Vithorio Polten <reach@vithor.io>
This commit is contained in:
@@ -2,13 +2,16 @@
|
||||
* @file src/platform/windows/display_base.cpp
|
||||
* @brief Definitions for the Windows display base code.
|
||||
*/
|
||||
// standard includes
|
||||
#include <cmath>
|
||||
#include <initguid.h>
|
||||
#include <thread>
|
||||
|
||||
// platform includes
|
||||
#include <initguid.h>
|
||||
|
||||
// lib includes
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/process/v1.hpp>
|
||||
|
||||
#include <MinHook.h>
|
||||
|
||||
// We have to include boost/process/v1.hpp before display.h due to WinSock.h,
|
||||
@@ -36,14 +39,14 @@ typedef enum _D3DKMT_GPU_PREFERENCE_QUERY_STATE: DWORD {
|
||||
namespace platf {
|
||||
using namespace std::literals;
|
||||
}
|
||||
|
||||
namespace platf::dxgi {
|
||||
namespace bp = boost::process;
|
||||
|
||||
/**
|
||||
* DDAPI-specific initialization goes here.
|
||||
*/
|
||||
int
|
||||
duplication_t::init(display_base_t *display, const ::video::config_t &config) {
|
||||
int duplication_t::init(display_base_t *display, const ::video::config_t &config) {
|
||||
HRESULT status;
|
||||
|
||||
// Capture format will be determined from the first call to AcquireNextFrame()
|
||||
@@ -81,8 +84,7 @@ namespace platf::dxgi {
|
||||
BOOST_LOG(warning) << "DuplicateOutput1 Failed [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
BOOST_LOG(warning) << "IDXGIOutput5 is not supported by your OS. Capture performance may be reduced."sv;
|
||||
|
||||
dxgi::output1_t output1 {};
|
||||
@@ -124,8 +126,7 @@ namespace platf::dxgi {
|
||||
return 0;
|
||||
}
|
||||
|
||||
capture_e
|
||||
duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p) {
|
||||
capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p) {
|
||||
auto capture_status = release_frame();
|
||||
if (capture_status != capture_e::ok) {
|
||||
return capture_status;
|
||||
@@ -157,8 +158,7 @@ namespace platf::dxgi {
|
||||
}
|
||||
}
|
||||
|
||||
capture_e
|
||||
duplication_t::reset(dup_t::pointer dup_p) {
|
||||
capture_e duplication_t::reset(dup_t::pointer dup_p) {
|
||||
auto capture_status = release_frame();
|
||||
|
||||
dup.reset(dup_p);
|
||||
@@ -166,8 +166,7 @@ namespace platf::dxgi {
|
||||
return capture_status;
|
||||
}
|
||||
|
||||
capture_e
|
||||
duplication_t::release_frame() {
|
||||
capture_e duplication_t::release_frame() {
|
||||
if (!has_frame) {
|
||||
return capture_e::ok;
|
||||
}
|
||||
@@ -195,16 +194,14 @@ namespace platf::dxgi {
|
||||
release_frame();
|
||||
}
|
||||
|
||||
capture_e
|
||||
display_base_t::capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
|
||||
capture_e display_base_t::capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
|
||||
auto adjust_client_frame_rate = [&]() -> DXGI_RATIONAL {
|
||||
// Adjust capture frame interval when display refresh rate is not integral but very close to requested fps.
|
||||
if (display_refresh_rate.Denominator > 1) {
|
||||
DXGI_RATIONAL candidate = display_refresh_rate;
|
||||
if (client_frame_rate % display_refresh_rate_rounded == 0) {
|
||||
candidate.Numerator *= client_frame_rate / display_refresh_rate_rounded;
|
||||
}
|
||||
else if (display_refresh_rate_rounded % client_frame_rate == 0) {
|
||||
} else if (display_refresh_rate_rounded % client_frame_rate == 0) {
|
||||
candidate.Denominator *= display_refresh_rate_rounded / client_frame_rate;
|
||||
}
|
||||
double candidate_rate = (double) candidate.Numerator / candidate.Denominator;
|
||||
@@ -215,7 +212,7 @@ namespace platf::dxgi {
|
||||
}
|
||||
}
|
||||
|
||||
return { (uint32_t) client_frame_rate, 1 };
|
||||
return {(uint32_t) client_frame_rate, 1};
|
||||
};
|
||||
|
||||
DXGI_RATIONAL client_frame_rate_adjusted = adjust_client_frame_rate();
|
||||
@@ -258,8 +255,7 @@ namespace platf::dxgi {
|
||||
frame_pacing_group_start = std::nullopt;
|
||||
frame_pacing_group_frames = 0;
|
||||
status = capture_e::timeout;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
timer->sleep_for(sleep_period);
|
||||
sleep_overshoot_logger.first_point(sleep_target);
|
||||
sleep_overshoot_logger.second_point_now_and_log();
|
||||
@@ -268,8 +264,7 @@ namespace platf::dxgi {
|
||||
|
||||
if (status == capture_e::ok && img_out) {
|
||||
frame_pacing_group_frames += 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
frame_pacing_group_start = std::nullopt;
|
||||
frame_pacing_group_frames = 0;
|
||||
}
|
||||
@@ -289,8 +284,7 @@ namespace platf::dxgi {
|
||||
}
|
||||
|
||||
frame_pacing_group_frames = 1;
|
||||
}
|
||||
else if (status == platf::capture_e::timeout) {
|
||||
} else if (status == platf::capture_e::timeout) {
|
||||
// The D3D11 device is protected by an unfair lock that is held the entire time that
|
||||
// IDXGIOutputDuplication::AcquireNextFrame() is running. This is normally harmless,
|
||||
// however sometimes the encoding thread needs to interact with our ID3D11Device to
|
||||
@@ -348,8 +342,7 @@ namespace platf::dxgi {
|
||||
* @param output The DXGI output to capture.
|
||||
* @param enumeration_only Specifies whether this test is occurring for display enumeration.
|
||||
*/
|
||||
bool
|
||||
test_dxgi_duplication(adapter_t &adapter, output_t &output, bool enumeration_only) {
|
||||
bool test_dxgi_duplication(adapter_t &adapter, output_t &output, bool enumeration_only) {
|
||||
D3D_FEATURE_LEVEL featureLevels[] {
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
@@ -366,11 +359,13 @@ namespace platf::dxgi {
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr,
|
||||
D3D11_CREATE_DEVICE_FLAGS,
|
||||
featureLevels, sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
|
||||
featureLevels,
|
||||
sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
|
||||
D3D11_SDK_VERSION,
|
||||
&device,
|
||||
nullptr,
|
||||
nullptr);
|
||||
nullptr
|
||||
);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Failed to create D3D11 device for DD test [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return false;
|
||||
@@ -403,8 +398,7 @@ namespace platf::dxgi {
|
||||
// capture the current desktop, just bail immediately. Retrying won't help.
|
||||
if (enumeration_only && status == E_ACCESSDENIED) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::this_thread::sleep_for(200ms);
|
||||
}
|
||||
}
|
||||
@@ -418,8 +412,7 @@ namespace platf::dxgi {
|
||||
* @param gpuPreference A pointer to the location where the preference will be written.
|
||||
* @return Always STATUS_SUCCESS if valid arguments are provided.
|
||||
*/
|
||||
NTSTATUS
|
||||
__stdcall NtGdiDdDDIGetCachedHybridQueryValueHook(D3DKMT_GPU_PREFERENCE_QUERY_STATE *gpuPreference) {
|
||||
NTSTATUS __stdcall NtGdiDdDDIGetCachedHybridQueryValueHook(D3DKMT_GPU_PREFERENCE_QUERY_STATE *gpuPreference) {
|
||||
// By faking a cached GPU preference state of D3DKMT_GPU_PREFERENCE_STATE_UNSPECIFIED, this will
|
||||
// prevent DXGI from performing the normal GPU preference resolution that looks at the registry,
|
||||
// power settings, and the hybrid adapter DDI interface to pick a GPU. Instead, we will not be
|
||||
@@ -428,14 +421,12 @@ namespace platf::dxgi {
|
||||
if (gpuPreference) {
|
||||
*gpuPreference = D3DKMT_GPU_PREFERENCE_STATE_UNSPECIFIED;
|
||||
return 0; // STATUS_SUCCESS
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
display_base_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
int display_base_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
std::once_flag windows_cpp_once_flag;
|
||||
|
||||
std::call_once(windows_cpp_once_flag, []() {
|
||||
@@ -479,7 +470,7 @@ namespace platf::dxgi {
|
||||
adapter_t::pointer adapter_p;
|
||||
for (int tries = 0; tries < 2; ++tries) {
|
||||
for (int x = 0; factory->EnumAdapters1(x, &adapter_p) != DXGI_ERROR_NOT_FOUND; ++x) {
|
||||
dxgi::adapter_t adapter_tmp { adapter_p };
|
||||
dxgi::adapter_t adapter_tmp {adapter_p};
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapter_desc;
|
||||
adapter_tmp->GetDesc1(&adapter_desc);
|
||||
@@ -490,7 +481,7 @@ namespace platf::dxgi {
|
||||
|
||||
dxgi::output_t::pointer output_p;
|
||||
for (int y = 0; adapter_tmp->EnumOutputs(y, &output_p) != DXGI_ERROR_NOT_FOUND; ++y) {
|
||||
dxgi::output_t output_tmp { output_p };
|
||||
dxgi::output_t output_tmp {output_p};
|
||||
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
output_tmp->GetDesc(&desc);
|
||||
@@ -512,8 +503,7 @@ namespace platf::dxgi {
|
||||
display_rotation == DXGI_MODE_ROTATION_ROTATE270) {
|
||||
width_before_rotation = height;
|
||||
height_before_rotation = width;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
width_before_rotation = width;
|
||||
height_before_rotation = height;
|
||||
}
|
||||
@@ -570,11 +560,13 @@ namespace platf::dxgi {
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr,
|
||||
D3D11_CREATE_DEVICE_FLAGS,
|
||||
featureLevels, sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
|
||||
featureLevels,
|
||||
sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
|
||||
D3D11_SDK_VERSION,
|
||||
&device,
|
||||
&feature_level,
|
||||
&device_ctx);
|
||||
&device_ctx
|
||||
);
|
||||
|
||||
adapter_p->Release();
|
||||
|
||||
@@ -632,7 +624,7 @@ namespace platf::dxgi {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DKMT_OPENADAPTERFROMLUID d3dkmt_adapter = { adapter };
|
||||
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;
|
||||
@@ -649,13 +641,12 @@ namespace platf::dxgi {
|
||||
|
||||
if (SUCCEEDED(d3dkmt_query_adapter_info(&d3dkmt_adapter_info))) {
|
||||
result = d3dkmt_adapter_caps.HwSchEnabled;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
BOOST_LOG(warning) << "D3DKMTQueryAdapterInfo() failed while trying to determine GPU HAGS status";
|
||||
result = false;
|
||||
}
|
||||
|
||||
D3DKMT_CLOSEADAPTER d3dkmt_close_adapter_wrap = { d3dkmt_adapter.hAdapter };
|
||||
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";
|
||||
}
|
||||
@@ -671,15 +662,16 @@ namespace platf::dxgi {
|
||||
// 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;
|
||||
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 {
|
||||
} else {
|
||||
BOOST_LOG(error) << "Couldn't load D3DKMTSetProcessSchedulingPriorityClass function from gdi32.dll to adjust GPU priority";
|
||||
}
|
||||
}
|
||||
@@ -740,8 +732,7 @@ namespace platf::dxgi {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
display_base_t::is_hdr() {
|
||||
bool display_base_t::is_hdr() {
|
||||
dxgi::output6_t output6 {};
|
||||
|
||||
auto status = output->QueryInterface(IID_IDXGIOutput6, (void **) &output6);
|
||||
@@ -756,8 +747,7 @@ namespace platf::dxgi {
|
||||
return desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
}
|
||||
|
||||
bool
|
||||
display_base_t::get_hdr_metadata(SS_HDR_METADATA &metadata) {
|
||||
bool display_base_t::get_hdr_metadata(SS_HDR_METADATA &metadata) {
|
||||
dxgi::output6_t output6 {};
|
||||
|
||||
std::memset(&metadata, 0, sizeof(metadata));
|
||||
@@ -928,20 +918,31 @@ namespace platf::dxgi {
|
||||
"DXGI_FORMAT_A8P8",
|
||||
"DXGI_FORMAT_B4G4R4A4_UNORM",
|
||||
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
"DXGI_FORMAT_P208",
|
||||
"DXGI_FORMAT_V208",
|
||||
"DXGI_FORMAT_V408"
|
||||
};
|
||||
|
||||
const char *
|
||||
display_base_t::dxgi_format_to_string(DXGI_FORMAT format) {
|
||||
const char *display_base_t::dxgi_format_to_string(DXGI_FORMAT format) {
|
||||
return format_str[format];
|
||||
}
|
||||
|
||||
const char *
|
||||
display_base_t::colorspace_to_string(DXGI_COLOR_SPACE_TYPE type) {
|
||||
const char *display_base_t::colorspace_to_string(DXGI_COLOR_SPACE_TYPE type) {
|
||||
const char *type_str[] = {
|
||||
"DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709",
|
||||
"DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709",
|
||||
@@ -972,8 +973,7 @@ namespace platf::dxgi {
|
||||
|
||||
if (type < ARRAYSIZE(type_str)) {
|
||||
return type_str[type];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
@@ -985,8 +985,7 @@ namespace platf {
|
||||
* Pick a display adapter and capture method.
|
||||
* @param hwdevice_type enables possible use of hardware encoder
|
||||
*/
|
||||
std::shared_ptr<display_t>
|
||||
display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
|
||||
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
|
||||
if (config::video.capture == "ddx" || config::video.capture.empty()) {
|
||||
if (hwdevice_type == mem_type_e::dxgi) {
|
||||
auto disp = std::make_shared<dxgi::display_ddup_vram_t>();
|
||||
@@ -994,8 +993,7 @@ namespace platf {
|
||||
if (!disp->init(config, display_name)) {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
else if (hwdevice_type == mem_type_e::system) {
|
||||
} else if (hwdevice_type == mem_type_e::system) {
|
||||
auto disp = std::make_shared<dxgi::display_ddup_ram_t>();
|
||||
|
||||
if (!disp->init(config, display_name)) {
|
||||
@@ -1011,8 +1009,7 @@ namespace platf {
|
||||
if (!disp->init(config, display_name)) {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
else if (hwdevice_type == mem_type_e::system) {
|
||||
} else if (hwdevice_type == mem_type_e::system) {
|
||||
auto disp = std::make_shared<dxgi::display_wgc_ram_t>();
|
||||
|
||||
if (!disp->init(config, display_name)) {
|
||||
@@ -1025,8 +1022,7 @@ namespace platf {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
display_names(mem_type_e) {
|
||||
std::vector<std::string> display_names(mem_type_e) {
|
||||
std::vector<std::string> display_names;
|
||||
|
||||
HRESULT status;
|
||||
@@ -1066,7 +1062,7 @@ namespace platf {
|
||||
|
||||
dxgi::output_t::pointer output_p {};
|
||||
for (int y = 0; adapter->EnumOutputs(y, &output_p) != DXGI_ERROR_NOT_FOUND; ++y) {
|
||||
dxgi::output_t output { output_p };
|
||||
dxgi::output_t output {output_p};
|
||||
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
output->GetDesc(&desc);
|
||||
@@ -1096,8 +1092,7 @@ namespace platf {
|
||||
* @brief Returns if GPUs/drivers have changed since the last call to this function.
|
||||
* @return `true` if a change has occurred or if it is unknown whether a change occurred.
|
||||
*/
|
||||
bool
|
||||
needs_encoder_reenumeration() {
|
||||
bool needs_encoder_reenumeration() {
|
||||
// Serialize access to the static DXGI factory
|
||||
static std::mutex reenumeration_state_lock;
|
||||
auto lg = std::lock_guard(reenumeration_state_lock);
|
||||
@@ -1117,8 +1112,7 @@ namespace platf {
|
||||
// can deal with any initialization races that may occur when the system is booting.
|
||||
BOOST_LOG(info) << "Encoder reenumeration is required"sv;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// The DXGI factory from last time is still current, so no encoder changes have occurred.
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user