Merge pull request #1048 from yuriks/microprofile

Integrate the MicroProfile profiling library
master
Yuri Kunde Schlesner 2015-08-24 18:30:11 +07:00
commit ac0104b8b0
30 changed files with 11174 additions and 5 deletions

@ -213,6 +213,7 @@ set(INI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/inih")
include_directories(${INI_PREFIX}) include_directories(${INI_PREFIX})
add_subdirectory(${INI_PREFIX}) add_subdirectory(${INI_PREFIX})
include_directories(externals/microprofile)
include_directories(externals/nihstro/include) include_directories(externals/nihstro/include)
if (MSVC) if (MSVC)

@ -0,0 +1,7 @@
# microprofile
MicroProfile is a embeddable profiler in a single file, written in C++
It can display profile information in the application, or by generating captures via a minimal built in webserver.
For more information see the project webpage at https://bitbucket.org/jonasmeyer/microprofile

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -6,6 +6,9 @@
#include <thread> #include <thread>
#include <iostream> #include <iostream>
// This needs to be included before getopt.h because the latter #defines symbols used by it
#include "common/microprofile.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#include <getopt.h> #include <getopt.h>
#else #else
@ -59,6 +62,8 @@ int main(int argc, char **argv) {
Log::Filter log_filter(Log::Level::Debug); Log::Filter log_filter(Log::Level::Debug);
Log::SetFilter(&log_filter); Log::SetFilter(&log_filter);
MicroProfileOnThreadCreate("EmuThread");
if (boot_filename.empty()) { if (boot_filename.empty()) {
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
return -1; return -1;
@ -89,5 +94,7 @@ int main(int argc, char **argv) {
delete emu_window; delete emu_window;
MicroProfileShutdown();
return 0; return 0;
} }

@ -18,6 +18,7 @@ set(SRCS
debugger/ramview.cpp debugger/ramview.cpp
debugger/registers.cpp debugger/registers.cpp
util/spinbox.cpp util/spinbox.cpp
util/util.cpp
bootmanager.cpp bootmanager.cpp
hotkeys.cpp hotkeys.cpp
main.cpp main.cpp
@ -42,6 +43,7 @@ set(HEADERS
debugger/ramview.h debugger/ramview.h
debugger/registers.h debugger/registers.h
util/spinbox.h util/spinbox.h
util/util.h
bootmanager.h bootmanager.h
hotkeys.h hotkeys.h
main.h main.h

@ -14,6 +14,7 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/key_map.h" #include "common/key_map.h"
#include "common/microprofile.h"
#include "core/core.h" #include "core/core.h"
#include "core/settings.h" #include "core/settings.h"
@ -37,6 +38,8 @@ EmuThread::EmuThread(GRenderWindow* render_window) :
void EmuThread::run() { void EmuThread::run() {
render_window->MakeCurrent(); render_window->MakeCurrent();
MicroProfileOnThreadCreate("EmuThread");
stop_run = false; stop_run = false;
// holds whether the cpu was running during the last iteration, // holds whether the cpu was running during the last iteration,
@ -69,6 +72,8 @@ void EmuThread::run() {
} }
} }
MicroProfileOnThreadExit();
render_window->moveContext(); render_window->moveContext();
} }

@ -7,6 +7,8 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDebug> #include <QDebug>
#include "citra_qt/util/util.h"
extern GraphicsDebugger g_debugger; extern GraphicsDebugger g_debugger;
GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0) GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0)
@ -79,7 +81,7 @@ GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr
QListView* command_list = new QListView; QListView* command_list = new QListView;
command_list->setModel(command_model); command_list->setModel(command_model);
command_list->setFont(QFont("monospace")); command_list->setFont(GetMonospaceFont());
setWidget(command_list); setWidget(command_list);
} }

@ -14,6 +14,8 @@
#include <QSpinBox> #include <QSpinBox>
#include <QComboBox> #include <QComboBox>
#include "citra_qt/util/util.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
@ -303,9 +305,7 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi
list_widget = new QTreeView; list_widget = new QTreeView;
list_widget->setModel(model); list_widget->setModel(model);
QFont font("monospace"); list_widget->setFont(GetMonospaceFont());
font.setStyleHint(QFont::Monospace); // Automatic fallback to a monospace font on on platforms without a font called "monospace"
list_widget->setFont(font);
list_widget->setRootIsDecorated(false); list_widget->setRootIsDecorated(false);
list_widget->setUniformRowHeights(true); list_widget->setUniformRowHeights(true);

