Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions PresentData/PresentMonTraceConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,8 @@
#include <stdlib.h>
#include <unordered_set>

static constexpr int PRESENTEVENT_CIRCULAR_BUFFER_SIZE = 4096;

static uint32_t gNextFrameId = 1;

static inline uint32_t GetRingIndex(uint32_t index)
{
return index % PRESENTEVENT_CIRCULAR_BUFFER_SIZE;
}

static inline uint64_t GenerateVidPnLayerId(uint32_t vidPnSourceId, uint32_t layerIndex)
{
return (((uint64_t) vidPnSourceId) << 32) | (uint64_t) layerIndex;
Expand Down Expand Up @@ -248,6 +241,16 @@ PresentEvent::PresentEvent(uint32_t fid)
PMTraceConsumer::PMTraceConsumer()
: mTrackedPresents(PRESENTEVENT_CIRCULAR_BUFFER_SIZE)
, mCompletedPresents(PRESENTEVENT_CIRCULAR_BUFFER_SIZE)
, mCircularBufferSize(PRESENTEVENT_CIRCULAR_BUFFER_SIZE)
, mGpuTrace(this)
{
hEventsReadyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
}

PMTraceConsumer::PMTraceConsumer(uint32_t circularBufferSize)
: mTrackedPresents(circularBufferSize)
, mCompletedPresents(circularBufferSize)
, mCircularBufferSize(circularBufferSize)
, mGpuTrace(this)
{
hEventsReadyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
Expand Down Expand Up @@ -2210,11 +2213,11 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr<PresentEvent> const& p)
if (present != nullptr) {
uint32_t index;
// if completed buffer is full
if (mCompletedCount == PRESENTEVENT_CIRCULAR_BUFFER_SIZE) {
if (mCompletedCount == mCircularBufferSize) {
// if we are in offline ETL processing mode, block instead of overwriting events
// unless either A) the buffer is full of non-ready events or B) backpressure disabled via CLI option
if (!mIsRealtimeSession && mReadyCount != 0 && !mDisableOfflineBackpressure) {
mCompletedRingCondition.wait(lock, [this] { return mCompletedCount < PRESENTEVENT_CIRCULAR_BUFFER_SIZE; });
mCompletedRingCondition.wait(lock, [this] { return mCompletedCount < mCircularBufferSize; });
index = GetRingIndex(mCompletedIndex + mCompletedCount);
mCompletedCount++;
}
Expand All @@ -2230,6 +2233,7 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr<PresentEvent> const& p)
if (mReadyCount > 0) {
mReadyCount--;
}
mNumOverflowedPresents++;
}
// otherwise, completed buffer still has available space
}
Expand Down
11 changes: 11 additions & 0 deletions PresentData/PresentMonTraceConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ struct PresentEvent {

struct PMTraceConsumer
{
static constexpr int PRESENTEVENT_CIRCULAR_BUFFER_SIZE = 2048;

// -------------------------------------------------------------------------------------------
// The following are parameters to the analysis, which can be configured prior to starting the
// trace session.
Expand Down Expand Up @@ -353,6 +355,8 @@ struct PMTraceConsumer
uint32_t mCompletedIndex = 0; // The index of mCompletedPresents of the oldest completed present.
uint32_t mCompletedCount = 0; // The total number of presents in mCompletedPresents.
uint32_t mReadyCount = 0; // The number of presents in mCompletedPresents, starting at mCompletedIndex, that are ready to be dequeued.
uint32_t mNumOverflowedPresents = 0; // The number of presents that have been lost due to the ring buffer wrapping.
uint32_t mCircularBufferSize = 0; // The size of the ring buffers for presents.

// Mutexs to protect consumer/dequeue access from different threads:
std::mutex mProcessEventMutex;
Expand Down Expand Up @@ -505,6 +509,7 @@ struct PMTraceConsumer
// Functions for decoding ETW and analysing process and present events.

PMTraceConsumer();
PMTraceConsumer(uint32_t circularBufferSize);
~PMTraceConsumer();

PMTraceConsumer(const PMTraceConsumer&) = delete;
Expand Down Expand Up @@ -566,4 +571,10 @@ struct PMTraceConsumer
AppTimingData* ExtractAppTimingData(uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime);
bool IsApplicationPresent(std::shared_ptr<PresentEvent> const& present);
void SetAppTimingDataAsComplete(uint32_t processId, uint32_t appFrameId);

inline uint32_t GetRingIndex(uint32_t index)
{
return index % mCircularBufferSize;
}

};
11 changes: 11 additions & 0 deletions PresentMon/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ void PrintUsage()
LR"(--track_hw_measurements)", LR"(Tracks HW-measured latency and/or power data coming from a LMT and/or PCAT device.)",
LR"(--track_app_timing)", LR"(Track app times for each displayed frame; requires application and/or driver instrumentation using Intel-PresentMon provider.)",
LR"(--track_hybrid_present)", LR"(Tracks if the present is a hybrid present and is performing a cross adapter copy.)",
LR"(--set_circular_buffer_size)", LR"(Overide the default present event circular buffer size of 2048. Must be a power of 2.)",
};

// Layout
Expand Down Expand Up @@ -384,6 +385,7 @@ bool ParseCommandLine(int argc, wchar_t** argv)
args->mTimer = 0;
args->mHotkeyModifiers = MOD_NOREPEAT;
args->mHotkeyVirtualKeyCode = 0;
args->mPresentEventCircularBufferSize = 0;
args->mConsoleOutput = ConsoleOutput::Statistics;
args->mTrackDisplay = true;
args->mTrackInput = true;
Expand Down Expand Up @@ -460,6 +462,7 @@ bool ParseCommandLine(int argc, wchar_t** argv)
else if (ParseArg(argv[i], L"restart_as_admin")) { args->mTryToElevate = true; continue; }
else if (ParseArg(argv[i], L"terminate_on_proc_exit")) { args->mTerminateOnProcExit = true; continue; }
else if (ParseArg(argv[i], L"terminate_after_timed")) { args->mTerminateAfterTimer = true; continue; }
else if (ParseArg(argv[i], L"set_circular_buffer_size")) { if (ParseValue(argv, argc, &i, &args->mPresentEventCircularBufferSize)) { continue; } }

// Beta options:
else if (ParseArg(argv[i], L"track_frame_type")) { args->mTrackFrameType = true; continue; }
Expand Down Expand Up @@ -507,6 +510,14 @@ bool ParseCommandLine(int argc, wchar_t** argv)
return false;
}

