1 #ifndef VK_QSRI_TIMELINE_H 2 #define VK_QSRI_TIMELINE_H 3 4 #include <cstdint> 5 #include <functional> 6 #include <map> 7 #include <mutex> 8 #include <sstream> 9 10 #include "host-common/logging.h" 11 12 namespace gfxstream { 13 namespace vk { 14 15 class VkQsriTimeline { 16 public: 17 using Callback = std::function<void()>; 18 signalNextPresentAndPoll()19 void signalNextPresentAndPoll() { 20 std::lock_guard<std::mutex> guard(mLock); 21 mPresentCount++; 22 pollLocked(); 23 } 24 registerCallbackForNextPresentAndPoll(Callback callback)25 void registerCallbackForNextPresentAndPoll(Callback callback) { 26 std::lock_guard<std::mutex> guard(mLock); 27 uint64_t requestPresentCount = mRequestPresentCount; 28 mRequestPresentCount++; 29 mPendingCallbacks.emplace(requestPresentCount, std::move(callback)); 30 pollLocked(); 31 } 32 VkQsriTimeline()33 VkQsriTimeline() : mPresentCount(0), mRequestPresentCount(0) {} ~VkQsriTimeline()34 ~VkQsriTimeline() { 35 std::lock_guard<std::mutex> guard(mLock); 36 if (mPendingCallbacks.empty()) { 37 return; 38 } 39 std::stringstream ss; 40 ss << mPendingCallbacks.size() 41 << " pending QSRI callbacks found when destroying the timeline, waiting for: "; 42 for (auto& [requiredPresentCount, callback] : mPendingCallbacks) { 43 callback(); 44 ss << requiredPresentCount << ", "; 45 } 46 ss << "just call all of callbacks."; 47 ERR("%s", ss.str().c_str()); 48 } 49 50 private: 51 std::map<uint64_t, Callback> mPendingCallbacks; 52 std::mutex mLock; 53 uint64_t mPresentCount; 54 uint64_t mRequestPresentCount; 55 pollLocked()56 void pollLocked() { 57 auto firstPendingCallback = mPendingCallbacks.lower_bound(mPresentCount); 58 for (auto readyCallback = mPendingCallbacks.begin(); readyCallback != firstPendingCallback; 59 readyCallback++) { 60 readyCallback->second(); 61 } 62 mPendingCallbacks.erase(mPendingCallbacks.begin(), firstPendingCallback); 63 } 64 }; 65 66 } // namespace vk 67 } // namespace gfxstream 68 69 #endif // VK_QSRI_TIMELINE_H