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