| 258 | } |
| 259 | |
| 260 | void GpuTrace::EnqueueWork(Context* context, uint32_t sequenceId, uint64_t timestamp, bool isWaitPacket) |
| 261 | { |
| 262 | auto packetTrace = context->mPacketTrace; |
| 263 | auto node = context->mNode; |
| 264 | |
| 265 | // A very rare (never observed) race exists where packetTrace can still be |
| 266 | // nullptr here. The context must have been created and this packet must |
| 267 | // have been submitted to the queue before the capture started. |
| 268 | // |
| 269 | // In this case, we have to ignore the DMA packet otherwise the node and |
| 270 | // process tracking will become out of sync. |
| 271 | if (packetTrace == nullptr) { |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | // If the queue is too small, enlarge it by 16 entries at a time. Typically, this will only be |
| 276 | // needed for the first packet observed on this node, which will result in sizing the queue from |
| 277 | // 0 to 16. However, there are other cases where the queue entries can grow beyond that. e.g., |
| 278 | // this seems to always happen when an application closes. |
| 279 | uint32_t queueSize = (uint32_t) node->mQueue.size(); |
| 280 | if (node->mQueueCount == queueSize) { |
| 281 | Node::EnqueuedPacket empty{}; |
| 282 | node->mQueue.insert(node->mQueue.begin() + node->mQueueIndex, 16, empty); |
| 283 | queueSize += 16; |
| 284 | node->mQueueIndex = (node->mQueueIndex + 16) % queueSize; |
| 285 | } |
| 286 | |
| 287 | // Enqueue the packet. |
| 288 | // |
| 289 | // Wait packets aren't counted as GPU work, but we still need to enqueue |
| 290 | // them so they block future work. We encode wait packets by setting their |
| 291 | // packetTrace to null. This saves some memory as we don't need the |
| 292 | // packetTrace pointer for wait packets. |
| 293 | if (isWaitPacket) { |
| 294 | packetTrace = nullptr; |
| 295 | } |
| 296 | |
| 297 | auto queueIndex = (node->mQueueIndex + node->mQueueCount) % queueSize; |
| 298 | auto entry = &node->mQueue[queueIndex]; |
| 299 | entry->mPacketTrace = packetTrace; |
| 300 | entry->mSequenceId = sequenceId; |
| 301 | entry->mCompleted = false; |
| 302 | node->mQueueCount += 1; |
| 303 | |
| 304 | // If the queue was empty, the packet starts running right away, otherwise |
| 305 | // it is just enqueued and will start running after all previous packets |
| 306 | // complete. |
| 307 | if (packetTrace != nullptr && node->mQueueCount == 1) { |
| 308 | StartPacket(packetTrace, timestamp); |
| 309 | } |
| 310 | |
| 311 | if (IsVerboseTraceEnabled()) { |
| 312 | PrintRunningContexts(); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | bool GpuTrace::CompleteWork(Context* context, uint32_t sequenceId, uint64_t timestamp) |
| 317 | { |
nothing calls this directly
no test coverage detected