20#include <unordered_map>
21#include <unordered_set>
32 fTrace = sk_make_sp<SkSL::DebugTracePriv>();
38 fTrace = sk_make_sp<SkSL::DebugTracePriv>();
39 fPlayer.
reset(
nullptr);
43void SkSLDebuggerSlide::showLoadTraceGUI() {
44 ImGui::InputText(
"Trace Path", fTraceFile, std::size(fTraceFile));
45 bool load = ImGui::Button(
"Load Debug Trace");
49 if (!file.isValid()) {
50 ImGui::OpenPopup(
"Can't Open Trace");
52 ImGui::OpenPopup(
"Invalid Trace");
55 fPlayer.
reset(fTrace);
62 if (ImGui::BeginPopupModal(
"Can't Open Trace",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
63 ImGui::Text(
"The trace file doesn't exist.");
65 if (ImGui::Button(
"OK", ImVec2(120, 0))) {
66 ImGui::CloseCurrentPopup();
71 if (ImGui::BeginPopupModal(
"Invalid Trace",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
72 ImGui::Text(
"The trace data could not be parsed.");
74 if (ImGui::Button(
"OK", ImVec2(120, 0))) {
75 ImGui::CloseCurrentPopup();
81void SkSLDebuggerSlide::showDebuggerGUI() {
82 if (ImGui::Button(
"Reset")) {
83 fPlayer.
reset(fTrace);
86 ImGui::SameLine(0, 100);
87 if (ImGui::Button(
"Step")) {
92 if (ImGui::Button(
"Step Over")) {
97 if (ImGui::Button(
"Step Out")) {
101 ImGui::SameLine(0, 100);
102 if (ImGui::Button(fPlayer.
getBreakpoints().empty() ?
"Run" :
"Run to Breakpoint")) {
107 this->showStackTraceTable();
108 this->showVariableTable();
109 this->showCodeTable();
112void SkSLDebuggerSlide::showCodeTable() {
113 constexpr ImGuiTableFlags kTableFlags =
114 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
115 ImGuiTableFlags_BordersV;
116 constexpr ImGuiTableColumnFlags kColumnFlags =
117 ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder |
118 ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoSort |
119 ImGuiTableColumnFlags_NoHeaderLabel;
121 ImVec2 contentRect = ImGui::GetContentRegionAvail();
122 ImVec2 codeViewSize = ImVec2(0.0f, contentRect.y);
123 if (ImGui::BeginTable(
"Code View", 2, kTableFlags, codeViewSize)) {
124 ImGui::TableSetupColumn(
"", kColumnFlags | ImGuiTableColumnFlags_WidthFixed);
125 ImGui::TableSetupColumn(
"Code", kColumnFlags | ImGuiTableColumnFlags_WidthStretch);
127 ImGuiListClipper clipper;
128 clipper.Begin(fTrace->
fSource.size());
129 while (clipper.Step()) {
130 for (
int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
131 size_t humanReadableLine = row + 1;
133 ImGui::TableNextRow();
135 ImGui::TableSetBgColor(
136 ImGuiTableBgTarget_RowBg1,
137 ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_TextSelectedBg)));
141 ImGui::TableSetColumnIndex(0);
143 LineNumberMap::const_iterator iter = lineNumberMap.find(humanReadableLine);
144 bool reachable = iter != lineNumberMap.end() && iter->second > 0;
145 bool breakpointOn = fPlayer.
getBreakpoints().count(humanReadableLine);
147 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
148 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 0.0f, 0.0f, 0.70f));
149 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.0f, 0.0f, 0.85f));
150 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
151 }
else if (reachable) {
152 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 0.75f));
153 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
154 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f));
155 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.4f));
157 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 0.25f));
158 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
159 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
160 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
162 if (ImGui::SmallButton(
SkStringPrintf(
"%03zu ", humanReadableLine).c_str())) {
165 }
else if (reachable) {
169 ImGui::PopStyleColor(4);
172 ImGui::TableSetColumnIndex(1);
173 ImGui::Text(
"%s", fTrace->
fSource[row].c_str());
178 int linesVisible = contentRect.y / ImGui::GetTextLineHeightWithSpacing();
179 int centerLine = (fPlayer.
getCurrentLine() - 1) - (linesVisible / 2);
180 centerLine = std::max(0, centerLine);
181 ImGui::SetScrollY(clipper.ItemsHeight * centerLine);
189void SkSLDebuggerSlide::showStackTraceTable() {
190 constexpr ImGuiTableFlags kTableFlags =
191 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
192 ImGuiTableFlags_BordersV | ImGuiTableFlags_NoHostExtendX;
193 constexpr ImGuiTableColumnFlags kColumnFlags =
194 ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
195 ImGuiTableColumnFlags_NoSort;
199 ImVec2 contentRect = ImGui::GetContentRegionAvail();
200 ImVec2 stackViewSize = ImVec2(contentRect.x / 3.0f,
201 ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
202 if (ImGui::BeginTable(
"Call Stack", 1, kTableFlags, stackViewSize)) {
203 ImGui::TableSetupColumn(
"Stack", kColumnFlags);
204 ImGui::TableHeadersRow();
206 ImGuiListClipper clipper;
207 clipper.Begin(callStack.size());
208 while (clipper.Step()) {
209 for (
int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
210 int funcIdx = callStack.rbegin()[row];
211 SkASSERT(funcIdx >= 0 && (
size_t)funcIdx < fTrace->fFuncInfo.size());
214 ImGui::TableNextRow();
215 ImGui::TableSetColumnIndex(0);
216 ImGui::Text(
"%s", funcInfo.
name.c_str());
225void SkSLDebuggerSlide::showVariableTable() {
226 constexpr ImGuiTableFlags kTableFlags =
227 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
228 ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable;
229 constexpr ImGuiTableColumnFlags kColumnFlags =
230 ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
231 ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthStretch;
234 std::vector<SkSL::SkSLDebugTracePlayer::VariableData>
vars;
240 ImVec2 varViewSize = ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
241 if (ImGui::BeginTable(
"Variables", 2, kTableFlags, varViewSize)) {
242 ImGui::TableSetupColumn(
"Variable", kColumnFlags);
243 ImGui::TableSetupColumn(
"Value", kColumnFlags);
244 ImGui::TableHeadersRow();
246 ImGuiListClipper clipper;
247 clipper.Begin(
vars.size());
248 while (clipper.Step()) {
249 for (
int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
255 ImGui::TableNextRow();
258 ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1,
259 ImGui::GetColorU32(ImVec4{0.0f, 1.0f, 0.0f, 0.20f}));
261 ImGui::TableSetColumnIndex(0);
262 ImGui::Text(
"%s%s", slotInfo.
name.c_str(),
264 ImGui::TableSetColumnIndex(1);
274void SkSLDebuggerSlide::showRootGUI() {
276 this->showLoadTraceGUI();
280 this->showDebuggerGUI();
285 ImGui::Begin(
"Debugger",
nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar);
constexpr SkColor SK_ColorWHITE
SkSL::SkSLDebugTracePlayer::LineNumberMap LineNumberMap
SK_API SkString static SkString SkStringPrintf()
void clear(SkColor color)
bool animate(double nanos) override
void draw(SkCanvas *canvas) override
void load(SkScalar winWidth, SkScalar winHeight) override
bool readTrace(SkStream *r)
std::vector< FunctionDebugInfo > fFuncInfo
std::vector< std::string > fSource
std::vector< SlotDebugInfo > fSlotInfo
std::string slotValueToString(int slotIndex, double value) const
std::string getSlotComponentSuffix(int slotIndex) const
const BreakpointSet & getBreakpoints()
int getStackDepth() const
const LineNumberMap & getLineNumbersReached() const
void reset(sk_sp< DebugTracePriv > trace)
std::vector< VariableData > getGlobalVariables() const
std::vector< VariableData > getLocalVariables(int stackFrameIndex) const
void removeBreakpoint(int line)
std::unordered_map< int, int > LineNumberMap
void setBreakpoints(std::unordered_set< int > breakpointLines)
int32_t getCurrentLine() const
std::vector< int > getCallStack() const
void addBreakpoint(int line)