diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 070e3c7d0..db5526f77 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -320,6 +320,7 @@ private: D3D11InitParams m_InitParams; uint64_t m_SectionVersion; + ReplayOptions m_ReplayOptions; ResourceId m_BBID; @@ -394,10 +395,11 @@ public: ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D11Device, AllocPoolCount); WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitParams params); - void SetInitParams(const D3D11InitParams ¶ms, uint64_t sectionVersion) + void SetInitParams(const D3D11InitParams ¶ms, uint64_t sectionVersion, const ReplayOptions &opts) { m_InitParams = params; m_SectionVersion = sectionVersion; + m_ReplayOptions = opts; } uint64_t GetLogVersion() { return m_SectionVersion; } virtual ~WrappedID3D11Device(); diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 9e2b4159e..893f3010e 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -3788,7 +3788,8 @@ ReplayStatus D3D11_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, I // support because using warp was not deliberate) bool warpFallback = false; - ChooseBestMatchingAdapter(GraphicsAPI::D3D11, factory, initParams.AdapterDesc, &useWarp, &adapter); + ChooseBestMatchingAdapter(GraphicsAPI::D3D11, factory, initParams.AdapterDesc, opts, &useWarp, + &adapter); if(useWarp) SAFE_RELEASE(adapter); @@ -3921,7 +3922,7 @@ ReplayStatus D3D11_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, I if(SUCCEEDED(hr) && device) { WrappedID3D11Device *wrappedDev = new WrappedID3D11Device(device, initParams); - wrappedDev->SetInitParams(initParams, ver); + wrappedDev->SetInitParams(initParams, ver, opts); RDCLOG("Created device."); D3D11Replay *replay = wrappedDev->GetReplay(); diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index d2ff28a6f..014fa6cf4 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -394,6 +394,7 @@ private: D3D12InitParams m_InitParams; uint64_t m_SectionVersion; + ReplayOptions m_ReplayOptions; ID3D12InfoQueue *m_pInfoQueue; D3D12ResourceRecord *m_FrameCaptureRecord; @@ -506,10 +507,11 @@ public: } const std::map &GetBackbufferFormats() { return m_BackbufferFormat; } void SetLogFile(const char *logfile); - void SetInitParams(const D3D12InitParams ¶ms, uint64_t sectionVersion) + void SetInitParams(const D3D12InitParams ¶ms, uint64_t sectionVersion, const ReplayOptions &opts) { m_InitParams = params; m_SectionVersion = sectionVersion; + m_ReplayOptions = opts; } uint64_t GetLogVersion() { return m_SectionVersion; } CaptureState GetState() { return m_State; } diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 2befbdc62..4e070cbcc 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -3754,7 +3754,8 @@ ReplayStatus D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, I IDXGIAdapter *adapter = NULL; - ChooseBestMatchingAdapter(GraphicsAPI::D3D12, factory, initParams.AdapterDesc, NULL, &adapter); + ChooseBestMatchingAdapter(GraphicsAPI::D3D12, factory, initParams.AdapterDesc, opts, NULL, + &adapter); bool EnableDebugLayer = false; @@ -3795,7 +3796,7 @@ ReplayStatus D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, I } WrappedID3D12Device *wrappedDev = new WrappedID3D12Device(dev, initParams, EnableDebugLayer); - wrappedDev->SetInitParams(initParams, ver); + wrappedDev->SetInitParams(initParams, ver, opts); RDCLOG("Created device."); D3D12Replay *replay = wrappedDev->GetReplay(); diff --git a/renderdoc/driver/dxgi/dxgi_common.cpp b/renderdoc/driver/dxgi/dxgi_common.cpp index f0fdc9f5b..a09898cce 100644 --- a/renderdoc/driver/dxgi/dxgi_common.cpp +++ b/renderdoc/driver/dxgi/dxgi_common.cpp @@ -1736,13 +1736,132 @@ std::string GetDriverVersion(DXGI_ADAPTER_DESC &desc) return device + " " + driverVersion; } +IDXGIAdapter *EnumBestAdapter(IDXGIFactory *factory, GPUVendor vendor, uint32_t deviceId) +{ + IDXGIAdapter *ret = NULL; + DXGI_ADAPTER_DESC retDesc = {}; + + for(UINT i = 0; i < 10; i++) + { + IDXGIAdapter *ad = NULL; + HRESULT hr = factory->EnumAdapters(i, &ad); + if(hr == S_OK && ad) + { + DXGI_ADAPTER_DESC desc; + ad->GetDesc(&desc); + + // if it's a better vendor match than the adapter we have, choose it + GPUVendor adVendor = GPUVendorFromPCIVendor(desc.VendorId); + if(adVendor == vendor && GPUVendorFromPCIVendor(retDesc.VendorId) != vendor) + { + ret = ad; + retDesc = desc; + continue; + } + else if(adVendor != vendor) + { + ad->Release(); + continue; + } + + // if they're the same vendor but this is a better device match, choose it + if(desc.DeviceId == deviceId && retDesc.DeviceId != deviceId) + { + ret = ad; + retDesc = desc; + continue; + } + + ad->Release(); + } + else + { + break; + } + } + + return ret; +} + void ChooseBestMatchingAdapter(GraphicsAPI api, IDXGIFactory *factory, - const DXGI_ADAPTER_DESC &AdapterDesc, bool *useWarp, - IDXGIAdapter **adapter) + const DXGI_ADAPTER_DESC &AdapterDesc, const ReplayOptions &opts, + bool *useWarp, IDXGIAdapter **adapter) { bool retWarp = false; IDXGIAdapter *ret = NULL; - DXGI_ADAPTER_DESC retDesc = {}; + + bool warpAvailable = false; + IDXGIAdapter *warpAdapter = NULL; + + if(api == GraphicsAPI::D3D11) + { + // D3D11 WARP is always available, we assume. + warpAvailable = true; + } + else + { + // on D3D12 we don't have WARP when we're on 12On7. The easy way to check this is to try and + // fetch a IDXGIFactory4, which we want to do anyway to get the warp adapter. + IDXGIFactory4 *factory4 = NULL; + HRESULT hr = factory->QueryInterface(__uuidof(IDXGIFactory4), (void **)&factory4); + if(SUCCEEDED(hr) && factory4) + { + hr = factory4->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&warpAdapter); + + if(FAILED(hr) || !warpAdapter) + { + RDCWARN("Couldn't enumerate WARP adapter from IDXGIFactory4"); + } + } + + warpAvailable = warpAdapter != NULL; + + SAFE_RELEASE(factory4); + } + + // if we're forcing WARP, try that first + if(opts.forceGPUVendor == GPUVendor::Software) + { + if(warpAvailable) + { + if(useWarp) + *useWarp = true; + if(adapter) + *adapter = warpAdapter; + return; + } + else + { + RDCWARN("WARP is not available to replay on. Falling back to default adapter selection."); + } + } + else if(opts.forceGPUVendor != GPUVendor::Unknown) + { + // otherwise we're trying to force a device, see if we can get it + ret = EnumBestAdapter(factory, opts.forceGPUVendor, opts.forceGPUDeviceID); + + if(ret == NULL) + { + RDCLOG( + "Couldn't find specified adapter to replay on, falling back to default adapter " + "selection"); + } + else + { + DXGI_ADAPTER_DESC retDesc = {}; + ret->GetDesc(&retDesc); + RDCLOG("Forcing use of %s / %ls adapter for replay", + ToStr(GPUVendorFromPCIVendor(retDesc.VendorId)).c_str(), retDesc.Description); + + if(useWarp) + *useWarp = false; + if(adapter) + *adapter = ret; + return; + } + } + + // default selection algorithm GPUVendor vendor = GPUVendorFromPCIVendor(AdapterDesc.VendorId); @@ -1750,43 +1869,23 @@ void ChooseBestMatchingAdapter(GraphicsAPI api, IDXGIFactory *factory, if(!wcscmp(AdapterDesc.Description, L"Software Adapter")) vendor = GPUVendor::Software; - // if the vendor is software we should try to use WARP + // if we're forcing WARP, try that first we should try to use WARP if(vendor == GPUVendor::Software) { - retWarp = true; - - // D3D11 WARP is always available, we assume. - if(api == GraphicsAPI::D3D11) + if(warpAvailable) { - ret = NULL; + ret = warpAdapter; + warpAdapter = NULL; + retWarp = true; } else { - // on D3D12 we don't have WARP when we're on 12On7. The easy way to check this is to try and - // fetch a IDXGIFactory4, which we want to do anyway to get the warp adapter. - IDXGIFactory4 *factory4 = NULL; - HRESULT hr = factory->QueryInterface(__uuidof(IDXGIFactory4), (void **)&factory4); - if(SUCCEEDED(hr) && factory4) - { - hr = factory4->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&ret); + RDCWARN( + "WARP would be the selected adapter, but is not available. Falling back to default " + "adapter selection."); - if(FAILED(hr) || !ret) - { - RDCWARN("Couldn't enumerate WARP adapter from IDXGIFactory4"); - retWarp = false; - ret = NULL; - } - } - else - { - // if WARP isn't available, fall back - RDCWARN( - "WARP is the best matching adapter, but is not available. Falling back to default " - "adapter selection."); - - retWarp = false; - ret = NULL; - } + retWarp = false; + ret = NULL; } } @@ -1795,51 +1894,24 @@ void ChooseBestMatchingAdapter(GraphicsAPI api, IDXGIFactory *factory, // matching adapter if(retWarp == false && ret == NULL && AdapterDesc.Description[0]) { - for(UINT i = 0; i < 10; i++) - { - IDXGIAdapter *ad = NULL; - HRESULT hr = factory->EnumAdapters(i, &ad); - if(hr == S_OK && ad) - { - DXGI_ADAPTER_DESC desc; - ad->GetDesc(&desc); - - // if it's a better vendor match than the adapter we have, choose it - if(desc.VendorId == AdapterDesc.VendorId && retDesc.VendorId != AdapterDesc.VendorId) - { - ret = ad; - retDesc = desc; - continue; - } - else if(desc.VendorId != AdapterDesc.VendorId) - { - ad->Release(); - continue; - } - - // if they're the same vendor but this is a better device match, choose it - if(desc.DeviceId == AdapterDesc.DeviceId && retDesc.DeviceId != AdapterDesc.DeviceId) - { - ret = ad; - retDesc = desc; - continue; - } - - ad->Release(); - } - else - { - break; - } - } + ret = + EnumBestAdapter(factory, GPUVendorFromPCIVendor(AdapterDesc.VendorId), AdapterDesc.DeviceId); if(ret == NULL) + { RDCLOG("Couldn't find similar adapter to replay on, using default adapter"); + } else + { + DXGI_ADAPTER_DESC retDesc = {}; + ret->GetDesc(&retDesc); RDCLOG("Selected %s / %ls adapter for replay", ToStr(GPUVendorFromPCIVendor(retDesc.VendorId)).c_str(), retDesc.Description); + } } + SAFE_RELEASE(warpAdapter); + if(useWarp) *useWarp = retWarp; if(adapter) diff --git a/renderdoc/driver/dxgi/dxgi_common.h b/renderdoc/driver/dxgi/dxgi_common.h index cd071c80f..8dc29e655 100644 --- a/renderdoc/driver/dxgi/dxgi_common.h +++ b/renderdoc/driver/dxgi/dxgi_common.h @@ -70,8 +70,8 @@ void WarnUnknownGUID(const char *name, REFIID riid); std::string GetDriverVersion(DXGI_ADAPTER_DESC &desc); void ChooseBestMatchingAdapter(GraphicsAPI api, IDXGIFactory *factory, - const DXGI_ADAPTER_DESC &AdapterDesc, bool *useWarp, - IDXGIAdapter **adapter); + const DXGI_ADAPTER_DESC &AdapterDesc, const ReplayOptions &opts, + bool *useWarp, IDXGIAdapter **adapter); DECLARE_REFLECTION_STRUCT(DXGI_SAMPLE_DESC); DECLARE_REFLECTION_STRUCT(DXGI_ADAPTER_DESC); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 69be3a3e6..c4862ba43 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -710,10 +710,12 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform) m_CurCtxDataTLS = Threading::AllocateTLSSlot(); } -void WrappedOpenGL::Initialise(GLInitParams ¶ms, uint64_t sectionVersion) +void WrappedOpenGL::Initialise(GLInitParams ¶ms, uint64_t sectionVersion, + const ReplayOptions &opts) { m_SectionVersion = sectionVersion; m_GlobalInitParams = params; + m_ReplayOptions = opts; } void WrappedOpenGL::MarkReferencedWhileCapturing(GLResourceRecord *record, FrameRefType refType) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index e8ce77052..0cf78c04e 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -130,6 +130,7 @@ private: uint64_t m_SectionVersion; GLInitParams m_GlobalInitParams; + ReplayOptions m_ReplayOptions; WriteSerialiser m_ScratchSerialiser; std::set m_StringDB; @@ -569,7 +570,7 @@ public: bool IsUnsafeDraw(uint32_t eventId) { return m_UnsafeDraws.find(eventId) != m_UnsafeDraws.end(); } // replay interface - void Initialise(GLInitParams ¶ms, uint64_t sectionVersion); + void Initialise(GLInitParams ¶ms, uint64_t sectionVersion, const ReplayOptions &opts); void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType); ReplayStatus ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers); diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 9ded3b554..cad654a31 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -3465,7 +3465,7 @@ ReplayStatus CreateReplayDevice(RDCDriver rdcdriver, RDCFile *rdc, const ReplayO replay->SetProxy(rdc == NULL); replay->SetReplayData(data); - gldriver->Initialise(initParams, ver); + gldriver->Initialise(initParams, ver, opts); *driver = (IReplayDriver *)replay; return ReplayStatus::Succeeded; diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 970eec887..42054d05e 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -720,6 +720,21 @@ StencilOperation MakeStencilOp(VkStencilOp op) return StencilOperation::Keep; } +rdcstr HumanDriverName(VkDriverIdKHR driverId) +{ + switch(driverId) + { + case VK_DRIVER_ID_AMD_PROPRIETARY_KHR: return "AMD Propriertary"; + case VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR: return "AMD Open-source"; + case VK_DRIVER_ID_MESA_RADV_KHR: return "AMD RADV"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR: return "Intel Propriertary"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR: return "Intel Open-source"; + default: break; + } + + return ""; +} + BASIC_TYPE_SERIALISE_STRINGIFY(VkPackedVersion, (uint32_t &)el, SDBasic::UnsignedInteger, 4); INSTANTIATE_SERIALISE_TYPE(VkPackedVersion); diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 139d061b6..bf61d188b 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -99,6 +99,7 @@ LogicOperation MakeLogicOp(VkLogicOp op); BlendMultiplier MakeBlendMultiplier(VkBlendFactor blend); BlendOperation MakeBlendOp(VkBlendOp op); StencilOperation MakeStencilOp(VkStencilOp op); +rdcstr HumanDriverName(VkDriverIdKHR driverId); // set conservative access bits for this image layout VkAccessFlags MakeAccessMask(VkImageLayout layout); diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index dc4515f47..8ba9bb307 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -272,6 +272,7 @@ private: std::vector m_ThreadTempMem; VulkanReplay m_Replay; + ReplayOptions m_ReplayOptions; VkInitParams m_InitParams; uint64_t m_SectionVersion; @@ -932,7 +933,7 @@ public: uint32_t GetQueueFamilyIndex() { return m_QueueFamilyIdx; } bool ReleaseResource(WrappedVkRes *res); - ReplayStatus Initialise(VkInitParams ¶ms, uint64_t sectionVersion); + ReplayStatus Initialise(VkInitParams ¶ms, uint64_t sectionVersion, const ReplayOptions &opts); uint64_t GetLogVersion() { return m_SectionVersion; } void SetStructuredExport(uint64_t sectionVersion) { diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 8195c0f1d..29e812ecf 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -139,15 +139,7 @@ rdcarray VulkanReplay::GetAvailableGPUs() dev.apis = {GraphicsAPI::Vulkan}; // only set the driver name when it's useful to disambiguate - switch(driverProps.driverID) - { - default: dev.driver = ""; - case VK_DRIVER_ID_AMD_PROPRIETARY_KHR: dev.driver = "AMD Propriertary"; break; - case VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR: dev.driver = "AMD Open-source"; break; - case VK_DRIVER_ID_MESA_RADV_KHR: dev.driver = "AMD RADV"; break; - case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR: dev.driver = "Intel Propriertary"; break; - case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR: dev.driver = "Intel Open-source"; break; - } + dev.driver = HumanDriverName(driverProps.driverID); // don't add duplicate devices even if they get enumerated. if(ret.indexOf(dev) == -1) @@ -4204,7 +4196,7 @@ ReplayStatus Vulkan_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, SAFE_DELETE(rgp); WrappedVulkan *vk = new WrappedVulkan(); - ReplayStatus status = vk->Initialise(initParams, ver); + ReplayStatus status = vk->Initialise(initParams, ver, opts); if(status != ReplayStatus::Succeeded) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 26db588a6..9ba3787bf 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -170,10 +170,12 @@ static void StripUnwantedExtensions(std::vector &Extensions) } } -ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVersion) +ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVersion, + const ReplayOptions &opts) { m_InitParams = params; m_SectionVersion = sectionVersion; + m_ReplayOptions = opts; StripUnwantedLayers(params.Layers); StripUnwantedExtensions(params.Extensions); @@ -988,12 +990,20 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR, }; + rdcarray compPhysPropsArray; + rdcarray compDriverPropsArray; + + compPhysPropsArray.resize(m_ReplayPhysicalDevices.size()); + compDriverPropsArray.resize(m_ReplayPhysicalDevices.size()); + + // first cache all the physical device data to compare against for(uint32_t i = 0; i < (uint32_t)m_ReplayPhysicalDevices.size(); i++) { - VkPhysicalDeviceProperties compPhysProps = {}; - VkPhysicalDeviceDriverPropertiesKHR compDriverProps = { - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR, - }; + VkPhysicalDeviceProperties &compPhysProps = compPhysPropsArray[i]; + RDCEraseEl(compPhysProps); + VkPhysicalDeviceDriverPropertiesKHR &compDriverProps = compDriverPropsArray[i]; + RDCEraseEl(compDriverProps); + compDriverProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; pd = m_ReplayPhysicalDevices[i]; @@ -1043,84 +1053,167 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk compDriverProps.conformanceVersion.subminor, compDriverProps.conformanceVersion.patch); } } + } - // the first is the best at the start - if(i == 0) + // if we're forcing use of a GPU, try to find that one + bool forced = false; + if(m_ReplayOptions.forceGPUVendor != GPUVendor::Unknown) + { + for(uint32_t i = 0; i < (uint32_t)m_ReplayPhysicalDevices.size(); i++) { - bestPhysProps = compPhysProps; - bestDriverProps = compDriverProps; - continue; - } + const VkPhysicalDeviceProperties &compPhysProps = compPhysPropsArray[i]; + const VkPhysicalDeviceDriverPropertiesKHR &compDriverProps = compDriverPropsArray[i]; - // an exact vendorID match is a better match than not - if(compPhysProps.vendorID == physProps.vendorID && bestPhysProps.vendorID != physProps.vendorID) - { - bestIdx = i; - bestPhysProps = compPhysProps; - bestDriverProps = compDriverProps; - continue; - } - else if(compPhysProps.vendorID != physProps.vendorID) - { - continue; - } + VkDriverInfo bestInfo(bestPhysProps); + VkDriverInfo compInfo(compPhysProps); - // ditto deviceID - if(compPhysProps.deviceID == physProps.deviceID && bestPhysProps.deviceID != physProps.deviceID) - { - bestIdx = i; - bestPhysProps = compPhysProps; - bestDriverProps = compDriverProps; - continue; - } - else if(compPhysProps.deviceID != physProps.deviceID) - { - continue; - } + // an exact vendorID match is a better match than not + if(compInfo.Vendor() == m_ReplayOptions.forceGPUVendor && + bestInfo.Vendor() != m_ReplayOptions.forceGPUVendor) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + forced = true; + continue; + } + else if(compInfo.Vendor() != m_ReplayOptions.forceGPUVendor) + { + continue; + } - // driver matching. Only do this if both capture and replay gave us valid driver info to - // compare - if(compDriverProps.driverID && driverProps.driverID) + // ditto deviceID + if(compPhysProps.deviceID == m_ReplayOptions.forceGPUDeviceID && + bestPhysProps.deviceID != m_ReplayOptions.forceGPUDeviceID) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + forced = true; + continue; + } + else if(compPhysProps.deviceID != m_ReplayOptions.forceGPUDeviceID) + { + continue; + } + + // driver matching. Only do this if we have a driver name to look at + if(compDriverProps.driverID && !m_ReplayOptions.forceGPUDriverName.empty()) + { + rdcstr compHumanDriverName = HumanDriverName(compDriverProps.driverID); + rdcstr bestHumanDriverName = HumanDriverName(bestDriverProps.driverID); + + // check for a better driverID match + if(compHumanDriverName == m_ReplayOptions.forceGPUDriverName && + bestHumanDriverName != m_ReplayOptions.forceGPUDriverName) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + forced = true; + continue; + } + } + } + } + + if(forced) + { + RDCLOG("Forcing use of physical device"); + } + else + { + bestIdx = 0; + RDCEraseEl(bestPhysProps); + RDCEraseEl(bestDriverProps); + + for(uint32_t i = 0; i < (uint32_t)m_ReplayPhysicalDevices.size(); i++) { - // check for a better driverID match - if(compDriverProps.driverID == driverProps.driverID && - bestDriverProps.driverID != driverProps.driverID) + const VkPhysicalDeviceProperties &compPhysProps = compPhysPropsArray[i]; + const VkPhysicalDeviceDriverPropertiesKHR &compDriverProps = compDriverPropsArray[i]; + + pd = m_ReplayPhysicalDevices[i]; + + // the first is the best at the start + if(i == 0) + { + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + continue; + } + + // an exact vendorID match is a better match than not + if(compPhysProps.vendorID == physProps.vendorID && + bestPhysProps.vendorID != physProps.vendorID) { bestIdx = i; bestPhysProps = compPhysProps; bestDriverProps = compDriverProps; continue; } - else if(compDriverProps.driverID != driverProps.driverID) + else if(compPhysProps.vendorID != physProps.vendorID) { continue; } - } - // if we have an exact driver version match, prefer that - if(compPhysProps.driverVersion == physProps.driverVersion && - bestPhysProps.driverVersion != physProps.driverVersion) - { - bestIdx = i; - bestPhysProps = compPhysProps; - bestDriverProps = compDriverProps; - continue; - } - else if(compPhysProps.driverVersion != physProps.driverVersion) - { - continue; - } + // ditto deviceID + if(compPhysProps.deviceID == physProps.deviceID && + bestPhysProps.deviceID != physProps.deviceID) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + continue; + } + else if(compPhysProps.deviceID != physProps.deviceID) + { + continue; + } - // if we have multiple identical devices, which isn't uncommon, favour the one - // that hasn't been assigned - if(m_ReplayPhysicalDevicesUsed[bestIdx] && !m_ReplayPhysicalDevicesUsed[i]) - { - bestIdx = i; - bestPhysProps = compPhysProps; - continue; - } + // driver matching. Only do this if both capture and replay gave us valid driver info to + // compare + if(compDriverProps.driverID && driverProps.driverID) + { + // check for a better driverID match + if(compDriverProps.driverID == driverProps.driverID && + bestDriverProps.driverID != driverProps.driverID) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + continue; + } + else if(compDriverProps.driverID != driverProps.driverID) + { + continue; + } + } - // this device isn't any better, ignore it + // if we have an exact driver version match, prefer that + if(compPhysProps.driverVersion == physProps.driverVersion && + bestPhysProps.driverVersion != physProps.driverVersion) + { + bestIdx = i; + bestPhysProps = compPhysProps; + bestDriverProps = compDriverProps; + continue; + } + else if(compPhysProps.driverVersion != physProps.driverVersion) + { + continue; + } + + // if we have multiple identical devices, which isn't uncommon, favour the one + // that hasn't been assigned + if(m_ReplayPhysicalDevicesUsed[bestIdx] && !m_ReplayPhysicalDevicesUsed[i]) + { + bestIdx = i; + bestPhysProps = compPhysProps; + continue; + } + + // this device isn't any better, ignore it + } } { @@ -1139,7 +1232,8 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk driverProps.conformanceVersion.patch); } - RDCLOG("Mapping during replay to best-match physical device %u", bestIdx); + RDCLOG("Mapping during replay to %s physical device %u", forced ? "forced" : "best-match", + bestIdx); } pd = m_ReplayPhysicalDevices[bestIdx];