Provide bit-casted slot values from DebugTracePlayer.

Previously, the VariableData returned from a DebugTracePlayer contained
values in an int32_t, regardless of the slot's NumberKind. We had a
helper function which could stringize the bits, but otherwise the caller
was responsible for bit-casting the value manually.

Now, the DebugTracePlayer will automatically manage bit-casting for the
caller. The value returned in the VariableData is now a double (so it
is able to store an int32, uint32, or float at full precision).

This change was inspired by the recent Typescript port. (The value in
the Typescript VariableData uses a compound `number | boolean` type, so
it is able to fully represent any slot value natively.)

Change-Id: I5eec414236f76ad0ff51b0b19974e4a0025c4d62
Bug: skia:12666
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/489896
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:
John Stiles 2021-12-29 10:29:52 -05:00 committed by SkCQ
parent 0ada61c87e
commit d67f1f8f50
6 changed files with 57 additions and 37 deletions

View File

@ -24,42 +24,57 @@ std::string SkVMDebugTrace::getSlotComponentSuffix(int slotIndex) const {
}
if (slot.columns > 1) {
switch (slot.componentIndex) {
case 0: return ".x"; break;
case 1: return ".y"; break;
case 2: return ".z"; break;
case 3: return ".w"; break;
default: return "[???]"; break;
case 0: return ".x";
case 1: return ".y";
case 2: return ".z";
case 3: return ".w";
default: return "[???]";
}
}
return {};
}
std::string SkVMDebugTrace::getSlotValue(int slotIndex, int32_t value) const {
const SkSL::SkVMSlotInfo& slot = fSlotInfo[slotIndex];
switch (slot.numberKind) {
case SkSL::Type::NumberKind::kBoolean:
return value ? "true" : "false";
case SkSL::Type::NumberKind::kSigned:
default:
return std::to_string(value);
double SkVMDebugTrace::interpretValueBits(int slotIndex, int32_t valueBits) const {
SkASSERT(slotIndex >= 0);
SkASSERT((size_t)slotIndex < fSlotInfo.size());
switch (fSlotInfo[slotIndex].numberKind) {
case SkSL::Type::NumberKind::kUnsigned: {
uint32_t unsignedVal;
memcpy(&unsignedVal, &value, sizeof(unsignedVal));
return std::to_string(unsignedVal);
uint32_t uintValue;
static_assert(sizeof(uintValue) == sizeof(valueBits));
memcpy(&uintValue, &valueBits, sizeof(uintValue));
return uintValue;
}
case SkSL::Type::NumberKind::kFloat: {
float floatVal;
static_assert(sizeof(floatVal) == sizeof(value));
memcpy(&floatVal, &value, sizeof(floatVal));
float floatValue;
static_assert(sizeof(floatValue) == sizeof(valueBits));
memcpy(&floatValue, &valueBits, sizeof(floatValue));
return floatValue;
}
default: {
return valueBits;
}
}
}
std::string SkVMDebugTrace::slotValueToString(int slotIndex, double value) const {
SkASSERT(slotIndex >= 0);
SkASSERT((size_t)slotIndex < fSlotInfo.size());
switch (fSlotInfo[slotIndex].numberKind) {
case SkSL::Type::NumberKind::kBoolean: {
return value ? "true" : "false";
}
default: {
char buffer[32];
snprintf(buffer, SK_ARRAY_COUNT(buffer), "%.8g", floatVal);
snprintf(buffer, SK_ARRAY_COUNT(buffer), "%.8g", value);
return buffer;
}
}
}
std::string SkVMDebugTrace::getSlotValue(int slotIndex, int32_t valueBits) const {
return this->slotValueToString(slotIndex, this->interpretValueBits(slotIndex, valueBits));
}
void SkVMDebugTrace::setTraceCoord(const SkIPoint& coord) {
fTraceCoord = coord;
}

View File

@ -73,9 +73,15 @@ public:
/** Returns a slot's component as a variable-name suffix, e.g. ".x" or "[2][2]". */
std::string getSlotComponentSuffix(int slotIndex) const;
/** Returns a slot's value in human-readable form, e.g. "3.14" or "true" or "12345". */
/** Bit-casts a slot's value, then converts to text, e.g. "3.14" or "true" or "12345". */
std::string getSlotValue(int slotIndex, int32_t value) const;
/** Bit-casts a value for a given slot into a double, honoring the slot's NumberKind. */
double interpretValueBits(int slotIndex, int32_t valueBits) const;
/** Converts a numeric value into text, based on the slot's NumberKind. */
std::string slotValueToString(int slotIndex, double value) const;
/** The device-coordinate pixel to trace (controlled by setTraceCoord) */
SkIPoint fTraceCoord = {};

View File

@ -135,12 +135,13 @@ int SkVMDebugTracePlayer::getStackDepth() const {
}
std::vector<SkVMDebugTracePlayer::VariableData> SkVMDebugTracePlayer::getVariablesForDisplayMask(
const SkBitSet& bits) const {
SkASSERT(bits.size() == fSlots.size());
const SkBitSet& displayMask) const {
SkASSERT(displayMask.size() == fSlots.size());
std::vector<VariableData> vars;
bits.forEachSetIndex([&](int slot) {
vars.push_back({slot, fDirtyMask->test(slot), fSlots[slot].fValue});
displayMask.forEachSetIndex([&](int slot) {
double typedValue = fDebugTrace->interpretValueBits(slot, fSlots[slot].fValue);
vars.push_back({slot, fDirtyMask->test(slot), typedValue});
});
// Order the variable list so that the most recently-written variables are shown at the top.
std::stable_sort(vars.begin(), vars.end(), [&](const VariableData& a, const VariableData& b) {

View File

@ -74,9 +74,9 @@ public:
/** Returns variables from a stack frame, or from global scope. */
struct VariableData {
int fSlotIndex;
bool fDirty; // has this slot been written-to since the last step call?
int32_t fValue; // caller must type-pun bits to float/bool based on slot type
int fSlotIndex;
bool fDirty; // has this slot been written-to since the last step call?
double fValue; // value in slot (with type-conversion applied)
};
std::vector<VariableData> getLocalVariables(int stackFrameIndex) const;
std::vector<VariableData> getGlobalVariables() const;

View File

@ -76,18 +76,15 @@ static std::string make_vars_string(
text += slot.name;
text += trace.getSlotComponentSuffix(var.fSlotIndex);
text += " = ";
text += trace.getSlotValue(var.fSlotIndex, var.fValue);
text += trace.slotValueToString(var.fSlotIndex, var.fValue);
}
return text;
}
static std::string make_local_vars_string(const SkSL::SkVMDebugTrace& trace,
const SkSL::SkVMDebugTracePlayer& player,
int frame = -1) {
if (frame == -1) {
frame = player.getStackDepth() - 1;
}
const SkSL::SkVMDebugTracePlayer& player) {
int frame = player.getStackDepth() - 1;
return make_vars_string(trace, player.getLocalVariables(frame));
}

View File

@ -254,7 +254,8 @@ void SkSLDebuggerSlide::showVariableTable() {
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::Text("%s",
fTrace->slotValueToString(var.fSlotIndex, var.fValue).c_str());
}
}
}