summaryrefslogtreecommitdiffstats
path: root/external/optick/optick.h
diff options
context:
space:
mode:
Diffstat (limited to 'external/optick/optick.h')
-rw-r--r--external/optick/optick.h872
1 files changed, 872 insertions, 0 deletions
diff --git a/external/optick/optick.h b/external/optick/optick.h
new file mode 100644
index 0000000..e3eb512
--- /dev/null
+++ b/external/optick/optick.h
@@ -0,0 +1,872 @@
+#pragma once
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Config
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#include "optick.config.h"
+
+#if USE_OPTICK
+#include <stdint.h>
+
+#if defined(__clang__) || defined(__GNUC__)
+# define OPTICK_GCC (1)
+# if defined(__APPLE_CC__)
+# define OPTICK_OSX (1)
+# elif defined(__linux__)
+# define OPTICK_LINUX (1)
+# elif defined(__ORBIS__)
+# define OPTICK_PS4 (1)
+# endif
+#elif defined(_MSC_VER)
+# define OPTICK_MSVC (1)
+# if defined(_DURANGO)
+# define OPTICK_XBOX (1)
+# else
+# define OPTICK_PC (1)
+#endif
+#else
+#error Compiler not supported
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// Target Platform
+////////////////////////////////////////////////////////////////////////
+
+#if defined(OPTICK_GCC)
+#define OPTICK_FUNC __PRETTY_FUNCTION__
+#elif defined(OPTICK_MSVC)
+#define OPTICK_FUNC __FUNCSIG__
+#else
+#error Compiler not supported
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// EXPORTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef OPTICK_EXPORTS
+#define OPTICK_API __declspec(dllexport)
+#else
+#define OPTICK_API //__declspec(dllimport)
+#endif
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#define OPTICK_CONCAT_IMPL(x, y) x##y
+#define OPTICK_CONCAT(x, y) OPTICK_CONCAT_IMPL(x, y)
+
+#if defined(OPTICK_MSVC)
+#define OPTICK_INLINE __forceinline
+#elif defined(OPTICK_GCC)
+#define OPTICK_INLINE __attribute__((always_inline)) inline
+#else
+#error Compiler is not supported
+#endif
+
+
+// Vulkan Forward Declarations
+#define OPTICK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+OPTICK_DEFINE_HANDLE(VkDevice);
+OPTICK_DEFINE_HANDLE(VkPhysicalDevice);
+OPTICK_DEFINE_HANDLE(VkQueue);
+OPTICK_DEFINE_HANDLE(VkCommandBuffer);
+
+// D3D12 Forward Declarations
+struct ID3D12CommandList;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+namespace Optick
+{
+ // Source: http://msdn.microsoft.com/en-us/library/system.windows.media.colors(v=vs.110).aspx
+ // Image: http://i.msdn.microsoft.com/dynimg/IC24340.png
+ struct Color
+ {
+ enum
+ {
+ Null = 0x00000000,
+ AliceBlue = 0xFFF0F8FF,
+ AntiqueWhite = 0xFFFAEBD7,
+ Aqua = 0xFF00FFFF,
+ Aquamarine = 0xFF7FFFD4,
+ Azure = 0xFFF0FFFF,
+ Beige = 0xFFF5F5DC,
+ Bisque = 0xFFFFE4C4,
+ Black = 0xFF000000,
+ BlanchedAlmond = 0xFFFFEBCD,
+ Blue = 0xFF0000FF,
+ BlueViolet = 0xFF8A2BE2,
+ Brown = 0xFFA52A2A,
+ BurlyWood = 0xFFDEB887,
+ CadetBlue = 0xFF5F9EA0,
+ Chartreuse = 0xFF7FFF00,
+ Chocolate = 0xFFD2691E,
+ Coral = 0xFFFF7F50,
+ CornflowerBlue = 0xFF6495ED,
+ Cornsilk = 0xFFFFF8DC,
+ Crimson = 0xFFDC143C,
+ Cyan = 0xFF00FFFF,
+ DarkBlue = 0xFF00008B,
+ DarkCyan = 0xFF008B8B,
+ DarkGoldenRod = 0xFFB8860B,
+ DarkGray = 0xFFA9A9A9,
+ DarkGreen = 0xFF006400,
+ DarkKhaki = 0xFFBDB76B,
+ DarkMagenta = 0xFF8B008B,
+ DarkOliveGreen = 0xFF556B2F,
+ DarkOrange = 0xFFFF8C00,
+ DarkOrchid = 0xFF9932CC,
+ DarkRed = 0xFF8B0000,
+ DarkSalmon = 0xFFE9967A,
+ DarkSeaGreen = 0xFF8FBC8F,
+ DarkSlateBlue = 0xFF483D8B,
+ DarkSlateGray = 0xFF2F4F4F,
+ DarkTurquoise = 0xFF00CED1,
+ DarkViolet = 0xFF9400D3,
+ DeepPink = 0xFFFF1493,
+ DeepSkyBlue = 0xFF00BFFF,
+ DimGray = 0xFF696969,
+ DodgerBlue = 0xFF1E90FF,
+ FireBrick = 0xFFB22222,
+ FloralWhite = 0xFFFFFAF0,
+ ForestGreen = 0xFF228B22,
+ Fuchsia = 0xFFFF00FF,
+ Gainsboro = 0xFFDCDCDC,
+ GhostWhite = 0xFFF8F8FF,
+ Gold = 0xFFFFD700,
+ GoldenRod = 0xFFDAA520,
+ Gray = 0xFF808080,
+ Green = 0xFF008000,
+ GreenYellow = 0xFFADFF2F,
+ HoneyDew = 0xFFF0FFF0,
+ HotPink = 0xFFFF69B4,
+ IndianRed = 0xFFCD5C5C,
+ Indigo = 0xFF4B0082,
+ Ivory = 0xFFFFFFF0,
+ Khaki = 0xFFF0E68C,
+ Lavender = 0xFFE6E6FA,
+ LavenderBlush = 0xFFFFF0F5,
+ LawnGreen = 0xFF7CFC00,
+ LemonChiffon = 0xFFFFFACD,
+ LightBlue = 0xFFADD8E6,
+ LightCoral = 0xFFF08080,
+ LightCyan = 0xFFE0FFFF,
+ LightGoldenRodYellow = 0xFFFAFAD2,
+ LightGray = 0xFFD3D3D3,
+ LightGreen = 0xFF90EE90,
+ LightPink = 0xFFFFB6C1,
+ LightSalmon = 0xFFFFA07A,
+ LightSeaGreen = 0xFF20B2AA,
+ LightSkyBlue = 0xFF87CEFA,
+ LightSlateGray = 0xFF778899,
+ LightSteelBlue = 0xFFB0C4DE,
+ LightYellow = 0xFFFFFFE0,
+ Lime = 0xFF00FF00,
+ LimeGreen = 0xFF32CD32,
+ Linen = 0xFFFAF0E6,
+ Magenta = 0xFFFF00FF,
+ Maroon = 0xFF800000,
+ MediumAquaMarine = 0xFF66CDAA,
+ MediumBlue = 0xFF0000CD,
+ MediumOrchid = 0xFFBA55D3,
+ MediumPurple = 0xFF9370DB,
+ MediumSeaGreen = 0xFF3CB371,
+ MediumSlateBlue = 0xFF7B68EE,
+ MediumSpringGreen = 0xFF00FA9A,
+ MediumTurquoise = 0xFF48D1CC,
+ MediumVioletRed = 0xFFC71585,
+ MidnightBlue = 0xFF191970,
+ MintCream = 0xFFF5FFFA,
+ MistyRose = 0xFFFFE4E1,
+ Moccasin = 0xFFFFE4B5,
+ NavajoWhite = 0xFFFFDEAD,
+ Navy = 0xFF000080,
+ OldLace = 0xFFFDF5E6,
+ Olive = 0xFF808000,
+ OliveDrab = 0xFF6B8E23,
+ Orange = 0xFFFFA500,
+ OrangeRed = 0xFFFF4500,
+ Orchid = 0xFFDA70D6,
+ PaleGoldenRod = 0xFFEEE8AA,
+ PaleGreen = 0xFF98FB98,
+ PaleTurquoise = 0xFFAFEEEE,
+ PaleVioletRed = 0xFFDB7093,
+ PapayaWhip = 0xFFFFEFD5,
+ PeachPuff = 0xFFFFDAB9,
+ Peru = 0xFFCD853F,
+ Pink = 0xFFFFC0CB,
+ Plum = 0xFFDDA0DD,
+ PowderBlue = 0xFFB0E0E6,
+ Purple = 0xFF800080,
+ Red = 0xFFFF0000,
+ RosyBrown = 0xFFBC8F8F,
+ RoyalBlue = 0xFF4169E1,
+ SaddleBrown = 0xFF8B4513,
+ Salmon = 0xFFFA8072,
+ SandyBrown = 0xFFF4A460,
+ SeaGreen = 0xFF2E8B57,
+ SeaShell = 0xFFFFF5EE,
+ Sienna = 0xFFA0522D,
+ Silver = 0xFFC0C0C0,
+ SkyBlue = 0xFF87CEEB,
+ SlateBlue = 0xFF6A5ACD,
+ SlateGray = 0xFF708090,
+ Snow = 0xFFFFFAFA,
+ SpringGreen = 0xFF00FF7F,
+ SteelBlue = 0xFF4682B4,
+ Tan = 0xFFD2B48C,
+ Teal = 0xFF008080,
+ Thistle = 0xFFD8BFD8,
+ Tomato = 0xFFFF6347,
+ Turquoise = 0xFF40E0D0,
+ Violet = 0xFFEE82EE,
+ Wheat = 0xFFF5DEB3,
+ White = 0xFFFFFFFF,
+ WhiteSmoke = 0xFFF5F5F5,
+ Yellow = 0xFFFFFF00,
+ YellowGreen = 0xFF9ACD32,
+ };
+ };
+
+ struct Filter
+ {
+ enum Type : uint32_t
+ {
+ None,
+
+ // CPU
+ AI,
+ Animation,
+ Audio,
+ Debug,
+ Camera,
+ Cloth,
+ GameLogic,
+ Input,
+ Navigation,
+ Network,
+ Physics,
+ Rendering,
+ Scene,
+ Script,
+ Streaming,
+ UI,
+ VFX,
+ Visibility,
+ Wait,
+
+ // IO
+ IO,
+
+ // GPU
+ GPU_Cloth,
+ GPU_Lighting,
+ GPU_PostFX,
+ GPU_Reflections,
+ GPU_Scene,
+ GPU_Shadows,
+ GPU_UI,
+ GPU_VFX,
+ GPU_Water,
+
+ };
+ };
+
+ #define OPTICK_MAKE_CATEGORY(filter, color) (((uint64_t)(1ull) << (filter + 32)) | (uint64_t)color)
+
+ struct Category
+ {
+ enum Type : uint64_t
+ {
+ // CPU
+ None = OPTICK_MAKE_CATEGORY(Filter::None, Color::Null),
+ AI = OPTICK_MAKE_CATEGORY(Filter::AI, Color::Purple),
+ Animation = OPTICK_MAKE_CATEGORY(Filter::Animation, Color::LightSkyBlue),
+ Audio = OPTICK_MAKE_CATEGORY(Filter::Audio, Color::HotPink),
+ Debug = OPTICK_MAKE_CATEGORY(Filter::Debug, Color::Black),
+ Camera = OPTICK_MAKE_CATEGORY(Filter::Camera, Color::Black),
+ Cloth = OPTICK_MAKE_CATEGORY(Filter::Cloth, Color::DarkGreen),
+ GameLogic = OPTICK_MAKE_CATEGORY(Filter::GameLogic, Color::RoyalBlue),
+ Input = OPTICK_MAKE_CATEGORY(Filter::Input, Color::Ivory),
+ Navigation = OPTICK_MAKE_CATEGORY(Filter::Navigation, Color::Magenta),
+ Network = OPTICK_MAKE_CATEGORY(Filter::Network, Color::Olive),
+ Physics = OPTICK_MAKE_CATEGORY(Filter::Physics, Color::LawnGreen),
+ Rendering = OPTICK_MAKE_CATEGORY(Filter::Rendering, Color::BurlyWood),
+ Scene = OPTICK_MAKE_CATEGORY(Filter::Scene, Color::RoyalBlue),
+ Script = OPTICK_MAKE_CATEGORY(Filter::Script, Color::Plum),
+ Streaming = OPTICK_MAKE_CATEGORY(Filter::Streaming, Color::Gold),
+ UI = OPTICK_MAKE_CATEGORY(Filter::UI, Color::PaleTurquoise),
+ VFX = OPTICK_MAKE_CATEGORY(Filter::VFX, Color::SaddleBrown),
+ Visibility = OPTICK_MAKE_CATEGORY(Filter::Visibility, Color::Snow),
+ Wait = OPTICK_MAKE_CATEGORY(Filter::Wait, Color::Tomato),
+ WaitEmpty = OPTICK_MAKE_CATEGORY(Filter::Wait, Color::White),
+ // IO
+ IO = OPTICK_MAKE_CATEGORY(Filter::IO, Color::Khaki),
+ // GPU
+ GPU_Cloth = OPTICK_MAKE_CATEGORY(Filter::GPU_Cloth, Color::DarkGreen),
+ GPU_Lighting = OPTICK_MAKE_CATEGORY(Filter::GPU_Lighting, Color::Khaki),
+ GPU_PostFX = OPTICK_MAKE_CATEGORY(Filter::GPU_PostFX, Color::Maroon),
+ GPU_Reflections = OPTICK_MAKE_CATEGORY(Filter::GPU_Reflections, Color::CadetBlue),
+ GPU_Scene = OPTICK_MAKE_CATEGORY(Filter::GPU_Scene, Color::RoyalBlue),
+ GPU_Shadows = OPTICK_MAKE_CATEGORY(Filter::GPU_Shadows, Color::LightSlateGray),
+ GPU_UI = OPTICK_MAKE_CATEGORY(Filter::GPU_UI, Color::PaleTurquoise),
+ GPU_VFX = OPTICK_MAKE_CATEGORY(Filter::GPU_VFX, Color::SaddleBrown),
+ GPU_Water = OPTICK_MAKE_CATEGORY(Filter::GPU_Water, Color::SteelBlue),
+ };
+
+ static uint32_t GetMask(Type t) { return (uint32_t)(t >> 32); }
+ static uint32_t GetColor(Type t) { return (uint32_t)(t); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+}
+
+
+namespace Optick
+{
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct Mode
+{
+ enum Type
+ {
+ OFF = 0x0,
+ INSTRUMENTATION_CATEGORIES = (1 << 0),
+ INSTRUMENTATION_EVENTS = (1 << 1),
+ INSTRUMENTATION = (INSTRUMENTATION_CATEGORIES | INSTRUMENTATION_EVENTS),
+ SAMPLING = (1 << 2),
+ TAGS = (1 << 3),
+ AUTOSAMPLING = (1 << 4),
+ SWITCH_CONTEXT = (1 << 5),
+ IO = (1 << 6),
+ GPU = (1 << 7),
+ END_SCREENSHOT = (1 << 8),
+ RESERVED_0 = (1 << 9),
+ RESERVED_1 = (1 << 10),
+ HW_COUNTERS = (1 << 11),
+ LIVE = (1 << 12),
+ RESERVED_2 = (1 << 13),
+ RESERVED_3 = (1 << 14),
+ RESERVED_4 = (1 << 15),
+ SYS_CALLS = (1 << 16),
+ OTHER_PROCESSES = (1 << 17),
+
+ TRACER = AUTOSAMPLING | SWITCH_CONTEXT | SYS_CALLS,
+ DEFAULT = INSTRUMENTATION | TAGS | AUTOSAMPLING | SWITCH_CONTEXT | IO | GPU | SYS_CALLS | OTHER_PROCESSES,
+ };
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPTICK_API int64_t GetHighPrecisionTime();
+OPTICK_API int64_t GetHighPrecisionFrequency();
+OPTICK_API uint32_t NextFrame();
+OPTICK_API bool IsActive(Mode::Type mode = Mode::INSTRUMENTATION_EVENTS);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct EventStorage;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPTICK_API bool RegisterFiber(uint64_t fiberId, EventStorage** slot);
+OPTICK_API bool RegisterThread(const char* name);
+OPTICK_API bool RegisterThread(const wchar_t* name);
+OPTICK_API bool UnRegisterThread(bool keepAlive);
+OPTICK_API EventStorage** GetEventStorageSlotForCurrentThread();
+OPTICK_API bool IsFiberStorage(EventStorage* fiberStorage);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct ThreadMask
+{
+ enum Type
+ {
+ None = 0,
+ Main = 1 << 0,
+ GPU = 1 << 1,
+ IO = 1 << 2,
+ Idle = 1 << 3,
+ };
+};
+
+OPTICK_API EventStorage* RegisterStorage(const char* name, uint64_t threadID = uint64_t(-1), ThreadMask::Type type = ThreadMask::None);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct State
+{
+ enum Type
+ {
+ // Starting a new capture
+ START_CAPTURE,
+
+ // Stopping current capture
+ STOP_CAPTURE,
+
+ // Dumping capture to the GUI
+ // Useful for attaching summary and screenshot to the capture
+ DUMP_CAPTURE,
+
+ // Cancel current capture
+ CANCEL_CAPTURE,
+ };
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sets a state change callback
+typedef bool (*StateCallback)(State::Type state);
+OPTICK_API bool SetStateChangedCallback(StateCallback cb);
+
+// Attaches a key-value pair to the capture's summary
+// Example: AttachSummary("Version", "v12.0.1");
+// AttachSummary("Platform", "Windows");
+// AttachSummary("Config", "Release_x64");
+// AttachSummary("Settings", "Ultra");
+// AttachSummary("Map", "Atlantida");
+// AttachSummary("Position", "123.0,120.0,41.1");
+// AttachSummary("CPU", "Intel(R) Xeon(R) CPU E5410@2.33GHz");
+// AttachSummary("GPU", "NVIDIA GeForce GTX 980 Ti");
+OPTICK_API bool AttachSummary(const char* key, const char* value);
+
+struct File
+{
+ enum Type
+ {
+ // Supported formats: PNG, JPEG, BMP, TIFF
+ OPTICK_IMAGE,
+
+ // Text file
+ OPTICK_TEXT,
+
+ // Any other type
+ OPTICK_OTHER,
+ };
+};
+// Attaches a file to the current capture
+OPTICK_API bool AttachFile(File::Type type, const char* name, const uint8_t* data, uint32_t size);
+OPTICK_API bool AttachFile(File::Type type, const char* name, const char* path);
+OPTICK_API bool AttachFile(File::Type type, const char* name, const wchar_t* path);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct EventDescription;
+struct Frame;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct EventTime
+{
+ static const int64_t INVALID_TIMESTAMP = (int64_t)-1;
+
+ int64_t start;
+ int64_t finish;
+
+ OPTICK_INLINE void Start() { start = Optick::GetHighPrecisionTime(); }
+ OPTICK_INLINE void Stop() { finish = Optick::GetHighPrecisionTime(); }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct EventData : public EventTime
+{
+ const EventDescription* description;
+
+ bool operator<(const EventData& other) const
+ {
+ if (start != other.start)
+ return start < other.start;
+
+ // Reversed order for finish intervals (parent first)
+ return finish > other.finish;
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API SyncData : public EventTime
+{
+ uint64_t newThreadId;
+ uint64_t oldThreadId;
+ uint8_t core;
+ int8_t reason;
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API FiberSyncData : public EventTime
+{
+ uint64_t threadId;
+
+ static void AttachToThread(EventStorage* storage, uint64_t threadId);
+ static void DetachFromThread(EventStorage* storage);
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+template<class T>
+struct TagData
+{
+ const EventDescription* description;
+ int64_t timestamp;
+ T data;
+ TagData() {}
+ TagData(const EventDescription& desc, T d) : description(&desc), timestamp(Optick::GetHighPrecisionTime()), data(d) {}
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API EventDescription
+{
+ // HOT \\
+ // Have to place "hot" variables at the beginning of the class (here will be some padding)
+ // COLD //
+
+ const char* name;
+ const char* file;
+ uint32_t line;
+ uint32_t index;
+ uint32_t color;
+ uint32_t filter;
+ float budget;
+
+ static EventDescription* Create(const char* eventName, const char* fileName, const unsigned long fileLine, const unsigned long eventColor = Color::Null, const unsigned long filter = 0);
+ static EventDescription* CreateShared(const char* eventName, const char* fileName = nullptr, const unsigned long fileLine = 0, const unsigned long eventColor = Color::Null, const unsigned long filter = 0);
+
+ EventDescription();
+private:
+ friend class EventDescriptionBoard;
+ EventDescription& operator=(const EventDescription&);
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API Event
+{
+ EventData* data;
+
+ static EventData* Start(const EventDescription& description);
+ static void Stop(EventData& data);
+
+ static void Push(const char* name);
+ static void Push(const EventDescription& description);
+ static void Pop();
+
+ static void Add(EventStorage* storage, const EventDescription* description, int64_t timestampStart, int64_t timestampFinish);
+ static void Push(EventStorage* storage, const EventDescription* description, int64_t timestampStart);
+ static void Pop(EventStorage* storage, int64_t timestampStart);
+
+
+ Event(const EventDescription& description)
+ {
+ data = Start(description);
+ }
+
+ ~Event()
+ {
+ if (data)
+ Stop(*data);
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPTICK_INLINE Optick::EventDescription* CreateDescription(const char* functionName, const char* fileName, int fileLine, const char* eventName = nullptr, const ::Optick::Category::Type category = ::Optick::Category::None)
+{
+ return ::Optick::EventDescription::Create(eventName != nullptr ? eventName : functionName, fileName, (unsigned long)fileLine, ::Optick::Category::GetColor(category), ::Optick::Category::GetMask(category));
+}
+OPTICK_INLINE Optick::EventDescription* CreateDescription(const char* functionName, const char* fileName, int fileLine, const ::Optick::Category::Type category)
+{
+ return ::Optick::EventDescription::Create(functionName, fileName, (unsigned long)fileLine, ::Optick::Category::GetColor(category), ::Optick::Category::GetMask(category));
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API GPUEvent
+{
+ EventData* data;
+
+ static EventData* Start(const EventDescription& description);
+ static void Stop(EventData& data);
+
+ GPUEvent(const EventDescription& description)
+ {
+ data = Start(description);
+ }
+
+ ~GPUEvent()
+ {
+ if (data)
+ Stop(*data);
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API Tag
+{
+ static void Attach(const EventDescription& description, float val);
+ static void Attach(const EventDescription& description, int32_t val);
+ static void Attach(const EventDescription& description, uint32_t val);
+ static void Attach(const EventDescription& description, uint64_t val);
+ static void Attach(const EventDescription& description, float val[3]);
+ static void Attach(const EventDescription& description, const char* val);
+
+ // Derived
+ static void Attach(const EventDescription& description, float x, float y, float z)
+ {
+ float p[3] = { x, y, z }; Attach(description, p);
+ }
+
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct ThreadScope
+{
+ bool keepAlive;
+
+ ThreadScope(const char* name, bool bKeepAlive = false) : keepAlive(bKeepAlive)
+ {
+ RegisterThread(name);
+ }
+
+ ThreadScope(const wchar_t* name)
+ {
+ RegisterThread(name);
+ }
+
+ ~ThreadScope()
+ {
+ UnRegisterThread(keepAlive);
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+enum OPTICK_API GPUQueueType
+{
+ GPU_QUEUE_GRAPHICS,
+ GPU_QUEUE_COMPUTE,
+ GPU_QUEUE_TRANSFER,
+ GPU_QUEUE_VSYNC,
+
+ GPU_QUEUE_COUNT,
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API GPUContext
+{
+ void* cmdBuffer;
+ GPUQueueType queue;
+ int node;
+ GPUContext(void* c = nullptr, GPUQueueType q = GPU_QUEUE_GRAPHICS, int n = 0) : cmdBuffer(c), queue(q), node(n) {}
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPTICK_API void InitGpuD3D12(void* device, void** cmdQueues, uint32_t numQueues);
+OPTICK_API void InitGpuVulkan(void* vkDevices, void* vkPhysicalDevices, void* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues);
+OPTICK_API void GpuFlip(void* swapChain);
+OPTICK_API GPUContext SetGpuContext(GPUContext context);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct OPTICK_API GPUContextScope
+{
+ GPUContext prevContext;
+
+ GPUContextScope(ID3D12CommandList* cmdList, GPUQueueType queue = GPU_QUEUE_GRAPHICS, int node = 0)
+ {
+ prevContext = SetGpuContext(GPUContext(cmdList, queue, node));
+ }
+
+ GPUContextScope(VkCommandBuffer cmdBuffer, GPUQueueType queue = GPU_QUEUE_GRAPHICS, int node = 0)
+ {
+ prevContext = SetGpuContext(GPUContext(cmdBuffer, queue, node));
+ }
+
+ ~GPUContextScope()
+ {
+ SetGpuContext(prevContext);
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct FrameType
+{
+ enum Type
+ {
+ CPU,
+ GPU,
+ Render,
+ COUNT,
+ };
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPTICK_API const EventDescription* GetFrameDescription(FrameType::Type frame);
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+}
+
+#define OPTICK_UNUSED(x) (void)(x)
+// Workaround for gcc compiler
+#define OPTICK_VA_ARGS(...) , ##__VA_ARGS__
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Scoped profiling event which automatically grabs current function name.
+// Use tis macro 95% of the time.
+// Example A:
+// void Function()
+// {
+// OPTICK_EVENT();
+// ... code ...
+// }
+// or
+// void Function()
+// {
+// OPTICK_EVENT("CustomFunctionName");
+// ... code ...
+// }
+// Notes:
+// Optick captures full name of the function including name space and arguments.
+// Full name is usually shortened in the Optick GUI in order to highlight the most important bits.
+#define OPTICK_EVENT(...) static ::Optick::EventDescription* OPTICK_CONCAT(autogen_description_, __LINE__) = nullptr; \
+ if (OPTICK_CONCAT(autogen_description_, __LINE__) == nullptr) OPTICK_CONCAT(autogen_description_, __LINE__) = ::Optick::CreateDescription(OPTICK_FUNC, __FILE__, __LINE__ OPTICK_VA_ARGS(__VA_ARGS__)); \
+ ::Optick::Event OPTICK_CONCAT(autogen_event_, __LINE__)( *(OPTICK_CONCAT(autogen_description_, __LINE__)) );
+
+// Backward compatibility with previous versions of Optick
+//#if !defined(PROFILE)
+//#define PROFILE OPTICK_EVENT()
+//#endif
+
+// Scoped profiling macro with predefined color.
+// Use this macro for high-level function calls (e.g. AI, Physics, Audio, Render etc.).
+// Example:
+// void UpdateAI()
+// {
+// OPTICK_CATEGORY("UpdateAI", Optick::Category::AI);
+// ... code ...
+// }
+//
+// Macro could automatically capture current function name:
+// void UpdateAI()
+// {
+// OPTICK_CATEGORY(OPTICK_FUNC, Optick::Category::AI);
+// ... code ...
+// }
+#define OPTICK_CATEGORY(NAME, CATEGORY) OPTICK_EVENT(NAME, CATEGORY)
+
+// Profiling event for Main Loop update.
+// You need to call this function in the beginning of the each new frame.
+// Example:
+// while (true)
+// {
+// OPTICK_FRAME("MainThread");
+// ... code ...
+// }
+#define OPTICK_FRAME(FRAME_NAME) static ::Optick::ThreadScope mainThreadScope(FRAME_NAME); \
+ OPTICK_UNUSED(mainThreadScope); \
+ uint32_t frameNumber = ::Optick::NextFrame(); \
+ ::Optick::Event OPTICK_CONCAT(autogen_event_, __LINE__)(*::Optick::GetFrameDescription(::Optick::FrameType::CPU)); \
+ OPTICK_TAG("Frame", frameNumber);
+
+
+// Thread registration macro.
+// Example:
+// void WorkerThread(...)
+// {
+// OPTICK_THREAD("Worker");
+// while (isRunning)
+// {
+// ...
+// }
+// }
+#define OPTICK_THREAD(THREAD_NAME) ::Optick::ThreadScope brofilerThreadScope(THREAD_NAME); \
+ OPTICK_UNUSED(brofilerThreadScope); \
+
+
+// Thread registration macros.
+// Useful for integration with custom job-managers.
+#define OPTICK_START_THREAD(FRAME_NAME) ::Optick::RegisterThread(FRAME_NAME);
+#define OPTICK_STOP_THREAD() ::Optick::UnRegisterThread(false);
+
+// Attaches a custom data-tag.
+// Supported types: int32, uint32, uint64, vec3, string (cut to 32 characters)
+// Example:
+// OPTICK_TAG("PlayerName", name[index]);
+// OPTICK_TAG("Health", 100);
+// OPTICK_TAG("Score", 0x80000000u);
+// OPTICK_TAG("Height(cm)", 176.3f);
+// OPTICK_TAG("Address", (uint64)*this);
+// OPTICK_TAG("Position", 123.0f, 456.0f, 789.0f);
+#define OPTICK_TAG(NAME, ...) static ::Optick::EventDescription* OPTICK_CONCAT(autogen_tag_, __LINE__) = nullptr; \
+ if (OPTICK_CONCAT(autogen_tag_, __LINE__) == nullptr) OPTICK_CONCAT(autogen_tag_, __LINE__) = ::Optick::EventDescription::Create( NAME, __FILE__, __LINE__ ); \
+ ::Optick::Tag::Attach(*OPTICK_CONCAT(autogen_tag_, __LINE__), __VA_ARGS__); \
+
+// Scoped macro with DYNAMIC name.
+// Optick holds a copy of the provided name.
+// Each scope does a search in hashmap for the name.
+// Please use variations with STATIC names where it's possible.
+// Use this macro for quick prototyping or intergratoin with other profiling systems (e.g. UE4)
+// Example:
+// const char* name = ... ;
+// OPTICK_EVENT_DYNAMIC(name);
+#define OPTICK_EVENT_DYNAMIC(NAME) OPTICK_CUSTOM_EVENT(::Optick::EventDescription::CreateShared(NAME, __FILE__, __LINE__));
+// Push\Pop profiling macro with DYNAMIC name.
+#define OPTICK_PUSH_DYNAMIC(NAME) ::Optick::Event::Push(NAME);
+
+// Push\Pop profiling macro with STATIC name.
+// Please avoid using Push\Pop approach in favor for scoped macros.
+// For backward compatibility with some engines.
+// Example:
+// OPTICK_PUSH("ScopeName");
+// ...
+// OPTICK_POP();
+#define OPTICK_PUSH(NAME) static ::Optick::EventDescription* OPTICK_CONCAT(autogen_description_, __LINE__) = nullptr; \
+ if (OPTICK_CONCAT(autogen_description_, __LINE__) == nullptr) OPTICK_CONCAT(autogen_description_, __LINE__) = ::Optick::EventDescription::Create( NAME, __FILE__, __LINE__ ); \
+ ::Optick::Event::Push(*OPTICK_CONCAT(autogen_description_, __LINE__));
+#define OPTICK_POP() ::Optick::Event::Pop();
+
+
+// Scoped macro with predefined Optick::EventDescription.
+// Use these events instead of DYNAMIC macros to minimize overhead.
+// Common use-case: integrating Optick with internal script languages (e.g. Lua, Actionscript(Scaleform), etc.).
+// Example:
+// Generating EventDescription once during initialization:
+// Optick::EventDescription* description = Optick::EventDescription::CreateShared("FunctionName");
+//
+// Then we could just use a pointer to cached description later for profiling:
+// OPTICK_CUSTOM_EVENT(description);
+#define OPTICK_CUSTOM_EVENT(DESCRIPTION) ::Optick::Event OPTICK_CONCAT(autogen_event_, __LINE__)( *DESCRIPTION ); \
+
+// Registration of a custom EventStorage (e.g. GPU, IO, etc.)
+// Use it to present any extra information on the timeline.
+// Example:
+// Optick::EventStorage* IOStorage = Optick::RegisterStorage("I/O");
+// Notes:
+// Registration of a new storage is thread-safe.
+#define OPTICK_STORAGE_REGISTER(STORAGE_NAME) ::Optick::RegisterStorage(STORAGE_NAME);
+
+// Adding events to the custom storage.
+// Helps to integrate Optick into already existing profiling systems (e.g. GPU Profiler, I/O profiler, etc.).
+// Example:
+// //Registering a storage - should be done once during initialization
+// static Optick::EventStorage* IOStorage = Optick::RegisterStorage("I/O");
+//
+// int64_t cpuTimestampStart = Optick::GetHighPrecisionTime();
+// ...
+// int64_t cpuTimestampFinish = Optick::GetHighPrecisionTime();
+//
+// //Creating a shared event-description
+// static Optick::EventDescription* IORead = Optick::EventDescription::CreateShared("IO Read");
+//
+// OPTICK_STORAGE_EVENT(IOStorage, IORead, cpuTimestampStart, cpuTimestampFinish);
+// Notes:
+// It's not thread-safe to add events to the same storage from multiple threads.
+// Please guarantee thread-safety on the higher level if access from multiple threads to the same storage is required.
+#define OPTICK_STORAGE_EVENT(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START, CPU_TIMESTAMP_FINISH) if (::Optick::IsActive()) { ::Optick::Event::Add(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START, CPU_TIMESTAMP_FINISH); }
+#define OPTICK_STORAGE_PUSH(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START) if (::Optick::IsActive()) { ::Optick::Event::Push(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START); }
+#define OPTICK_STORAGE_POP(STORAGE, CPU_TIMESTAMP_FINISH) if (::Optick::IsActive()) { ::Optick::Event::Pop(STORAGE, CPU_TIMESTAMP_FINISH); }
+
+
+// Registers state change callback
+// If callback returns false - the call is repeated the next frame
+#define OPTICK_SET_STATE_CHANGED_CALLBACK(CALLBACK) ::Optick::SetStateChangedCallback(CALLBACK);
+
+
+// GPU events
+#define OPTICK_GPU_INIT_D3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS) ::Optick::InitGpuD3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS);
+#define OPTICK_GPU_INIT_VULKAN(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS) ::Optick::InitGpuVulkan(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS);
+
+// Setup GPU context:
+// Params:
+// (CommandBuffer\CommandList, [Optional] Optick::GPUQueue queue, [Optional] int NodeIndex)
+// Examples:
+// OPTICK_GPU_CONTEXT(cmdBuffer); - all OPTICK_GPU_EVENT will use the same command buffer within the scope
+// OPTICK_GPU_CONTEXT(cmdBuffer, Optick::GPU_QUEUE_COMPUTE); - all events will use the same command buffer and queue for the scope
+// OPTICK_GPU_CONTEXT(cmdBuffer, Optick::GPU_QUEUE_COMPUTE, gpuIndex); - all events will use the same command buffer and queue for the scope
+#define OPTICK_GPU_CONTEXT(...) ::Optick::GPUContextScope OPTICK_CONCAT(gpu_autogen_context_, __LINE__)(__VA_ARGS__); \
+ (void)OPTICK_CONCAT(gpu_autogen_context_, __LINE__);
+
+#define OPTICK_GPU_EVENT(NAME) OPTICK_EVENT(NAME); \
+ static ::Optick::EventDescription* OPTICK_CONCAT(gpu_autogen_description_, __LINE__) = nullptr; \
+ if (OPTICK_CONCAT(gpu_autogen_description_, __LINE__) == nullptr) OPTICK_CONCAT(gpu_autogen_description_, __LINE__) = ::Optick::EventDescription::Create( NAME, __FILE__, __LINE__ ); \
+ ::Optick::GPUEvent OPTICK_CONCAT(gpu_autogen_event_, __LINE__)( *(OPTICK_CONCAT(gpu_autogen_description_, __LINE__)) ); \
+
+#define OPTICK_GPU_FLIP(SWAP_CHAIN) ::Optick::GpuFlip(SWAP_CHAIN);
+
+#else
+#define OPTICK_EVENT(...)
+#define OPTICK_CATEGORY(NAME, COLOR)
+#define OPTICK_FRAME(NAME)
+#define OPTICK_THREAD(FRAME_NAME)
+#define OPTICK_START_THREAD(FRAME_NAME)
+#define OPTICK_STOP_THREAD()
+#define OPTICK_TAG(NAME, DATA)
+#define OPTICK_EVENT_DYNAMIC(NAME)
+#define OPTICK_PUSH_DYNAMIC(NAME)
+#define OPTICK_PUSH(NAME)
+#define OPTICK_POP()
+#define OPTICK_CUSTOM_EVENT(DESCRIPTION)
+#define OPTICK_STORAGE_REGISTER(STORAGE_NAME)
+#define OPTICK_STORAGE_EVENT(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START, CPU_TIMESTAMP_FINISH)
+#define OPTICK_STORAGE_PUSH(STORAGE, DESCRIPTION, CPU_TIMESTAMP_START)
+#define OPTICK_STORAGE_POP(STORAGE, CPU_TIMESTAMP_FINISH)
+#define OPTICK_SET_STATE_CHANGED_CALLBACK(CALLBACK)
+#define OPTICK_GPU_INIT_D3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS)
+#define OPTICK_GPU_INIT_VULKAN(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS)
+#define OPTICK_GPU_CONTEXT(...)
+#define OPTICK_GPU_EVENT(NAME)
+#define OPTICK_GPU_FLIP(SWAP_CHAIN)
+#endif