@ -15,6 +15,8 @@
#include <QSpinBox> #include <QSpinBox>
#include <QTreeView> #include <QTreeView>
#include "citra_qt/util/util.h"
#include "video_core/shader/shader.h" #include "video_core/shader/shader.h"
#include "graphics_vertex_shader.h" #include "graphics_vertex_shader.h"
@ -245,7 +247,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
} }
case Qt::FontRole: case Qt::FontRole:
return QFont("monospace"); return GetMonospaceFont();
case Qt::BackgroundRole: case Qt::BackgroundRole:
// Highlight instructions which have no debug data associated to them // Highlight instructions which have no debug data associated to them

@ -2,9 +2,21 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <QMouseEvent>
#include <QPainter>
#include <QString>
#include "profiler.h" #include "profiler.h"
#include "citra_qt/util/util.h"
#include "common/profiler_reporting.h" #include "common/profiler_reporting.h"
#include "common/microprofile.h"
// Include the implementation of the UI in this file. This isn't in microprofile.cpp because the
// non-Qt frontends don't need it (and don't implement the UI drawing hooks either).
#define MICROPROFILEUI_IMPL 1
#include "common/microprofileui.h"
using namespace Common::Profiling; using namespace Common::Profiling;
@ -136,3 +148,193 @@ void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable)
update_timer.stop(); update_timer.stop();
} }
} }
class MicroProfileWidget : public QWidget {
public:
MicroProfileWidget(QWidget* parent = 0);
protected:
void paintEvent(QPaintEvent* ev) override;
void showEvent(QShowEvent* ev) override;
void hideEvent(QHideEvent* ev) override;
void mouseMoveEvent(QMouseEvent* ev) override;
void mousePressEvent(QMouseEvent* ev) override;
void mouseReleaseEvent(QMouseEvent* ev) override;
void wheelEvent(QWheelEvent* ev) override;
void keyPressEvent(QKeyEvent* ev) override;
void keyReleaseEvent(QKeyEvent* ev) override;
private:
/// This timer is used to redraw the widget's contents continuously. To save resources, it only
/// runs while the widget is visible.
QTimer update_timer;
};
MicroProfileDialog::MicroProfileDialog(QWidget* parent)
: QWidget(parent, Qt::Dialog)
{
setObjectName("MicroProfile");
setWindowTitle(tr("MicroProfile"));
resize(1000, 600);
// Remove the "?" button from the titlebar and enable the maximize button
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint | Qt::WindowMaximizeButtonHint);
MicroProfileWidget* widget = new MicroProfileWidget(this);
QLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(widget);
setLayout(layout);
// Configure focus so that widget is focusable and the dialog automatically forwards focus to it.
setFocusProxy(widget);
widget->setFocusPolicy(Qt::StrongFocus);
widget->setFocus();
}
QAction* MicroProfileDialog::toggleViewAction() {
if (toggle_view_action == nullptr) {
toggle_view_action = new QAction(windowTitle(), this);
toggle_view_action->setCheckable(true);
toggle_view_action->setChecked(isVisible());
connect(toggle_view_action, SIGNAL(toggled(bool)), SLOT(setVisible(bool)));
}
return toggle_view_action;
}
void MicroProfileDialog::showEvent(QShowEvent* ev) {
if (toggle_view_action) {
toggle_view_action->setChecked(isVisible());
}
QWidget::showEvent(ev);
}
void MicroProfileDialog::hideEvent(QHideEvent* ev) {
if (toggle_view_action) {
toggle_view_action->setChecked(isVisible());
}
QWidget::hideEvent(ev);
}
/// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the
/// QPainter available inside the drawing callbacks.
static QPainter* mp_painter = nullptr;
MicroProfileWidget::MicroProfileWidget(QWidget* parent) : QWidget(parent) {
// Send mouse motion events even when not dragging.
setMouseTracking(true);
MicroProfileSetDisplayMode(1); // Timers screen
MicroProfileInitUI();
connect(&update_timer, SIGNAL(timeout()), SLOT(update()));
}
void MicroProfileWidget::paintEvent(QPaintEvent* ev) {
QPainter painter(this);
painter.setBackground(Qt::black);
painter.eraseRect(rect());
QFont font = GetMonospaceFont();
font.setPixelSize(MICROPROFILE_TEXT_HEIGHT);
painter.setFont(font);
mp_painter = &painter;
MicroProfileDraw(rect().width(), rect().height());
mp_painter = nullptr;
}
void MicroProfileWidget::showEvent(QShowEvent* ev) {
update_timer.start(15); // ~60 Hz
QWidget::showEvent(ev);
}
void MicroProfileWidget::hideEvent(QHideEvent* ev) {
update_timer.stop();
QWidget::hideEvent(ev);
}
void MicroProfileWidget::mouseMoveEvent(QMouseEvent* ev) {
MicroProfileMousePosition(ev->x(), ev->y(), 0);
ev->accept();
}
void MicroProfileWidget::mousePressEvent(QMouseEvent* ev) {
MicroProfileMousePosition(ev->x(), ev->y(), 0);
MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton);
ev->accept();
}
void MicroProfileWidget::mouseReleaseEvent(QMouseEvent* ev) {
MicroProfileMousePosition(ev->x(), ev->y(), 0);
MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton);
ev->accept();
}
void MicroProfileWidget::wheelEvent(QWheelEvent* ev) {
MicroProfileMousePosition(ev->x(), ev->y(), ev->delta() / 120);
ev->accept();
}
void MicroProfileWidget::keyPressEvent(QKeyEvent* ev) {
if (ev->key() == Qt::Key_Control) {
// Inform MicroProfile that the user is holding Ctrl.
MicroProfileModKey(1);
}
QWidget::keyPressEvent(ev);
}
void MicroProfileWidget::keyReleaseEvent(QKeyEvent* ev) {
if (ev->key() == Qt::Key_Control) {
MicroProfileModKey(0);
}
QWidget::keyReleaseEvent(ev);
}
// These functions are called by MicroProfileDraw to draw the interface elements on the screen.
void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 text_length) {
// hex_color does not include an alpha, so it must be assumed to be 255
mp_painter->setPen(QColor::fromRgb(hex_color));
// It's impossible to draw a string using a monospaced font with a fixed width per cell in a
// way that's reliable across different platforms and fonts as far as I (yuriks) can tell, so
// draw each character individually in order to precisely control the text advance.
for (u32 i = 0; i < text_length; ++i) {
// Position the text baseline 1 pixel above the bottom of the text cell, this gives nice
// vertical alignment of text for a wide range of tested fonts.
mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QChar(text[i]));
x += MICROPROFILE_TEXT_WIDTH + 1;
}
}
void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, MicroProfileBoxType type) {
QColor color = QColor::fromRgba(hex_color);
QBrush brush = color;
if (type == MicroProfileBoxTypeBar) {
QLinearGradient gradient(left, top, left, bottom);
gradient.setColorAt(0.f, color.lighter(125));
gradient.setColorAt(1.f, color.darker(125));
brush = gradient;
}
mp_painter->fillRect(left, top, right - left, bottom - top, brush);
}
void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color) {
// Temporary vector used to convert between the float array and QPointF. Marked static to reuse
// the allocation across calls.
static std::vector<QPointF> point_buf;
for (u32 i = 0; i < vertices_length; ++i) {
point_buf.emplace_back(vertices[i*2 + 0], vertices[i*2 + 1]);
}
// hex_color does not include an alpha, so it must be assumed to be 255
mp_painter->setPen(QColor::fromRgb(hex_color));
mp_painter->drawPolyline(point_buf.data(), vertices_length);
point_buf.clear();
}

