| 314 | } |
| 315 | |
| 316 | bool GpuTrace::CompleteWork(Context* context, uint32_t sequenceId, uint64_t timestamp) |
| 317 | { |
| 318 | auto node = context->mNode; |
| 319 | |
| 320 | // It's possible to miss DmaPacket events during realtime analysis, so try |
| 321 | // to handle it gracefully here. |
| 322 | // |
| 323 | // If we get a DmaPacket_Info event for a packet that we didn't get a |
| 324 | // DmaPacket_Start event for (or that we ignored because we didn't know the |
| 325 | // process yet) then sequenceId will be smaller than expected. If this |
| 326 | // happens, we ignore the DmaPacket_Info event which means that, if there |
| 327 | // was idle time before the missing DmaPacket_Start event, |
| 328 | // mAccumulatedPacketTime will be too large. |
| 329 | // |
| 330 | // measured: ---------------- ------- --------------------- |
| 331 | // [--- [-- |
| 332 | // actual: [-----] [-----] [-----] [-----]-----]-------] |
| 333 | // ^ ^ x ^ ^ ^ x ^ ^ |
| 334 | // s1 i1 s2 i2 s3 i3 s2 i1 s3 |
| 335 | if (context->mPacketTrace == nullptr || node->mQueueCount == 0) { |
| 336 | return false; |
| 337 | } |
| 338 | |
| 339 | auto runningSequenceId = node->mQueue[node->mQueueIndex].mSequenceId; |
| 340 | if (sequenceId < runningSequenceId) { |
| 341 | return false; |
| 342 | } |
| 343 | |
| 344 | // If we get a DmaPacket_Start event with no corresponding DmaPacket_Info, |
| 345 | // then sequenceId will be larger than expected. If this happens, we search |
| 346 | // through the queue for a match and if no match was found then we ignore |
| 347 | // this event (we missed both the DmaPacket_Start and DmaPacket_Info for |
| 348 | // the packet). In this case, both the missing packet's execution time as |
| 349 | // well as any idle time afterwards will be associated with the previous |
| 350 | // packet. |
| 351 | // |
| 352 | // If a match is found, then we don't know when the pre-match packets ended |
| 353 | // (nor when the matched packet started). We treat this case as if the |
| 354 | // first packet with a missed DmaPacket_Info ran the whole time, and all |
| 355 | // other packets up to the match executed with zero time. Any idle time |
| 356 | // during this range is ignored, and the correct association of gpu work to |
| 357 | // process will not be correct (unless all these contexts come from the |
| 358 | // same process). |
| 359 | // |
| 360 | // measured: ------- ---------------- --------------------- |
| 361 | // [--- [-- |
| 362 | // actual: [-----] [-----] [-----] [-----]-----]-------] |
| 363 | // ^ ^ ^ x ^ ^ ^ ^ x |
| 364 | // s1 i1 s2 i2 s3 i3 s2 i1 i2 |
| 365 | if (sequenceId > runningSequenceId) { |
| 366 | for (uint32_t missingCount = 1; ; ++missingCount) { |
| 367 | if (missingCount == node->mQueueCount) { |
| 368 | return false; |
| 369 | } |
| 370 | |
| 371 | uint32_t queueIndex = (node->mQueueIndex + missingCount) % (uint32_t) node->mQueue.size(); |
| 372 | auto entry = &node->mQueue[queueIndex]; |
| 373 | if (entry->mSequenceId == sequenceId) { |