wall_clock.cpp 3.1 KB

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