duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

PIXEvents.h (22461B)


      1 // Copyright (c) Microsoft Corporation. All rights reserved.
      2 
      3 /*==========================================================================;
      4  *
      5  *  Copyright (C) Microsoft Corporation.  All Rights Reserved.
      6  *
      7  *  File:       PIXEvents.h
      8  *  Content:    PIX include file
      9  *              Don't include this file directly - use pix3.h
     10  *
     11  ****************************************************************************/
     12 #pragma once
     13 
     14 #ifndef _PixEvents_H_
     15 #define _PixEvents_H_
     16 
     17 #ifndef _PIX3_H_
     18 # error Do not include this file directly - use pix3.h
     19 #endif
     20 
     21 #include "PIXEventsCommon.h"
     22 
     23 #if _MSC_VER < 1800
     24 # error This version of pix3.h is only supported on Visual Studio 2013 or higher
     25 #elif _MSC_VER < 1900
     26 # ifndef constexpr // Visual Studio 2013 doesn't support constexpr
     27 #  define constexpr
     28 #  define PIX3__DEFINED_CONSTEXPR
     29 # endif
     30 #endif
     31 
     32 // Xbox does not support CPU events for retail scenarios
     33 #if defined(USE_PIX) || !defined(PIX_XBOX)
     34 #define PIX_CONTEXT_EMIT_CPU_EVENTS
     35 #endif
     36 
     37 namespace PIXEventsDetail
     38 {
     39     template<typename... ARGS>
     40     struct PIXEventTypeInferer
     41     {
     42         static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_VarArgs; }
     43         static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_VarArgs; }
     44         static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
     45         static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
     46 
     47         // Xbox and Windows store different types of events for context events.
     48         // On Xbox these include a context argument, while on Windows they do
     49         // not. It is important not to change the event types used on the
     50         // Windows version as there are OS components (eg debug layer & DRED)
     51         // that decode event structs.
     52 #ifdef PIX_XBOX
     53         static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
     54         static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
     55 #else
     56         static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; }
     57         static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; }
     58 #endif
     59     };
     60 
     61     template<>
     62     struct PIXEventTypeInferer<>
     63     {
     64         static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_NoArgs; }
     65         static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_NoArgs; }
     66         static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
     67         static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
     68 
     69 #ifdef PIX_XBOX
     70         static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
     71         static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
     72 #else
     73         static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; }
     74         static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; }
     75 #endif
     76     };
     77 
     78     inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
     79     {
     80         // nothing
     81         UNREFERENCED_PARAMETER(destination);
     82         UNREFERENCED_PARAMETER(limit);
     83     }
     84 
     85     template<typename ARG, typename... ARGS>
     86     void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args)
     87     {
     88         PIXCopyEventArgument(destination, limit, arg);
     89         PIXCopyEventArguments(destination, limit, args...);
     90     }
     91 
     92     template<typename STR, typename... ARGS>
     93     __declspec(noinline) void PIXBeginEventAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
     94     {
     95 #ifdef PIX_XBOX
     96         UINT64 time = PIXEventsReplaceBlock(false);
     97 #else
     98         UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
     99 #endif
    100         if (!time)
    101             return;
    102 
    103         UINT64* destination = threadInfo->destination;
    104         UINT64* limit = threadInfo->biasedLimit;
    105         if (destination >= limit)
    106             return;
    107 
    108         limit += PIXEventsSafeFastCopySpaceQwords;
    109         *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::Begin());
    110         *destination++ = color;
    111 
    112         PIXCopyEventArguments(destination, limit, formatString, args...);
    113 
    114         *destination = PIXEventsBlockEndMarker;
    115         threadInfo->destination = destination;
    116     }
    117 
    118     template<typename STR, typename... ARGS>
    119     void PIXBeginEvent(UINT64 color, STR formatString, ARGS... args)
    120     {
    121         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    122         UINT64* limit = threadInfo->biasedLimit;
    123         if (limit != nullptr)
    124         {
    125             UINT64* destination = threadInfo->destination;
    126             if (destination < limit)
    127             {
    128                 limit += PIXEventsSafeFastCopySpaceQwords;
    129                 UINT64 time = PIXGetTimestampCounter();
    130                 *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::Begin());
    131                 *destination++ = color;
    132 
    133                 PIXCopyEventArguments(destination, limit, formatString, args...);
    134 
    135                 *destination = PIXEventsBlockEndMarker;
    136                 threadInfo->destination = destination;
    137             }
    138             else
    139             {
    140                 PIXBeginEventAllocate(threadInfo, color, formatString, args...);
    141             }
    142         }
    143     }
    144 
    145     template<typename STR, typename... ARGS>
    146     __declspec(noinline) void PIXSetMarkerAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
    147     {
    148 #ifdef PIX_XBOX
    149         UINT64 time = PIXEventsReplaceBlock(false);
    150 #else
    151         UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
    152 #endif
    153         if (!time)
    154             return;
    155 
    156         UINT64* destination = threadInfo->destination;
    157         UINT64* limit = threadInfo->biasedLimit;
    158 
    159         if (destination >= limit)
    160             return;
    161 
    162         limit += PIXEventsSafeFastCopySpaceQwords;
    163         *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::SetMarker());
    164         *destination++ = color;
    165 
    166         PIXCopyEventArguments(destination, limit, formatString, args...);
    167 
    168         *destination = PIXEventsBlockEndMarker;
    169         threadInfo->destination = destination;
    170     }
    171 
    172     template<typename STR, typename... ARGS>
    173     void PIXSetMarker(UINT64 color, STR formatString, ARGS... args)
    174     {
    175         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    176         UINT64* limit = threadInfo->biasedLimit;
    177         if (limit != nullptr)
    178         {
    179             UINT64* destination = threadInfo->destination;
    180             if (destination < limit)
    181             {
    182                 limit += PIXEventsSafeFastCopySpaceQwords;
    183                 UINT64 time = PIXGetTimestampCounter();
    184                 *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::SetMarker());
    185                 *destination++ = color;
    186 
    187                 PIXCopyEventArguments(destination, limit, formatString, args...);
    188 
    189                 *destination = PIXEventsBlockEndMarker;
    190                 threadInfo->destination = destination;
    191             }
    192             else
    193             {
    194                 PIXSetMarkerAllocate(threadInfo, color, formatString, args...);
    195             }
    196         }
    197     }
    198 
    199     template<typename STR, typename... ARGS>
    200     __declspec(noinline) void PIXBeginEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
    201     {
    202 #ifdef PIX_XBOX
    203         UINT64 time = PIXEventsReplaceBlock(false);
    204 #else
    205         UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
    206 #endif
    207         if (!time)
    208             return;
    209 
    210         UINT64* destination = threadInfo->destination;
    211         UINT64* limit = threadInfo->biasedLimit;
    212 
    213         if (destination >= limit)
    214             return;
    215 
    216         limit += PIXEventsSafeFastCopySpaceQwords;
    217         *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::BeginOnContext());
    218         *destination++ = color;
    219 
    220 #ifdef PIX_XBOX
    221         UNREFERENCED_PARAMETER(context);
    222         PIXCopyEventArguments(destination, limit, formatString, args...);
    223 #else
    224         PIXCopyEventArguments(destination, limit, context, formatString, args...);
    225 #endif
    226 
    227         *destination = PIXEventsBlockEndMarker;
    228         threadInfo->destination = destination;
    229     }
    230 
    231     template<typename STR, typename... ARGS>
    232     void PIXBeginEventOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args)
    233     {
    234         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    235         UINT64* limit = threadInfo->biasedLimit;
    236         if (limit != nullptr)
    237         {
    238             UINT64* destination = threadInfo->destination;
    239             if (destination < limit)
    240             {
    241                 limit += PIXEventsSafeFastCopySpaceQwords;
    242                 UINT64 time = PIXGetTimestampCounter();
    243                 *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::BeginOnContext());
    244                 *destination++ = color;
    245 
    246 #ifdef PIX_XBOX
    247                 PIXCopyEventArguments(destination, limit, formatString, args...);
    248 #else
    249                 PIXCopyEventArguments(destination, limit, context, formatString, args...);
    250 #endif
    251 
    252                 *destination = PIXEventsBlockEndMarker;
    253                 threadInfo->destination = destination;
    254             }
    255             else
    256             {
    257                 PIXBeginEventOnContextCpuAllocate(threadInfo, context, color, formatString, args...);
    258             }
    259         }
    260     }
    261 
    262     template<typename CONTEXT, typename STR, typename... ARGS>
    263     void PIXBeginEvent(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
    264     {
    265 #ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
    266         PIXBeginEventOnContextCpu(context, color, formatString, args...);
    267 #endif
    268 
    269         // TODO: we've already encoded this once for the CPU event - figure out way to avoid doing it again
    270         UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
    271         UINT64* destination = buffer;
    272         UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
    273 
    274         *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuBeginOnContext());
    275         *destination++ = color;
    276 
    277         PIXCopyEventArguments(destination, limit, formatString, args...);
    278         *destination = 0ull;
    279 
    280         PIXBeginGPUEventOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
    281     }
    282 
    283     template<typename STR, typename... ARGS>
    284     __declspec(noinline) void PIXSetMarkerOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
    285     {
    286 #ifdef PIX_XBOX
    287         UINT64 time = PIXEventsReplaceBlock(false);
    288 #else
    289         UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
    290 #endif
    291         if (!time)
    292             return;
    293 
    294         UINT64* destination = threadInfo->destination;
    295         UINT64* limit = threadInfo->biasedLimit;
    296 
    297         if (destination >= limit)
    298             return;
    299 
    300         limit += PIXEventsSafeFastCopySpaceQwords;
    301         *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::SetMarkerOnContext());
    302         *destination++ = color;
    303 
    304 #ifdef PIX_XBOX
    305         UNREFERENCED_PARAMETER(context);
    306         PIXCopyEventArguments(destination, limit, formatString, args...);
    307 #else
    308         PIXCopyEventArguments(destination, limit, context, formatString, args...);
    309 #endif
    310 
    311         *destination = PIXEventsBlockEndMarker;
    312         threadInfo->destination = destination;
    313     }
    314 
    315     template<typename STR, typename... ARGS>
    316     void PIXSetMarkerOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args)
    317     {
    318         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    319         UINT64* limit = threadInfo->biasedLimit;
    320         if (limit != nullptr)
    321         {
    322             UINT64* destination = threadInfo->destination;
    323             if (destination < limit)
    324             {
    325                 limit += PIXEventsSafeFastCopySpaceQwords;
    326                 UINT64 time = PIXGetTimestampCounter();
    327                 *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer<ARGS...>::SetMarkerOnContext());
    328                 *destination++ = color;
    329 
    330 #ifdef PIX_XBOX
    331                 PIXCopyEventArguments(destination, limit, formatString, args...);
    332 #else
    333                 PIXCopyEventArguments(destination, limit, context, formatString, args...);
    334 #endif
    335 
    336                 *destination = PIXEventsBlockEndMarker;
    337                 threadInfo->destination = destination;
    338             }
    339             else
    340             {
    341                 PIXSetMarkerOnContextCpuAllocate(threadInfo, context, color, formatString, args...);
    342             }
    343         }
    344     }
    345 
    346     template<typename CONTEXT, typename STR, typename... ARGS>
    347     void PIXSetMarker(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
    348     {
    349 #ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
    350         PIXSetMarkerOnContextCpu(context, color, formatString, args...);
    351 #endif
    352 
    353         UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
    354         UINT64* destination = buffer;
    355         UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
    356 
    357         *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuSetMarkerOnContext());
    358         *destination++ = color;
    359 
    360         PIXCopyEventArguments(destination, limit, formatString, args...);
    361         *destination = 0ull;
    362 
    363         PIXSetGPUMarkerOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
    364     }
    365 
    366     __declspec(noinline) inline void PIXEndEventAllocate(PIXEventsThreadInfo* threadInfo)
    367     {
    368 #ifdef PIX_XBOX
    369         UINT64 time = PIXEventsReplaceBlock(true);
    370 #else
    371         UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
    372 #endif
    373         if (!time)
    374             return;
    375 
    376         UINT64* destination = threadInfo->destination;
    377         UINT64* limit = threadInfo->biasedLimit;
    378 
    379         if (destination >= limit)
    380             return;
    381 
    382         limit += PIXEventsSafeFastCopySpaceQwords;
    383         *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent);
    384         *destination = PIXEventsBlockEndMarker;
    385         threadInfo->destination = destination;
    386     }
    387 
    388     inline void PIXEndEvent()
    389     {
    390         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    391         UINT64* limit = threadInfo->biasedLimit;
    392         if (limit != nullptr)
    393         {
    394             UINT64* destination = threadInfo->destination;
    395             if (destination < limit)
    396             {
    397                 limit += PIXEventsSafeFastCopySpaceQwords;
    398                 UINT64 time = PIXGetTimestampCounter();
    399                 *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent);
    400                 *destination = PIXEventsBlockEndMarker;
    401                 threadInfo->destination = destination;
    402             }
    403             else
    404             {
    405                 PIXEndEventAllocate(threadInfo);
    406             }
    407         }
    408     }
    409 
    410     __declspec(noinline) inline void PIXEndEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context)
    411     {
    412 #ifdef PIX_XBOX
    413         UINT64 time = PIXEventsReplaceBlock(true);
    414 #else
    415         UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
    416 #endif
    417         if (!time)
    418             return;
    419 
    420         UINT64* destination = threadInfo->destination;
    421         UINT64* limit = threadInfo->biasedLimit;
    422 
    423         if (destination >= limit)
    424             return;
    425 
    426         limit += PIXEventsSafeFastCopySpaceQwords;
    427         *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext);
    428 #ifdef PIX_XBOX
    429         UNREFERENCED_PARAMETER(context);
    430 #else
    431         PIXCopyEventArgument(destination, limit, context);
    432 #endif
    433         *destination = PIXEventsBlockEndMarker;
    434         threadInfo->destination = destination;
    435     }
    436 
    437     inline void PIXEndEventOnContextCpu(void* context)
    438     {
    439         PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
    440         UINT64* limit = threadInfo->biasedLimit;
    441         if (limit != nullptr)
    442         {
    443             UINT64* destination = threadInfo->destination;
    444             if (destination < limit)
    445             {
    446                 limit += PIXEventsSafeFastCopySpaceQwords;
    447                 UINT64 time = PIXGetTimestampCounter();
    448                 *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext);
    449 #ifndef PIX_XBOX
    450                 PIXCopyEventArgument(destination, limit, context);
    451 #endif
    452                 *destination = PIXEventsBlockEndMarker;
    453                 threadInfo->destination = destination;
    454             }
    455             else
    456             {
    457                 PIXEndEventOnContextCpuAllocate(threadInfo, context);
    458             }
    459         }
    460     }
    461 
    462     template<typename CONTEXT>
    463     void PIXEndEvent(CONTEXT* context)
    464     {
    465 #ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
    466         PIXEndEventOnContextCpu(context);
    467 #endif
    468         PIXEndGPUEventOnContext(context);
    469     }
    470 }
    471 
    472 #if defined(USE_PIX)
    473 
    474 template<typename... ARGS>
    475 void PIXBeginEvent(UINT64 color, PCWSTR formatString, ARGS... args)
    476 {
    477     PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
    478 }
    479 
    480 template<typename... ARGS>
    481 void PIXBeginEvent(UINT64 color, PCSTR formatString, ARGS... args)
    482 {
    483     PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
    484 }
    485 
    486 template<typename... ARGS>
    487 void PIXSetMarker(UINT64 color, PCWSTR formatString, ARGS... args)
    488 {
    489     PIXEventsDetail::PIXSetMarker(color, formatString, args...);
    490 }
    491 
    492 template<typename... ARGS>
    493 void PIXSetMarker(UINT64 color, PCSTR formatString, ARGS... args)
    494 {
    495     PIXEventsDetail::PIXSetMarker(color, formatString, args...);
    496 }
    497 
    498 template<typename CONTEXT, typename... ARGS>
    499 void PIXBeginEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    500 {
    501     PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
    502 }
    503 
    504 template<typename CONTEXT, typename... ARGS>
    505 void PIXBeginEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    506 {
    507     PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
    508 }
    509 
    510 template<typename CONTEXT, typename... ARGS>
    511 void PIXSetMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    512 {
    513     PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
    514 }
    515 
    516 template<typename CONTEXT, typename... ARGS>
    517 void PIXSetMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    518 {
    519     PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
    520 }
    521 
    522 inline void PIXEndEvent()
    523 {
    524     PIXEventsDetail::PIXEndEvent();
    525 }
    526 
    527 template<typename CONTEXT>
    528 void PIXEndEvent(CONTEXT* context)
    529 {
    530     PIXEventsDetail::PIXEndEvent(context);
    531 }
    532 
    533 #else // USE_PIX_RETAIL
    534 
    535 inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {}
    536 inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {}
    537 inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {}
    538 inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {}
    539 inline void PIXEndEvent() {}
    540 inline void PIXEndEvent(void*) {}
    541 inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {}
    542 inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {}
    543 inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {}
    544 inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {}
    545 
    546 #endif // USE_PIX
    547 
    548 template<typename CONTEXT, typename... ARGS>
    549 void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    550 {
    551     PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
    552 }
    553 
    554 template<typename CONTEXT, typename... ARGS>
    555 void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    556 {
    557     PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
    558 }
    559 
    560 template<typename CONTEXT, typename... ARGS>
    561 void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    562 {
    563     PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
    564 }
    565 
    566 template<typename CONTEXT, typename... ARGS>
    567 void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    568 {
    569     PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
    570 }
    571 
    572 template<typename CONTEXT>
    573 void PIXEndRetailEvent(CONTEXT* context)
    574 {
    575     PIXEventsDetail::PIXEndEvent(context);
    576 }
    577 
    578 template<typename CONTEXT>
    579 class PIXScopedEventObject
    580 {
    581     CONTEXT* m_context;
    582 
    583 public:
    584     template<typename... ARGS>
    585     PIXScopedEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    586         : m_context(context)
    587     {
    588         PIXBeginEvent(m_context, color, formatString, args...);
    589     }
    590 
    591     template<typename... ARGS>
    592     PIXScopedEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    593         : m_context(context)
    594     {
    595         PIXBeginEvent(m_context, color, formatString, args...);
    596     }
    597 
    598     ~PIXScopedEventObject()
    599     {
    600         PIXEndEvent(m_context);
    601     }
    602 };
    603 
    604 template<typename CONTEXT>
    605 class PIXScopedRetailEventObject
    606 {
    607     CONTEXT* m_context;
    608 
    609 public:
    610     template<typename... ARGS>
    611     PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
    612         : m_context(context)
    613     {
    614         PIXBeginRetailEvent(m_context, color, formatString, args...);
    615     }
    616 
    617     template<typename... ARGS>
    618     PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
    619         : m_context(context)
    620     {
    621         PIXBeginRetailEvent(m_context, color, formatString, args...);
    622     }
    623 
    624     ~PIXScopedRetailEventObject()
    625     {
    626         PIXEndRetailEvent(m_context);
    627     }
    628 };
    629 
    630 template<>
    631 class PIXScopedEventObject<void>
    632 {
    633 public:
    634     template<typename... ARGS>
    635     PIXScopedEventObject(UINT64 color, PCWSTR formatString, ARGS... args)
    636     {
    637         PIXBeginEvent(color, formatString, args...);
    638     }
    639 
    640     template<typename... ARGS>
    641     PIXScopedEventObject(UINT64 color, PCSTR formatString, ARGS... args)
    642     {
    643         PIXBeginEvent(color, formatString, args...);
    644     }
    645 
    646     ~PIXScopedEventObject()
    647     {
    648         PIXEndEvent();
    649     }
    650 };
    651 
    652 #define PIXConcatenate(a, b) a ## b
    653 #define PIXGetScopedEventVariableName(a, b) PIXConcatenate(a, b)
    654 #define PIXScopedEvent(context, ...) PIXScopedEventObject<PIXInferScopedEventType<decltype(context)>::Type> PIXGetScopedEventVariableName(pixEvent, __LINE__)(context, __VA_ARGS__)
    655 
    656 #ifdef PIX3__DEFINED_CONSTEXPR
    657 #undef constexpr
    658 #undef PIX3__DEFINED_CONSTEXPR
    659 #endif
    660 
    661 #endif // _PIXEvents_H__