blob: e8a9526527f406f875b36009d879caedf2898732 [file] [log] [blame]
#ifndef VK_QSRI_TIMELINE_H
#define VK_QSRI_TIMELINE_H
#include <cstdint>
#include <functional>
#include <map>
#include <mutex>
#include <sstream>
#include "host-common/logging.h"
namespace gfxstream {
namespace vk {
class VkQsriTimeline {
public:
using Callback = std::function<void()>;
void signalNextPresentAndPoll() {
std::lock_guard<std::mutex> guard(mLock);
mPresentCount++;
pollLocked();
}
void registerCallbackForNextPresentAndPoll(Callback callback) {
std::lock_guard<std::mutex> guard(mLock);
uint64_t requestPresentCount = mRequestPresentCount;
mRequestPresentCount++;
mPendingCallbacks.emplace(requestPresentCount, std::move(callback));
pollLocked();
}
VkQsriTimeline() : mPresentCount(0), mRequestPresentCount(0) {}
~VkQsriTimeline() {
std::lock_guard<std::mutex> guard(mLock);
if (mPendingCallbacks.empty()) {
return;
}
std::stringstream ss;
ss << mPendingCallbacks.size()
<< " pending QSRI callbacks found when destroying the timeline, waiting for: ";
for (auto& [requiredPresentCount, callback] : mPendingCallbacks) {
callback();
ss << requiredPresentCount << ", ";
}
ss << "just call all of callbacks.";
ERR("%s", ss.str().c_str());
}
private:
std::map<uint64_t, Callback> mPendingCallbacks;
std::mutex mLock;
uint64_t mPresentCount;
uint64_t mRequestPresentCount;
void pollLocked() {
auto firstPendingCallback = mPendingCallbacks.lower_bound(mPresentCount);
for (auto readyCallback = mPendingCallbacks.begin(); readyCallback != firstPendingCallback;
readyCallback++) {
readyCallback->second();
}
mPendingCallbacks.erase(mPendingCallbacks.begin(), firstPendingCallback);
}
};
} // namespace vk
} // namespace gfxstream
#endif // VK_QSRI_TIMELINE_H