OptickProfilerEventForwarder.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <OptickProfilerEventForwarder.h>
  9. #include <AzCore/Debug/ProfilerBus.h>
  10. #include <AzCore/Interface/Interface.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <AzCore/Utils/Utils.h>
  13. #include <AzCore/std/parallel/thread.h>
  14. #include <AzCore/std/time.h>
  15. #include <optick.h>
  16. namespace OptickProfiler
  17. {
  18. thread_local Optick::EventStorage* OptickProfilerEventForwarder::m_pOptickStorage = nullptr;
  19. bool OnOptickStateChanged(Optick::State::Type state)
  20. {
  21. switch (state)
  22. {
  23. case Optick::State::DUMP_CAPTURE:
  24. {
  25. auto projectName = AZ::Utils::GetProjectName();
  26. Optick::AttachSummary("Project", projectName.c_str());
  27. }
  28. break;
  29. }
  30. return true;
  31. }
  32. void OptickProfilerEventForwarder::Init()
  33. {
  34. AZ::Interface<AZ::Debug::Profiler>::Register(this);
  35. AZ::TickBus::Handler::BusConnect();
  36. AZStd::ThreadEventBus::Handler::BusConnect();
  37. Optick::SetStateChangedCallback(OnOptickStateChanged);
  38. m_pOptickFrameTag = Optick::EventDescription::Create("Frame", "", 0);
  39. m_pOptickStorage = Optick::RegisterStorage("Main Thread", AZStd::this_thread::get_id().m_id);
  40. m_initialized = true;
  41. }
  42. void OptickProfilerEventForwarder::Shutdown()
  43. {
  44. if (!m_initialized)
  45. {
  46. return;
  47. }
  48. // When this call is made, no more thread profiling calls can be performed anymore
  49. AZ::Interface<AZ::Debug::Profiler>::Unregister(this);
  50. // Wait for the remaining threads that might still be processing its profiling calls
  51. AZStd::unique_lock<AZStd::shared_mutex> shutdownLock(m_shutdownMutex);
  52. AZStd::ThreadEventBus::Handler::BusDisconnect();
  53. AZ::TickBus::Handler::BusDisconnect();
  54. Optick::StopCapture();
  55. Optick::Shutdown();
  56. }
  57. void OptickProfilerEventForwarder::BeginRegion(
  58. [[maybe_unused]] const AZ::Debug::Budget* budget, [[maybe_unused]] const char* eventName, ...)
  59. {
  60. if (!m_pOptickStorage && m_threadIdToNameMutex.try_lock_shared())
  61. {
  62. AZStd::native_thread_id_type id = AZStd::this_thread::get_id().m_id;
  63. const AZStd::string& name = m_threadIdToName.contains(id) ? m_threadIdToName.at(id) : "";
  64. m_pOptickStorage = Optick::RegisterStorage(name.c_str(), id);
  65. m_threadIdToNameMutex.unlock_shared();
  66. }
  67. // Try to lock here, the shutdownMutex will only be contested when the CpuProfiler is shutting down.
  68. if (m_shutdownMutex.try_lock_shared())
  69. {
  70. Optick::EventDescription* pDesc = Optick::EventDescription::CreateShared(eventName);
  71. Optick::Event::Push(m_pOptickStorage, pDesc, Optick::GetHighPrecisionTime());
  72. m_shutdownMutex.unlock_shared();
  73. }
  74. }
  75. void OptickProfilerEventForwarder::EndRegion([[maybe_unused]] const AZ::Debug::Budget* budget)
  76. {
  77. // Try to lock here, the shutdownMutex will only be contested when the CpuProfiler is shutting down.
  78. if (m_shutdownMutex.try_lock_shared())
  79. {
  80. Optick::Event::Pop(m_pOptickStorage, Optick::GetHighPrecisionTime());
  81. m_shutdownMutex.unlock_shared();
  82. }
  83. }
  84. int OptickProfilerEventForwarder::GetTickOrder()
  85. {
  86. return AZ::ComponentTickBus::TICK_FIRST;
  87. }
  88. void OptickProfilerEventForwarder::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  89. {
  90. const int64_t frameTick = Optick::GetHighPrecisionTime();
  91. Optick::Event::Pop(m_pOptickStorage, frameTick);
  92. Optick::EndFrame(Optick::FrameType::CPU);
  93. Optick::Update();
  94. const uint32_t frameNumber = Optick::BeginFrame(Optick::FrameType::CPU, frameTick);
  95. Optick::Event::Push(m_pOptickStorage, Optick::GetFrameDescription(), frameTick);
  96. Optick::AttachTag(m_pOptickStorage, *m_pOptickFrameTag, frameNumber, frameTick);
  97. }
  98. void OptickProfilerEventForwarder::OnThreadEnter(const AZStd::thread::id& id, const AZStd::thread_desc* desc)
  99. {
  100. AZStd::unique_lock<AZStd::shared_mutex> lock(m_threadIdToNameMutex);
  101. m_threadIdToName[id.m_id] = desc->m_name;
  102. }
  103. void OptickProfilerEventForwarder::OnThreadExit([[maybe_unused]] const AZStd::thread::id& id)
  104. {
  105. }
  106. } // namespace OptickProfiler