Skip to content

Commit

Permalink
Frame timing logic update
Browse files Browse the repository at this point in the history
* Imagine: Add FrameTimeSource into FrameParams
* Imagine: Don't implicitly call setNeedsDraw() in Window::dispatchOnFrame()
* EmuFramework: Move all frame timing logic into EmuSystemTask's thread and update it to check if the previous frame was presented before starting a new frame
* EmuFramework: Cap frame skip to 4 if the previous frame is falling behind to prevent accumulation of late frames
* EmuFramework: Re-implement fast/slow mode using a variable frame rate, allowing for refresh rate switching when speeding up
* EmuFramework: Use single-buffered textures since only one frame is ever rendering
* EmuFramework: Add EmuSystem::addThreadGroupIds() to add emulator system threads for CPU affinity/performance hint management
* C64.emu: Add the emulation thread id to the thread group
  • Loading branch information
Robert Broglia committed Jan 25, 2024
1 parent c8a5c69 commit 5076793
Show file tree
Hide file tree
Showing 17 changed files with 191 additions and 223 deletions.
3 changes: 3 additions & 0 deletions C64.emu/src/main/MainSystem.hh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public:
EmuAudio *audioPtr{};
struct video_canvas_s *activeCanvas{};
const char *sysFileDir{};
ThreadId emuThreadId{};
VicePlugin plugin{};
mutable ArchiveIO firmwareArch;
std::string defaultPaletteName{};
Expand Down Expand Up @@ -134,6 +135,7 @@ public:
makeDetachedThread(
[this]()
{
emuThreadId = thisThreadId();
execSem.acquire();
logMsg("starting maincpu_mainloop()");
plugin.maincpu_mainloop();
Expand Down Expand Up @@ -220,6 +222,7 @@ public:
void renderFramebuffer(EmuVideo &);
bool shouldFastForward() const;
bool onVideoRenderFormatChange(EmuVideo &, PixelFormat);
void addThreadGroupIds(std::vector<ThreadId> &ids) const { ids.emplace_back(emuThreadId); }

protected:
void initC64(EmuApp &app);
Expand Down
7 changes: 4 additions & 3 deletions EmuFramework/include/emuframework/EmuApp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ public:
static std::unique_ptr<View> makeView(ViewAttachParams, ViewID);
void applyOSNavStyle(IG::ApplicationContext, bool inGame);
void setCPUNeedsLowLatency(IG::ApplicationContext, bool needed);
void runFrames(EmuSystemTaskContext, EmuVideo *, EmuAudio *, int frames, bool skipForward);
void advanceFrames(FrameParams, EmuSystemTask *);
void runFrames(EmuSystemTaskContext, EmuVideo *, EmuAudio *, int frames);
void skipFrames(EmuSystemTaskContext, int frames, EmuAudio *);
bool skipForwardFrames(EmuSystemTaskContext, int frames);
IG::Audio::Manager &audioManager() { return audioManager_; }
Expand All @@ -271,7 +272,7 @@ public:
IG::Viewport makeViewport(const Window &win) const;
void setEmuViewOnExtraWindow(bool on, IG::Screen &);
void record(FrameTimeStatEvent, SteadyClockTimePoint t = {});
bool supportsPresentModes() const { return windowFrameTimeSource != WindowFrameTimeSource::RENDERER; }
bool supportsPresentModes() const { return windowFrameTimeSource != FrameTimeSource::renderer; }
void setIntendedFrameRate(Window &, FrameTimeConfig);
static std::u16string_view mainViewName();
void runBenchmarkOneShot(EmuVideo &);
Expand Down Expand Up @@ -560,7 +561,7 @@ public:
IG_UseMemberIf(Config::Input::BLUETOOTH && Config::BASE_CAN_BACKGROUND_APP, bool, keepBluetoothActive){};
IG_UseMemberIf(Config::Input::DEVICE_HOTSWAP, bool, notifyOnInputDeviceChange){true};
IG_UseMemberIf(Config::multipleScreenFrameRates, FrameRate, overrideScreenFrameRate){};
WindowFrameTimeSource windowFrameTimeSource{WindowFrameTimeSource::AUTO};
FrameTimeSource windowFrameTimeSource{FrameTimeSource::unset};
IG_UseMemberIf(Config::cpuAffinity, CPUAffinityMode, cpuAffinityMode){CPUAffinityMode::Auto};
IG_UseMemberIf(Config::envIsAndroid && Config::DEBUG_BUILD, bool, useNoopThread){};
IG_UseMemberIf(enableFrameTimeStats, bool, showFrameTimeStats){};
Expand Down
13 changes: 11 additions & 2 deletions EmuFramework/include/emuframework/EmuSystem.hh
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ public:
bool shouldFastForward() const;
FS::FileString contentDisplayNameForPath(CStringView path) const;
IG::Rotation contentRotation() const;
void addThreadGroupIds(std::vector<ThreadId> &) const;

ApplicationContext appContext() const { return appCtx; }
bool isActive() const { return state == State::ACTIVE; }
Expand Down Expand Up @@ -342,12 +343,20 @@ public:
EmuSystemCreateParams, OnLoadProgressDelegate);
int updateAudioFramesPerVideoFrame();
double frameRate() const { return toHz(frameTime()); }
FrameTime scaledFrameTime() const
{
auto t = std::chrono::duration_cast<FloatSeconds>(frameTime()) * frameTimeMultiplier;
return std::chrono::duration_cast<FrameTime>(t);
}
double scaledFrameRate() const
{
return toHz(std::chrono::duration_cast<FloatSeconds>(frameTime()) * frameTimeMultiplier);
}
void onFrameTimeChanged();
static double audioMixRate(int outputRate, double inputFrameRate, FrameTime outputFrameTime);
double audioMixRate(int outputRate, FrameTime outputFrameTime) const { return audioMixRate(outputRate, frameRate(), outputFrameTime); }
void configFrameTime(int outputRate, FrameTime outputFrameTime);
auto advanceFramesWithTime(SteadyClockTimePoint time) { return emuTiming.advanceFramesWithTime(time); }
void setSpeedMultiplier(EmuAudio &, double speed);
SteadyClockTime benchmark(EmuVideo &video);
bool hasContent() const;
void resetFrameTime();
Expand Down Expand Up @@ -385,7 +394,7 @@ protected:

public:
IG::OnFrameDelegate onFrameUpdate;
double targetSpeed{1.};
double frameTimeMultiplier{1.};
static constexpr double minFrameRate = 48.;
};

