wall_clock.cpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/uint128.h"
  5. #include "common/wall_clock.h"
  6. #ifdef ARCHITECTURE_x86_64
  7. #include "common/x64/cpu_detect.h"
  8. #include "common/x64/native_clock.h"
  9. #endif
  10. namespace Common {
  11. using base_timer = std::chrono::steady_clock;
  12. using base_time_point = std::chrono::time_point<base_timer>;
  13. class StandardWallClock final : public WallClock {
  14. public:
  15. explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_)
  16. : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false) {
  17. start_time = base_timer::now();
  18. }
  19. std::chrono::nanoseconds GetTimeNS() override {
  20. base_time_point current = base_timer::now();
  21. auto elapsed = current - start_time;
  22. return std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed);
  23. }
  24. std::chrono::microseconds GetTimeUS() override {
  25. base_time_point current = base_timer::now();
  26. auto elapsed = current - start_time;
  27. return std::chrono::duration_cast<std::chrono::microseconds>(elapsed);
  28. }
  29. std::chrono::milliseconds GetTimeMS() override {
  30. base_time_point current = base_timer::now();
  31. auto elapsed = current - start_time;
  32. return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);
  33. }
  34. u64 GetClockCycles() override {
  35. std::chrono::nanoseconds time_now = GetTimeNS();
  36. const u128 temporary =
  37. Common::Multiply64Into128(time_now.count(), emulated_clock_frequency);
  38. return Common::Divide128On32(temporary, 1000000000).first;
  39. }
  40. u64 GetCPUCycles() override {
  41. std::chrono::nanoseconds time_now = GetTimeNS();
  42. const u128 temporary = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency);
  43. return Common::Divide128On32(temporary, 1000000000).first;
  44. }
  45. void Pause([[maybe_unused]] bool is_paused) override {
  46. // Do nothing in this clock type.
  47. }
  48. private:
  49. base_time_point start_time;
  50. };
  51. #ifdef ARCHITECTURE_x86_64
  52. std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency,
  53. u32 emulated_clock_frequency) {
  54. const auto& caps = GetCPUCaps();
  55. u64 rtsc_frequency = 0;
  56. if (caps.invariant_tsc) {
  57. rtsc_frequency = EstimateRDTSCFrequency();
  58. }
  59. if (rtsc_frequency == 0) {
  60. return std::make_unique<StandardWallClock>(emulated_cpu_frequency,
  61. emulated_clock_frequency);
  62. } else {
  63. return std::make_unique<X64::NativeClock>(emulated_cpu_frequency, emulated_clock_frequency,
  64. rtsc_frequency);
  65. }
  66. }
  67. #else
  68. std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency,
  69. u32 emulated_clock_frequency) {
  70. return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
  71. }
  72. #endif
  73. } // namespace Common