From a138c1cf40c23830d49c3300712ef41606be40e0 Mon Sep 17 00:00:00 2001 From: Andres Rodriguez Date: Fri, 3 May 2019 17:38:21 -0400 Subject: [PATCH] Fix processing of etl gpu packets Previously I interpreted incorrectly the meaning of the QueuePacket event. The mapping that we actually want is: * QueuePacket/Info -> Received by SW scheduler * DmaPacket/Start -> Moved to the HW queue * DmaPacket/Info -> Finished processing by gpu ISR Verified by comparing against gpuview output. --- src/gpuvis_etl.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/src/gpuvis_etl.cpp b/src/gpuvis_etl.cpp index 50cee7b7..549c4f29 100644 --- a/src/gpuvis_etl.cpp +++ b/src/gpuvis_etl.cpp @@ -566,6 +566,35 @@ class queue_packet_header_entry_t : public event_entry_t } }; +class dma_packet_header_entry_t : public event_entry_t +{ +public: + void *ctx; + void *qctx; + uint32_t ptype; + uint32_t submit_seq; + uint32_t seq; + + dma_packet_header_entry_t( etl_reader_t::etl_reader_cb_data_t *cbdata ) : + event_entry_t( cbdata ) + { + int i = 0; + UCHAR opcode = cbdata->event->EventHeader.EventDescriptor.Opcode; + + ETL_EXTRACT( i++, ctx ); + + // Field only present in the start packet + if ( opcode == EVENT_TRACE_TYPE_START ) + ETL_EXTRACT( i++, qctx ); + else + qctx = nullptr; + + ETL_EXTRACT( i++, ptype ); + ETL_EXTRACT( i++, submit_seq ); + ETL_EXTRACT( i++, seq ); + } +}; + /** * Parses the ETL information stream * @@ -577,8 +606,10 @@ class etl_parser_t class __declspec( uuid( "{8F8F13B1-60EB-4B6A-A433-DE86104115AC}" ) ) kSteamVrProvider; class __declspec( uuid( "{802ec45a-1e99-4b83-9920-87c98277ba9d}" ) ) kDxcProvider; + // Get these from Microsoft-Windows-DxgKrnl.manifest.xml static const int kDxcVsyncTaskId = 10; static const int kDxcQueuePacketTaskId = 9; + static const int kDxcDmaPacketTaskId = 8; public: // Forward the callback to the right object @@ -660,6 +691,9 @@ class etl_parser_t case kDxcQueuePacketTaskId: ret = process_queue_packet_entry( cbdata ); break; + case kDxcDmaPacketTaskId: + ret = process_dma_packet_entry( cbdata ); + break; } } else @@ -875,17 +909,18 @@ class etl_parser_t switch ( opcode ) { case EVENT_TRACE_TYPE_START: + // Packet was received by the scheduler event.name = mStrPool.getstr( "amdgpu_cs_ioctl" ); // For dat compatibility event.flags = TRACE_FLAG_SW_QUEUE; break; case EVENT_TRACE_TYPE_INFO: - event.name = mStrPool.getstr( "amdgpu_sched_run_job" ); // For dat compatibility - event.flags = TRACE_FLAG_HW_QUEUE; - break; + // Begin move to HW queue? Use DmaPacket/Start instead + return 0; case EVENT_TRACE_TYPE_STOP: - event.name = mStrPool.getstr( "fence_signaled" ); // For dat compatibility - event.flags = TRACE_FLAG_FENCE_SIGNALED; - break; + // Packet is no longer in use by the driver, don't care + return 0; + default: + return 0; } err = process_event_entry( header, event ); @@ -894,12 +929,57 @@ class etl_parser_t event.system = mStrPool.getstr( "QueuePacket" ); - event.numfields = 2; + event.numfields = 3; event.fields = new event_field_t[event.numfields]; event.fields[0].key = mStrPool.getstr( "timeline" ); event.fields[0].value = mStrPool.getstr( timeline.c_str() ); event.fields[1].key = mStrPool.getstr( "context" ); event.fields[1].value = mStrPool.getstrf( "0x%xll", header.ctx ); + event.fields[ 2 ].key = mStrPool.getstr( "seq" ); + event.fields[ 2 ].value = mStrPool.getstrf( "%u", header.seq ); + event.seqno = header.seq; + + return mCallback( event ); + } + + int process_dma_packet_entry( etl_reader_t::etl_reader_cb_data_t *cbdata ) + { + int err = -1; + trace_event_t event; + dma_packet_header_entry_t header( cbdata ); + std::string timeline = "gfx"; + UCHAR opcode = cbdata->event->EventHeader.EventDescriptor.Opcode; + + switch ( opcode ) + { + case EVENT_TRACE_TYPE_START: + // Submit to the HW engine + event.name = mStrPool.getstr( "amdgpu_sched_run_job" ); // For dat compatibility + event.flags = TRACE_FLAG_HW_QUEUE; + break; + case EVENT_TRACE_TYPE_INFO: + // Finished processing by the GPU ISR + event.name = mStrPool.getstr( "fence_signaled" ); // For dat compatibility + event.flags = TRACE_FLAG_FENCE_SIGNALED; + break; + default: + return 0; + } + + err = process_event_entry( header, event ); + if ( err ) + return err; + + event.system = mStrPool.getstr( "QueuePacket" ); + + event.numfields = 3; + event.fields = new event_field_t[ event.numfields ]; + event.fields[ 0 ].key = mStrPool.getstr( "timeline" ); + event.fields[ 0 ].value = mStrPool.getstr( timeline.c_str() ); + event.fields[ 1 ].key = mStrPool.getstr( "context" ); + event.fields[ 1 ].value = mStrPool.getstrf( "0x%xll", header.ctx ); + event.fields[ 2 ].key = mStrPool.getstr( "seq" ); + event.fields[ 2 ].value = mStrPool.getstrf( "%u", header.seq ); event.seqno = header.seq; return mCallback( event );