Skip to content

Commit

Permalink
Add static pacing to video network packets
Browse files Browse the repository at this point in the history
  • Loading branch information
ns6089 authored and cgutman committed Jul 10, 2024
1 parent 945d1f8 commit 4fb8438
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 62 deletions.
28 changes: 28 additions & 0 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <mutex>
#include <string>

#include <boost/core/noncopyable.hpp>

#include "src/config.h"
#include "src/logging.h"
#include "src/stat_trackers.h"
Expand Down Expand Up @@ -799,4 +801,30 @@ namespace platf {
*/
std::vector<supported_gamepad_t> &
supported_gamepads(input_t *input);

struct high_precision_timer: private boost::noncopyable {
virtual ~high_precision_timer() = default;

/**
* @brief Sleep for the duration
* @param duration Sleep duration
*/
virtual void
sleep_for(const std::chrono::nanoseconds &duration) = 0;

/**
* @brief Check if platform-specific timer backend has been initialized successfully
* @return `true` on success, `false` on error
*/
virtual
operator bool() = 0;
};

/**
* @brief Create platform-specific timer capable of high-precision sleep
* @return A unique pointer to timer
*/
std::unique_ptr<high_precision_timer>
create_high_precision_timer();

} // namespace platf
17 changes: 17 additions & 0 deletions src/platform/linux/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -933,4 +933,21 @@ namespace platf {

return std::make_unique<deinit_t>();
}

class linux_high_precision_timer: public high_precision_timer {

Check warning on line 937 in src/platform/linux/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/misc.cpp#L937

Added line #L937 was not covered by tests
public:
void
sleep_for(const std::chrono::nanoseconds &duration) override {
std::this_thread::sleep_for(duration);

Check warning on line 941 in src/platform/linux/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/misc.cpp#L940-L941

Added lines #L940 - L941 were not covered by tests
}

operator bool() override {
return true;

Check warning on line 945 in src/platform/linux/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/misc.cpp#L944-L945

Added lines #L944 - L945 were not covered by tests
}
};

std::unique_ptr<high_precision_timer>
create_high_precision_timer() {
return std::make_unique<linux_high_precision_timer>();

Check warning on line 951 in src/platform/linux/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/misc.cpp#L950-L951

Added lines #L950 - L951 were not covered by tests
}
} // namespace platf
16 changes: 16 additions & 0 deletions src/platform/macos/misc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,22 @@
return std::make_unique<qos_t>(sockfd, reset_options);
}

class macos_high_precision_timer: public high_precision_timer {
public:
void
sleep_for(const std::chrono::nanoseconds &duration) override {
std::this_thread::sleep_for(duration);

Check warning on line 514 in src/platform/macos/misc.mm

View check run for this annotation

Codecov / codecov/patch

src/platform/macos/misc.mm#L513-L514

Added lines #L513 - L514 were not covered by tests
}

operator bool() override {
return true;

Check warning on line 518 in src/platform/macos/misc.mm

View check run for this annotation

Codecov / codecov/patch

src/platform/macos/misc.mm#L517-L518

Added lines #L517 - L518 were not covered by tests
}
};

std::unique_ptr<high_precision_timer>
create_high_precision_timer() {
return std::make_unique<macos_high_precision_timer>();

Check warning on line 524 in src/platform/macos/misc.mm

View check run for this annotation

Codecov / codecov/patch

src/platform/macos/misc.mm#L523-L524

Added lines #L523 - L524 were not covered by tests
}
} // namespace platf

