From 868ba6279a20e4d1412c2d576c67400167de6694 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Tue, 30 Apr 2019 16:12:35 +0500 Subject: Integrated Optick profiler --- external/optick/optick.h | 872 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 external/optick/optick.h (limited to 'external/optick/optick.h') 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 + +#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 +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 -- cgit v1.2.3