| 2082 | } |
| 2083 | |
| 2084 | void PMTraceConsumer::CompletePresent(std::shared_ptr<PresentEvent> const& p) |
| 2085 | { |
| 2086 | // We use the first completed present to indicate that all necessary |
| 2087 | // providers are running and able to successfully track/complete presents. |
| 2088 | // |
| 2089 | // At the first completion, there may be numerous presents that have been |
| 2090 | // created but not properly tracked due to missed events. This is |
| 2091 | // especially prevalent in ETLs that start runtime providers before backend |
| 2092 | // providers and/or start capturing while an intensive graphics application |
| 2093 | // is already running. When that happens, PresentStartTime/TimeInPresentAPI and |
| 2094 | // ReadyTime/ScreenTime times can become mis-matched, and that offset can |
| 2095 | // persist for the full capture. |
| 2096 | // |
| 2097 | // We handle this by throwing away all queued presents up to this point. |
| 2098 | if (!mHasCompletedAPresent && !p->IsLost) { |
| 2099 | for (auto const& pr : mOrderedPresentsByProcessId) { |
| 2100 | for (auto orderedPresents = &pr.second; !orderedPresents->empty(); ) { |
| 2101 | RemoveLostPresent(orderedPresents->begin()->second); |
| 2102 | } |
| 2103 | } |
| 2104 | |
| 2105 | mHasCompletedAPresent = true; |
| 2106 | return; |
| 2107 | } |
| 2108 | |
| 2109 | // Protect against CompletePresent() being called twice for the same present. That isn't |
| 2110 | // intended, but there have been cases observed where it happens (in some cases leading to |
| 2111 | // infinite recursion with a DWM present and a dependent present completing each other). |
| 2112 | // |
| 2113 | // The exact pattern causing this has not yet been identified, so is the best fix for now. |
| 2114 | DebugAssert(p->IsCompleted == false); |
| 2115 | if (p->IsCompleted) { |
| 2116 | return; |
| 2117 | } |
| 2118 | |
| 2119 | // Mark the present as completed. |
| 2120 | VerboseTraceBeforeModifyingPresent(p.get()); |
| 2121 | p->IsCompleted = true; |
| 2122 | |
| 2123 | // It is possible for a present to be displayed or discarded before Present_Stop. If this |
| 2124 | // happens, we stop tracking the present (except for mPresentByThreadId which is required by |
| 2125 | // Present_Stop to lookup the present) but do not add the present to the dequeue list yet. |
| 2126 | // Present_Stop will check if the present is completed and add it to the dequeue list if so. |
| 2127 | if (!p->IsLost && p->Runtime != Runtime::Other && p->TimeInPresent == 0) { |
| 2128 | VerboseTraceBeforeModifyingPresent(p.get()); |
| 2129 | p->WaitingForPresentStop = true; |
| 2130 | } |
| 2131 | |
| 2132 | // If flip frame type tracking is enabled, we defer the completion because we may see subsequent |
| 2133 | // FlipFrameType events that need to refer back to this PresentEvent. The deferral will be |
| 2134 | // completed when we see another MMIOFlipMultiPlaneOverlay3_Info event for the same |
| 2135 | // (VidPnSourceId, LayerIndex) pair. |
| 2136 | if (!p->IsLost && !p->DoneWaitingForFlipFrameType && mEnableFlipFrameTypeEvents && p->FinalState == PresentResult::Presented) { |
| 2137 | VerboseTraceBeforeModifyingPresent(p.get()); |
| 2138 | p->WaitingForFlipFrameType = true; |
| 2139 | } |
| 2140 | |
| 2141 | // If this is a DWM present, update the dependent presents' final state and complete them as |