Fix(FrameInfo): Improve robustness of frame info history management (#9496)
Address potential issues in FrameInfoImpl and FrameInfoManager: - Modify FrameInfoManager::beginFrame to handle cases where the circular queue is full and the oldest frame is not yet ready, logging a warning and skipping the frame. This prevents potential use-after-free or data corruption by ensuring only ready frames are removed from the history. FIXES=[466081317]
This commit is contained in:
@@ -101,11 +101,22 @@ void FrameInfoManager::beginFrame(FSwapChain* swapChain, DriverApi& driver,
|
||||
auto& history = mFrameTimeHistory;
|
||||
// don't exceed the capacity, drop the oldest entry
|
||||
if (UTILS_LIKELY(history.size() == history.capacity())) {
|
||||
if (!mDisableGpuFrameComplete) {
|
||||
assert_invariant(history.back().fence);
|
||||
driver.destroyFence(std::move(history.back().fence));
|
||||
FrameInfoImpl& frameInfo = history.back();
|
||||
if (frameInfo.ready.load(std::memory_order_relaxed)) {
|
||||
if (!mDisableGpuFrameComplete) {
|
||||
assert_invariant(frameInfo.fence);
|
||||
driver.destroyFence(std::move(frameInfo.fence));
|
||||
}
|
||||
history.pop_back();
|
||||
} else {
|
||||
// This is a big problem, we ran out of space in the circular queue and that entry
|
||||
// hasn't been processed yet. Because the code below keeps a reference to the
|
||||
// front element of the queue, we can't pop/push. Our only option is to not record
|
||||
// a new entry for this frame, which will create a false skipped frame in the
|
||||
// data.
|
||||
LOG(WARNING) << "FrameInfo's circular queue is full, but the latest item hasn't "
|
||||
" been processed yet. Skipping this frame, id = " << frameId;
|
||||
}
|
||||
history.pop_back();
|
||||
}
|
||||
|
||||
// create a new entry
|
||||
|
||||
@@ -95,33 +95,8 @@ struct FrameInfoImpl : public details::FrameInfo {
|
||||
assert_invariant(!fence);
|
||||
}
|
||||
|
||||
FrameInfoImpl(FrameInfoImpl&& rhs) noexcept :
|
||||
details::FrameInfo(rhs),
|
||||
frameId(rhs.frameId),
|
||||
beginFrame(rhs.beginFrame),
|
||||
endFrame(rhs.endFrame),
|
||||
backendBeginFrame(rhs.backendBeginFrame),
|
||||
backendEndFrame(rhs.backendEndFrame),
|
||||
gpuFrameComplete(rhs.gpuFrameComplete),
|
||||
vsync(rhs.vsync),
|
||||
fence(rhs.fence),
|
||||
ready(rhs.ready.load())
|
||||
{
|
||||
}
|
||||
|
||||
FrameInfoImpl& operator=(FrameInfoImpl&& rhs) noexcept {
|
||||
details::FrameInfo::operator=(rhs);
|
||||
frameId = rhs.frameId;
|
||||
beginFrame = rhs.beginFrame;
|
||||
endFrame = rhs.endFrame;
|
||||
backendBeginFrame = rhs.backendBeginFrame;
|
||||
backendEndFrame = rhs.backendEndFrame;
|
||||
gpuFrameComplete = rhs.gpuFrameComplete;
|
||||
vsync = rhs.vsync;
|
||||
fence = rhs.fence;
|
||||
ready.store(rhs.ready.load());
|
||||
return *this;
|
||||
}
|
||||
FrameInfoImpl(FrameInfoImpl& rhs) noexcept = delete;
|
||||
FrameInfoImpl& operator=(FrameInfoImpl& rhs) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename T, size_t CAPACITY>
|
||||
|
||||
Reference in New Issue
Block a user