@@ -272,16 +272,21 @@ namespace dxvk {
272
272
}
273
273
274
274
275
- Rc<DxvkDevice> DxvkAdapter::createDevice (
276
- const Rc<DxvkInstance>& instance,
277
- DxvkDeviceFeatures enabledFeatures) {
278
- DxvkDeviceExtensions devExtensions;
275
+ bool DxvkAdapter::getDeviceCreateInfo (
276
+ const Rc<DxvkInstance>& instance,
277
+ VkDeviceCreateInfo& info,
278
+ DxvkDeviceFeatures& enabledFeatures,
279
+ DxvkDeviceCreateExtInfo& extInfo,
280
+ DxvkDeviceCreateQueueInfo& queueInfo) const {
281
+ auto & [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo;
282
+ auto & [queueFamilies, queueInfos] = queueInfo;
283
+
279
284
auto devExtensionList = getExtensionList (devExtensions);
280
285
281
286
// Only enable Cuda interop extensions in 64-bit builds in
282
287
// order to avoid potential driver or address space issues.
283
288
// VK_KHR_buffer_device_address is expensive on some drivers.
284
- bool enableCudaInterop = !env::is32BitHostPlatform () &&
289
+ enableCudaInterop = !env::is32BitHostPlatform () &&
285
290
m_deviceExtensions.supports (devExtensions.nvxBinaryImport .name ()) &&
286
291
m_deviceExtensions.supports (devExtensions.nvxImageViewHandle .name ()) &&
287
292
m_deviceFeatures.vk12 .bufferDeviceAddress ;
@@ -298,17 +303,15 @@ namespace dxvk {
298
303
if (!m_deviceExtensions.supports (devExtensions.extPageableDeviceLocalMemory .name ()))
299
304
devExtensions.amdMemoryOverallocationBehaviour .setMode (DxvkExtMode::Optional);
300
305
301
- DxvkNameSet extensionsEnabled;
302
-
303
306
if (!m_deviceExtensions.enableExtensions (
304
307
devExtensionList.size (),
305
308
devExtensionList.data (),
306
309
&extensionsEnabled))
307
- throw DxvkError ( " DxvkAdapter: Failed to create device " ) ;
310
+ return false ;
308
311
309
312
// Enable additional extensions if necessary
310
313
extensionsEnabled.merge (m_extraExtensions);
311
- DxvkNameList extensionNameList = extensionsEnabled.toNameList ();
314
+ extensionNameList = extensionsEnabled.toNameList ();
312
315
313
316
// Always enable robust buffer access
314
317
enabledFeatures.core .features .robustBufferAccess = VK_TRUE;
@@ -443,34 +446,22 @@ namespace dxvk {
443
446
// Create pNext chain for additional device features
444
447
initFeatureChain (enabledFeatures, devExtensions, instance->extensions ());
445
448
446
- // Log feature support info an extension list
447
- Logger::info (str::format (" Device properties:"
448
- " \n Device : " , m_deviceInfo.core .properties .deviceName ,
449
- " \n Driver : " , m_deviceInfo.vk12 .driverName , " " , m_deviceInfo.driverVersion .toString ()));
450
-
451
- Logger::info (" Enabled device extensions:" );
452
- this ->logNameList (extensionNameList);
453
- this ->logFeatures (enabledFeatures);
454
-
455
449
// Report the desired overallocation behaviour to the driver
456
450
VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD };
457
451
overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD;
458
452
459
453
// Create the requested queues
460
- float queuePriority = 1 .0f ;
461
- std::vector<VkDeviceQueueCreateInfo> queueInfos;
454
+ static const float queuePriority = 1 .0f ;
462
455
463
456
std::unordered_set<uint32_t > queueFamiliySet;
464
457
465
- DxvkAdapterQueueIndices queueFamilies = findQueueFamilies ();
458
+ queueFamilies = findQueueFamilies ();
466
459
queueFamiliySet.insert (queueFamilies.graphics );
467
460
queueFamiliySet.insert (queueFamilies.transfer );
468
461
469
462
if (queueFamilies.sparse != VK_QUEUE_FAMILY_IGNORED)
470
463
queueFamiliySet.insert (queueFamilies.sparse );
471
464
472
- this ->logQueueFamilies (queueFamilies);
473
-
474
465
for (uint32_t family : queueFamiliySet) {
475
466
VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
476
467
graphicsQueue.queueFamilyIndex = family;
@@ -479,7 +470,8 @@ namespace dxvk {
479
470
queueInfos.push_back (graphicsQueue);
480
471
}
481
472
482
- VkDeviceCreateInfo info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, enabledFeatures.core .pNext };
473
+ info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
474
+ info.pNext = enabledFeatures.core .pNext ;
483
475
info.queueCreateInfoCount = queueInfos.size ();
484
476
info.pQueueCreateInfos = queueInfos.data ();
485
477
info.enabledExtensionCount = extensionNameList.count ();
@@ -489,6 +481,34 @@ namespace dxvk {
489
481
if (devExtensions.amdMemoryOverallocationBehaviour )
490
482
overallocInfo.pNext = std::exchange (info.pNext , &overallocInfo);
491
483
484
+ return true ;
485
+ }
486
+
487
+ Rc<DxvkDevice> DxvkAdapter::createDevice (
488
+ const Rc<DxvkInstance>& instance,
489
+ DxvkDeviceFeatures enabledFeatures) {
490
+ VkDeviceCreateInfo info;
491
+ DxvkDeviceCreateExtInfo extInfo;
492
+ DxvkDeviceCreateQueueInfo queueInfo;
493
+
494
+ // Get device creation info
495
+ if (!getDeviceCreateInfo (instance, info, enabledFeatures, extInfo, queueInfo))
496
+ throw DxvkError (" DxvkAdapter: Failed to create device" );
497
+
498
+ auto & [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo;
499
+ auto & [queueFamilies, queueInfos] = queueInfo;
500
+
501
+ // Log feature support info, extension list, and queue families
502
+ Logger::info (str::format (" Device properties:"
503
+ " \n Device : " , m_deviceInfo.core .properties .deviceName ,
504
+ " \n Driver : " , m_deviceInfo.vk12 .driverName , " " , m_deviceInfo.driverVersion .toString ()));
505
+
506
+ Logger::info (" Enabled device extensions:" );
507
+ this ->logNameList (extensionNameList);
508
+ this ->logFeatures (enabledFeatures);
509
+ this ->logQueueFamilies (queueFamilies);
510
+
511
+ // Create device!
492
512
VkDevice device = VK_NULL_HANDLE;
493
513
VkResult vr = m_vki->vkCreateDevice (m_handle, &info, nullptr , &device);
494
514
@@ -661,11 +681,17 @@ namespace dxvk {
661
681
// Create device loader
662
682
Rc<vk::DeviceFn> vkd = new vk::DeviceFn (m_vki, false , args.device );
663
683
664
- // We only support one queue when importing devices, and no sparse.
684
+ // By default, we only use one queue when importing devices, and no sparse.
665
685
DxvkDeviceQueueSet queues = { };
666
686
queues.graphics = { args.queue , args.queueFamily };
667
687
queues.transfer = queues.graphics ;
668
688
689
+ if (args.transferQueue != VK_NULL_HANDLE && args.transferQueueFamily != VK_QUEUE_FAMILY_IGNORED)
690
+ queues.transfer = { args.transferQueue , args.transferQueueFamily };
691
+
692
+ if (args.sparseQueue != VK_NULL_HANDLE && args.sparseQueueFamily != VK_QUEUE_FAMILY_IGNORED)
693
+ queues.sparse = { args.sparseQueue , args.sparseQueueFamily };
694
+
669
695
return new DxvkDevice (instance, this , vkd, enabledFeatures, queues, args.queueCallback );
670
696
}
671
697
@@ -992,7 +1018,7 @@ namespace dxvk {
992
1018
993
1019
994
1020
std::vector<DxvkExt*> DxvkAdapter::getExtensionList (
995
- DxvkDeviceExtensions& devExtensions) {
1021
+ DxvkDeviceExtensions& devExtensions) const {
996
1022
return {{
997
1023
&devExtensions.amdMemoryOverallocationBehaviour ,
998
1024
&devExtensions.amdShaderFragmentMask ,
0 commit comments