@ -48,3 +48,20 @@ private:
QTimer update_timer; QTimer update_timer;
}; };
class MicroProfileDialog : public QWidget {
Q_OBJECT
public:
MicroProfileDialog(QWidget* parent = 0);
/// Returns a QAction that can be used to toggle visibility of this dialog.
QAction* toggleViewAction();
protected:
void showEvent(QShowEvent* ev) override;
void hideEvent(QHideEvent* ev) override;
private:
QAction* toggle_view_action = nullptr;
};

@ -17,6 +17,7 @@
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/logging/filter.h" #include "common/logging/filter.h"
#include "common/make_unique.h" #include "common/make_unique.h"
#include "common/microprofile.h"
#include "common/platform.h" #include "common/platform.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
@ -64,6 +65,9 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); addDockWidget(Qt::BottomDockWidgetArea, profilerWidget);
profilerWidget->hide(); profilerWidget->hide();
microProfileDialog = new MicroProfileDialog(this);
microProfileDialog->hide();
disasmWidget = new DisassemblerWidget(this, emu_thread.get()); disasmWidget = new DisassemblerWidget(this, emu_thread.get());
addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); addDockWidget(Qt::BottomDockWidgetArea, disasmWidget);
disasmWidget->hide(); disasmWidget->hide();
@ -102,6 +106,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging"));
debug_menu->addAction(profilerWidget->toggleViewAction()); debug_menu->addAction(profilerWidget->toggleViewAction());
debug_menu->addAction(microProfileDialog->toggleViewAction());
debug_menu->addAction(disasmWidget->toggleViewAction()); debug_menu->addAction(disasmWidget->toggleViewAction());
debug_menu->addAction(registersWidget->toggleViewAction()); debug_menu->addAction(registersWidget->toggleViewAction());
debug_menu->addAction(callstackWidget->toggleViewAction()); debug_menu->addAction(callstackWidget->toggleViewAction());
@ -128,6 +133,8 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
restoreGeometry(settings.value("geometry").toByteArray()); restoreGeometry(settings.value("geometry").toByteArray());
restoreState(settings.value("state").toByteArray()); restoreState(settings.value("state").toByteArray());
render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray()); render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray());
microProfileDialog->restoreGeometry(settings.value("microProfileDialogGeometry").toByteArray());
microProfileDialog->setVisible(settings.value("microProfileDialogVisible").toBool());
ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer); ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer);
SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked()); SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked());
@ -434,6 +441,8 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
settings.setValue("geometry", saveGeometry()); settings.setValue("geometry", saveGeometry());
settings.setValue("state", saveState()); settings.setValue("state", saveState());
settings.setValue("geometryRenderWindow", render_window->saveGeometry()); settings.setValue("geometryRenderWindow", render_window->saveGeometry());
settings.setValue("microProfileDialogGeometry", microProfileDialog->saveGeometry());
settings.setValue("microProfileDialogVisible", microProfileDialog->isVisible());
settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked()); settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked());
settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked()); settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked());
settings.setValue("firstStart", false); settings.setValue("firstStart", false);
@ -456,6 +465,11 @@ int main(int argc, char* argv[]) {
Log::Filter log_filter(Log::Level::Info); Log::Filter log_filter(Log::Level::Info);
Log::SetFilter(&log_filter); Log::SetFilter(&log_filter);
MicroProfileOnThreadCreate("Frontend");
SCOPE_EXIT({
MicroProfileShutdown();
});
// Init settings params // Init settings params
QSettings::setDefaultFormat(QSettings::IniFormat); QSettings::setDefaultFormat(QSettings::IniFormat);
QCoreApplication::setOrganizationName("Citra team"); QCoreApplication::setOrganizationName("Citra team");

@ -14,6 +14,7 @@ class GImageInfo;
class GRenderWindow; class GRenderWindow;
class EmuThread; class EmuThread;
class ProfilerWidget; class ProfilerWidget;
class MicroProfileDialog;
class DisassemblerWidget; class DisassemblerWidget;
class RegistersWidget; class RegistersWidget;
class CallstackWidget; class CallstackWidget;
@ -104,6 +105,7 @@ private:
std::unique_ptr<EmuThread> emu_thread; std::unique_ptr<EmuThread> emu_thread;
ProfilerWidget* profilerWidget; ProfilerWidget* profilerWidget;
MicroProfileDialog* microProfileDialog;
DisassemblerWidget* disasmWidget; DisassemblerWidget* disasmWidget;
RegistersWidget* registersWidget; RegistersWidget* registersWidget;
CallstackWidget* callstackWidget; CallstackWidget* callstackWidget;

@ -0,0 +1,13 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "util.h"
QFont GetMonospaceFont() {
QFont font("monospace");
// Automatic fallback to a monospace font on on platforms without a font called "monospace"
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
return font;
}

@ -0,0 +1,8 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QFont>
/// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc.
QFont GetMonospaceFont();

@ -11,6 +11,7 @@ set(SRCS
logging/text_formatter.cpp logging/text_formatter.cpp
logging/backend.cpp logging/backend.cpp
memory_util.cpp memory_util.cpp
microprofile.cpp
misc.cpp misc.cpp
profiler.cpp profiler.cpp
scm_rev.cpp scm_rev.cpp
@ -43,6 +44,8 @@ set(HEADERS
make_unique.h make_unique.h
math_util.h math_util.h
memory_util.h memory_util.h
microprofile.h
microprofileui.h
platform.h platform.h
profiler.h profiler.h
profiler_reporting.h profiler_reporting.h

@ -0,0 +1,7 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
// Includes the MicroProfile implementation in this file for compilation
#define MICROPROFILE_IMPL 1
#include "common/microprofile.h"

@ -0,0 +1,25 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
// Customized Citra settings.
// This file wraps the MicroProfile header so that these are consistent everywhere.
#define MICROPROFILE_WEBSERVER 0
#define MICROPROFILE_GPU_TIMERS 0 // TODO: Implement timer queries when we upgrade to OpenGL 3.3
#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<12) // 8 MB
#include <microprofile.h>
#define MP_RGB(r, g, b) ((r) << 16 | (g) << 8 | (b) << 0)
// On OS X, some Mach header included by MicroProfile defines these as macros, conflicting with
// identifiers we use.
#ifdef PAGE_SIZE
#undef PAGE_SIZE
#endif
#ifdef PAGE_MASK
#undef PAGE_MASK
#endif

@ -0,0 +1,16 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/microprofile.h"
// Customized Citra settings.
// This file wraps the MicroProfile header so that these are consistent everywhere.
#define MICROPROFILE_TEXT_WIDTH 6
#define MICROPROFILE_TEXT_HEIGHT 12
#define MICROPROFILE_HELP_ALT "Right-Click"
#define MICROPROFILE_HELP_MOD "Ctrl"
#include <microprofileui.h>

@ -9,6 +9,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "core/memory.h" #include "core/memory.h"
@ -3522,8 +3523,11 @@ enum {
FETCH_EXCEPTION FETCH_EXCEPTION
}; };
MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
Common::Profiling::ScopeTimer timer_decode(profile_decode); Common::Profiling::ScopeTimer timer_decode(profile_decode);
MICROPROFILE_SCOPE(DynCom_Decode);
// Decode instruction, get index // Decode instruction, get index
// Allocate memory and init InsCream // Allocate memory and init InsCream
@ -3588,8 +3592,11 @@ static int clz(unsigned int x) {
return n; return n;
} }
MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0));
unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned InterpreterMainLoop(ARMul_State* cpu) {
Common::Profiling::ScopeTimer timer_execute(profile_execute); Common::Profiling::ScopeTimer timer_execute(profile_execute);
MICROPROFILE_SCOPE(DynCom_Execute);
#undef RM #undef RM
#undef RS #undef RS

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/microprofile.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
@ -229,6 +230,10 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
if (Pica::g_debug_context) if (Pica::g_debug_context)
Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
if (screen_id == 0) {
MicroProfileFlip();
}
} }
/** /**

@ -5,6 +5,7 @@
#include <map> #include <map>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "common/symbols.h" #include "common/symbols.h"
@ -969,8 +970,11 @@ static const FunctionDef* GetSVCInfo(u32 func_num) {
return &SVC_Table[func_num]; return &SVC_Table[func_num];
} }
MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
void CallSVC(u32 immediate) { void CallSVC(u32 immediate) {
Common::Profiling::ScopeTimer timer_svc(profiler_svc); Common::Profiling::ScopeTimer timer_svc(profiler_svc);
MICROPROFILE_SCOPE(Kernel_SVC);
const FunctionDef* info = GetSVCInfo(immediate); const FunctionDef* info = GetSVCInfo(immediate);
if (info) { if (info) {

@ -9,6 +9,7 @@
#include "common/color.h" #include "common/color.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "core/settings.h" #include "core/settings.h"
@ -85,6 +86,9 @@ static Math::Vec4<u8> DecodePixel(Regs::PixelFormat input_format, const u8* src_
} }
} }
MICROPROFILE_DEFINE(GPU_DisplayTransfer, "GPU", "DisplayTransfer", MP_RGB(100, 100, 255));
MICROPROFILE_DEFINE(GPU_CmdlistProcessing, "GPU", "Cmdlist Processing", MP_RGB(100, 255, 100));
template <typename T> template <typename T>
inline void Write(u32 addr, const T data) { inline void Write(u32 addr, const T data) {
addr -= HW::VADDR_GPU; addr -= HW::VADDR_GPU;
@ -150,6 +154,8 @@ inline void Write(u32 addr, const T data) {
case GPU_REG_INDEX(display_transfer_config.trigger): case GPU_REG_INDEX(display_transfer_config.trigger):
{ {
MICROPROFILE_SCOPE(GPU_DisplayTransfer);
const auto& config = g_regs.display_transfer_config; const auto& config = g_regs.display_transfer_config;
if (config.trigger & 1) { if (config.trigger & 1) {
@ -344,6 +350,8 @@ inline void Write(u32 addr, const T data) {
const auto& config = g_regs.command_processor_config; const auto& config = g_regs.command_processor_config;
if (config.trigger & 1) if (config.trigger & 1)
{ {
MICROPROFILE_SCOPE(GPU_CmdlistProcessing);
u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress());
if (Pica::g_debug_context && Pica::g_debug_context->recorder) { if (Pica::g_debug_context && Pica::g_debug_context->recorder) {

@ -4,6 +4,7 @@
#include <boost/range/algorithm/fill.hpp> #include <boost/range/algorithm/fill.hpp>
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "core/hle/service/gsp_gpu.h" #include "core/hle/service/gsp_gpu.h"
@ -43,6 +44,8 @@ static const u32 expand_bits_to_bytes[] = {
0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
}; };
MICROPROFILE_DEFINE(GPU_Drawing, "GPU", "Drawing", MP_RGB(50, 50, 240));
static void WritePicaReg(u32 id, u32 value, u32 mask) { static void WritePicaReg(u32 id, u32 value, u32 mask) {
auto& regs = g_state.regs; auto& regs = g_state.regs;
@ -126,6 +129,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(trigger_draw_indexed): case PICA_REG_INDEX(trigger_draw_indexed):
{ {
Common::Profiling::ScopeTimer scope_timer(category_drawing); Common::Profiling::ScopeTimer scope_timer(category_drawing);
MICROPROFILE_SCOPE(GPU_Drawing);
#if PICA_LOG_TEV #if PICA_LOG_TEV
DebugUtils::DumpTevStageConfig(regs.GetTevStages()); DebugUtils::DumpTevStageConfig(regs.GetTevStages());

@ -7,6 +7,7 @@
#include "common/color.h" #include "common/color.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "core/hw/gpu.h" #include "core/hw/gpu.h"
@ -267,6 +268,7 @@ static int SignedArea (const Math::Vec2<Fix12P4>& vtx1,
}; };
static Common::Profiling::TimingCategory rasterization_category("Rasterization"); static Common::Profiling::TimingCategory rasterization_category("Rasterization");
MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240));
/** /**
* Helper function for ProcessTriangle with the "reversed" flag to allow for implementing * Helper function for ProcessTriangle with the "reversed" flag to allow for implementing
@ -279,6 +281,7 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
{ {
const auto& regs = g_state.regs; const auto& regs = g_state.regs;
Common::Profiling::ScopeTimer timer(rasterization_category); Common::Profiling::ScopeTimer timer(rasterization_category);
MICROPROFILE_SCOPE(GPU_Rasterization);
// vertex positions in rasterizer coordinates // vertex positions in rasterizer coordinates
static auto FloatToFix = [](float24 flt) { static auto FloatToFix = [](float24 flt) {

@ -7,6 +7,7 @@
#include "common/color.h" #include "common/color.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "core/hw/gpu.h" #include "core/hw/gpu.h"
@ -777,12 +778,16 @@ void RasterizerOpenGL::SyncDrawState() {
state.Apply(); state.Apply();
} }
MICROPROFILE_DEFINE(OpenGL_FramebufferReload, "OpenGL", "FB Reload", MP_RGB(70, 70, 200));
void RasterizerOpenGL::ReloadColorBuffer() { void RasterizerOpenGL::ReloadColorBuffer() {
u8* color_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetColorBufferPhysicalAddress()); u8* color_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetColorBufferPhysicalAddress());
if (color_buffer == nullptr) if (color_buffer == nullptr)
return; return;
MICROPROFILE_SCOPE(OpenGL_FramebufferReload);
u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format); u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format);
std::unique_ptr<u8[]> temp_fb_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]); std::unique_ptr<u8[]> temp_fb_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]);
@ -822,6 +827,8 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
if (depth_buffer == nullptr) if (depth_buffer == nullptr)
return; return;
MICROPROFILE_SCOPE(OpenGL_FramebufferReload);
u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format); u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format);
// OpenGL needs 4 bpp alignment for D24 // OpenGL needs 4 bpp alignment for D24
@ -868,6 +875,7 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
} }
Common::Profiling::TimingCategory buffer_commit_category("Framebuffer Commit"); Common::Profiling::TimingCategory buffer_commit_category("Framebuffer Commit");
MICROPROFILE_DEFINE(OpenGL_FramebufferCommit, "OpenGL", "FB Commit", MP_RGB(70, 70, 200));
void RasterizerOpenGL::CommitColorBuffer() { void RasterizerOpenGL::CommitColorBuffer() {
if (last_fb_color_addr != 0) { if (last_fb_color_addr != 0) {
@ -875,6 +883,7 @@ void RasterizerOpenGL::CommitColorBuffer() {
if (color_buffer != nullptr) { if (color_buffer != nullptr) {
Common::Profiling::ScopeTimer timer(buffer_commit_category); Common::Profiling::ScopeTimer timer(buffer_commit_category);
MICROPROFILE_SCOPE(OpenGL_FramebufferCommit);
u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format); u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format);
@ -911,6 +920,7 @@ void RasterizerOpenGL::CommitDepthBuffer() {
if (depth_buffer != nullptr) { if (depth_buffer != nullptr) {
Common::Profiling::ScopeTimer timer(buffer_commit_category); Common::Profiling::ScopeTimer timer(buffer_commit_category);
MICROPROFILE_SCOPE(OpenGL_FramebufferCommit);
u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format); u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format);

@ -4,6 +4,7 @@
#include "common/make_unique.h" #include "common/make_unique.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/microprofile.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "core/memory.h" #include "core/memory.h"
@ -16,6 +17,8 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
FullFlush(); FullFlush();
} }
MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) { void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) {
PAddr texture_addr = config.config.GetPhysicalAddress(); PAddr texture_addr = config.config.GetPhysicalAddress();
@ -25,6 +28,8 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.handle; state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.handle;
state.Apply(); state.Apply();
} else { } else {
MICROPROFILE_SCOPE(OpenGL_TextureUpload);
std::unique_ptr<CachedTexture> new_texture = Common::make_unique<CachedTexture>(); std::unique_ptr<CachedTexture> new_texture = Common::make_unique<CachedTexture>();
new_texture->texture.Create(); new_texture->texture.Create();

@ -9,6 +9,7 @@
#include "common/hash.h" #include "common/hash.h"
#include "common/make_unique.h" #include "common/make_unique.h"
#include "common/microprofile.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
@ -55,11 +56,13 @@ void Shutdown() {
} }
static Common::Profiling::TimingCategory shader_category("Vertex Shader"); static Common::Profiling::TimingCategory shader_category("Vertex Shader");
MICROPROFILE_DEFINE(GPU_VertexShader, "GPU", "Vertex Shader", MP_RGB(50, 50, 240));
OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attributes) { OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attributes) {
auto& config = g_state.regs.vs; auto& config = g_state.regs.vs;
Common::Profiling::ScopeTimer timer(shader_category); Common::Profiling::ScopeTimer timer(shader_category);
MICROPROFILE_SCOPE(GPU_VertexShader);
state.program_counter = config.main_offset; state.program_counter = config.main_offset;
state.debug.max_offset = 0; state.debug.max_offset = 0;