Files
Xenia-Canary/src/xenia/profiling.cc
Ben Vanik c631b965d7 Adding generic immediate mode drawing API and migrating microprofile.
Future changes will move elemental-forms and imgui to the common API as
well.
2015-11-05 21:36:05 -08:00

314 lines
8.7 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <gflags/gflags.h>
#include <string>
// NOTE: this must be included before microprofile as macro expansion needs
// XELOGI.
#include "xenia/base/logging.h"
// NOTE: microprofile must be setup first, before profiling.h is included.
#define MICROPROFILE_ENABLED 1
#define MICROPROFILEUI_ENABLED 1
#define MICROPROFILE_IMPL 1
#define MICROPROFILEUI_IMPL 1
#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (1024 * 1024 * 10)
#define MICROPROFILE_USE_THREAD_NAME_CALLBACK 1
#define MICROPROFILE_WEBSERVER_MAXFRAMES 3
#define MICROPROFILE_PRINTF XELOGI
#define MICROPROFILE_WEBSERVER 0
#define MICROPROFILE_DEBUG 0
#define MICROPROFILE_MAX_THREADS 128
#include "third_party/microprofile/microprofile.h"
#include "xenia/base/assert.h"
#include "xenia/profiling.h"
#include "xenia/ui/window.h"
#if XE_OPTION_PROFILING
#include "third_party/microprofile/microprofileui.h"
#endif // XE_OPTION_PROFILING
#if XE_OPTION_PROFILING_UI
#undef DrawText
#include "xenia/ui/microprofile_drawer.h"
#endif // XE_OPTION_PROFILING_UI
DEFINE_bool(show_profiler, false, "Show profiling UI by default.");
namespace xe {
ui::Window* Profiler::window_ = nullptr;
std::unique_ptr<ui::MicroprofileDrawer> Profiler::drawer_ = nullptr;
#if XE_OPTION_PROFILING
bool Profiler::is_enabled() { return true; }
bool Profiler::is_visible() { return is_enabled() && MicroProfileIsDrawing(); }
void Profiler::Initialize() {
// Custom groups.
MicroProfileSetEnableAllGroups(false);
MicroProfileForceEnableGroup("apu", MicroProfileTokenTypeCpu);
MicroProfileForceEnableGroup("cpu", MicroProfileTokenTypeCpu);
MicroProfileForceEnableGroup("gpu", MicroProfileTokenTypeCpu);
MicroProfileForceEnableGroup("internal", MicroProfileTokenTypeCpu);
g_MicroProfile.nGroupMask = g_MicroProfile.nForceGroup;
g_MicroProfile.nActiveGroup = g_MicroProfile.nActiveGroupWanted =
g_MicroProfile.nGroupMask;
// Custom timers: time, average.
g_MicroProfile.nBars |= 0x1 | 0x2;
g_MicroProfile.nActiveBars |= 0x1 | 0x2;
#if XE_OPTION_PROFILING_UI
MicroProfileInitUI();
g_MicroProfileUI.bShowSpikes = true;
g_MicroProfileUI.nOpacityBackground = 0x40u << 24;
g_MicroProfileUI.nOpacityForeground = 0xc0u << 24;
if (FLAGS_show_profiler) {
MicroProfileSetDisplayMode(1);
}
#else
MicroProfileSetForceEnable(true);
MicroProfileSetEnableAllGroups(true);
MicroProfileSetForceMetaCounters(false);
#endif // XE_OPTION_PROFILING_UI
}
void Profiler::Dump() {
#if XE_OPTION_PROFILING_UI
MicroProfileDumpTimers();
#endif // XE_OPTION_PROFILING_UI
MicroProfileDumpHtml("profile.html");
MicroProfileDumpHtmlToFile();
}
void Profiler::Shutdown() {
drawer_.reset();
window_ = nullptr;
MicroProfileShutdown();
}
uint32_t Profiler::GetColor(const char* str) {
std::hash<std::string> fn;
size_t value = fn(str);
return value & 0xFFFFFF;
}
void Profiler::ThreadEnter(const char* name) {
MicroProfileOnThreadCreate(name);
}
void Profiler::ThreadExit() { MicroProfileOnThreadExit(); }
bool Profiler::OnKeyDown(int key_code) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
switch (key_code) {
case VK_OEM_3: // `
MicroProfileTogglePause();
return true;
#if XE_OPTION_PROFILING_UI
case VK_TAB:
MicroProfileToggleDisplayMode();
return true;
case 0x31: // 1
MicroProfileModKey(1);
return true;
#endif // XE_OPTION_PROFILING_UI
}
return false;
}
bool Profiler::OnKeyUp(int key_code) {
switch (key_code) {
#if XE_OPTION_PROFILING_UI
case 0x31: // 1
MicroProfileModKey(0);
return true;
#endif // XE_OPTION_PROFILING_UI
}
return false;
}
#if XE_OPTION_PROFILING_UI
void Profiler::OnMouseDown(bool left_button, bool right_button) {
MicroProfileMouseButton(left_button, right_button);
}
void Profiler::OnMouseUp() { MicroProfileMouseButton(0, 0); }
void Profiler::OnMouseMove(int x, int y) { MicroProfileMousePosition(x, y, 0); }
void Profiler::OnMouseWheel(int x, int y, int dy) {
MicroProfileMousePosition(x, y, dy);
}
void Profiler::ToggleDisplay() { MicroProfileToggleDisplayMode(); }
void Profiler::TogglePause() { MicroProfileTogglePause(); }
#else
void Profiler::OnMouseDown(bool left_button, bool right_button) {}
void Profiler::OnMouseUp() {}
void Profiler::OnMouseMove(int x, int y) {}
void Profiler::OnMouseWheel(int x, int y, int dy) {}
void Profiler::ToggleDisplay() {}
void Profiler::TogglePause() {}
#endif // XE_OPTION_PROFILING_UI
void Profiler::set_window(ui::Window* window) {
assert_null(window_);
if (!window) {
return;
}
window_ = window;
drawer_ = std::make_unique<ui::MicroprofileDrawer>(window);
window_->on_painted.AddListener([](ui::UIEvent* e) { Profiler::Present(); });
// Pass through mouse events.
window_->on_mouse_down.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseDown(e->button() == ui::MouseEvent::Button::kLeft,
e->button() == ui::MouseEvent::Button::kRight);
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_mouse_up.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseUp();
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_mouse_move.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseMove(e->x(), e->y());
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_mouse_wheel.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseWheel(e->x(), e->y(), -e->dy());
e->set_handled(true);
window_->Invalidate();
}
});
// Watch for toggle/mode keys and such.
window_->on_key_down.AddListener([](ui::KeyEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnKeyDown(e->key_code());
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_key_up.AddListener([](ui::KeyEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnKeyUp(e->key_code());
e->set_handled(true);
window_->Invalidate();
}
});
}
void Profiler::Present() {
SCOPE_profile_cpu_f("internal");
MicroProfileFlip();
#if XE_OPTION_PROFILING_UI
if (!window_ || !drawer_) {
return;
}
drawer_->Begin();
MicroProfileDraw(window_->width(), window_->height());
drawer_->End();
#endif // XE_OPTION_PROFILING_UI
}
#else
bool Profiler::is_enabled() { return false; }
bool Profiler::is_visible() { return false; }
void Profiler::Initialize() {}
void Profiler::Dump() {}
void Profiler::Shutdown() {}
uint32_t Profiler::GetColor(const char* str) { return 0; }
void Profiler::ThreadEnter(const char* name) {}
void Profiler::ThreadExit() {}
bool Profiler::OnKeyDown(int key_code) { return false; }
bool Profiler::OnKeyUp(int key_code) { return false; }
void Profiler::OnMouseDown(bool left_button, bool right_button) {}
void Profiler::OnMouseUp() {}
void Profiler::OnMouseMove(int x, int y) {}
void Profiler::OnMouseWheel(int x, int y, int dy) {}
void Profiler::set_display(std::unique_ptr<ui::MicroprofilerDrawer> display) {}
void Profiler::Present() {}
#endif // XE_OPTION_PROFILING
} // namespace xe
#if XE_OPTION_PROFILING
uint32_t MicroProfileGpuInsertTimeStamp() { return 0; }
uint64_t MicroProfileGpuGetTimeStamp(uint32_t nKey) { return 0; }
uint64_t MicroProfileTicksPerSecondGpu() { return 0; }
const char* MicroProfileGetThreadName() { return "TODO: get thread name!"; }
#if XE_OPTION_PROFILING_UI
void MicroProfileDrawBox(int nX, int nY, int nX1, int nY1, uint32_t nColor,
MicroProfileBoxType type) {
auto drawer = xe::Profiler::drawer();
if (!drawer) {
return;
}
drawer->DrawBox(nX, nY, nX1, nY1, nColor,
static_cast<xe::ui::MicroprofileDrawer::BoxType>(type));
}
void MicroProfileDrawLine2D(uint32_t nVertices, float* pVertices,
uint32_t nColor) {
auto drawer = xe::Profiler::drawer();
if (!drawer) {
return;
}
drawer->DrawLine2D(nVertices, pVertices, nColor);
}
void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText,
uint32_t nLen) {
auto drawer = xe::Profiler::drawer();
if (!drawer) {
return;
}
drawer->DrawText(nX, nY, nColor, pText, nLen);
}
#endif // XE_OPTION_PROFILING_UI
#endif // XE_OPTION_PROFILING