mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-12 11:22:59 -10:00
screen/video: Add refresh rate hint mechanism (#1447)
This constitutes one puzzle piece that will help improve ares's frame pacing, particularly for variable refresh rate displays. While continued work on ares's audio drivers is likely to smooth the pace at which ares generates video frames, transient changes in application and system load inevitably means that frames will be delivered earlier or later than expected. Additionally, relying on video frames to be generated precisely when needed and presenting them immediately is fairly demanding. If we can pace frames some distance in advance, it can significantly lessen the burden on the CPU and GPU. This PR is one tool to help the video backend deal with these issues. Cores can now inform the screen of their expected rate of frame generation at any given time, and the screen will inform the video backend. The backend can then employ various strategies to perform optimal frame pacing and drop frames when necessary. The function is emphasized as a 'hint' to indicate that the rate is only that which is expected, rather than certain. Unpredictable changes in system conditions mean that we can never be entirely certain when a frame will be generated or presented. > [!NOTE] > No concrete `refreshRateHint` implementations are added in this PR. Given the variety of core refresh rates across ares, as well as the consideration that for some cores refresh rates can change during runtime, that work is left for separate PRs. Co-authored-by: jcm <[email protected]>
This commit is contained in:
1 parent
e24e89b272
commit
a3c57b4fbd
8 files changed
+21
-2
No files matched your search
@@ -72,6 +72,11 @@ auto Screen::setRefresh(function<void ()> refresh) -> void {
|
||||
_refresh = refresh;
|
||||
}
|
||||
|
||||
auto Screen::refreshRateHint(double refreshRate) -> void {
|
||||
lock_guard<recursive_mutex> lock(_mutex);
|
||||
platform->refreshRateHint(refreshRate);
|
||||
}
|
||||
|
||||
auto Screen::setViewport(u32 x, u32 y, u32 width, u32 height) -> void {
|
||||
lock_guard<recursive_mutex> lock(_mutex);
|
||||
_viewportX = x;
|
||||
|
||||
@@ -34,6 +34,7 @@ struct Screen : Video {
|
||||
|
||||
auto setRefresh(function<void ()> refresh) -> void;
|
||||
auto setViewport(u32 x, u32 y, u32 width, u32 height) -> void;
|
||||
auto refreshRateHint(double refreshRate) -> void;
|
||||
|
||||
auto setSize(u32 width, u32 height) -> void;
|
||||
auto setScale(f64 scaleX, f64 scaleY) -> void;
|
||||
|
||||
@@ -18,6 +18,7 @@ struct Platform {
|
||||
virtual auto log(Node::Debugger::Tracer::Tracer, string_view message) -> void {}
|
||||
virtual auto status(string_view message) -> void {}
|
||||
virtual auto video(Node::Video::Screen, const u32* data, u32 pitch, u32 width, u32 height) -> void {}
|
||||
virtual auto refreshRateHint(double refreshRate) -> void {}
|
||||
virtual auto audio(Node::Audio::Stream) -> void {}
|
||||
virtual auto input(Node::Input::Input) -> void {}
|
||||
virtual auto cheat(u32 addr) -> maybe<u32> { return nothing; }
|
||||
|
||||
@@ -132,6 +132,10 @@ auto Program::video(ares::Node::Video::Screen node, const u32* data, u32 pitch,
|
||||
}
|
||||
}
|
||||
|
||||
auto Program::refreshRateHint(double refreshRate) -> void {
|
||||
ruby::video.refreshRateHint(refreshRate);
|
||||
}
|
||||
|
||||
auto Program::audio(ares::Node::Audio::Stream node) -> void {
|
||||
if(!streams) return;
|
||||
|
||||
@@ -187,4 +191,4 @@ auto Program::input(ares::Node::Input::Input node) -> void {
|
||||
|
||||
auto Program::cheat(u32 address) -> maybe<u32> {
|
||||
return cheatEditor.find(address);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ struct Program : ares::Platform {
|
||||
auto log(ares::Node::Debugger::Tracer::Tracer tracer, string_view message) -> void override;
|
||||
auto status(string_view message) -> void override;
|
||||
auto video(ares::Node::Video::Screen, const u32* data, u32 pitch, u32 width, u32 height) -> void override;
|
||||
auto refreshRateHint(double refreshRate) -> void override;
|
||||
auto audio(ares::Node::Audio::Stream) -> void override;
|
||||
auto input(ares::Node::Input::Input) -> void override;
|
||||
auto cheat(u32 address) -> maybe<u32> override;
|
||||
|
||||
@@ -79,7 +79,7 @@ struct VideoMetal : VideoDriver, Metal {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto hintRefreshRate(double refreshRate) -> void {
|
||||
auto refreshRateHint(double refreshRate) -> void {
|
||||
_refreshRateHint = refreshRate;
|
||||
updatePresentInterval();
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@ auto Video::setShader(string shader) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Video::refreshRateHint(double refreshRate) -> void {
|
||||
lock_guard<recursive_mutex> lock(mutex);
|
||||
instance->refreshRateHint(refreshRate);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto Video::focused() -> bool {
|
||||
|
||||
@@ -29,6 +29,7 @@ struct VideoDriver {
|
||||
virtual auto setFlush(bool flush) -> bool { return true; }
|
||||
virtual auto setFormat(string format) -> bool { return true; }
|
||||
virtual auto setShader(string shader) -> bool { return true; }
|
||||
virtual auto refreshRateHint(double refreshRate) -> void {}
|
||||
|
||||
virtual auto focused() -> bool { return true; }
|
||||
virtual auto clear() -> void {}
|
||||
@@ -114,6 +115,7 @@ struct Video {
|
||||
auto setFlush(bool flush) -> bool;
|
||||
auto setFormat(string format) -> bool;
|
||||
auto setShader(string shader) -> bool;
|
||||
auto refreshRateHint(double refreshRate) -> void;
|
||||
|
||||
auto focused() -> bool;
|
||||
auto clear() -> void;
|
||||
|
||||
Reference in new issue
Block a user