From ce8686f842f9f432e102d9703f49e7452f89eb98 Mon Sep 17 00:00:00 2001 From: Jesse Date: Sat, 6 May 2017 19:51:44 -0700 Subject: [PATCH] Move hWnd association for GPU-GDI blt model presents to token propagation instead of creation. This aligns to when DWM receives the token and decides which frame should be composed into a window, and is where similar logic already existed for composition buffer presents. This was causing PresentMon's latencies for this mode to be off by ~1 VSync for some apps. Also fixed several regressions in ETL file processing introduced by refactoring: 1. ETL file is not mutually exclusive with filename. 2. ETL files can cause the ETW thread to exit without an external signal. This was triggering asserts. When this happens, the app should exit cleanly (at least, that's how it used to behave). 3. The start time for a trace session was uninitialized and caused CSV files to have impossible "time in second" values for each frame. --- README.md | 4 ++-- source/CommandLine.cpp | 9 ++++----- source/PresentMon.cpp | 6 +++++- source/PresentMonTraceConsumer.cpp | 12 ++++++------ source/TraceSession.hpp | 1 + 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2f39d3ef..edf8e2ec 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,10 @@ SOFTWARE. ## Command line options ```html -Capture target options (use one of the following): +Capture target options: -captureall Record all processes (default). -process_name [exe name] Record specific process specified by name. -process_id [integer] Record specific process specified by ID. - -etl_file [path] Consume events from an ETL file instead of a running process. Output options: -no_csv Do not create any output file. @@ -41,6 +40,7 @@ Output options: PresentMon-PROCESSNAME-TIME.csv. Control and filtering options: + -etl_file [path] Consume events from an ETL file instead of a running process. -scroll_toggle Only record events while scroll lock is enabled. -scroll_indicator Set scroll lock while recording events. -hotkey [key] Use specified key to start and stop recording, writing to a diff --git a/source/CommandLine.cpp b/source/CommandLine.cpp index 100014ee..d2f26844 100644 --- a/source/CommandLine.cpp +++ b/source/CommandLine.cpp @@ -220,11 +220,10 @@ void PrintHelp() fprintf(stderr, "PresentMon version 1.1.0\n" "\n" - "Capture target options (use one of the following):\n" + "Capture target options:\n" " -captureall Record all processes (default).\n" " -process_name [exe name] Record specific process specified by name.\n" " -process_id [integer] Record specific process specified by ID.\n" - " -etl_file [path] Consume events from an ETL file instead of a running process.\n" "\n" "Output options:\n" " -no_csv Do not create any output file.\n" @@ -232,6 +231,7 @@ void PrintHelp() " PresentMon-PROCESSNAME-TIME.csv.\n" "\n" "Control and filtering options:\n" + " -etl_file [path] Consume events from an ETL file instead of a running process.\n" " -scroll_toggle Only record events while scroll lock is enabled.\n" " -scroll_indicator Set scroll lock while recording events.\n" " -hotkey [key] Use specified key to start and stop recording, writing to a\n" @@ -303,9 +303,8 @@ bool ParseCommandLine(int argc, char** argv, CommandLineArgs* args) // Validate command line arguments if (((args->mTargetProcessName == nullptr) ? 0 : 1) + - ((args->mTargetPid <= 0 ) ? 0 : 1) + - ((args->mEtlFileName == nullptr) ? 0 : 1) > 1) { - fprintf(stderr, "error: only specify one of -captureall, -process_name, -process_id, or -etl_file.\n"); + ((args->mTargetPid <= 0 ) ? 0 : 1) > 1) { + fprintf(stderr, "error: only specify one of -captureall, -process_name, or -process_id.\n"); PrintHelp(); return false; } diff --git a/source/PresentMon.cpp b/source/PresentMon.cpp index ff3e2653..fd87254e 100644 --- a/source/PresentMon.cpp +++ b/source/PresentMon.cpp @@ -523,7 +523,11 @@ void EtwConsumingThread(const CommandLineArgs& args) } if (doneProcessingEvents) { - assert(EtwThreadsShouldQuit()); + assert(EtwThreadsShouldQuit() || args.mEtlFileName); + if (!EtwThreadsShouldQuit()) { + PostStopRecording(); + PostQuitProcess(); + } break; } diff --git a/source/PresentMonTraceConsumer.cpp b/source/PresentMonTraceConsumer.cpp index 5c331a74..ae727aed 100644 --- a/source/PresentMonTraceConsumer.cpp +++ b/source/PresentMonTraceConsumer.cpp @@ -323,12 +323,6 @@ void PMTraceConsumer::OnDXGKrnlEvent(PEVENT_RECORD pEventRecord) CompletePresent(eventIter->second); } - if (eventIter->second->PresentMode == PresentMode::Composed_Copy_GPU_GDI) { - // Manipulate the map here - // When DWM is ready to present, we'll query for the most recent blt targeting this window and take it out of the map - mPresentByWindow[hWnd] = eventIter->second; - } - // For all other events, just remember the hWnd, we might need it later eventIter->second->Hwnd = hWnd; eventIter->second->SeenDxgkPresent = true; @@ -433,6 +427,12 @@ void PMTraceConsumer::OnDXGKrnlEvent(PEVENT_RECORD pEventRecord) mPresentsWaitingForDWM.emplace_back(eventIter->second); } + if (eventIter->second->PresentMode == PresentMode::Composed_Copy_GPU_GDI) { + // Manipulate the map here + // When DWM is ready to present, we'll query for the most recent blt targeting this window and take it out of the map + mPresentByWindow[eventIter->second->Hwnd] = eventIter->second; + } + mDxgKrnlPresentHistoryTokens.erase(eventIter); break; } diff --git a/source/TraceSession.hpp b/source/TraceSession.hpp index 9485e591..505f82f5 100644 --- a/source/TraceSession.hpp +++ b/source/TraceSession.hpp @@ -50,6 +50,7 @@ struct TraceSession { TraceSession() : sessionHandle_(0) , traceHandle_(INVALID_PROCESSTRACE_HANDLE) + , startTime_(0) , pmData_(nullptr) , pmTraceConsumer_(nullptr) {