Expand Down
6 changes: 6 additions & 0 deletions EmuFramework/include/emuframework/EmuSystemInlines.hh
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,10 @@ void EmuSystem::onStop()
static_cast<MainSystem*>(this)->onStop();
}

void EmuSystem::addThreadGroupIds(std::vector<ThreadId> &ids) const
{
if(&MainSystem::addThreadGroupIds != &EmuSystem::addThreadGroupIds)
static_cast<const MainSystem*>(this)->addThreadGroupIds(ids);
}

}
23 changes: 6 additions & 17 deletions EmuFramework/include/emuframework/EmuSystemTask.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <imagine/base/MessagePort.hh>
#include <imagine/thread/Thread.hh>
#include <imagine/time/Time.hh>
#include <variant>

namespace EmuEx
Expand All @@ -31,32 +32,20 @@ class EmuApp;
class EmuSystemTask
{
public:
enum class Command: uint8_t
struct FrameParamsCommand
{
UNSET,
RUN_FRAME,
PAUSE,
EXIT,
};

struct RunFrameCommand
{
EmuVideo *video{};
EmuAudio *audio{};
int8_t frames{};
bool skipForward{};
bool fastForward{};
FrameParams params;
};

struct PauseCommand {};
struct ExitCommand {};

using CommandVariant = std::variant<RunFrameCommand, PauseCommand, ExitCommand>;
using CommandVariant = std::variant<FrameParamsCommand, PauseCommand, ExitCommand>;

struct CommandMessage
{
std::binary_semaphore *semPtr{};
CommandVariant command{RunFrameCommand{}};
CommandVariant command{PauseCommand{}};

void setReplySemaphore(std::binary_semaphore *semPtr_) { assert(!semPtr); semPtr = semPtr_; };
};
Expand All @@ -65,7 +54,7 @@ public:
void start();
void pause();
void stop();
void runFrame(EmuVideo *, EmuAudio *, int8_t frames, bool skipForward, bool fastForward);
void updateFrameParams(FrameParams);
void sendVideoFormatChangedReply(EmuVideo &);
void sendFrameFinishedReply(EmuVideo &);
void sendScreenshotReply(bool success);
Expand Down
5 changes: 0 additions & 5 deletions EmuFramework/include/emuframework/EmuTiming.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,11 @@ public:
EmuFrameTimeInfo advanceFramesWithTime(SteadyClockTimePoint);
void setFrameTime(SteadyClockTime time);
void reset();
void setSpeedMultiplier(double newSpeed);

protected:
SteadyClockTime timePerVideoFrame{};
SteadyClockTime timePerVideoFrameScaled{};
SteadyClockTimePoint startFrameTime{};
double speed = 1;
int64_t lastFrame = 0;

void updateScaledFrameTime();
};

}
Loading

0 comments on commit 5076793

Please sign in to comment.