#include "apitracecall.h"
#include "thumbnail.h"
-#include "image.hpp"
+#include "image/image.hpp"
+
+#include "trace_profiler.hpp"
#include <QDebug>
#include <QVariant>
: QThread(parent),
m_benchmarking(false),
m_doubleBuffered(true),
+ m_singlethread(false),
m_captureState(false),
- m_captureCall(0)
+ m_captureCall(0),
+ m_profileGpu(false),
+ m_profileCpu(false),
+ m_profilePixels(false)
{
qRegisterMetaType<QList<ApiTraceError> >();
-
-#ifdef Q_OS_WIN
- QString format = QLatin1String("%1;");
-#else
- QString format = QLatin1String("%1:");
-#endif
- QString buildPath = format.arg(APITRACE_BINARY_DIR);
- m_processEnvironment = QProcessEnvironment::systemEnvironment();
- m_processEnvironment.insert("PATH", buildPath +
- m_processEnvironment.value("PATH"));
-
- qputenv("PATH",
- m_processEnvironment.value("PATH").toLatin1());
}
QString Retracer::fileName() const
m_fileName = name;
}
+QString Retracer::remoteTarget() const
+{
+ return m_remoteTarget;
+}
+
+void Retracer::setRemoteTarget(const QString &host)
+{
+ m_remoteTarget = host;
+}
+
void Retracer::setAPI(trace::API api)
{
m_api = api;
m_doubleBuffered = db;
}
+bool Retracer::isSinglethread() const
+{
+ return m_singlethread;
+}
+
+void Retracer::setSinglethread(bool singlethread)
+{
+ m_singlethread = singlethread;
+}
+
+bool Retracer::isProfilingGpu() const
+{
+ return m_profileGpu;
+}
+
+bool Retracer::isProfilingCpu() const
+{
+ return m_profileCpu;
+}
+
+bool Retracer::isProfilingPixels() const
+{
+ return m_profilePixels;
+}
+
+bool Retracer::isProfiling() const
+{
+ return m_profileGpu || m_profileCpu || m_profilePixels;
+}
+
+void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
+{
+ m_profileGpu = gpu;
+ m_profileCpu = cpu;
+ m_profilePixels = pixels;
+}
+
void Retracer::setCaptureAtCallNumber(qlonglong num)
{
m_captureCall = num;
m_captureThumbnails = enable;
}
-
/**
* Starting point for the retracing thread.
*
case trace::API_D3D7:
case trace::API_D3D8:
case trace::API_D3D9:
- case trace::API_D3D10:
- case trace::API_D3D10_1:
- case trace::API_D3D11:
+ case trace::API_DXGI:
#ifdef Q_OS_WIN
prog = QLatin1String("d3dretrace");
#else
return;
}
- if (m_doubleBuffered) {
- arguments << QLatin1String("-db");
- } else {
- arguments << QLatin1String("-sb");
+ if (m_singlethread) {
+ arguments << QLatin1String("--singlethread");
}
if (m_captureState) {
} else if (m_captureThumbnails) {
arguments << QLatin1String("-s"); // emit snapshots
arguments << QLatin1String("-"); // emit to stdout
- } else if (m_benchmarking) {
- arguments << QLatin1String("-b");
+ } else if (isProfiling()) {
+ if (m_profileGpu) {
+ arguments << QLatin1String("--pgpu");
+ }
+
+ if (m_profileCpu) {
+ arguments << QLatin1String("--pcpu");
+ }
+
+ if (m_profilePixels) {
+ arguments << QLatin1String("--ppd");
+ }
+ } else {
+ if (m_doubleBuffered) {
+ arguments << QLatin1String("--db");
+ } else {
+ arguments << QLatin1String("--sb");
+ }
+
+ if (m_benchmarking) {
+ arguments << QLatin1String("-b");
+ }
}
arguments << m_fileName;
+ /*
+ * Support remote execution on a separate target.
+ */
+
+ if (m_remoteTarget.length() != 0) {
+ arguments.prepend(prog);
+ arguments.prepend(m_remoteTarget);
+ prog = QLatin1String("ssh");
+ }
+
/*
* Start the process.
*/
QList<QImage> thumbnails;
QVariantMap parsedJson;
+ trace::Profile* profile = NULL;
process.setReadChannel(QProcess::StandardOutput);
if (process.waitForReadyRead(-1)) {
bool ok = false;
QJson::Parser jsonParser;
+
+ // Allow Nan/Infinity
+ jsonParser.allowSpecialNumbers(true);
#if 0
parsedJson = jsonParser.parse(&io, &ok).toMap();
#else
*/
while (!io.atEnd()) {
- unsigned channels = 0;
- unsigned width = 0;
- unsigned height = 0;
+ image::PNMInfo info;
char header[512];
qint64 headerSize = 0;
headerSize += headerRead;
}
- const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);
+ const char *headerEnd = image::readPNMHeader(header, headerSize, info);
// if invalid PNM header was encountered, ...
- if (header == headerEnd) {
+ if (headerEnd == NULL ||
+ info.channelType != image::TYPE_UNORM8) {
qDebug() << "error: invalid snapshot stream encountered";
break;
}
+ unsigned channels = info.channels;
+ unsigned width = info.width;
+ unsigned height = info.height;
+
// qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";
QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);
unsigned char *scanLine = snapshot.scanLine(y);
qint64 readBytes = io.read((char *) scanLine, rowBytes);
Q_ASSERT(readBytes == rowBytes);
+ (void)readBytes;
}
QImage thumb = thumbnail(snapshot);
}
Q_ASSERT(process.state() != QProcess::Running);
+ } else if (isProfiling()) {
+ profile = new trace::Profile();
+
+ while (!io.atEnd()) {
+ char line[256];
+ qint64 lineLength;
+ lineLength = io.readLine(line, 256);
+
+ if (lineLength == -1)
+ break;
+
+ trace::Profiler::parseLine(line, profile);
+ }
} else {
QByteArray output;
output = process.readAllStandardOutput();
error.type = regexp.cap(2);
error.message = regexp.cap(3);
errors.append(error);
+ } else if (!errors.isEmpty()) {
+ // Probably a multiligne message
+ ApiTraceError &previous = errors.last();
+ if (line.endsWith("\n")) {
+ line.chop(1);
+ }
+ previous.message.append('\n');
+ previous.message.append(line);
}
}
if (m_captureState) {
ApiTraceState *state = new ApiTraceState(parsedJson);
emit foundState(state);
- msg = QLatin1String("State fetched.");
}
if (m_captureThumbnails && !thumbnails.isEmpty()) {
emit foundThumbnails(thumbnails);
}
+ if (isProfiling() && profile) {
+ emit foundProfile(profile);
+ }
+
if (!errors.isEmpty()) {
emit retraceErrors(errors);
}