mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #1048 from yuriks/microprofile
Integrate the MicroProfile profiling library
This commit is contained in:
		
						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) | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								externals/microprofile/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								externals/microprofile/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
							
								
								
									
										3571
									
								
								externals/microprofile/microprofile.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3571
									
								
								externals/microprofile/microprofile.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										3868
									
								
								externals/microprofile/microprofile_html.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3868
									
								
								externals/microprofile/microprofile_html.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										3348
									
								
								externals/microprofile/microprofileui.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3348
									
								
								externals/microprofile/microprofileui.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												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; | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								src/citra_qt/util/util.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/citra_qt/util/util.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/citra_qt/util/util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/citra_qt/util/util.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										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/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; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue