Add SkVMDebugInfo::setSource.

This associates the input SkSL source with our debug info. It is
serialized out to .trace files. This will actually let us display the
code associated with `trace_line`.

Bug: skia:12614
Change-Id: I6c10af6fa6dd97ed8411f3460e103f442722b7f6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/472999
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-11-17 16:17:48 -05:00 committed by SkCQ
parent 2fb8dac598
commit 54b7bd33a1
4 changed files with 72 additions and 6 deletions

View File

@ -349,6 +349,9 @@ void SkVMGenerator::writeProgram(SkSpan<skvm::Val> uniforms,
void SkVMGenerator::setupGlobals(SkSpan<skvm::Val> uniforms, skvm::Coord device) {
if (fDebugInfo) {
// Copy the program source into the debug info so that it will be written in the trace file.
fDebugInfo->setSource(*fProgram.fSource);
// If we are debugging, we need to create a trace mask. This will be true when the current
// device coordinates match the requested trace coordinates.
if (fDebugInfo->fTraceCoord) {

View File

@ -10,6 +10,8 @@
#include "src/utils/SkJSON.h"
#include "src/utils/SkJSONWriter.h"
#include <sstream>
namespace SkSL {
void SkVMDebugInfo::setTraceCoord(skvm::Coord coord) {
@ -18,6 +20,14 @@ void SkVMDebugInfo::setTraceCoord(skvm::Coord coord) {
fTraceCoord = {coord.x + 0.5, coord.y + 0.5};
}
void SkVMDebugInfo::setSource(std::string source) {
std::stringstream stream{std::move(source)};
while (stream.good()) {
fSource.push_back({});
std::getline(stream, fSource.back(), '\n');
}
}
void SkVMDebugInfo::dump(SkWStream* o) const {
for (size_t index = 0; index < fSlotInfo.size(); ++index) {
const SkVMSlotInfo& info = fSlotInfo[index];
@ -69,6 +79,13 @@ void SkVMDebugInfo::writeTrace(SkWStream* w) const {
SkJSONWriter json(w);
json.beginObject(); // root
json.beginArray("source");
for (const std::string& line : fSource) {
json.appendString(line.c_str());
}
json.endArray(); // code
json.beginArray("slots");
for (size_t index = 0; index < fSlotInfo.size(); ++index) {
@ -109,6 +126,20 @@ bool SkVMDebugInfo::readTrace(SkStream* r) {
if (!root) {
return false;
}
const skjson::ArrayValue* source = (*root)["source"];
if (!source) {
return false;
}
fSource.clear();
for (const skjson::StringValue* line : *source) {
if (!line) {
return false;
}
fSource.push_back(line->begin());
}
const skjson::ArrayValue* slots = (*root)["slots"];
if (!slots) {
return false;

View File

@ -45,6 +45,9 @@ public:
*/
void setTraceCoord(skvm::Coord coord);
/** Attaches the SkSL source to be debugged. */
void setSource(std::string source);
/** Serialization for .trace files. */
bool readTrace(SkStream* r);
void writeTrace(SkWStream* w) const;
@ -56,6 +59,9 @@ public:
std::vector<SkVMSlotInfo> fSlotInfo;
std::vector<SkVMFunctionInfo> fFuncInfo;
/** The SkSL code, split line-by-line. */
std::vector<std::string> fSource;
skvm::Coord fTraceCoord;
};

View File

@ -9,8 +9,27 @@
#include "src/sksl/codegen/SkVMDebugInfo.h"
#include "tests/Test.h"
DEF_TEST(SkVMDebugInfoSetSource, r) {
SkSL::SkVMDebugInfo i;
i.setSource("SkVMDebugInfo::setSource unit test\n"
"\t// first line\n"
"\t// second line\n"
"\t// third line");
REPORTER_ASSERT(r, i.fSource.size() == 4);
REPORTER_ASSERT(r, i.fSource[0] == "SkVMDebugInfo::setSource unit test");
REPORTER_ASSERT(r, i.fSource[1] == "\t// first line");
REPORTER_ASSERT(r, i.fSource[2] == "\t// second line");
REPORTER_ASSERT(r, i.fSource[3] == "\t// third line");
}
DEF_TEST(SkVMDebugInfoWriteTrace, r) {
SkSL::SkVMDebugInfo i;
i.fSource = {
"\t// first line",
"// \"second line\"",
"//\\\\//\\\\ third line",
};
i.fSlotInfo = {
{"SkVM_Debug_Info", 1, 2, 3, (SkSL::Type::NumberKind)4, 5},
{"Unit_Test", 6, 7, 8, (SkSL::Type::NumberKind)9, 10},
@ -23,9 +42,10 @@ DEF_TEST(SkVMDebugInfoWriteTrace, r) {
sk_sp<SkData> trace = wstream.detachAsData();
static constexpr char kExpected[] =
R"({"slots":[{"slot":0,"name":"SkVM_Debug_Info","columns":1,"rows":2,"index":3,"ki)"
R"(nd":4,"line":5},{"slot":1,"name":"Unit_Test","columns":6,"rows":7,"index":8,"ki)"
R"(nd":9,"line":10}],"functions":[{"slot":0,"name":"void testFunc();"}]})";
R"({"source":["\t// first line","// \"second line\"","//\\\\//\\\\ third line"],"s)"
R"(lots":[{"slot":0,"name":"SkVM_Debug_Info","columns":1,"rows":2,"index":3,"kind")"
R"(:4,"line":5},{"slot":1,"name":"Unit_Test","columns":6,"rows":7,"index":8,"kind")"
R"(:9,"line":10}],"functions":[{"slot":0,"name":"void testFunc();"}]})";
skstd::string_view actual{reinterpret_cast<const char*>(trace->bytes()), trace->size()};
@ -36,17 +56,23 @@ DEF_TEST(SkVMDebugInfoWriteTrace, r) {
DEF_TEST(SkVMDebugInfoReadTrace, r) {
const skstd::string_view kJSONTrace =
R"({"slots":[{"slot":0,"name":"SkVM_Debug_Info","columns":1,"rows":2,"index":3,"ki)"
R"(nd":4,"line":5},{"slot":1,"name":"Unit_Test","columns":6,"rows":7,"index":8,"ki)"
R"(nd":9,"line":10}],"functions":[{"slot":0,"name":"void testFunc();"}]})";
R"({"source":["\t// first line","// \"second line\"","//\\\\//\\\\ third line"],"s)"
R"(lots":[{"slot":0,"name":"SkVM_Debug_Info","columns":1,"rows":2,"index":3,"kind")"
R"(:4,"line":5},{"slot":1,"name":"Unit_Test","columns":6,"rows":7,"index":8,"kind")"
R"(:9,"line":10}],"functions":[{"slot":0,"name":"void testFunc();"}]})";
SkMemoryStream stream(kJSONTrace.data(), kJSONTrace.size(), /*copyData=*/false);
SkSL::SkVMDebugInfo i;
REPORTER_ASSERT(r, i.readTrace(&stream));
REPORTER_ASSERT(r, i.fSource.size() == 3);
REPORTER_ASSERT(r, i.fSlotInfo.size() == 2);
REPORTER_ASSERT(r, i.fFuncInfo.size() == 1);
REPORTER_ASSERT(r, i.fSource[0] == "\t// first line");
REPORTER_ASSERT(r, i.fSource[1] == "// \"second line\"");
REPORTER_ASSERT(r, i.fSource[2] == "//\\\\//\\\\ third line");
REPORTER_ASSERT(r, i.fSlotInfo[0].name == "SkVM_Debug_Info");
REPORTER_ASSERT(r, i.fSlotInfo[0].columns == 1);
REPORTER_ASSERT(r, i.fSlotInfo[0].rows == 2);