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 SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
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)
static float max(float r, float g, float b)
std::string void void auto Separator()
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size