Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSync無効時にフレームレートを制限する機能の提案 #1180

Open
m4saka opened this issue Jan 2, 2024 · 7 comments
Open

VSync無効時にフレームレートを制限する機能の提案 #1180

m4saka opened this issue Jan 2, 2024 · 7 comments
Labels

Comments

@m4saka
Copy link
Contributor

m4saka commented Jan 2, 2024

追加する機能の内容 | Describe the solution you'd like

過去バージョンに存在していた、下記の関数を別の実装で復活させたいと思っています。

  • Graphics::SetTargetFrameRateHz
  • Graphics::GetTargetFrameRateHz

下記のQiita記事に記載したstd::this_thread::sleep_untilを使う方法で、Windows版・macOS版の2通りで安定して300fpsに固定できることを確認できました。
OpenSiv3Dでフレームレートを60fps以外に固定する方法(FrameRateLimitアドオン) | Qiita

そこで、上記と同じような内容の実装をSiv3D内に組み込んで、VSync無効時のフレームレートを指定できるようにしたいと思っています。

その機能の追加によって解決する問題 | Is your feature request related to a problem? Please describe.

60fps以外のフレームレートで安定動作させられる。
ソフトウェア作成者が適切なウェイトを入れないままVSyncを無効化してしまい、ソフトウェア利用者の環境にて過剰な負荷が発生するのを防げる。

備考 | Additional context

もしよろしければ、実装についてぜひ私の方で挑戦してみたいです。
そこで、まずは実装方針について3点ご相談したいです。

  1. ユーザー側で呼び出すインタフェースは旧バージョンにあったGraphics::SetTargetFrameRateHzと同じにすべきでしょうか?それとも、より適切な名前があれば名前空間や関数名を別のものに変更しても問題ないでしょうか?
  2. フレームレート制限は旧バージョンと同様、VSyncを無効化した場合のみ効くようにした方が良いでしょうか?それとも、VSync有効のままで120Hzモニタや144Hzモニタでも60fpsに固定したいユーザーなどを想定して、VSyncが有効な場合も効くようにした方が良いでしょうか?
  3. プラットフォーム間で同一実装になる見込みです。そこで、時間待ちは旧バージョンで実装していたD3DSwapChain.cpp等ではなく、ISiv3DFrameRateLimitインタフェース、CFrameRateLimitクラスを新たに作成して実装し、System::Update内のAddonのpostPresentの直前か直後のタイミングにSIV3D_ENGINE(FrameRateLimit)->update();を入れて実行する形が良さそうですが、方針について問題なさそうでしょうか?
@Reputeless
Copy link
Member

ご提案ありがとうございます。#1179 の調査完了後に検討します。

@Reputeless
Copy link
Member

#1179 をマージしたので、こちら進めます。

  1. Hz を外して void Graphics::SetTargetFrameRate(const Optional<double>& fps) / Optional<double> Graphics::GetTargetFrameRate() にしましょう。
  2. 既存のコードへの影響を小さくするため、VSync が無効な場合のみ有効としたいです。
  3. 新しいエンジンインタフェース FrameRateLimit の追加 OK です。その実装方針で良さそうです。

@m4saka
Copy link
Contributor Author

m4saka commented Jan 9, 2024

ご確認ありがとうございます。1〜3について承知しました!
実装に進展がありましたらお知らせいたします!

@m4saka
Copy link
Contributor Author

m4saka commented Feb 14, 2024

@Reputeless
下記で仮実装しました。実装内容に問題ないかご確認いただけますと幸いです!
m4saka@da52430

実装にあたって気になっている点は下記2点です。

  1. 目標フレームレート(fps引数)にゼロや負の値を指定した時に例外を投げているのは問題ないか?
  2. 目標フレームレート(fps引数)にNaNや+inf、-infを指定した場合も例外を投げるべきか?

補足事項として、Qiita記事での実装ではMaxDrift(=10ミリ秒)という定数値を導入していましたが、now < sleepUntilの場合のみsleepを実行することで不要になったので、今回の実装には入っていません。

手元では現状Windows版のみで動作確認しているので、macOS版、Linux版、Web版でも正常動作するかどうかは今後確認予定です。
(Xcodeプロジェクトへのソースファイル追加についても現状は未対応です)

@Reputeless
Copy link
Member

ありがとうございます。確認します、

@m4saka
Copy link
Contributor Author

m4saka commented Feb 16, 2024

レビューコメントが記載できるように一旦Draft PRにいたしました。
#1205

@Reputeless
Copy link
Member

目標フレームレート(fps引数)にゼロや負の値を指定した時に例外を投げているのは問題ないか?
目標フレームレート(fps引数)にNaNや+inf、-infを指定した場合も例外を投げるべきか?

  • ほかの関数のほとんどがそうなので、NaN の挙動は未定義(対策なし)で問題ありませんが、例外で知らせても良いです。
  • 「スリープ無し / 目標フレームレート ∞」である状態を、+inf で表現するのはどうでしょうか。
  • あまりにも低すぎるフレームレートは他の機能(入力関連など)に悪影響を及ぼす可能性があるため、目標フレームレートの下限を 1.0 fps にしたいです。
  • 目標フレームレートの有効範囲を関数内部で自動的に 1.0 以上 +inf 以下にクランプすると良さそうな気がします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Investigating
Development

No branches or pull requests

2 participants