mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add a $dispatch() helper to filter only dispatches (and properties)
This commit is contained in:
@@ -1219,6 +1219,7 @@ public:
|
||||
MAKE_BUILTIN_FILTER(param);
|
||||
MAKE_BUILTIN_FILTER(event);
|
||||
MAKE_BUILTIN_FILTER(draw);
|
||||
MAKE_BUILTIN_FILTER(dispatch);
|
||||
}
|
||||
}
|
||||
void ResetCache() { m_VisibleCache.clear(); }
|
||||
@@ -1852,6 +1853,246 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
IEventBrowser::EventFilterCallback filterFunction_dispatch(QString name, QString parameters,
|
||||
ParseError &errors)
|
||||
{
|
||||
// $dispatch(...) => returns true only for dispatches, optionally with a particular property
|
||||
// filter
|
||||
QList<Token> tokens = tokenise(parameters);
|
||||
|
||||
// no parameters, just return if it's a draw
|
||||
if(tokens.isEmpty())
|
||||
return [](ICaptureContext *, const rdcstr &, const rdcstr &, uint32_t eventId,
|
||||
const SDChunk *, const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch);
|
||||
};
|
||||
|
||||
// we upcast to int64_t so we can compare both unsigned and signed values without losing any
|
||||
// precision (we don't have any uint64_ts to compare)
|
||||
using PropGetter = int64_t (*)(const DrawcallDescription *);
|
||||
|
||||
struct NamedProp
|
||||
{
|
||||
const char *name;
|
||||
PropGetter getter;
|
||||
};
|
||||
|
||||
static const NamedProp namedProps[] = {
|
||||
NAMED_PROP("dispatchx", draw->dispatchDimension[0]),
|
||||
NAMED_PROP("dispatchy", draw->dispatchDimension[1]),
|
||||
NAMED_PROP("dispatchz", draw->dispatchDimension[2]),
|
||||
NAMED_PROP("x", draw->dispatchDimension[0]), NAMED_PROP("y", draw->dispatchDimension[1]),
|
||||
NAMED_PROP("z", draw->dispatchDimension[2]),
|
||||
NAMED_PROP("dispatchsize", draw->dispatchDimension[0] * draw->dispatchDimension[1] *
|
||||
draw->dispatchDimension[2]),
|
||||
NAMED_PROP("size", draw->dispatchDimension[0] * draw->dispatchDimension[1] *
|
||||
draw->dispatchDimension[2]),
|
||||
};
|
||||
|
||||
QByteArray prop = tokens[0].text.toLower().toLatin1();
|
||||
|
||||
int numericPropIndex = -1;
|
||||
for(size_t i = 0; i < ARRAY_COUNT(namedProps); i++)
|
||||
{
|
||||
if(prop == namedProps[i].name)
|
||||
numericPropIndex = (int)i;
|
||||
}
|
||||
|
||||
// any numeric value that can be compared to a number
|
||||
if(numericPropIndex >= 0)
|
||||
{
|
||||
PropGetter propGetter = namedProps[numericPropIndex].getter;
|
||||
|
||||
static const QStringList operators = {
|
||||
lit("=="), lit("!="), lit("<"), lit(">"), lit("<="), lit(">="),
|
||||
};
|
||||
|
||||
int operatorIdx = tokens.size() > 1 ? operators.indexOf(tokens[1].text) : -1;
|
||||
|
||||
if(tokens.size() > 1 && tokens[1].text == lit("="))
|
||||
operatorIdx = 0;
|
||||
|
||||
if(tokens.size() != 3 || operatorIdx < 0 || operatorIdx >= operators.size())
|
||||
{
|
||||
errors.setText(tr("Invalid expression, expected single comparison with operators: %3",
|
||||
"EventFilterModel")
|
||||
.arg(operators.join(lit(", "))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
int64_t value = tokens[2].text.toLongLong(&ok, 0);
|
||||
|
||||
if(!ok)
|
||||
{
|
||||
errors.position = tokens[2].position;
|
||||
errors.length = tokens[2].length;
|
||||
errors.setText(tr("Invalid value, expected integer", "EventFilterModel"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(operatorIdx)
|
||||
{
|
||||
case 0:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) == value;
|
||||
};
|
||||
case 1:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) != value;
|
||||
};
|
||||
case 2:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) < value;
|
||||
};
|
||||
case 3:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) > value;
|
||||
};
|
||||
case 4:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) <= value;
|
||||
};
|
||||
case 5:
|
||||
return [propGetter, value](ICaptureContext *, const rdcstr &, const rdcstr &,
|
||||
uint32_t eventId, const SDChunk *,
|
||||
const DrawcallDescription *draw, const rdcstr &) {
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
propGetter(draw) >= value;
|
||||
};
|
||||
default: errors.setText(tr("Internal error", "EventFilterModel")); return NULL;
|
||||
}
|
||||
}
|
||||
else if(tokens[0].text.toLower() == lit("duration"))
|
||||
{
|
||||
// deliberately don't allow equality/inequality
|
||||
static const QStringList operators = {
|
||||
lit("<"), lit(">"), lit("<="), lit(">="),
|
||||
};
|
||||
|
||||
int operatorIdx = tokens.size() > 1 ? operators.indexOf(tokens[1].text) : -1;
|
||||
|
||||
if(tokens.size() != 3 || operatorIdx < 0 || operatorIdx >= operators.size())
|
||||
{
|
||||
errors.setText(tr("Invalid expression, expected single comparison with operators: %3",
|
||||
"EventFilterModel")
|
||||
.arg(operators.join(lit(", "))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// multiplier to change the read value into nanoseconds
|
||||
double mult = 1.0;
|
||||
if(tokens[2].text.endsWith(lit("ms")))
|
||||
{
|
||||
mult = 1000000.0;
|
||||
tokens[2].text.resize(tokens[2].text.size() - 2);
|
||||
}
|
||||
else if(tokens[2].text.endsWith(lit("us")))
|
||||
{
|
||||
mult = 1000.0;
|
||||
tokens[2].text.resize(tokens[2].text.size() - 2);
|
||||
}
|
||||
else if(tokens[2].text.endsWith(lit("ns")))
|
||||
{
|
||||
mult = 1.0;
|
||||
tokens[2].text.resize(tokens[2].text.size() - 2);
|
||||
}
|
||||
else if(tokens[2].text.endsWith(lit("s")))
|
||||
{
|
||||
mult = 1000000000.0;
|
||||
tokens[2].text.resize(tokens[2].text.size() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.position = tokens[2].position;
|
||||
errors.length = tokens[2].length;
|
||||
errors.setText(
|
||||
tr("Duration must be suffixed with one of s, ms, us, or ns", "EventFilterModel"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
double value = tokens[2].text.toDouble(&ok);
|
||||
|
||||
// if it doesn't read as a double, try as an integer
|
||||
if(!ok)
|
||||
{
|
||||
int64_t valInt = tokens[2].text.toLongLong(&ok);
|
||||
|
||||
if(ok)
|
||||
value = double(valInt);
|
||||
}
|
||||
|
||||
if(!ok)
|
||||
{
|
||||
errors.position = tokens[2].position;
|
||||
errors.length = tokens[2].length;
|
||||
errors.setText(tr("Invalid value, expected duration suffixed with one of s, ms, us, or ns",
|
||||
"EventFilterModel"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t nanoValue = int64_t(value * mult);
|
||||
|
||||
switch(operatorIdx)
|
||||
{
|
||||
case 0:
|
||||
return
|
||||
[this, nanoValue](ICaptureContext *, const rdcstr &, const rdcstr &, uint32_t eventId,
|
||||
const SDChunk *, const DrawcallDescription *draw, const rdcstr &) {
|
||||
double dur = m_Model->GetSecondsDurationForEID(eventId);
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
dur >= 0.0 && int64_t(dur * 1000000000.0) < nanoValue;
|
||||
};
|
||||
case 1:
|
||||
return
|
||||
[this, nanoValue](ICaptureContext *, const rdcstr &, const rdcstr &, uint32_t eventId,
|
||||
const SDChunk *, const DrawcallDescription *draw, const rdcstr &) {
|
||||
double dur = m_Model->GetSecondsDurationForEID(eventId);
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
dur >= 0.0 && int64_t(dur * 1000000000.0) > nanoValue;
|
||||
};
|
||||
case 2:
|
||||
return
|
||||
[this, nanoValue](ICaptureContext *, const rdcstr &, const rdcstr &, uint32_t eventId,
|
||||
const SDChunk *, const DrawcallDescription *draw, const rdcstr &) {
|
||||
double dur = m_Model->GetSecondsDurationForEID(eventId);
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
dur >= 0.0 && int64_t(dur * 1000000000.0) <= nanoValue;
|
||||
};
|
||||
case 3:
|
||||
return
|
||||
[this, nanoValue](ICaptureContext *, const rdcstr &, const rdcstr &, uint32_t eventId,
|
||||
const SDChunk *, const DrawcallDescription *draw, const rdcstr &) {
|
||||
double dur = m_Model->GetSecondsDurationForEID(eventId);
|
||||
return draw->eventId == eventId && (draw->flags & DrawFlags::Dispatch) &&
|
||||
dur >= 0.0 && int64_t(dur * 1000000000.0) >= nanoValue;
|
||||
};
|
||||
default: errors.setText(tr("Internal error", "EventFilterModel")); return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.setText(tr("Unrecognised property expression", "EventFilterModel"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IEventBrowser::EventFilterCallback MakeFunctionMatcher(QString name, QString parameters,
|
||||
ParseError &errors)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user