Add a Variables pane to the SkSL debugger.
The currently-active stack frame is always shown. Values which were modified during the last step action are highlighted. http://screen/4E4BLXYJsDR5bhk Change-Id: I521d92fa6c1eabd64aaeeb188c71f04a79f827f5 Bug: skia:12666 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/483602 Commit-Queue: John Stiles <johnstiles@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
0385de0f88
commit
49cb6d7668
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2021 Google LLC
|
* Copyright 2021 Google LLC
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools/viewer/SkSLDebuggerSlide.h"
|
#include "tools/viewer/SkSLDebuggerSlide.h"
|
||||||
|
|
||||||
@ -44,6 +44,7 @@ void SkSLDebuggerSlide::showLoadTraceGUI() {
|
|||||||
// Trace loaded successfully. On the next refresh, the user will see the debug UI.
|
// Trace loaded successfully. On the next refresh, the user will see the debug UI.
|
||||||
fPlayer.reset(fTrace);
|
fPlayer.reset(fTrace);
|
||||||
fPlayer.step();
|
fPlayer.step();
|
||||||
|
fRefresh = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,27 +69,29 @@ void SkSLDebuggerSlide::showLoadTraceGUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkSLDebuggerSlide::showDebuggerGUI() {
|
void SkSLDebuggerSlide::showDebuggerGUI() {
|
||||||
bool updateScroll = false;
|
|
||||||
|
|
||||||
if (ImGui::Button("Step")) {
|
if (ImGui::Button("Step")) {
|
||||||
fPlayer.step();
|
fPlayer.step();
|
||||||
updateScroll = true;
|
fRefresh = true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Step Over")) {
|
if (ImGui::Button("Step Over")) {
|
||||||
fPlayer.stepOver();
|
fPlayer.stepOver();
|
||||||
updateScroll = true;
|
fRefresh = true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Step Out")) {
|
if (ImGui::Button("Step Out")) {
|
||||||
fPlayer.stepOut();
|
fPlayer.stepOut();
|
||||||
updateScroll = true;
|
fRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->showVariableTable();
|
||||||
|
this->showCodeTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkSLDebuggerSlide::showCodeTable() {
|
||||||
constexpr ImGuiTableFlags kTableFlags =
|
constexpr ImGuiTableFlags kTableFlags =
|
||||||
ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
|
ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
|
||||||
ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
|
ImGuiTableFlags_BordersV;
|
||||||
ImGuiTableFlags_Hideable;
|
|
||||||
constexpr ImGuiTableColumnFlags kColumnFlags =
|
constexpr ImGuiTableColumnFlags kColumnFlags =
|
||||||
ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder |
|
ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder |
|
||||||
ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoSort |
|
ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoSort |
|
||||||
@ -119,17 +122,66 @@ void SkSLDebuggerSlide::showDebuggerGUI() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateScroll) {
|
if (fRefresh) {
|
||||||
int linesVisible = contentRect.y / ImGui::GetTextLineHeightWithSpacing();
|
int linesVisible = contentRect.y / ImGui::GetTextLineHeightWithSpacing();
|
||||||
int centerLine = (fPlayer.getCurrentLine() - 1) - (linesVisible / 2);
|
int centerLine = (fPlayer.getCurrentLine() - 1) - (linesVisible / 2);
|
||||||
centerLine = std::max(0, centerLine);
|
centerLine = std::max(0, centerLine);
|
||||||
ImGui::SetScrollY(clipper.ItemsHeight * centerLine);
|
ImGui::SetScrollY(clipper.ItemsHeight * centerLine);
|
||||||
|
fRefresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkSLDebuggerSlide::showVariableTable() {
|
||||||
|
constexpr ImGuiTableFlags kTableFlags =
|
||||||
|
ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
|
||||||
|
ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable;
|
||||||
|
constexpr ImGuiTableColumnFlags kColumnFlags =
|
||||||
|
ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
|
||||||
|
ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthStretch;
|
||||||
|
|
||||||
|
int frame = fPlayer.getStackDepth() - 1;
|
||||||
|
std::vector<SkSL::SkVMDebugTracePlayer::VariableData> vars;
|
||||||
|
if (frame >= 0) {
|
||||||
|
vars = fPlayer.getLocalVariables(frame);
|
||||||
|
}
|
||||||
|
if (vars.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
constexpr int kVarNumRows = 12;
|
||||||
|
ImVec2 varViewSize = ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * kVarNumRows);
|
||||||
|
if (ImGui::BeginTable("Variables", /*column=*/2, kTableFlags, varViewSize)) {
|
||||||
|
ImGui::TableSetupColumn("Variable", kColumnFlags);
|
||||||
|
ImGui::TableSetupColumn("Value", kColumnFlags);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
ImGuiListClipper clipper;
|
||||||
|
clipper.Begin(vars.size());
|
||||||
|
while (clipper.Step()) {
|
||||||
|
for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
|
||||||
|
const SkSL::SkVMDebugTracePlayer::VariableData& var = vars.at(row);
|
||||||
|
SkASSERT(var.fSlotIndex >= 0 && (size_t)var.fSlotIndex < fTrace->fSlotInfo.size());
|
||||||
|
const SkSL::SkVMSlotInfo& slotInfo = fTrace->fSlotInfo[var.fSlotIndex];
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
if (var.fDirty) {
|
||||||
|
// Highlight recently-changed variables.
|
||||||
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1,
|
||||||
|
ImGui::GetColorU32(ImVec4{0.0f, 1.0f, 0.0f, 0.20f}));
|
||||||
|
}
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("%s%s", slotInfo.name.c_str(),
|
||||||
|
fTrace->getSlotComponentSuffix(var.fSlotIndex).c_str());
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::Text("%s", fTrace->getSlotValue(var.fSlotIndex, var.fValue).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SkSLDebuggerSlide::showRootGUI() {
|
void SkSLDebuggerSlide::showRootGUI() {
|
||||||
if (fTrace->fSource.empty()) {
|
if (fTrace->fSource.empty()) {
|
||||||
this->showLoadTraceGUI();
|
this->showLoadTraceGUI();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2021 Google LLC
|
* Copyright 2021 Google LLC
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SkSLDebuggerSlide_DEFINED
|
#ifndef SkSLDebuggerSlide_DEFINED
|
||||||
#define SkSLDebuggerSlide_DEFINED
|
#define SkSLDebuggerSlide_DEFINED
|
||||||
@ -32,9 +32,12 @@ private:
|
|||||||
void showRootGUI();
|
void showRootGUI();
|
||||||
void showLoadTraceGUI();
|
void showLoadTraceGUI();
|
||||||
void showDebuggerGUI();
|
void showDebuggerGUI();
|
||||||
|
void showCodeTable();
|
||||||
|
void showVariableTable();
|
||||||
|
|
||||||
sk_sp<SkSL::SkVMDebugTrace> fTrace;
|
sk_sp<SkSL::SkVMDebugTrace> fTrace;
|
||||||
SkSL::SkVMDebugTracePlayer fPlayer;
|
SkSL::SkVMDebugTracePlayer fPlayer;
|
||||||
|
bool fRefresh = false;
|
||||||
|
|
||||||
char fTraceFile[256] = "SkVMDebugTrace.json";
|
char fTraceFile[256] = "SkVMDebugTrace.json";
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user