Skip to content

Commit f393670

Browse files
committed
GPU Display Console: Add plenty of useful commands
1 parent 713a5aa commit f393670

13 files changed

Lines changed: 614 additions & 89 deletions

‎GPU/GPUTracking/Definitions/GPUSettingsListDisplay.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ AddOption(consoleVertical, float, 0.5f, "", 0, "Fraction of the window height co
122122
AddOption(consoleHistorySize, uint32_t, 1000000, "", 0, "Number of console lines kept, the history is shortened to this when it reaches twice the size")
123123
AddOption(setInfoTime, float, 5.0f, "", 0, "Time in seconds an info message (SetInfo) is shown fully opaque")
124124
AddOption(setInfoTransition, float, 1.0f, "", 0, "Time in seconds an info message fades out after setInfoTime")
125+
AddOption(consolePrintToTerminal, bool, false, "", 0, "Also write the replies of console commands to the terminal")
125126
AddHelp("help", 'h')
126127
EndConfig()
127128

‎GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::output>(int32_t nBlocks
191191
uint32_t nOutCl2 = 0;
192192
float t1 = 0, t2 = 0;
193193
int32_t sector1 = 0, sector2 = 0;
194-
const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem() -> ioPtrs.clustersNative;
194+
const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem()->ioPtrs.clustersNative;
195195
for (uint32_t j = 0; j < track.NClusters(); j++) {
196196
if ((trackClusters[track.FirstClusterRef() + j].state & flagsReject)) {
197197
continue;
@@ -284,7 +284,7 @@ template <>
284284
GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::mc>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() merger)
285285
{
286286
#ifndef GPUCA_GPUCODE
287-
const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem() -> ioPtrs.clustersNative;
287+
const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem()->ioPtrs.clustersNative;
288288
if (clusters == nullptr || clusters->clustersMCTruth == nullptr) {
289289
return;
290290
}

‎GPU/GPUTracking/Merger/GPUTPCGMSectorTrack.cxx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ GPUd() bool GPUTPCGMSectorTrack::TransportToXAlpha(GPUTPCGMMerger* merger, float
495495

496496
GPUd() void GPUTPCGMSectorTrack::CopyBaseTrackCov()
497497
{
498-
const float* GPUrestrict() cov = mOrigTrack -> Param().mC;
498+
const float* GPUrestrict() cov = mOrigTrack->Param().mC;
499499
mParam.mC0 = cov[0];
500500
mParam.mC2 = cov[2];
501501
mParam.mC3 = cov[3];

‎GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_
5252
constexpr float kDeg2Rad = M_PI / 180.f;
5353
CADEBUG(static constexpr float kSectAngle = 2 * M_PI / 18.f);
5454

55-
const GPUParam& GPUrestrict() param = merger -> Param();
55+
const GPUParam& GPUrestrict() param = merger->Param();
5656

5757
GPUdEdx dEdx, dEdxAlt;
5858
GPUTPCGMPropagator prop;
@@ -126,7 +126,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_
126126
const float clAlpha = param.Alpha(clusters[ihit].sector);
127127
float xx, yy, zz;
128128
{
129-
const ClusterNative& GPUrestrict() cl = merger -> GetConstantMem()->ioPtrs.clustersNative->clustersLinear[clusters[ihit].num];
129+
const ClusterNative& GPUrestrict() cl = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[clusters[ihit].num];
130130
merger->GetConstantMem()->calibObjects.fastTransform->Transform(clusters[ihit].sector, clusters[ihit].row, cl.getPad(), cl.getTime(), xx, yy, zz, mTOffset);
131131
}
132132
// clang-format off
@@ -440,7 +440,7 @@ GPUd() int32_t GPUTPCGMTrackParam::MergeDoubleRowClusters(int32_t& ihit, int32_t
440440
xx = yy = zz = 0.f;
441441
clusterState = 0;
442442
while (true) {
443-
const ClusterNative& GPUrestrict() cl = merger -> GetConstantMem()->ioPtrs.clustersNative->clustersLinear[clusters[ihit].num];
443+
const ClusterNative& GPUrestrict() cl = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[clusters[ihit].num];
444444
float clamp = cl.getQtot();
445445
float clx, cly, clz;
446446
merger->GetConstantMem()->calibObjects.fastTransform->Transform(clusters[ihit].sector, clusters[ihit].row, cl.getPad(), cl.getTime(), clx, cly, clz, mTOffset);
@@ -493,7 +493,7 @@ GPUd() float GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestric
493493
if (param.rec.tpc.disableRefitAttachment & 1) {
494494
return -1e6f;
495495
}
496-
const GPUTPCTracker& GPUrestrict() tracker = *(Merger -> GetConstantMem()->tpcTrackers + sector);
496+
const GPUTPCTracker& GPUrestrict() tracker = *(Merger->GetConstantMem()->tpcTrackers + sector);
497497
const GPUTPCRow& GPUrestrict() row = tracker.Row(iRow);
498498
GPUglobalref() const cahit2* hits = tracker.HitData(row);
499499
GPUglobalref() const calink* firsthit = tracker.FirstHitInBin(row);
@@ -803,7 +803,7 @@ GPUd() float GPUTPCGMTrackParam::ShiftZ(const GPUTPCGMMergedTrackHit* clusters,
803803
if (N == 0) {
804804
N = 1;
805805
}
806-
const auto& GPUrestrict() cls = merger -> GetConstantMem()->ioPtrs.clustersNative->clustersLinear;
806+
const auto& GPUrestrict() cls = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear;
807807
float z0 = cls[clusters[0].num].getTime(), zn = cls[clusters[N - 1].num].getTime();
808808
const auto tmp = zn > z0 ? std::array<float, 3>{zn, z0, GPUTPCGeometry::Row2X(clusters[N - 1].row)} : std::array<float, 3>{z0, zn, GPUTPCGeometry::Row2X(clusters[0].row)};
809809
return ShiftZ(merger, clusters[0].sector, tmp[0], tmp[1], tmp[2]);

‎GPU/GPUTracking/display/GPUDisplay.cxx‎

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ int32_t GPUDisplay::DrawGLScene(bool suspended)
245245
mLoadAndShowEvent = false;
246246
}
247247
mCVLoadAndShowEvent.notify_one();
248+
mNEventsShown++;
248249
}
249250
mSemLockDisplay.Unlock();
250251

@@ -376,15 +377,7 @@ void GPUDisplay::DrawGLScene_cameraAndAnimation(bool suspended, float animateTim
376377
} else {
377378
nextViewMatrix = nextViewMatrix * HMM_Translate({{moveX, moveY * mYFactor, moveZ}});
378379
if (!rotateModel) {
379-
if (rotYaw != 0.f) {
380-
nextViewMatrix = nextViewMatrix * HMM_Rotate(rotYaw, {{0, 1, 0}});
381-
}
382-
if (rotPitch != 0.f) {
383-
nextViewMatrix = nextViewMatrix * HMM_Rotate(rotPitch * mYFactor, {{1, 0, 0}});
384-
}
385-
if (!yUp && rotRoll != 0.f) {
386-
nextViewMatrix = nextViewMatrix * HMM_Rotate(rotRoll * mYFactor, {{0, 0, 1}});
387-
}
380+
nextViewMatrix = nextViewMatrix * cameraRotation({rotYaw, rotPitch, yUp ? 0.f : rotRoll}); // Keyboard and mouse, as rotateCamera
388381
}
389382
nextViewMatrix = nextViewMatrix * *mViewMatrix; // Apply previous translation / rotation
390383
if (yUp) {

‎GPU/GPUTracking/display/GPUDisplay.h‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ class GPUDisplay : public GPUDisplayInterface
6262
void UpdateCalib(const GPUCalibObjectsConst* calib) override { mCalib = calib; }
6363
void UpdateParam(const GPUParam* param) override { mParam = param; }
6464

65-
void HandleKey(uint8_t key, bool external = false); // external: from the Qt GUI or the console, not typed into the event display console
65+
void HandleKey(uint8_t key, bool external = false, bool bypassConsole = false); // external: from the Qt GUI or the console, not typed into the event display console; bypassConsole: handled as key also while the console is shown (injectKey)
6666
int32_t DrawGLScene(bool suspended = false);
67-
void HandleExternalGUIKey(int32_t key);
67+
void HandleExternalGUIKey(int32_t key, bool bypassConsole = false); // key >= 256: special key with SHIFT
6868
int32_t InitDisplay(bool initFailure = false);
6969
void ResizeScene(int32_t width, int32_t height, bool init = false);
7070
void checkAndApplyConfigChanges(); // Set update flags / apply the settings that changed compared to mOldCfg
@@ -194,6 +194,11 @@ class GPUDisplay : public GPUDisplayInterface
194194
void takeScreenshot();
195195
void runAnimation(); // Starts the animation if it has enough points
196196
void setAnimationPoint();
197+
void setCamera(const float (&xyz)[3], const float (&angles)[3]); // Position and angles (radians, as mAngle: pitch, yaw, roll)
198+
void addAnimationPoint(const float (&xyz)[3], const float (&angles)[3]); // Animation point for this camera, the current camera is kept
199+
bool lookAt(const float (&target)[3]); // Turn the camera to the point, false if it is the camera position
200+
void rotateCamera(const float (&angles)[3]); // Yaw, pitch, roll in degrees relative to the view, as the keyboard
201+
hmm_mat4 cameraRotation(const float (&angles)[3]) const; // Rotation of rotateCamera, applied to the view matrix also for keyboard / mouse
197202
void resetAnimation();
198203
void removeAnimationPoint();
199204
void startAnimation();
@@ -310,6 +315,7 @@ class GPUDisplay : public GPUDisplayInterface
310315
volatile bool mUpdateDrawCommands = true;
311316
volatile bool mUpdateRenderPipeline = false;
312317
volatile bool mLoadAndShowEvent = false;
318+
uint32_t mNEventsShown = 0; // Events loaded and drawn, in the frontend thread
313319
bool mTracksArePropagated = false;
314320

315321
int32_t mAnimate = 0;

‎GPU/GPUTracking/display/frontend/GPUDisplayConsole.cxx‎

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
/// \author David Rohr
1414

1515
#include "GPUDisplayConsole.h"
16+
#include "GPULogging.h"
1617
#include <algorithm>
1718
#include <charconv>
1819
#include <stdexcept>
@@ -85,12 +86,17 @@ void GPUDisplayConsole::handleConsoleKey(uint8_t key)
8586

8687
void GPUDisplayConsole::consolePrint(const char* format, ...)
8788
{
88-
char buffer[1024];
89-
va_list args;
89+
va_list args, argsCopy;
9090
va_start(args, format);
91-
vsnprintf(buffer, sizeof(buffer), format, args);
91+
va_copy(argsCopy, args);
92+
std::string buffer(std::max(0, vsnprintf(nullptr, 0, format, args)), '\0');
9293
va_end(args);
93-
consoleAppend(std::string(" ") + buffer); // Indented: output, not a command, skipped by up / down
94+
vsnprintf(buffer.data(), buffer.size() + 1, format, argsCopy);
95+
va_end(argsCopy);
96+
consoleAppend(" " + buffer); // Indented: output, not a command, skipped by up / down
97+
if (mPrintToTerminal) {
98+
GPUInfo("%s", buffer.c_str());
99+
}
94100
}
95101

96102
void GPUDisplayConsole::consoleInfo(const char* format, const char* text)
@@ -180,16 +186,15 @@ std::tuple<const GPUDisplayConsole::GPUDisplayConsoleCommand&, std::vector<GPUDi
180186
if (nArgs < nFixed || (!more && nArgs > nFixed)) {
181187
throw std::runtime_error(name + ": " + std::to_string(nFixed) + (more ? " or more" : "") + " arguments expected, got " + std::to_string(nArgs));
182188
}
183-
auto autoType = [](const std::string& text, bool plain) -> consoleArg { // int64_t for [+-]digits, double for [+-]digits with one '.', string otherwise or if plain text
189+
auto autoType = [](const std::string& text, bool plain) -> consoleArg { // int64_t for [+-]digits, double for other decimal numbers (also with exponent, as saveSettings writes them), string otherwise or if plain text
184190
const char *begin = text.c_str() + (text[0] == '+' || text[0] == '-'), *end = text.c_str() + text.size();
185-
const size_t nDigits = std::count_if(begin, end, [](char c) { return c >= '0' && c <= '9'; });
186-
const size_t nDots = std::count(begin, end, '.');
187-
const bool number = !plain && nDigits && nDigits + nDots == (size_t)(end - begin);
191+
const bool number = !plain && begin < end && ((*begin >= '0' && *begin <= '9') || *begin == '.') && std::all_of(begin, end, [](char c) { return (c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-'; });
188192
int64_t intValue = 0;
189-
if (number && nDots == 0 && std::from_chars(begin, end, intValue).ec == std::errc()) {
193+
double doubleValue = 0.;
194+
if (const auto rInt = std::from_chars(begin, end, intValue); number && rInt.ec == std::errc() && rInt.ptr == end) {
190195
return text[0] == '-' ? -intValue : intValue;
191-
} else if (number && nDots <= 1) {
192-
return std::stod(text); // Also integers out of the int64_t range
196+
} else if (const auto rDouble = std::from_chars(begin, end, doubleValue); number && rDouble.ec == std::errc() && rDouble.ptr == end) {
197+
return text[0] == '-' ? -doubleValue : doubleValue; // Also integers out of the int64_t range
193198
}
194199
return text;
195200
};
@@ -206,7 +211,7 @@ std::tuple<const GPUDisplayConsole::GPUDisplayConsoleCommand&, std::vector<GPUDi
206211
} else if (!std::holds_alternative<double>(value)) {
207212
throw std::runtime_error(name + ": argument " + std::to_string(i + 1) + " (" + text + ") must be a number");
208213
}
209-
} else if (type != 's' && type != 'i' && type != '+') {
214+
} else if (type != 's' && type != 'i' && type != 'a' && type != '+') {
210215
throw std::runtime_error(name + ": invalid argument types " + types);
211216
}
212217
args.emplace_back(std::move(value));
@@ -229,7 +234,11 @@ void GPUDisplayConsole::handleConsoleCommand(std::string_view cmd)
229234
consolePrint("Invalid command: %s", e.what());
230235
return;
231236
}
232-
command->func(args);
237+
try { // A failing command must not end the display
238+
command->func(args);
239+
} catch (const std::exception& e) {
240+
consolePrint("Error in command %.*s: %s", (int32_t)cmd.size(), cmd.data(), e.what());
241+
}
233242
}
234243

235244
void GPUDisplayConsole::runScript(std::string_view script)
@@ -238,13 +247,44 @@ void GPUDisplayConsole::runScript(std::string_view script)
238247
consolePrint("Scripts nested too deeply");
239248
return;
240249
}
241-
mScriptDepth++;
250+
std::vector<ScriptLine> lines;
242251
for (size_t pos = 0; pos < script.size();) {
243252
const size_t end = std::min(script.find_first_of("\r\n", pos), script.size());
244-
handleConsoleCommand(script.substr(pos, end - pos)); // Empty lines (consecutive \r / \n) are ignored
253+
if (end > pos) { // Empty lines (consecutive \r / \n) are ignored
254+
lines.push_back({std::string(script.substr(pos, end - pos)), mScriptDepth + 1});
255+
}
245256
pos = end + 1;
246257
}
247-
mScriptDepth--;
258+
mScriptQueue.insert(mScriptQueue.begin(), lines.begin(), lines.end()); // Before the remaining lines of a script running this one
259+
processScripts(false);
260+
}
261+
262+
void GPUDisplayConsole::processScripts(bool newFrame)
263+
{
264+
if (newFrame) {
265+
mWaitFrames -= mWaitFrames > 0;
266+
if (mBenchmarkLeft && --mBenchmarkLeft == 0) {
267+
const double time = std::chrono::duration<double>(std::chrono::steady_clock::now() - mBenchmarkStart).count();
268+
consolePrint("benchmark: %u frames in %.3f s, %.2f fps, %.3f ms per frame", mBenchmarkFrames, time, mBenchmarkFrames / time, time * 1000. / mBenchmarkFrames);
269+
}
270+
}
271+
if (mWaitCondition && mWaitCondition()) {
272+
mWaitCondition = nullptr;
273+
}
274+
const uint32_t outerDepth = mScriptDepth;
275+
for (uint32_t n = 0; n < 100000 && mScriptQueue.size() && !mWaitFrames && !mBenchmarkLeft && !mWaitCondition && std::chrono::steady_clock::now() >= mWaitUntil; n++) { // Limit per call: a script must not block the display
276+
ScriptLine line = std::move(mScriptQueue.front());
277+
mScriptQueue.pop_front();
278+
mScriptDepth = line.depth;
279+
handleConsoleCommand(line.text);
280+
}
281+
mScriptDepth = outerDepth;
282+
}
283+
284+
void GPUDisplayConsole::startBenchmark(uint32_t n)
285+
{
286+
mBenchmarkFrames = mBenchmarkLeft = n;
287+
mBenchmarkStart = std::chrono::steady_clock::now();
248288
}
249289

250290
void GPUDisplayConsole::runScriptFile(const std::string& filename)
@@ -266,7 +306,7 @@ void GPUDisplayConsole::printCommands(const std::function<void(const std::string
266306
names.emplace_back(name);
267307
}
268308
std::sort(names.begin(), names.end());
269-
print("Console commands (argument types: s string, i integer, d number, + further arguments):");
309+
print("Console commands (argument types: s string, i integer, d number, a any, + further arguments):");
270310
for (const auto& name : names) {
271311
const auto& command = mConsoleCommands[name];
272312
print(" " + name + (command.args.empty() ? "" : " ") + command.args + ": " + command.description);

0 commit comments

Comments
 (0)