Files
2025-09-18 17:55:52 -04:00

468 lines
9.6 KiB
C++

#include "rbx/Profiler.h"
#include "rbx/Debug.h"
FASTFLAGVARIABLE(OnScreenProfiler, false)
#ifdef RBXPROFILER
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4244 4995 4996)
#endif
#define NOMINMAX
#ifdef __APPLE__
#include <boost/thread.hpp>
#include <boost/function.hpp>
namespace std
{
using boost::thread;
using boost::recursive_mutex;
using boost::lock_guard;
using boost::function;
enum memory_order
{
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
};
template <typename T>
class atomic
{
public:
atomic()
{
}
T load(memory_order order = memory_order_seq_cst) const
{
T result = value;
if (order != memory_order_relaxed) __sync_synchronize();
return result;
}
void store(T desired, memory_order order = memory_order_seq_cst)
{
if (order != memory_order_relaxed) __sync_synchronize();
value = desired;
}
T fetch_add(T arg, memory_order order = std::memory_order_seq_cst)
{
return __sync_fetch_and_add(&value, arg);
}
private:
template <int N> struct __attribute__((aligned(N))) pad_t {};
union { volatile T value; pad_t<sizeof(T)> pad; };
};
}
#define MICROPROFILE_NOCXX11
#endif
#ifdef __ANDROID__
#include <android/log.h>
#define MICROPROFILE_PRINTF(...) __android_log_print(ANDROID_LOG_DEBUG, "MicroProfile", __VA_ARGS__)
#endif
#ifdef _WIN32
static void MicroProfileDebugPrintf(const char* format, ...)
{
char message[256];
va_list args;
va_start(args, format);
vsprintf_s(message, format, args);
va_end(args);
OutputDebugStringA(message);
}
#define MICROPROFILE_PRINTF(...) MicroProfileDebugPrintf(__VA_ARGS__)
#endif
#define MP_ASSERT(e) RBXASSERT(e)
#define MICROPROFILE_WEBSERVER 0
#ifdef RBX_PLATFORM_DURANGO
#define MICROPROFILE_WEBSERVER_PORT 4600
#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
#define getenv(name) NULL
#endif
#if defined(_WIN32)
#define MICROPROFILE_GPU_TIMERS_D3D11 1
#elif defined(__APPLE__) && !defined(RBX_PLATFORM_IOS)
#include <OpenGL/gl3.h>
#define MICROPROFILE_GPU_TIMERS_GL 0
#endif
#if defined(RBX_PLATFORM_DURANGO)
#include <d3d11_x.h>
#endif
#define MICROPROFILE_IMPL
#include "microprofile/microprofile.h"
#define MICROPROFILE_DRAWCURSOR 1
#define MICROPROFILEUI_IMPL
#include "microprofile/microprofileui.h"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
struct InputState
{
int mouseX, mouseY, mouseWheel;
bool mouseButton[4];
};
RBX::Profiler::Renderer* gProfileRenderer = 0;
InputState gInputState;
void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, uint32_t nNumCharacters)
{
gProfileRenderer->drawText(nX, nY, nColor, pText, nNumCharacters, MICROPROFILE_TEXT_WIDTH, MICROPROFILE_TEXT_HEIGHT);
}
void MicroProfileDrawBox(int nX, int nY, int nX1, int nY1, uint32_t nColor, MicroProfileBoxType type)
{
if (type == MicroProfileBoxTypeBar)
{
uint32_t r = 0xff & (nColor>>16);
uint32_t g = 0xff & (nColor>>8);
uint32_t b = 0xff & nColor;
uint32_t nMax = MicroProfileMax(MicroProfileMax(MicroProfileMax(r, g), b), 30u);
uint32_t nMin = MicroProfileMin(MicroProfileMin(MicroProfileMin(r, g), b), 180u);
uint32_t r0 = 0xff & ((r + nMax)/2);
uint32_t g0 = 0xff & ((g + nMax)/2);
uint32_t b0 = 0xff & ((b + nMax)/2);
uint32_t r1 = 0xff & ((r+nMin)/2);
uint32_t g1 = 0xff & ((g+nMin)/2);
uint32_t b1 = 0xff & ((b+nMin)/2);
uint32_t nColor0 = (r0<<16)|(g0<<8)|(b0<<0)|(0xff000000&nColor);
uint32_t nColor1 = (r1<<16)|(g1<<8)|(b1<<0)|(0xff000000&nColor);
gProfileRenderer->drawBox(nX, nY, nX1, nY1, nColor0, nColor1);
}
else
{
gProfileRenderer->drawBox(nX, nY, nX1, nY1, nColor, nColor);
}
}
void MicroProfileDrawLine2D(uint32_t nVertices, float* pVertices, uint32_t nColor)
{
gProfileRenderer->drawLine(nVertices, const_cast<const float*>(pVertices), nColor);
}
namespace RBX
{
namespace Profiler
{
MicroProfileTokenType getTokenType(const char* group)
{
return strcmp(group, "GPU") == 0 ? MicroProfileTokenTypeGpu : MicroProfileTokenTypeCpu;
}
Token getToken(const char* group, const char* name, int color)
{
return MicroProfileGetToken(group, name, color, getTokenType(group));
}
Token getLabelToken(const char* group)
{
return MicroProfileGetLabelToken(group, getTokenType(group));
}
Token getCounterToken(const char* name)
{
return MicroProfileGetCounterToken(name);
}
uint64_t enterRegion(Token token)
{
if (!FFlag::OnScreenProfiler) return MICROPROFILE_INVALID_TICK;
return MicroProfileEnter(token);
}
void addLabel(Token token, const char* name)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileLabel(token, name);
}
void addLabelFormat(Token token, const char* name, ...)
{
if (!FFlag::OnScreenProfiler) return;
va_list args;
va_start(args, name);
MicroProfileLabelFormatV(token, name, args);
va_end(args);
}
void leaveRegion(Token token, uint64_t enterTimestamp)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileLeave(token, enterTimestamp);
}
void counterAdd(Token token, long long count)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileCounterAdd(token, count);
}
void counterSet(Token token, long long count)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileCounterSet(token, count);
}
void onThreadCreate(const char* name)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileOnThreadCreate(name);
}
void onThreadExit()
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileOnThreadExit();
}
void onFrame()
{
if (!FFlag::OnScreenProfiler) return;
if (g_MicroProfile.nWebServerDataSent)
{
// Set the defaults for web serving after the first connect
MicroProfileSetEnableAllGroups(true);
}
MicroProfileFlip();
}
void gpuInit(void* context)
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileGpuInit(context);
}
void gpuShutdown()
{
if (!FFlag::OnScreenProfiler) return;
MicroProfileGpuShutdown();
}
bool isCapturingMouseInput()
{
if (!FFlag::OnScreenProfiler) return false;
return (MicroProfileIsDrawing() && !g_MicroProfile.nRunning);
}
bool handleMouse(unsigned int flags, int mouseX, int mouseY, int mouseWheel, int mouseButton)
{
if (!FFlag::OnScreenProfiler) return false;
if (flags & Flag_MouseMove)
{
gInputState.mouseX = mouseX;
gInputState.mouseY = mouseY;
}
if (flags & Flag_MouseWheel)
gInputState.mouseWheel = mouseWheel;
if (flags & Flag_MouseDown)
gInputState.mouseButton[mouseButton] = true;
if (flags & Flag_MouseUp)
gInputState.mouseButton[mouseButton] = false;
MicroProfileMousePosition(std::max(gInputState.mouseX, 0), std::max(gInputState.mouseY, 0), gInputState.mouseWheel);
MicroProfileMouseButton(gInputState.mouseButton[0], gInputState.mouseButton[1]);
return isCapturingMouseInput();
}
bool toggleVisible()
{
if (!FFlag::OnScreenProfiler) return false;
if (MicroProfileIsDrawing())
{
MicroProfileSetDisplayMode(MP_DRAW_OFF);
if (!g_MicroProfile.nRunning)
g_MicroProfile.nToggleRunning = 1;
}
else
{
MicroProfileSetDisplayMode(MP_DRAW_FRAME);
}
return true;
}
bool togglePause()
{
if (!FFlag::OnScreenProfiler) return false;
if (MicroProfileIsDrawing())
{
if (g_MicroProfile.nRunning && g_MicroProfile.nDisplay == MP_DRAW_FRAME)
MicroProfileSetDisplayMode(MP_DRAW_DETAILED);
else if (!g_MicroProfile.nRunning && g_MicroProfile.nDisplay == MP_DRAW_DETAILED)
MicroProfileSetDisplayMode(MP_DRAW_FRAME);
MicroProfileTogglePause();
return true;
}
return false;
}
bool isVisible()
{
if (!FFlag::OnScreenProfiler) return false;
return MicroProfileIsDrawing();
}
void render(Renderer* renderer, unsigned int width, unsigned int height)
{
if (!FFlag::OnScreenProfiler) return;
static bool initialized = false;
if (!initialized)
{
MicroProfileInitUI();
g_MicroProfileUI.nOpacityBackground = 0x40<<24;
}
gProfileRenderer = renderer;
MicroProfileDraw(width, height);
gProfileRenderer = 0;
if (!initialized)
{
// MicroProfileDraw loads the preset; after it has loaded it we can check if we need to set up the defaults to enable all groups
if (g_MicroProfile.nActiveGroupWanted == 0)
MicroProfileSetEnableAllGroups(true);
initialized = true;
}
gInputState.mouseWheel = 0;
}
}
}
#else
namespace RBX
{
namespace Profiler
{
Token getToken(const char* group, const char* name, int color)
{
return 0;
}
uint64_t enterRegion(Token token)
{
return 0;
}
void addLabel(Token token, const char* name)
{
}
void leaveRegion(Token token, uint64_t enterTimestamp)
{
}
void onThreadCreate(const char* name)
{
}
void onThreadExit()
{
}
void onFrame()
{
}
void gpuInit(void* context)
{
}
void gpuShutdown()
{
}
bool isCapturingMouseInput()
{
return false;
}
bool handleMouse(unsigned int flags, int mouseX, int mouseY, int mouseWheel, int mouseButton)
{
return false;
}
bool toggleVisible()
{
return false;
}
bool togglePause()
{
return false;
}
bool isVisible()
{
return false;
}
void render(Renderer* renderer, unsigned int width, unsigned int height)
{
}
}
}
#endif