// Disallow a circular buffer size that is not a power of 2.
if (args->mPresentEventCircularBufferSize != 0) {
if ((args->mPresentEventCircularBufferSize & (args->mPresentEventCircularBufferSize - 1)) != 0) {
PrintError(L"error: --set_circular_buffer_size must be a power of 2.\n");
return false;
}
}

// Ensure only one of --output_file --output_stdout --no_csv.
if (csvOutputNone + csvOutputStdout + (args->mOutputCsvFileName != nullptr) > 1) {
PrintWarning(L"warning: only one of the following options may be used:");
Expand Down
14 changes: 13 additions & 1 deletion PresentMon/MainThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,11 @@ int wmain(int argc, wchar_t** argv)
SetConsoleCtrlHandler(HandleCtrlEvent, TRUE);

// Create event consumers
PMTraceConsumer pmConsumer;
PMTraceConsumer pmConsumer(
args.mPresentEventCircularBufferSize != 0
? args.mPresentEventCircularBufferSize
: PMTraceConsumer::PRESENTEVENT_CIRCULAR_BUFFER_SIZE);

pmConsumer.mTrackDisplay = args.mTrackDisplay;
pmConsumer.mTrackGPU = args.mTrackGPU;
pmConsumer.mTrackGPUVideo = args.mTrackGPUVideo;
Expand Down Expand Up @@ -383,6 +387,14 @@ int wmain(int argc, wchar_t** argv)
if (pmSession.mNumEventsLost > 0) {
PrintWarning(L"warning: %lu ETW events were lost.\n", pmSession.mNumEventsLost);
}
if (pmConsumer.mNumOverflowedPresents > 0) {
PrintWarning(L"warning: %lu overflowed present events detected. This could be due to a high-fps application.\n",
pmConsumer.mNumOverflowedPresents);
PrintWarning(L" Consider increasing the present event circular buffer size to a value larger\n");
PrintWarning(L" than the default of 2048, e.g., --set_circular_buffer_size 4096.\n");


}

/* We cannot remove the Ctrl handler because it is in an infinite sleep so
* this call will never return, either hanging the application or having
Expand Down
1 change: 1 addition & 0 deletions PresentMon/PresentMon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct CommandLineArgs {
UINT mTimer;
UINT mHotkeyModifiers;
UINT mHotkeyVirtualKeyCode;
UINT mPresentEventCircularBufferSize;
TimeUnit mTimeUnit;
CSVOutput mCSVOutput;
ConsoleOutput mConsoleOutput;
Expand Down