namespace dyn {
Expand Down
5 changes: 1 addition & 4 deletions src/platform/windows/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,6 @@ namespace platf::dxgi {
int
init(const ::video::config_t &config, const std::string &display_name);

void
high_precision_sleep(std::chrono::nanoseconds duration);

capture_e
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override;

Expand All @@ -184,7 +181,7 @@ namespace platf::dxgi {
DXGI_FORMAT capture_format;
D3D_FEATURE_LEVEL feature_level;

util::safe_ptr_v2<std::remove_pointer_t<HANDLE>, BOOL, CloseHandle> timer;
std::unique_ptr<high_precision_timer> timer = create_high_precision_timer();

typedef enum _D3DKMT_SCHEDULINGPRIORITYCLASS {
D3DKMT_SCHEDULINGPRIORITYCLASS_IDLE, ///< Idle priority class
Expand Down
35 changes: 4 additions & 31 deletions src/platform/windows/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,27 +182,6 @@ namespace platf::dxgi {
release_frame();
}

void
display_base_t::high_precision_sleep(std::chrono::nanoseconds duration) {
if (!timer) {
BOOST_LOG(error) << "Attempting high_precision_sleep() with uninitialized timer";
return;
}
if (duration < 0s) {
BOOST_LOG(error) << "Attempting high_precision_sleep() with negative duration";
return;
}
if (duration > 5s) {
BOOST_LOG(error) << "Attempting high_precision_sleep() with unexpectedly large duration (>5s)";
return;
}

LARGE_INTEGER due_time;
due_time.QuadPart = duration.count() / -100;
SetWaitableTimer(timer.get(), &due_time, 0, nullptr, nullptr, false);
WaitForSingleObject(timer.get(), INFINITE);
}

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 {
Expand Down Expand Up @@ -268,7 +247,7 @@ namespace platf::dxgi {
status = capture_e::timeout;
}
else {
high_precision_sleep(sleep_period);
timer->sleep_for(sleep_period);
std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - sleep_target;
log_sleep_overshoot(overshoot_ns);

Expand Down Expand Up @@ -799,15 +778,9 @@ namespace platf::dxgi {
<< "Max Full Luminance : "sv << desc1.MaxFullFrameLuminance << " nits"sv;
}

// Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+)
timer.reset(CreateWaitableTimerEx(nullptr, nullptr, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS));
if (!timer) {
timer.reset(CreateWaitableTimerEx(nullptr, nullptr, 0, TIMER_ALL_ACCESS));
if (!timer) {
auto winerr = GetLastError();
BOOST_LOG(error) << "Failed to create timer: "sv << winerr;
return -1;
}
if (!timer || !*timer) {
BOOST_LOG(error) << "Uninitialized high precision timer";
return -1;

Check warning on line 783 in src/platform/windows/display_base.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/display_base.cpp#L783

Added line #L783 was not covered by tests
}

return 0;
Expand Down
51 changes: 51 additions & 0 deletions src/platform/windows/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1803,4 +1803,55 @@ namespace platf {

return output;
}

class win32_high_precision_timer: public high_precision_timer {
public:
win32_high_precision_timer() {
// Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+)
timer = CreateWaitableTimerEx(nullptr, nullptr, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if (!timer) {
timer = CreateWaitableTimerEx(nullptr, nullptr, 0, TIMER_ALL_ACCESS);

Check warning on line 1813 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1813

Added line #L1813 was not covered by tests
if (!timer) {
BOOST_LOG(error) << "Unable to create high_precision_timer, CreateWaitableTimerEx() failed: " << GetLastError();
}
}
}

~win32_high_precision_timer() {
if (timer) CloseHandle(timer);
}

void
sleep_for(const std::chrono::nanoseconds &duration) override {

Check warning on line 1825 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1825

Added line #L1825 was not covered by tests
if (!timer) {
BOOST_LOG(error) << "Attempting high_precision_timer::sleep_for() with uninitialized timer";
return;

Check warning on line 1828 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1828

Added line #L1828 was not covered by tests
}
if (duration < 0s) {
BOOST_LOG(error) << "Attempting high_precision_timer::sleep_for() with negative duration";
return;

Check warning on line 1832 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1832

Added line #L1832 was not covered by tests
}
if (duration > 5s) {
BOOST_LOG(error) << "Attempting high_precision_timer::sleep_for() with unexpectedly large duration (>5s)";
return;

Check warning on line 1836 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1836

Added line #L1836 was not covered by tests
}

LARGE_INTEGER due_time;
due_time.QuadPart = duration.count() / -100;
SetWaitableTimer(timer, &due_time, 0, nullptr, nullptr, false);
WaitForSingleObject(timer, INFINITE);

Check warning on line 1842 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1839-L1842

Added lines #L1839 - L1842 were not covered by tests
}

operator bool() override {
return timer != NULL;

Check warning on line 1846 in src/platform/windows/misc.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/misc.cpp#L1845-L1846

Added lines #L1845 - L1846 were not covered by tests
}

private:
HANDLE timer = NULL;
};

std::unique_ptr<high_precision_timer>
create_high_precision_timer() {
return std::make_unique<win32_high_precision_timer>();
}
} // namespace platf
Loading

0 comments on commit 4fb8438

Please sign in to comment.