mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 22:00:05 +00:00 
			
		
		
		
	Integrate the MicroProfile profiling library
This brings goodies such as a configurable user interface and multi-threaded timeline view.
This commit is contained in:
		
							parent
							
								
									c7745408f7
								
							
						
					
					
						commit
						0fcabd2b11
					
				
					 24 changed files with 11142 additions and 0 deletions
				
			
		|  | @ -6,6 +6,9 @@ | |||
| #include <thread> | ||||
| #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 | ||||
| #include <getopt.h> | ||||
| #else | ||||
|  | @ -59,6 +62,8 @@ int main(int argc, char **argv) { | |||
|     Log::Filter log_filter(Log::Level::Debug); | ||||
|     Log::SetFilter(&log_filter); | ||||
| 
 | ||||
|     MicroProfileOnThreadCreate("EmuThread"); | ||||
| 
 | ||||
|     if (boot_filename.empty()) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); | ||||
|         return -1; | ||||
|  | @ -89,5 +94,7 @@ int main(int argc, char **argv) { | |||
| 
 | ||||
|     delete emu_window; | ||||
| 
 | ||||
|     MicroProfileShutdown(); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "common/string_util.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/key_map.h" | ||||
| #include "common/microprofile.h" | ||||
| 
 | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
|  | @ -37,6 +38,8 @@ EmuThread::EmuThread(GRenderWindow* render_window) : | |||
| void EmuThread::run() { | ||||
|     render_window->MakeCurrent(); | ||||
| 
 | ||||
|     MicroProfileOnThreadCreate("EmuThread"); | ||||
| 
 | ||||
|     stop_run = false; | ||||
| 
 | ||||
|     // holds whether the cpu was running during the last iteration,
 | ||||
|  | @ -69,6 +72,8 @@ void EmuThread::run() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     MicroProfileOnThreadExit(); | ||||
| 
 | ||||
|     render_window->moveContext(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,9 +2,21 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QMouseEvent> | ||||
| #include <QPainter> | ||||
| #include <QString> | ||||
| 
 | ||||
| #include "profiler.h" | ||||
| 
 | ||||
| #include "citra_qt/util/util.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; | ||||
| 
 | ||||
|  | @ -136,3 +148,193 @@ void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) | |||
|         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; | ||||
| }; | ||||
| 
 | ||||
| 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/filter.h" | ||||
| #include "common/make_unique.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/platform.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
|  | @ -64,6 +65,9 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) | |||
|     addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); | ||||
|     profilerWidget->hide(); | ||||
| 
 | ||||
|     microProfileDialog = new MicroProfileDialog(this); | ||||
|     microProfileDialog->hide(); | ||||
| 
 | ||||
|     disasmWidget = new DisassemblerWidget(this, emu_thread.get()); | ||||
|     addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); | ||||
|     disasmWidget->hide(); | ||||
|  | @ -102,6 +106,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) | |||
| 
 | ||||
