mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-17 21:17:09 +00:00
Move available GPU check onto thread at startup
* This hides a stall when first opening a window that needs the list of GPUs.
This commit is contained in:
+123
-106
@@ -480,6 +480,112 @@ void RenderDoc::ProcessGlobalEnvironment(GlobalEnvironment env, const std::vecto
|
||||
for(size_t i = 0; i < args.size(); i++)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if(driverType == RDCDriver::Unknown || !HasReplayDriver(driverType))
|
||||
continue;
|
||||
|
||||
IReplayDriver *driver = NULL;
|
||||
ReplayStatus status = m_ReplayDriverProviders[driverType](NULL, ReplayOptions(), &driver);
|
||||
|
||||
if(status == ReplayStatus::Succeeded)
|
||||
{
|
||||
rdcarray<GPUDevice> gpus = driver->GetAvailableGPUs();
|
||||
|
||||
for(const GPUDevice &newgpu : gpus)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool RenderDoc::MatchClosestWindow(void *&dev, void *&wnd)
|
||||
@@ -1152,116 +1258,21 @@ std::vector<CaptureFileFormat> RenderDoc::GetCaptureFileFormats()
|
||||
|
||||
rdcarray<GPUDevice> RenderDoc::GetAvailableGPUs()
|
||||
{
|
||||
if(m_AvailableGPUs.empty())
|
||||
{
|
||||
for(GraphicsAPI api : {GraphicsAPI::D3D11, GraphicsAPI::D3D12, GraphicsAPI::Vulkan})
|
||||
{
|
||||
RDCDriver driverType = RDCDriver::Unknown;
|
||||
|
||||
switch(api)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if(driverType == RDCDriver::Unknown || !HasReplayDriver(driverType))
|
||||
continue;
|
||||
|
||||
IReplayDriver *driver = NULL;
|
||||
ReplayStatus status = CreateProxyReplayDriver(driverType, &driver);
|
||||
|
||||
if(status == ReplayStatus::Succeeded)
|
||||
{
|
||||
rdcarray<GPUDevice> gpus = driver->GetAvailableGPUs();
|
||||
|
||||
for(const GPUDevice &newgpu : gpus)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("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());
|
||||
}
|
||||
}
|
||||
SyncAvailableGPUThread();
|
||||
|
||||
return m_AvailableGPUs;
|
||||
}
|
||||
|
||||
void RenderDoc::SyncAvailableGPUThread()
|
||||
{
|
||||
if(m_AvailableGPUThread)
|
||||
{
|
||||
Threading::JoinThread(m_AvailableGPUThread);
|
||||
Threading::CloseThread(m_AvailableGPUThread);
|
||||
m_AvailableGPUThread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderDoc::HasReplaySupport(RDCDriver driverType)
|
||||
{
|
||||
if(driverType == RDCDriver::Image)
|
||||
@@ -1275,6 +1286,8 @@ bool RenderDoc::HasReplaySupport(RDCDriver driverType)
|
||||
|
||||
ReplayStatus RenderDoc::CreateProxyReplayDriver(RDCDriver proxyDriver, IReplayDriver **driver)
|
||||
{
|
||||
SyncAvailableGPUThread();
|
||||
|
||||
// passing RDCDriver::Unknown means 'I don't care, give me a proxy driver of any type'
|
||||
if(proxyDriver == RDCDriver::Unknown)
|
||||
{
|
||||
@@ -1295,6 +1308,8 @@ ReplayStatus RenderDoc::CreateReplayDriver(RDCFile *rdc, const ReplayOptions &op
|
||||
if(driver == NULL)
|
||||
return ReplayStatus::InternalError;
|
||||
|
||||
SyncAvailableGPUThread();
|
||||
|
||||
// allows passing NULL rdcfile as 'I don't care, give me a proxy driver of any type'
|
||||
if(rdc == NULL)
|
||||
{
|
||||
@@ -1324,6 +1339,8 @@ ReplayStatus RenderDoc::CreateRemoteDriver(RDCFile *rdc, const ReplayOptions &op
|
||||
if(rdc == NULL || driver == NULL)
|
||||
return ReplayStatus::InternalError;
|
||||
|
||||
SyncAvailableGPUThread();
|
||||
|
||||
RDCDriver driverType = rdc->GetDriver();
|
||||
|
||||
if(m_RemoteDriverProviders.find(driverType) != m_RemoteDriverProviders.end())
|
||||
|
||||
Reference in New Issue
Block a user