Optick: C++ Profiler For Games

Optick: C++ Profiler For Games

GitHub GitHub release
Optick is a super-lightweight C++ profiler for Games.
It provides access for all the necessary tools required for efficient performance analysis and optimization:
instrumentation, switch-contexts, sampling, GPU counters.

Looking for 'Brofiler'? It has been renamed to 'Optick', so you are in the right place.

Build Status

Windows (x64: msvc) Linux (x64: clang, gcc) MacOS (x64: clang, gcc) Static Code Analysis
Windows Build status Linux+MacOS Build Status Linux+MacOS Build Status Total alerts Codacy Badge
Features Windows Linux MacOS XBox PS4 UE4
Instrumentation ✔️ ✔️ ✔️ ✔️ ✔️
Switch Contexts ✔️ ETW ✔️ FTrace ✔️ DTrace ✔️ ✔️ Win
Sampling ✔️ ETW ✔️ Win
GPU ✔️ D3D12, Vulkan ✔️ Vulkan ✔️ Vulkan

✔️ - works out of the box, - in progress, - coming soon for the certified developers

List of Games and Studios using Optick(Brofiler)

Allods Team 4A Games CryEngine Larian Studios Skyforge Metro Exodus Warface Armored Warfare

Video Tutorial

Optick Video Tutorial

Basic Integration (one line of code)

  1. Copy 'src' folder from the repository or latest release to your game project
  2. Add OPTICK_FRAME("MainThread"); macro to the main loop of your game and #include "optick.h" header
#include "optick.h"
...
while( true ) 
{
	OPTICK_FRAME("MainThread");
	engine.Update();
}
  1. Use OPTICK_EVENT(); macro to instrument a function
void SlowFunction()
{ 
	OPTICK_EVENT();
	...
}
  1. Add OPTICK_THREAD("Name"); macro to declare a new thread with Optick
void WorkerThread(...)
{
	OPTICK_THREAD("Worker");
	while (isRunning)
	{
		...
	}
}
  1. Edit optick.config.h to enable/disable some of the features in specific configs or platforms.
    (e.g. disabling Optick in final builds)

⚠️ If your Game uses dynamic linking and you are planning to use Optick from multiple dlls within the same executable - please make sure that Optick's code is added to the common Dynamic Library and this library is compiled with OPTICK_EXPORT define (Static Library won't work).
You could also use precompiled OptickCore.dll which is packaged with every release:

  • Add include folder to the extra include dirs of your project
  • Add lib/x64/debug and lib/x64/release to the extra library dirs of your project
  • Copy lib/x64/debug/OptickCore.dll and lib/x64/release/OptickCore.dll to the debug and release output folders of your project respectively

API

All the available API calls are documented here:
https://github.com/bombomby/optick/wiki/Optick-API

Unreal Engine

Optick provides a special plugin for UE4. Check more detailed documentation here: https://github.com/bombomby/optick/wiki/UE4-Optick-Plugin

Samples

Run GenerateProjects_gpu.bat to generate project files. To compile the samples you'll need to install VulkanSDK. Alternatively you could use GenerateProjects.bat to generate only minimal solution with ConsoleApp sample.
Open solution build\vs2017\Optick.sln with generated samples.

WindowsD3D12 WindowsVulkan ConsoleApp
WindowsD3D12 WindowsVulkan ConsoleApp
DirectX12 multithreading sample with Optick integration SaschaWillems's vulkan multithreading sample with Optick integration Basic ConsoleApp with Optick integration (Windows, Linux, MacOS)

Brofiler

Brofiler has been renamed into Optick starting from v1.2.0.
All the future development is going under the new name.
Cheatsheet for upgrading to the new version:

  • BROFILER_FRAME("MainThread"); => OPTICK_FRAME("MainThread");
  • BROFILER_THREAD("WorkerThread"); => OPTICK_THREAD("WorkerThread");
  • BROFILER_CATEGORY("Physics", Brofiler::Color::Green); => OPTICK_CATEGORY("Physics", Optick::Category::Physics);
  • BROFILER_EVENT(NAME); => OPTICK_EVENT(NAME);
  • PROFILE; => OPTICK_EVENT();

How To Start?

You can find a short instruction here:
https://github.com/bombomby/optick/wiki/How-to-start%3F-(Programmers-Setup)

Comments
  • How can I launch Brofiler at program startup?

    How can I launch Brofiler at program startup?

    Currently I start Brofiler while my program is running, so I can't catch the initial frames of my application. Is there a way to attach them on startup?

  • Adding support for Vulkan Functions to be loaded by user

    Adding support for Vulkan Functions to be loaded by user

    After posting this issue: https://github.com/bombomby/optick/issues/108 I figured I'd dig in and at least see what would be needed to support vulkan meta-loaders. This is the solution I've whipped up so far. I've tested this in a personal engine and it seems to work great.

  • Crash brofiling static constructor

    Crash brofiling static constructor

    I get a crash using this minimal example:

    #include "Brofiler.h"
    class Foo
    {
    public:
    	Foo(){ BROFILER_CATEGORY(__FUNCSIG__, Brofiler::Color::Khaki) }
    };
    
    Foo foo;
    
    int main( int argc, char * argv[] ) {}
    

    Details on the crash:

    Exception thrown: 'System.AccessViolationException' in BrofilerTest.exe Additional information: Attempted to read or write protected memory. This often an indication that other memory is corrupt. If there is a handler for this exception, the program may be safely continued.

    I get the crash when brofiling the constructors of static members of global variables. I guess that this is because the BROFILER_CATEGORY call is done before the BrofilerCore library is loaded?

    Is there any way to ensure the library is loaded before any global member is initialized?

  • Not recording session

    Not recording session

    OptickApp.png Attachments: [OptickApp.png] Once I have the app running and then click start profiling session, optick begins to capture frames. Then when I want to stop, there is a red sqaure icon, but it says start profiling session still and not 'stop'.

    Then once I've clicked that and exited the app, optick is sat in this same place. Even if I save the session, close optick and reopen that session there is nothing there.

    I've tried recording a session a few times now, but I always get stuck here. Is there something I am missing?

    quick edit: This is when I have my project added to the Optick_vs2017 GUI solution and added a reference to the Optick c# project. I my project from that solution and then have a separate Optick application from 'optick-master\bin\vs2017\x64\Debug' that is what I start the profiling from.

  • Optick cant connect to my app

    Optick cant connect to my app

    I'm sure it's not a BUG/Issue but a user issue.

    However, I was not able to get the information from the documentation.,,

    I am trying to use Optick to profile my application running on OpenFramworks.

    I included the src files in my project. I went thru the ConsoleApp example.

    I added: OPTICK_SET_MEMORY_ALLOCATOR( [](size_t size) -> void* { return operator new(size); }, [](void* p) { operator delete(p); }, []() { /* Do some TLS initialization here if needed */ } ); To Main.

    I added: OPTICK_FRAME("MainThread"); before the ofApp runs.

    finally, I added some ` OPTICK_EVENT();' calles within my code.

    When I run Opcick and click on the "start profiling" button, the GUI displays "Connecting .... " with my computers IP. And that's it. What am I missing to have Optick "see" my app?

  • Width and Height must be non-negative

    Width and Height must be non-negative

    When I somehow capture empty frames, this error happens:

    Version 1.2.3

    ************** Exception Text ************** System.ArgumentException: Width and Height must be non-negative. at System.Windows.Size..ctor(Double width, Double height) at Profiler.DirectX.DynamicMesh.AddRect(Rect rect, Color color) at Profiler.ThreadView.DrawSelection(DirectXCanvas canvas) at Profiler.ThreadView.OnDraw(DirectXCanvas canvas, Layer layer) at Profiler.DirectX.DirectXCanvas.RenderCanvas_Paint(Object sender, PaintEventArgs e) at System.Windows.Forms.Control.OnPaint(PaintEventArgs e) at SharpDX.Windows.RenderControl.OnPaint(PaintEventArgs e) at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer) at System.Windows.Forms.Control.WmPaint(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.UserControl.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    optick-issue

  • fix kernel_logger_name with /permisive-

    fix kernel_logger_name with /permisive-

    Hi again, I apologize for the forgotten (LPSTR) cast hotfix that has sneaked into my previous PR :( Anyway, when compiling with /permisive-, which forces visual studio to be more conformant with c++ standard, it fails on assigning const pointer to non-const variable. This PR does a proper fix. There are also few fixed line endings. I hope that is ok.

  • segfault with clang

    segfault with clang

    repro case: https://github.com/malytomas/optick-test-clang

    when compiling Optick and/or the application that uses Optick with clang++ on linux with debug symbols and enabled optimizations, the application crashes

  • Make EventDescription's deletable

    Make EventDescription's deletable

    In my usecase I am profiling the script running inside a scriptVM. So the same function can belong to many different script files. Thus I can't make the EventDescription static per function. I solved that by just having one EventDescription per file but after a reset in game every script is recompiled and I want to clear all EventDescriptions instead of creating memory leaks everywhere.

    Maybe you have a better idea on how to solve this? I first wanted to just add a Event::Delete on https://github.com/bombomby/brofiler/pull/31/files#diff-71975803275f8f3cc69ffb081a77aad7R274 but I found out that each Description has an index corresponding to their position in the board (https://github.com/bombomby/brofiler/pull/31/files#diff-60b37754b374b6cbb51603dfd1148165R78) array which means I would have to change all indeces.

    Also may I ask why your code looks so old? No ranged for loops?

  • Crash in ProfileServer.cpp: Server::Update() CRITICAL_SECTION(lock)

    Crash in ProfileServer.cpp: Server::Update() CRITICAL_SECTION(lock)

    Hi,

    I've got brofiler working fine with a trivial 32-bit application, but get a crash in a more complex program in the first call of Server::Update() in ProfilerServer.cpp with "Access violation writing location 0x00000014.".

    The crash happens in the CRITICAL_SECTION(lock) call, and it looks like the 'lock' object is not initialized (in fact it looks like the entire Server object is not initialized, everything is initialized to zero, and the Server::Server() constructor is never called:

    brofiler_1

    On the other hand, the constructor Core::Core() is called, and the CRITICAL_SECTION(lock) in Core::Update() works fine.

    In the simpler program which works, the Server object is initialized when Server::Update() is called (although a breakpoint in the constructor is also never triggered, so this is a bit strange...):

    brofiler_2

    Any idea what's going on there, and how to fix or workaround?

    Thanks! -Floh.

  • Fix file corruption when using storage upload

    Fix file corruption when using storage upload

    When using the "Report a bug" feature targeting a network storage, we were experiencing file corruption issues when loading back the saved capture:

    image

    image

    image

    When debugging the issue, I noticed that the files saved out manually using the Save button vs the file from the Report Bug button were different sizes:

    image

    I eventually found that this was caused by not calling Dispose on the GZipStream created by Capture.Create. Reading the documentation on GZipStream, it's not totally clear why this becomes necessary, but the issue is a solid repro without the Dispose and I have not been able to repro with it.

    image

    ~Before finding this issue, I also found that the Save button leads to TimeLine.Save/TimeLine.ForEachResponse which appears as if it could save out more data that may be missed in TaskTrackerViewModel.SetGroup. My fix is to introduce a new interface, ISavable. The FrameGroup now has a reference back to the TimeLine as an ISavable and this is used to save the capture if available. I didn't confirm this was a "real" issue, so I can drop this part of the change if desired. If nothing else, it ensures that the two methods of saving follow a more similar code path.~ Dropped with b6ae6f1

  • Optick UE5 plugin deadlocks when stopping capture

    Optick UE5 plugin deadlocks when stopping capture

    I have a deadlock when stopping Optick capture on a cook from UE5. It happens around 100% times during gameplay, in main menu is around 50%. OptickPlugin version is 1.4.0

    Looking at callstacks two threads deadlock - the main game thread and render thread.

    Game thread looks like this: image Core::Update() locks the coreLock and above it FOptickPlugin::StopCapture tries to lock UpdateCriticalSection

    Render thread looks like this: image And here FOptickPlugin::OnEndFrameRT locks UpdateCriticalSection and Core::EndUpdateFrame tries to lock already locked coreLock.

    That results in deadlock. Unfortunately seems to me that fixing it requires a bit more understanding of the plugin than I have, so am reporting this as an issue instead of going for a pull request already.

  • extern

    extern "C" NextEvent seems like it was never used.

    We were looking into static build of the library, and looked into what symbols it exported - spotted this one, seems like it's not used (e.g. the extern "C" one).

  • Add a shutdown D3D12 function to correctly free the D3D12 resources

    Add a shutdown D3D12 function to correctly free the D3D12 resources

    When closing a D3D12 based application, there will be some errors due to the optick resources. Would be called like so:

    void ShutdownD3D12()
    {
    #ifdef WITH_OPTICK
    	OPTICK_GPU_SHUTDOWN_D3D12();
    #endif
    
    //the rest of d3d12 shutting down
    }
    

    this pull related to https://github.com/bombomby/optick/issues/121

  • Add a shutdown Vulkan function to correctly free the Vulkan resources

    Add a shutdown Vulkan function to correctly free the Vulkan resources

    When closing a Vulkan based application, there will be some validation errors due to the optick resources. Would be called like so:

    void ShutdownVulkan()
    {
    #ifdef WITH_OPTICK
    	OPTICK_GPU_SHUTDOWN_VULKAN();
    #endif
    
    //the rest of vulkan shutting down
    }
    

    this pull related to #121

  • OPTICK_FRAME causes Access violation executing location error while binding socket

    OPTICK_FRAME causes Access violation executing location error while binding socket

    I've used optick in the past and it still works with all my other projects, when I tried to integrate it into my engine as a static library it crashed when I use OPTICK_FRAME looks like it cannot bind the socket.

    https://github.com/bombomby/optick/blob/eb392f1647b1bb7c77f6a44e28641eaa29e37253/src/optick_server.cpp#L161-L163

    In my other projects I compile optick and my vulkan abstractions as a single static library and they work but my engine is a dll which uses optics as a static lib and it crashes while trying to call the winsockets bind.

    ============================================================

    OS : Windows 10 Home Processor : Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz 2.60 GHz Vulkan API Version : 1.3.194 GPU Name : NVIDIA GeForce RTX 2060 Vendor ID : 4318 Device Type : DISCRETE GPU Driver Version : 511.316.0 OS Build : 22000.675

Open-source, cross-platform, C++ game engine for creating 2D/3D games.

GamePlay v3.0.0 GamePlay is an open-source, cross-platform, C++ game framework/engine for creating 2D/3D mobile and desktop games. Website Wiki API De

Jun 17, 2022
A C math library targeted at games

Kazmath Kazmath is a simple 3D maths library written in C. It was initially coded for use in my book, Beginning OpenGL Game Programming - Second editi

May 25, 2022
3D games console based on RP2040 and iCE40 UP5k
3D games console based on RP2040 and iCE40 UP5k

PicoStation 3D This is an unfinished, untested project to develop a 3D games console based on an RP2040 microcontroller and an iCE40 UP5k FPGA. Quick

Jun 5, 2022
A set of libraries and tools to make MSX games using the C programming language.

ubox MSX lib This is a set of libraries and tools to make MSX games using the C programming language. There are three main components: ubox: thin wrap

May 30, 2022
TIC-80 is a fantasy computer for making, playing and sharing tiny games.
TIC-80 is a fantasy computer for making, playing and sharing tiny games.

TIC-80 is a fantasy computer for making, playing and sharing tiny games.

Jun 16, 2022
Enfusion Artifical Intelligence for DayZ and future Bohemia Interactive games.

Enfusion AI Project (eAI) This mod adds headless player units under the control of a script on the server. Although the script is very rudimentary now

Jun 13, 2022
Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.
Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.

Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.

Jun 17, 2022
Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++
Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++

Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++. CF comprises of different features, where the various features avoid inter-dependencies. In this way using CF is about picking and choosing which pieces are needed for your game

Jun 22, 2022
Modding (hacking) il2cpp games by classes, methods, fields names.

ByNameModding Modding (hacking) il2cpp games by classes, methods, fields names. Status: Ready to use Why did I do it 1. In order not to update the off

Jun 14, 2022
OGRE is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce games and demos utilising 3D hardware.
OGRE  is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce games and demos utilising 3D hardware.

OGRE (Object-Oriented Graphics Rendering Engine) is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce games and demos utilising 3D hardware. The class library abstracts all the details of using the underlying system libraries like Direct3D and OpenGL and provides an interface based on world objects and other intuitive classes.

Jun 20, 2022
Insomniac games cache simulation tool plugin for UE4
Insomniac games cache simulation tool plugin for UE4

Insomniac Games CacheSim plugin for UE4 This plugin for Unreal Engine 4 lets you use the Insomniac Games Cache Simulation tool to detect cache misses

Jan 19, 2022
Bounce is a 3D physics engine for games.

Bounce Welcome! Bounce is a 3D physics engine for games. Features Common Efficient data structures with no use of STL Fast memory allocators Built-in

Jun 5, 2022
Project DELTA - An open-source trainer built on the Void Engine for Toby Fox's games and their spin-offs.

Project DELTA v3 Project DELTA - An open-source, modular mod menu for Toby Fox's games and their spin-offs. Important note to Grossley: Yes, it is out

Apr 20, 2022
Speedrun plugin for Source engine games.

Features Automatic demo recording Accurate session timing Speedrun timer with complex custom rule system Tools for segmented and tool-assisted speedru

Jun 19, 2022
A single-header C++ library for making simple 2D games
A single-header C++ library for making simple 2D games

A single-header C++ library for making simple 2D games PLATFORM: Windows LANGUAGE: C++ ENVIRONMENT: Visual Studio Why? Learning C++ is often seen as d

May 24, 2022
Add FidelityFX SuperResolution to SteamVR games

Modified OpenVR DLL with AMD FidelityFX SuperResolution Upscaler This modified openvr_api.dll allows you to apply FidelityFX SuperResolution upscaling

Jun 21, 2022
Stream Raspberry Pi games to the GBA via the Link Cable
Stream Raspberry Pi games to the GBA via the Link Cable

gba-remote-play video-only.mp4 This software streams games from a Raspberry Pi to a Game Boy Advance, through its Link Port. Video and audio are compr

Jun 1, 2022
Graphical improvements mod for Hyperdimension Neptunia Re;Birth1, Re;Birth2 and Re;Birth3 games.
Graphical improvements mod for Hyperdimension Neptunia Re;Birth1, Re;Birth2 and Re;Birth3 games.

Neptastic Mod Graphical improvements mod for Hyperdimension Neptunia Re;Birth1, Re;Birth2 and Re;Birth3 games. Features: Resolution upscaling and down

May 23, 2022