|     QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); | ||||
|     debug_menu->addAction(profilerWidget->toggleViewAction()); | ||||
|     debug_menu->addAction(microProfileDialog->toggleViewAction()); | ||||
|     debug_menu->addAction(disasmWidget->toggleViewAction()); | ||||
|     debug_menu->addAction(registersWidget->toggleViewAction()); | ||||
|     debug_menu->addAction(callstackWidget->toggleViewAction()); | ||||
|  | @ -128,6 +133,8 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) | |||
|     restoreGeometry(settings.value("geometry").toByteArray()); | ||||
|     restoreState(settings.value("state").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); | ||||
|     SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked()); | ||||
|  | @ -434,6 +441,8 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
|     settings.setValue("geometry", saveGeometry()); | ||||
|     settings.setValue("state", saveState()); | ||||
|     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("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked()); | ||||
|     settings.setValue("firstStart", false); | ||||
|  | @ -456,6 +465,11 @@ int main(int argc, char* argv[]) { | |||
|     Log::Filter log_filter(Log::Level::Info); | ||||
|     Log::SetFilter(&log_filter); | ||||
| 
 | ||||
|     MicroProfileOnThreadCreate("Frontend"); | ||||
|     SCOPE_EXIT({ | ||||
|         MicroProfileShutdown(); | ||||
|     }); | ||||
| 
 | ||||
|     // Init settings params
 | ||||
|     QSettings::setDefaultFormat(QSettings::IniFormat); | ||||
|     QCoreApplication::setOrganizationName("Citra team"); | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ class GImageInfo; | |||
| class GRenderWindow; | ||||
| class EmuThread; | ||||
| class ProfilerWidget; | ||||
| class MicroProfileDialog; | ||||
| class DisassemblerWidget; | ||||
| class RegistersWidget; | ||||
| class CallstackWidget; | ||||
|  | @ -104,6 +105,7 @@ private: | |||
|     std::unique_ptr<EmuThread> emu_thread; | ||||
| 
 | ||||
|     ProfilerWidget* profilerWidget; | ||||
|     MicroProfileDialog* microProfileDialog; | ||||
|     DisassemblerWidget* disasmWidget; | ||||
|     RegistersWidget* registersWidget; | ||||
|     CallstackWidget* callstackWidget; | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ set(SRCS | |||
|             logging/text_formatter.cpp | ||||
|             logging/backend.cpp | ||||
|             memory_util.cpp | ||||
|             microprofile.cpp | ||||
|             misc.cpp | ||||
|             profiler.cpp | ||||
|             scm_rev.cpp | ||||
|  | @ -43,6 +44,8 @@ set(HEADERS | |||
|             make_unique.h | ||||
|             math_util.h | ||||
|             memory_util.h | ||||
|             microprofile.h | ||||
|             microprofileui.h | ||||
|             platform.h | ||||
|             profiler.h | ||||
|             profiler_reporting.h | ||||
|  |  | |||
							
								
								
									
										7
									
								
								src/common/microprofile.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/common/microprofile.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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" | ||||
							
								
								
									
										25
									
								
								src/common/microprofile.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/microprofile.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
							
								
								
									
										16
									
								
								src/common/microprofileui.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/common/microprofileui.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.h" | ||||
| 
 | ||||
| #include "core/memory.h" | ||||
|  | @ -3522,8 +3523,11 @@ enum { | |||
|     FETCH_EXCEPTION | ||||
| }; | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); | ||||
| 
 | ||||
| static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | ||||
|     Common::Profiling::ScopeTimer timer_decode(profile_decode); | ||||
|     MICROPROFILE_SCOPE(DynCom_Decode); | ||||
| 
 | ||||
|     // Decode instruction, get index
 | ||||
|     // Allocate memory and init InsCream
 | ||||
|  | @ -3588,8 +3592,11 @@ static int clz(unsigned int x) { | |||
|     return n; | ||||
| } | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0)); | ||||
| 
 | ||||
| unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||
|     Common::Profiling::ScopeTimer timer_execute(profile_execute); | ||||
|     MICROPROFILE_SCOPE(DynCom_Execute); | ||||
| 
 | ||||
|     #undef RM | ||||
|     #undef RS | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/bit_field.h" | ||||
| #include "common/microprofile.h" | ||||
| 
 | ||||
| #include "core/memory.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
|  | @ -229,6 +230,10 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 
 | ||||
|     if (Pica::g_debug_context) | ||||
|         Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); | ||||
| 
 | ||||
