X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fretracer.cpp;h=2928ed63f321f31e34667e2448e1b8f765f2fdbf;hb=ebe01ce9942e570f23b40793e97cf02b6f3616ee;hp=84f974244943b45a551fd561a1f01ce8d8e108ac;hpb=12a22803faa06a0db229b6dfb6130a0e8156ba31;p=apitrace diff --git a/gui/retracer.cpp b/gui/retracer.cpp index 84f9742..2928ed6 100644 --- a/gui/retracer.cpp +++ b/gui/retracer.cpp @@ -3,7 +3,9 @@ #include "apitracecall.h" #include "thumbnail.h" -#include "image.hpp" +#include "image/image.hpp" + +#include "trace_profiler.hpp" #include #include @@ -129,22 +131,12 @@ Retracer::Retracer(QObject *parent) m_benchmarking(false), m_doubleBuffered(true), m_captureState(false), - m_captureCall(0) + m_captureCall(0), + m_profileGpu(false), + m_profileCpu(false), + m_profilePixels(false) { qRegisterMetaType >(); - -#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 @@ -182,6 +174,33 @@ void Retracer::setDoubleBuffered(bool db) m_doubleBuffered = db; } +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; @@ -212,7 +231,6 @@ void Retracer::setCaptureThumbnails(bool enable) m_captureThumbnails = enable; } - /** * Starting point for the retracing thread. * @@ -229,29 +247,58 @@ void Retracer::run() QString prog; QStringList arguments; - if (m_api == trace::API_GL) { + switch (m_api) { + case trace::API_GL: prog = QLatin1String("glretrace"); - } else if (m_api == trace::API_EGL) { + break; + case trace::API_EGL: prog = QLatin1String("eglretrace"); - } else { + break; + case trace::API_DX: + case trace::API_D3D7: + case trace::API_D3D8: + case trace::API_D3D9: + case trace::API_DXGI: +#ifdef Q_OS_WIN + prog = QLatin1String("d3dretrace"); +#else + prog = QLatin1String("wine"); + arguments << QLatin1String("d3dretrace.exe"); +#endif + break; + default: emit finished(QLatin1String("Unsupported API")); return; } - if (m_doubleBuffered) { - arguments << QLatin1String("-db"); - } else { - arguments << QLatin1String("-sb"); - } - if (m_captureState) { arguments << QLatin1String("-D"); arguments << QString::number(m_captureCall); } 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; @@ -274,6 +321,7 @@ void Retracer::run() QList thumbnails; QVariantMap parsedJson; + trace::Profile* profile = NULL; process.setReadChannel(QProcess::StandardOutput); if (process.waitForReadyRead(-1)) { @@ -283,8 +331,6 @@ void Retracer::run() /* * Parse JSON from the output. * - * XXX: QJSON expects blocking IO. - * * XXX: QJSON's scanner is inneficient as it abuses single * character QIODevice::peek (not cheap), instead of maintaining a * lookahead character on its own. @@ -292,7 +338,19 @@ void Retracer::run() bool ok = false; QJson::Parser jsonParser; + + // Allow Nan/Infinity + jsonParser.allowSpecialNumbers(true); +#if 0 parsedJson = jsonParser.parse(&io, &ok).toMap(); +#else + /* + * XXX: QJSON expects blocking IO, and it looks like + * BlockingIODevice does not work reliably in all cases. + */ + process.waitForFinished(-1); + parsedJson = jsonParser.parse(&process, &ok).toMap(); +#endif if (!ok) { msg = QLatin1String("failed to parse JSON"); } @@ -338,6 +396,7 @@ void Retracer::run() unsigned char *scanLine = snapshot.scanLine(y); qint64 readBytes = io.read((char *) scanLine, rowBytes); Q_ASSERT(readBytes == rowBytes); + (void)readBytes; } QImage thumb = thumbnail(snapshot); @@ -345,7 +404,20 @@ void Retracer::run() } 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(); @@ -382,6 +454,14 @@ void Retracer::run() 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); } } @@ -399,6 +479,10 @@ void Retracer::run() emit foundThumbnails(thumbnails); } + if (isProfiling() && profile) { + emit foundProfile(profile); + } + if (!errors.isEmpty()) { emit retraceErrors(errors); }