| 517 | } |
| 518 | |
| 519 | void GpuTrace::CompleteFrame(PresentEvent* pEvent, uint64_t timestamp) |
| 520 | { |
| 521 | // There are a few different events that can be used to complete the GPU |
| 522 | // trace for each frame, e.g. QueuePacket_Stop for a present packet, or |
| 523 | // MMIOFlipMultiPlaneOverlay_Info, and they can occur in any order so we |
| 524 | // only apply the first one we see. |
| 525 | if (pEvent->GpuFrameCompleted) { |
| 526 | return; |
| 527 | } |
| 528 | |
| 529 | VerboseTraceBeforeModifyingPresent(pEvent); |
| 530 | pEvent->GpuFrameCompleted = true; |
| 531 | |
| 532 | auto ii = mProcessFrameInfo.find(pEvent->ProcessId); |
| 533 | if (ii != mProcessFrameInfo.end()) { |
| 534 | auto frameInfo = &ii->second; |
| 535 | auto packetTrace = &frameInfo->mOtherEngines; |
| 536 | auto videoTrace = &frameInfo->mVideoEngines; |
| 537 | |
| 538 | // Update GPUStartTime/ReadyTime/GPUDuration if any DMA packets were |
| 539 | // observed. |
| 540 | if (packetTrace->mFirstPacketTime != 0) { |
| 541 | pEvent->GPUStartTime = packetTrace->mFirstPacketTime; |
| 542 | pEvent->ReadyTime = packetTrace->mLastPacketTime; |
| 543 | pEvent->GPUDuration = packetTrace->mAccumulatedPacketTime; |
| 544 | packetTrace->mFirstPacketTime = 0; |
| 545 | packetTrace->mLastPacketTime = 0; |
| 546 | packetTrace->mAccumulatedPacketTime = 0; |
| 547 | } |
| 548 | |
| 549 | pEvent->GPUVideoDuration = videoTrace->mAccumulatedPacketTime; |
| 550 | videoTrace->mFirstPacketTime = 0; |
| 551 | videoTrace->mLastPacketTime = 0; |
| 552 | videoTrace->mAccumulatedPacketTime = 0; |
| 553 | |
| 554 | if (IsVerboseTraceEnabled()) { |
| 555 | wprintf(L" GPU: pid=%u completing frame\n", pEvent->ProcessId); |
| 556 | } |
| 557 | |
| 558 | // There are some cases where the QueuePacket_Stop timestamp is before |
| 559 | // the previous dma packet completes. e.g., this seems to be typical |
| 560 | // of DWM present packets. In these cases, instead of loosing track of |
| 561 | // the previous dma work, we split it at this time and assign portions |
| 562 | // to both frames. Note this is incorrect, as the dma's full cost |
| 563 | // should be fully attributed to the previous frame. |
| 564 | if (packetTrace->mRunningPacketCount > 0) { |
| 565 | |
| 566 | pEvent->ReadyTime = timestamp; |
| 567 | |
| 568 | auto accumulatedTime = timestamp - packetTrace->mRunningPacketStartTime; |
| 569 | if (accumulatedTime > 0) { |
| 570 | if (IsVerboseTraceEnabled()) { |
| 571 | DebugPrintAccumulatedGpuTime(pEvent->ProcessId, |
| 572 | pEvent->GPUDuration, |
| 573 | packetTrace->mRunningPacketStartTime, |
| 574 | timestamp); |
| 575 | wprintf(L" GPU: work still running; splitting and considering as new work for next frame\n"); |
| 576 | } |
no test coverage detected