|     if (screen_id == 0) { | ||||
|         MicroProfileFlip(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <map> | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/symbols.h" | ||||
|  | @ -969,8 +970,11 @@ static const FunctionDef* GetSVCInfo(u32 func_num) { | |||
|     return &SVC_Table[func_num]; | ||||
| } | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | ||||
| 
 | ||||
| void CallSVC(u32 immediate) { | ||||
|     Common::Profiling::ScopeTimer timer_svc(profiler_svc); | ||||
|     MICROPROFILE_SCOPE(Kernel_SVC); | ||||
| 
 | ||||
|     const FunctionDef* info = GetSVCInfo(immediate); | ||||
|     if (info) { | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include "common/color.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/vector_math.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> | ||||
| inline void Write(u32 addr, const T data) { | ||||
|     addr -= HW::VADDR_GPU; | ||||
|  | @ -150,6 +154,8 @@ inline void Write(u32 addr, const T data) { | |||
| 
 | ||||
|     case GPU_REG_INDEX(display_transfer_config.trigger): | ||||
|     { | ||||
|         MICROPROFILE_SCOPE(GPU_DisplayTransfer); | ||||
| 
 | ||||
|         const auto& config = g_regs.display_transfer_config; | ||||
|         if (config.trigger & 1) { | ||||
| 
 | ||||
|  | @ -344,6 +350,8 @@ inline void Write(u32 addr, const T data) { | |||
|         const auto& config = g_regs.command_processor_config; | ||||
|         if (config.trigger & 1) | ||||
|         { | ||||
|             MICROPROFILE_SCOPE(GPU_CmdlistProcessing); | ||||
| 
 | ||||
|             u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); | ||||
| 
 | ||||
|             if (Pica::g_debug_context && Pica::g_debug_context->recorder) { | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #include <boost/range/algorithm/fill.hpp> | ||||
| 
 | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.h" | ||||
| 
 | ||||
| #include "core/hle/service/gsp_gpu.h" | ||||
|  | @ -43,6 +44,8 @@ static const u32 expand_bits_to_bytes[] = { | |||
|     0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff | ||||
| }; | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(GPU_Drawing, "GPU", "Drawing", MP_RGB(50, 50, 240)); | ||||
| 
 | ||||
| static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||
|     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): | ||||
|         { | ||||
|             Common::Profiling::ScopeTimer scope_timer(category_drawing); | ||||
|             MICROPROFILE_SCOPE(GPU_Drawing); | ||||
| 
 | ||||
| #if PICA_LOG_TEV | ||||
|             DebugUtils::DumpTevStageConfig(regs.GetTevStages()); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "common/color.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.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"); | ||||
| MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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; | ||||
|     Common::Profiling::ScopeTimer timer(rasterization_category); | ||||
|     MICROPROFILE_SCOPE(GPU_Rasterization); | ||||
| 
 | ||||
|     // vertex positions in rasterizer coordinates
 | ||||
|     static auto FloatToFix = [](float24 flt) { | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| #include "common/color.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.h" | ||||
| 
 | ||||
| #include "core/hw/gpu.h" | ||||
|  | @ -777,12 +778,16 @@ void RasterizerOpenGL::SyncDrawState() { | |||
|     state.Apply(); | ||||
| } | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(OpenGL_FramebufferReload, "OpenGL", "FB Reload", MP_RGB(70, 70, 200)); | ||||
| 
 | ||||
| void RasterizerOpenGL::ReloadColorBuffer() { | ||||
|     u8* color_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetColorBufferPhysicalAddress()); | ||||
| 
 | ||||
|     if (color_buffer == nullptr) | ||||
|         return; | ||||
| 
 | ||||
|     MICROPROFILE_SCOPE(OpenGL_FramebufferReload); | ||||
| 
 | ||||
|     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]); | ||||
|  | @ -822,6 +827,8 @@ void RasterizerOpenGL::ReloadDepthBuffer() { | |||
|     if (depth_buffer == nullptr) | ||||
|         return; | ||||
| 
 | ||||
|     MICROPROFILE_SCOPE(OpenGL_FramebufferReload); | ||||
| 
 | ||||
|     u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format); | ||||
| 
 | ||||
|     // OpenGL needs 4 bpp alignment for D24
 | ||||
|  | @ -868,6 +875,7 @@ void RasterizerOpenGL::ReloadDepthBuffer() { | |||
| } | ||||
| 
 | ||||
| Common::Profiling::TimingCategory buffer_commit_category("Framebuffer Commit"); | ||||
| MICROPROFILE_DEFINE(OpenGL_FramebufferCommit, "OpenGL", "FB Commit", MP_RGB(70, 70, 200)); | ||||
| 
 | ||||
| void RasterizerOpenGL::CommitColorBuffer() { | ||||
|     if (last_fb_color_addr != 0) { | ||||
|  | @ -875,6 +883,7 @@ void RasterizerOpenGL::CommitColorBuffer() { | |||
| 
 | ||||
|         if (color_buffer != nullptr) { | ||||
|             Common::Profiling::ScopeTimer timer(buffer_commit_category); | ||||
|             MICROPROFILE_SCOPE(OpenGL_FramebufferCommit); | ||||
| 
 | ||||
|             u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format); | ||||
| 
 | ||||
|  | @ -911,6 +920,7 @@ void RasterizerOpenGL::CommitDepthBuffer() { | |||
| 
 | ||||
|         if (depth_buffer != nullptr) { | ||||
|             Common::Profiling::ScopeTimer timer(buffer_commit_category); | ||||
|             MICROPROFILE_SCOPE(OpenGL_FramebufferCommit); | ||||
| 
 | ||||
|             u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #include "common/make_unique.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/vector_math.h" | ||||
| 
 | ||||
| #include "core/memory.h" | ||||
|  | @ -16,6 +17,8 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { | |||
|     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) { | ||||
|     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.Apply(); | ||||
|     } else { | ||||
|         MICROPROFILE_SCOPE(OpenGL_TextureUpload); | ||||
| 
 | ||||
|         std::unique_ptr<CachedTexture> new_texture = Common::make_unique<CachedTexture>(); | ||||
| 
 | ||||
|         new_texture->texture.Create(); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| 
 | ||||
| #include "common/hash.h" | ||||
| #include "common/make_unique.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/profiler.h" | ||||
| 
 | ||||
| #include "video_core/debug_utils/debug_utils.h" | ||||
|  | @ -55,11 +56,13 @@ void Shutdown() { | |||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     auto& config = g_state.regs.vs; | ||||
| 
 | ||||
|     Common::Profiling::ScopeTimer timer(shader_category); | ||||
|     MICROPROFILE_SCOPE(GPU_VertexShader); | ||||
| 
 | ||||
|     state.program_counter = config.main_offset; | ||||
|     state.debug.max_offset = 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue