summaryrefslogtreecommitdiff
path: root/src/citra_qt/debugger
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-04-04 12:57:31 +0200
committerGravatar Tony Wasserka2015-07-13 22:27:20 +0200
commit902fa4da52737d43e04c2a028658ad9840811a89 (patch)
tree0a2346b4e08b5865c3369247f5720453b170e0c6 /src/citra_qt/debugger
parentGPU: Be robust against nullptr addresses; properly reset busy bits in the tri... (diff)
downloadyuzu-902fa4da52737d43e04c2a028658ad9840811a89.tar.gz
yuzu-902fa4da52737d43e04c2a028658ad9840811a89.tar.xz
yuzu-902fa4da52737d43e04c2a028658ad9840811a89.zip
Add CiTrace recording support.
This is exposed in the GUI as a new "CiTrace Recording" widget. Playback is implemented by a standalone 3DS homebrew application (which only runs reliably within Citra currently; on an actual 3DS it will often crash still).
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r--src/citra_qt/debugger/graphics_breakpoint_observer.h2
-rw-r--r--src/citra_qt/debugger/graphics_tracing.cpp123
-rw-r--r--src/citra_qt/debugger/graphics_tracing.h27
3 files changed, 151 insertions, 1 deletions
diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.h b/src/citra_qt/debugger/graphics_breakpoint_observer.h
index f0d3361f8..02a0f4f4f 100644
--- a/src/citra_qt/debugger/graphics_breakpoint_observer.h
+++ b/src/citra_qt/debugger/graphics_breakpoint_observer.h
@@ -13,7 +13,7 @@
13 * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while 13 * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while
14 * the widget usually wants to perform reactions in the GUI thread. 14 * the widget usually wants to perform reactions in the GUI thread.
15 */ 15 */
16class BreakPointObserverDock : public QDockWidget, private Pica::DebugContext::BreakPointObserver { 16class BreakPointObserverDock : public QDockWidget, protected Pica::DebugContext::BreakPointObserver {
17 Q_OBJECT 17 Q_OBJECT
18 18
19public: 19public:
diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp
new file mode 100644
index 000000000..2e74193f5
--- /dev/null
+++ b/src/citra_qt/debugger/graphics_tracing.cpp
@@ -0,0 +1,123 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6
7#include <QBoxLayout>
8#include <QComboBox>
9#include <QFileDialog>
10#include <QLabel>
11#include <QPushButton>
12#include <QSpinBox>
13
14#include "core/hw/gpu.h"
15#include "video_core/pica.h"
16
17#include "nihstro/float24.h"
18
19#include "graphics_tracing.h"
20
21GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context,
22 QWidget* parent)
23 : BreakPointObserverDock(debug_context, tr("CiTrace Recorder"), parent) {
24
25 setObjectName("CiTracing");
26
27 QPushButton* start_recording = new QPushButton(tr("Start Recording"));
28 QPushButton* stop_recording = new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save"));
29 QPushButton* abort_recording = new QPushButton(tr("Abort Recording"));
30
31 connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, SLOT(setVisible(bool)));
32 connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, SLOT(setVisible(bool)));
33 connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, SLOT(setVisible(bool)));
34 connect(start_recording, SIGNAL(clicked()), this, SLOT(StartRecording()));
35 connect(stop_recording, SIGNAL(clicked()), this, SLOT(StopRecording()));
36 connect(abort_recording, SIGNAL(clicked()), this, SLOT(AbortRecording()));
37
38 stop_recording->setVisible(false);
39 abort_recording->setVisible(false);
40
41 auto main_widget = new QWidget;
42 auto main_layout = new QVBoxLayout;
43 {
44 auto sub_layout = new QHBoxLayout;
45 sub_layout->addWidget(start_recording);
46 sub_layout->addWidget(stop_recording);
47 sub_layout->addWidget(abort_recording);
48 main_layout->addLayout(sub_layout);
49 }
50 main_widget->setLayout(main_layout);
51 setWidget(main_widget);
52
53 // TODO: Make sure to have this widget disabled as soon as emulation is started!
54}
55
56void GraphicsTracingWidget::StartRecording() {
57 auto context = context_weak.lock();
58 if (!context)
59 return;
60
61 auto shader_binary = Pica::g_state.vs.program_code;
62 auto swizzle_data = Pica::g_state.vs.swizzle_data;
63
64 // Encode floating point numbers to 24-bit values
65 // TODO: Drop this explicit conversion once we store float24 values bit-correctly internally.
66 std::array<Math::Vec4<uint32_t>, 96> vs_float_uniforms;
67 for (unsigned i = 0; i < 96; ++i)
68 for (unsigned comp = 0; comp < 3; ++comp)
69 vs_float_uniforms[i][comp] = nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32());
70
71 auto recorder = new CiTrace::Recorder((u32*)&GPU::g_regs, 0x700, nullptr, 0, (u32*)&Pica::g_state.regs, 0x300,
72 shader_binary.data(), shader_binary.size(),
73 swizzle_data.data(), swizzle_data.size(),
74 (u32*)vs_float_uniforms.data(), vs_float_uniforms.size() * 4,
75 nullptr, 0, nullptr, 0, nullptr, 0 // Geometry shader is not implemented yet, so submit dummy data for now
76 );
77 context->recorder = std::shared_ptr<CiTrace::Recorder>(recorder);
78
79 emit SetStartTracingButtonEnabled(false);
80 emit SetStopTracingButtonEnabled(true);
81 emit SetAbortTracingButtonEnabled(true);
82}
83
84void GraphicsTracingWidget::StopRecording() {
85 auto context = context_weak.lock();
86 if (!context)
87 return;
88
89 QString filename = QFileDialog::getSaveFileName(this, tr("Save CiTrace"), "citrace.ctf",
90 tr("CiTrace File (*.ctf)"));
91
92 if (filename.isEmpty()) {
93 // If the user canceled the dialog, keep recording
94 return;
95 }
96
97 context->recorder->Finish(filename.toStdString());
98 context->recorder = nullptr;
99
100 emit SetStopTracingButtonEnabled(false);
101 emit SetAbortTracingButtonEnabled(false);
102 emit SetStartTracingButtonEnabled(true);
103}
104
105void GraphicsTracingWidget::AbortRecording() {
106 auto context = context_weak.lock();
107 if (!context)
108 return;
109
110 context->recorder = nullptr;
111
112 emit SetStopTracingButtonEnabled(false);
113 emit SetAbortTracingButtonEnabled(false);
114 emit SetStartTracingButtonEnabled(true);
115}
116
117void GraphicsTracingWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) {
118 widget()->setEnabled(true);
119}
120
121void GraphicsTracingWidget::OnResumed() {
122 widget()->setEnabled(false);
123}
diff --git a/src/citra_qt/debugger/graphics_tracing.h b/src/citra_qt/debugger/graphics_tracing.h
new file mode 100644
index 000000000..397a7173b
--- /dev/null
+++ b/src/citra_qt/debugger/graphics_tracing.h
@@ -0,0 +1,27 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "graphics_breakpoint_observer.h"
8
9class GraphicsTracingWidget : public BreakPointObserverDock {
10 Q_OBJECT
11
12public:
13 GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr);
14
15private slots:
16 void StartRecording();
17 void StopRecording();
18 void AbortRecording();
19
20 void OnBreakPointHit(Pica::DebugContext::Event event, void* data) override;
21 void OnResumed() override;
22
23signals:
24 void SetStartTracingButtonEnabled(bool enable);
25 void SetStopTracingButtonEnabled(bool enable);
26 void SetAbortTracingButtonEnabled(bool enable);
27};