diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index d62668c5a..02e39087b 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -608,6 +608,12 @@ struct GlobalEnvironment DOCUMENT( "The handle to the X display to use internally. If left ``NULL``, wayland cannot be used."); wl_display *waylandDisplay = NULL; + + DOCUMENT(R"(Whether to enumerate available GPUs. If the replay program is only being used for +internal operation where enumerating GPUs would be too expensive or problematic, it can be disabled +here. +)"); + bool enumerateGPUs = true; }; DOCUMENT("The result of executing or injecting into a program.") diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index efcf28cfe..d5e7edeb0 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -509,111 +509,114 @@ void RenderDoc::ProcessGlobalEnvironment(GlobalEnvironment env, const std::vecto RDCDEBUG("[%u]: %s", (uint32_t)i, args[i].c_str()); } - m_AvailableGPUThread = Threading::CreateThread([this]() { - for(GraphicsAPI api : {GraphicsAPI::D3D11, GraphicsAPI::D3D12, GraphicsAPI::Vulkan}) - { - RDCDriver driverType = RDCDriver::Unknown; - - switch(api) + if(env.enumerateGPUs) + { + m_AvailableGPUThread = Threading::CreateThread([this]() { + for(GraphicsAPI api : {GraphicsAPI::D3D11, GraphicsAPI::D3D12, GraphicsAPI::Vulkan}) { - case GraphicsAPI::D3D11: driverType = RDCDriver::D3D11; break; - case GraphicsAPI::D3D12: driverType = RDCDriver::D3D12; break; - case GraphicsAPI::OpenGL: break; - case GraphicsAPI::Vulkan: driverType = RDCDriver::Vulkan; break; - } + RDCDriver driverType = RDCDriver::Unknown; - if(driverType == RDCDriver::Unknown || !HasReplayDriver(driverType)) - continue; - - IReplayDriver *driver = NULL; - ReplayStatus status = m_ReplayDriverProviders[driverType](NULL, ReplayOptions(), &driver); - - if(status == ReplayStatus::Succeeded) - { - rdcarray gpus = driver->GetAvailableGPUs(); - - for(const GPUDevice &newgpu : gpus) + switch(api) { - bool addnew = true; - - for(GPUDevice &oldgpu : m_AvailableGPUs) - { - // if we have this GPU listed already, just add its API to the previous list - if(oldgpu == newgpu) - { - oldgpu.apis.push_back(api); - addnew = false; - } - } - - if(addnew) - m_AvailableGPUs.push_back(newgpu); + case GraphicsAPI::D3D11: driverType = RDCDriver::D3D11; break; + case GraphicsAPI::D3D12: driverType = RDCDriver::D3D12; break; + case GraphicsAPI::OpenGL: break; + case GraphicsAPI::Vulkan: driverType = RDCDriver::Vulkan; break; } - } - else - { - RDCWARN("Couldn't create proxy replay driver for %s: %s", ToStr(driverType).c_str(), - ToStr(status).c_str()); - } - if(driver) - driver->Shutdown(); - } - - // we now have a list of GPUs, however we might have some duplicates if some APIs have - // multiple drivers for a single device. To compact this list, for each GPU with no driver - // we find all matching multi-drive GPUs and merge it into all matching copies. - bool hasDriverNames = false; - for(size_t i = 0; i < m_AvailableGPUs.size(); i++) - hasDriverNames |= !m_AvailableGPUs[i].driver.empty(); - - if(hasDriverNames) - { - for(size_t i = 0; i < m_AvailableGPUs.size();) - { - bool applied = false; - - if(!m_AvailableGPUs[i].driver.empty()) - { - i++; + if(driverType == RDCDriver::Unknown || !HasReplayDriver(driverType)) continue; - } - // scan all subsequent GPUs, if we find a duplicate, merge the APIs - for(size_t j = i + 1; j < m_AvailableGPUs.size(); j++) + IReplayDriver *driver = NULL; + ReplayStatus status = m_ReplayDriverProviders[driverType](NULL, ReplayOptions(), &driver); + + if(status == ReplayStatus::Succeeded) { - if(m_AvailableGPUs[i].vendor == m_AvailableGPUs[j].vendor && - m_AvailableGPUs[i].deviceID == m_AvailableGPUs[j].deviceID) + rdcarray gpus = driver->GetAvailableGPUs(); + + for(const GPUDevice &newgpu : gpus) { - RDCASSERT(!m_AvailableGPUs[j].driver.empty()); - for(GraphicsAPI a : m_AvailableGPUs[i].apis) - { - if(m_AvailableGPUs[j].apis.indexOf(a) == -1) - m_AvailableGPUs[j].apis.push_back(a); - } - applied = true; - } - } + bool addnew = true; - // we "applied" this GPU to all its driver-based duplicates, so we can remove it now - if(applied) - { - m_AvailableGPUs.erase(i); + for(GPUDevice &oldgpu : m_AvailableGPUs) + { + // if we have this GPU listed already, just add its API to the previous list + if(oldgpu == newgpu) + { + oldgpu.apis.push_back(api); + addnew = false; + } + } + + if(addnew) + m_AvailableGPUs.push_back(newgpu); + } } else { - i++; + RDCWARN("Couldn't create proxy replay driver for %s: %s", ToStr(driverType).c_str(), + ToStr(status).c_str()); + } + + if(driver) + driver->Shutdown(); + } + + // we now have a list of GPUs, however we might have some duplicates if some APIs have + // multiple drivers for a single device. To compact this list, for each GPU with no driver + // we find all matching multi-drive GPUs and merge it into all matching copies. + bool hasDriverNames = false; + for(size_t i = 0; i < m_AvailableGPUs.size(); i++) + hasDriverNames |= !m_AvailableGPUs[i].driver.empty(); + + if(hasDriverNames) + { + for(size_t i = 0; i < m_AvailableGPUs.size();) + { + bool applied = false; + + if(!m_AvailableGPUs[i].driver.empty()) + { + i++; + continue; + } + + // scan all subsequent GPUs, if we find a duplicate, merge the APIs + for(size_t j = i + 1; j < m_AvailableGPUs.size(); j++) + { + if(m_AvailableGPUs[i].vendor == m_AvailableGPUs[j].vendor && + m_AvailableGPUs[i].deviceID == m_AvailableGPUs[j].deviceID) + { + RDCASSERT(!m_AvailableGPUs[j].driver.empty()); + for(GraphicsAPI a : m_AvailableGPUs[i].apis) + { + if(m_AvailableGPUs[j].apis.indexOf(a) == -1) + m_AvailableGPUs[j].apis.push_back(a); + } + applied = true; + } + } + + // we "applied" this GPU to all its driver-based duplicates, so we can remove it now + if(applied) + { + m_AvailableGPUs.erase(i); + } + else + { + i++; + } } } - } - // sort the APIs list in each GPU, and sort the GPUs - std::sort(m_AvailableGPUs.begin(), m_AvailableGPUs.end()); - for(GPUDevice &dev : m_AvailableGPUs) - { - std::sort(dev.apis.begin(), dev.apis.end()); - } - }); + // sort the APIs list in each GPU, and sort the GPUs + std::sort(m_AvailableGPUs.begin(), m_AvailableGPUs.end()); + for(GPUDevice &dev : m_AvailableGPUs) + { + std::sort(dev.apis.begin(), dev.apis.end()); + } + }); + } } bool RenderDoc::MatchClosestWindow(void *&dev, void *&wnd) diff --git a/renderdoccmd/renderdoccmd.cpp b/renderdoccmd/renderdoccmd.cpp index daef13d86..21916827d 100644 --- a/renderdoccmd/renderdoccmd.cpp +++ b/renderdoccmd/renderdoccmd.cpp @@ -473,6 +473,8 @@ struct RemoteServerCommand : public Command { std::string host = parser.get("host"); + m_Env.enumerateGPUs = true; + RENDERDOC_InitGlobalEnv(m_Env, convertArgs(parser.rest())); std::cerr << "Spawning a replay host listening on " << (host.empty() ? "*" : host) << "..." @@ -1169,8 +1171,11 @@ struct EmbeddedSectionCommand : public Command REPLAY_PROGRAM_MARKER() -int renderdoccmd(const GlobalEnvironment &env, std::vector &argv) +int renderdoccmd(GlobalEnvironment &env, std::vector &argv) { + // we don't need this in renderdoccmd. + env.enumerateGPUs = false; + try { // add basic commands, and common aliases @@ -1330,7 +1335,7 @@ int renderdoccmd(const GlobalEnvironment &env, std::vector &argv) } } -int renderdoccmd(const GlobalEnvironment &env, int argc, char **c_argv) +int renderdoccmd(GlobalEnvironment &env, int argc, char **c_argv) { std::vector argv; argv.resize(argc); diff --git a/renderdoccmd/renderdoccmd.h b/renderdoccmd/renderdoccmd.h index cc42d0466..d85f046a6 100644 --- a/renderdoccmd/renderdoccmd.h +++ b/renderdoccmd/renderdoccmd.h @@ -50,8 +50,8 @@ void add_version_line(const std::string &str); void add_command(const std::string &name, Command *cmd); void add_alias(const std::string &alias, const std::string &command); -int renderdoccmd(const GlobalEnvironment &env, int argc, char **argv); -int renderdoccmd(const GlobalEnvironment &env, std::vector &argv); +int renderdoccmd(GlobalEnvironment &env, int argc, char **argv); +int renderdoccmd(GlobalEnvironment &env, std::vector &argv); void readCapOpts(const std::string &str, CaptureOptions *opts); diff --git a/renderdoccmd/renderdoccmd_android.cpp b/renderdoccmd/renderdoccmd_android.cpp index a42cc7568..a65b64f3a 100644 --- a/renderdoccmd/renderdoccmd_android.cpp +++ b/renderdoccmd/renderdoccmd_android.cpp @@ -417,7 +417,8 @@ void *cmdthread(void *) { ANDROID_LOG("Entering cmd thread"); m_CmdLock.lock(); - renderdoccmd(GlobalEnvironment(), args); + GlobalEnvironment env; + renderdoccmd(env, args); m_CmdLock.unlock(); ANDROID_LOG("Exiting cmd thread"); } diff --git a/renderdoccmd/renderdoccmd_apple.cpp b/renderdoccmd/renderdoccmd_apple.cpp index 7521554f6..22ede9e5b 100644 --- a/renderdoccmd/renderdoccmd_apple.cpp +++ b/renderdoccmd/renderdoccmd_apple.cpp @@ -51,5 +51,7 @@ int main(int argc, char *argv[]) // process any apple-specific arguments here - return renderdoccmd(GlobalEnvironment(), argc, argv); + GlobalEnvironment env; + + return renderdoccmd(env, argc, argv); }