mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
Give our threads debugger-friendly names
This commit is contained in:
@@ -702,6 +702,7 @@ void CaptureContext::LoadCapture(const rdcstr &captureFile, const ReplayOptions
|
||||
new LambdaThread([this, captureFile, opts, origFilename, temporary, local]() {
|
||||
LoadCaptureThreaded(captureFile, opts, origFilename, temporary, local);
|
||||
});
|
||||
thread->setName(lit("LoadCapture"));
|
||||
thread->selfDelete(true);
|
||||
thread->start();
|
||||
|
||||
@@ -1095,6 +1096,7 @@ void CaptureContext::RecompressCapture()
|
||||
LambdaThread *th = new LambdaThread([cap, destFilename, &progress]() {
|
||||
cap->Convert(destFilename.toUtf8().data(), "rdc", NULL, [&progress](float p) { progress = p; });
|
||||
});
|
||||
th->setName(lit("RecompressCapture"));
|
||||
th->start();
|
||||
// wait a few ms before popping up a progress bar
|
||||
th->wait(500);
|
||||
@@ -1319,6 +1321,7 @@ bool CaptureContext::ImportCapture(const CaptureFileFormat &fmt, const rdcstr &i
|
||||
[&progress](float p) { progress = 0.5f + p * 0.5f; });
|
||||
file->Shutdown();
|
||||
});
|
||||
th->setName(lit("ImportCapture"));
|
||||
th->start();
|
||||
// wait a few ms before popping up a progress bar
|
||||
th->wait(500);
|
||||
@@ -1394,6 +1397,7 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
|
||||
status = file->Convert(exportfile.c_str(), ext.toUtf8().data(), sdfile,
|
||||
[&progress](float p) { progress = p; });
|
||||
});
|
||||
th->setName(lit("ExportCapture"));
|
||||
th->start();
|
||||
// wait a few ms before popping up a progress bar
|
||||
th->wait(500);
|
||||
|
||||
@@ -158,6 +158,7 @@ static ShaderToolOutput RunTool(const ShaderProcessingTool &tool, QWidget *windo
|
||||
process.moveToThread(mainThread);
|
||||
});
|
||||
|
||||
thread->setName(lit("ShaderProcessingTool %s").arg(tool.name));
|
||||
thread->moveObjectToThread(&process);
|
||||
|
||||
thread->start();
|
||||
|
||||
@@ -2275,6 +2275,7 @@ void ShowProgressDialog(QWidget *window, const QString &labelText, ProgressFinis
|
||||
|
||||
GUIInvoke::call(&dialog, [&dialog]() { dialog.closeAndReset(); });
|
||||
});
|
||||
progressTickerThread.setName(lit("Progress Dialog"));
|
||||
progressTickerThread.start();
|
||||
|
||||
// show the dialog
|
||||
@@ -2448,3 +2449,65 @@ void *AccessWaylandPlatformInterface(const QByteArray &resource, QWindow *window
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
return native->nativeResourceForWindow(resource, window);
|
||||
}
|
||||
|
||||
// Default Qt doesn't do this in release Qt builds, which is all we use
|
||||
#if defined(Q_OS_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HRESULT(WINAPI *PFN_SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
|
||||
|
||||
const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
#pragma pack(push, 8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
static void SetThreadNameWithException(const char *name)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
info.dwThreadID = GetCurrentThreadId();
|
||||
info.dwFlags = 0;
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)(&info));
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void LambdaThread::windowsSetName()
|
||||
{
|
||||
// try to use the fancy modern API
|
||||
static PFN_SetThreadDescription setThreadDesc = (PFN_SetThreadDescription)GetProcAddress(
|
||||
GetModuleHandleA("kernel32.dll"), "SetThreadDescription");
|
||||
|
||||
if(setThreadDesc)
|
||||
{
|
||||
setThreadDesc(GetCurrentThread(), m_Name.toStdWString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't throw the exception if there's no debugger present
|
||||
if(!IsDebuggerPresent())
|
||||
return;
|
||||
|
||||
SetThreadNameWithException(m_Name.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void LambdaThread::windowsSetName()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -318,10 +318,15 @@ private:
|
||||
QThread *m_Thread;
|
||||
QSemaphore completed;
|
||||
bool m_SelfDelete = false;
|
||||
QString m_Name;
|
||||
|
||||
void windowsSetName();
|
||||
|
||||
public slots:
|
||||
void process()
|
||||
{
|
||||
if(!m_Name.isEmpty())
|
||||
windowsSetName();
|
||||
m_func();
|
||||
m_Thread->quit();
|
||||
m_Thread = NULL;
|
||||
@@ -342,6 +347,11 @@ public:
|
||||
QObject::connect(m_Thread, &QThread::finished, m_Thread, &QThread::deleteLater);
|
||||
}
|
||||
|
||||
void setName(QString name)
|
||||
{
|
||||
m_Name = name;
|
||||
m_Thread->setObjectName(name);
|
||||
}
|
||||
void start(QThread::Priority prio = QThread::InheritPriority) { m_Thread->start(prio); }
|
||||
bool isRunning() { return completed.available(); }
|
||||
bool wait(unsigned long time = ULONG_MAX)
|
||||
|
||||
@@ -54,6 +54,7 @@ void ReplayManager::OpenCapture(const QString &capturefile, const ReplayOptions
|
||||
m_Thread = new LambdaThread([this, proxyRenderer, capturefile, opts, progress]() {
|
||||
run(proxyRenderer, capturefile, opts, progress);
|
||||
});
|
||||
m_Thread->setName(lit("ReplayManager"));
|
||||
m_Thread->start(QThread::HighestPriority);
|
||||
|
||||
while(m_Thread->isRunning() && !m_Running)
|
||||
@@ -185,6 +186,7 @@ rdcstr ReplayManager::CopyCaptureToRemote(const rdcstr &localpath, QWidget *wind
|
||||
{
|
||||
LambdaThread *thread = new LambdaThread([&lambda]() { lambda(NULL); });
|
||||
thread->selfDelete(true);
|
||||
thread->setName(lit("CopyCaptureToRemote"));
|
||||
thread->start();
|
||||
}
|
||||
|
||||
@@ -219,6 +221,7 @@ void ReplayManager::CopyCaptureFromRemote(const rdcstr &remotepath, const rdcstr
|
||||
{
|
||||
LambdaThread *thread = new LambdaThread([&lambda]() { lambda(NULL); });
|
||||
thread->selfDelete(true);
|
||||
thread->setName(lit("CopyCaptureFromRemote"));
|
||||
thread->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -2560,6 +2560,7 @@ void BufferViewer::populateBBox(PopulateBufferData *bufdata)
|
||||
|
||||
GUIInvoke::call(this, [this, bbox]() { UI_UpdateBoundingBox(*bbox); });
|
||||
});
|
||||
thread->setName(lit("BBox calc"));
|
||||
thread->selfDelete(true);
|
||||
thread->start();
|
||||
|
||||
|
||||
@@ -585,6 +585,7 @@ void CaptureDialog::CheckAndroidSetup(QString &filename)
|
||||
}
|
||||
});
|
||||
|
||||
scan->setName(lit("CheckAndroidSetup"));
|
||||
scan->start();
|
||||
scan->deleteLater();
|
||||
}
|
||||
@@ -663,6 +664,7 @@ Would you like RenderDoc to try patching your package?
|
||||
}
|
||||
});
|
||||
|
||||
patch->setName(lit("Android patch"));
|
||||
patch->start();
|
||||
// wait a few ms before popping up a progress bar
|
||||
patch->wait(500);
|
||||
|
||||
@@ -181,6 +181,7 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
|
||||
}
|
||||
}
|
||||
});
|
||||
m_RemoteProbe->setName(lit("Remote Probe"));
|
||||
m_RemoteProbe->start();
|
||||
|
||||
SetTitle();
|
||||
@@ -607,6 +608,7 @@ void MainWindow::OnCaptureTrigger(const QString &exe, const QString &workingDir,
|
||||
callback(live);
|
||||
});
|
||||
});
|
||||
th->setName(lit("ExecuteAndInject"));
|
||||
th->start();
|
||||
// wait a few ms before popping up a progress bar
|
||||
th->wait(500);
|
||||
@@ -1943,6 +1945,7 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
// update status
|
||||
host.CheckStatus();
|
||||
});
|
||||
launchthread->setName(lit("Remote host launch"));
|
||||
launchthread->start();
|
||||
|
||||
ShowProgressDialog(this, tr("Attempting to update remote server, please wait..."),
|
||||
@@ -2017,6 +2020,7 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
m_Ctx.GetCaptureDialog()->UpdateRemoteHost();
|
||||
});
|
||||
});
|
||||
th->setName(lit("Remote host check"));
|
||||
th->selfDelete(true);
|
||||
th->start();
|
||||
}
|
||||
|
||||
@@ -713,6 +713,7 @@ void PythonShell::on_runScript_clicked()
|
||||
});
|
||||
});
|
||||
|
||||
thread->setName(lit("Python script"));
|
||||
thread->selfDelete(true);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
@@ -696,6 +696,8 @@ struct AndroidController : public IDeviceProtocolHandler
|
||||
|
||||
void ThreadEntry()
|
||||
{
|
||||
Threading::SetCurrentThreadName("AndroidController");
|
||||
|
||||
while(Atomic::CmpExch32(&running, 1, 1) == 1)
|
||||
{
|
||||
Threading::Sleep(5);
|
||||
@@ -956,6 +958,8 @@ ExecuteResult AndroidRemoteServer::ExecuteAndInject(const char *a, const char *w
|
||||
// we spin up a thread to Ping() every second, since starting a package can block for a long time.
|
||||
volatile int32_t done = 0;
|
||||
Threading::ThreadHandle pingThread = Threading::CreateThread([&done, this]() {
|
||||
Threading::SetCurrentThreadName("Android Ping");
|
||||
|
||||
bool ok = true;
|
||||
while(ok && Atomic::CmpExch32(&done, 0, 0) == 0)
|
||||
ok = Ping();
|
||||
|
||||
@@ -154,6 +154,8 @@ struct ClientThread
|
||||
|
||||
static void InactiveRemoteClientThread(ClientThread *threadData)
|
||||
{
|
||||
Threading::SetCurrentThreadName("InactiveRemoteClientThread");
|
||||
|
||||
uint32_t ip = threadData->socket->GetRemoteIP();
|
||||
|
||||
{
|
||||
@@ -209,6 +211,8 @@ static void InactiveRemoteClientThread(ClientThread *threadData)
|
||||
static void ActiveRemoteClientThread(ClientThread *threadData,
|
||||
RENDERDOC_PreviewWindowCallback previewWindow)
|
||||
{
|
||||
Threading::SetCurrentThreadName("ActiveRemoteClientThread");
|
||||
|
||||
Network::Socket *&client = threadData->socket;
|
||||
|
||||
#if ENABLED(RDOC_DEVEL)
|
||||
|
||||
@@ -2570,6 +2570,8 @@ void ReplayProxy::EndRemoteExecution()
|
||||
|
||||
void ReplayProxy::RemoteExecutionThreadEntry()
|
||||
{
|
||||
Threading::SetCurrentThreadName("RemoteExecutionThreadEntry");
|
||||
|
||||
// while we're alive
|
||||
while(Atomic::CmpExch32(&m_RemoteExecutionKill, 0, 0) == 0)
|
||||
{
|
||||
|
||||
@@ -100,6 +100,8 @@ rdcstr DoStringise(const PacketType &el)
|
||||
|
||||
void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *client)
|
||||
{
|
||||
Threading::SetCurrentThreadName("TargetControlClientThread");
|
||||
|
||||
Threading::KeepModuleAlive();
|
||||
|
||||
WriteSerialiser writer(new StreamWriter(client, Ownership::Nothing), Ownership::Stream);
|
||||
@@ -375,6 +377,8 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
|
||||
void RenderDoc::TargetControlServerThread(Network::Socket *sock)
|
||||
{
|
||||
Threading::SetCurrentThreadName("TargetControlServerThread");
|
||||
|
||||
Threading::KeepModuleAlive();
|
||||
|
||||
RenderDoc::Inst().m_SingleClientName = "";
|
||||
|
||||
@@ -145,6 +145,8 @@ void SetTLSValue(uint64_t slot, void *value);
|
||||
|
||||
// must typedef CriticalSectionTemplate<X> CriticalSection
|
||||
|
||||
void SetCurrentThreadName(const rdcstr &name);
|
||||
|
||||
typedef uint64_t ThreadHandle;
|
||||
ThreadHandle CreateThread(std::function<void()> entryFunc);
|
||||
uint64_t GetCurrentID();
|
||||
|
||||
@@ -38,3 +38,7 @@ uint64_t Timing::GetTick()
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
|
||||
}
|
||||
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,3 +40,7 @@ uint64_t Timing::GetTick()
|
||||
{
|
||||
return mach_absolute_time();
|
||||
}
|
||||
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,3 +38,7 @@ uint64_t Timing::GetTick()
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
|
||||
}
|
||||
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "os/os_specific.h"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -38,3 +39,8 @@ uint64_t Timing::GetTick()
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
|
||||
}
|
||||
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
prctl(PR_SET_NAME, (unsigned long)name.c_str(), 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1346,6 +1346,8 @@ static GlobalHookData *globalHook = NULL;
|
||||
// the global hook.
|
||||
static void GlobalHookThread()
|
||||
{
|
||||
Threading::SetCurrentThreadName("GlobalHookThread");
|
||||
|
||||
// keep looping doing an atomic compare-exchange to check that finished is still 0
|
||||
while(Atomic::CmpExch32(&globalHook->finished, 0, 0) == 0)
|
||||
{
|
||||
|
||||
@@ -262,6 +262,55 @@ ThreadHandle CreateThread(std::function<void()> entryFunc)
|
||||
return (ThreadHandle)h;
|
||||
}
|
||||
|
||||
typedef HRESULT(WINAPI *PFN_SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
|
||||
|
||||
const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
#pragma pack(push, 8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
static void SetThreadNameWithException(const char *name)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
info.dwThreadID = GetCurrentThreadId();
|
||||
info.dwFlags = 0;
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)(&info));
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
// try to use the fancy modern API
|
||||
static PFN_SetThreadDescription setThreadDesc = (PFN_SetThreadDescription)GetProcAddress(
|
||||
GetModuleHandleA("kernel32.dll"), "SetThreadDescription");
|
||||
|
||||
if(setThreadDesc)
|
||||
{
|
||||
setThreadDesc(GetCurrentThread(), StringFormat::UTF82Wide(name).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't throw the exception if there's no debugger present
|
||||
if(!IsDebuggerPresent())
|
||||
return;
|
||||
|
||||
SetThreadNameWithException(name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t GetCurrentID()
|
||||
{
|
||||
return (uint64_t)::GetCurrentThreadId();
|
||||
|
||||
Reference in New Issue
Block a user