Skip to content

Commit 15565e5

Browse files
committed
[dxvk] Support getting device create info without creating device
1 parent 5868b06 commit 15565e5

File tree

2 files changed

+105
-35
lines changed

2 files changed

+105
-35
lines changed

src/dxvk/dxvk_adapter.cpp

+52-26
Original file line numberDiff line numberDiff line change
@@ -272,16 +272,21 @@ namespace dxvk {
272272
}
273273

274274

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+
279284
auto devExtensionList = getExtensionList(devExtensions);
280285

281286
// Only enable Cuda interop extensions in 64-bit builds in
282287
// order to avoid potential driver or address space issues.
283288
// VK_KHR_buffer_device_address is expensive on some drivers.
284-
bool enableCudaInterop = !env::is32BitHostPlatform() &&
289+
enableCudaInterop = !env::is32BitHostPlatform() &&
285290
m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) &&
286291
m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) &&
287292
m_deviceFeatures.vk12.bufferDeviceAddress;
@@ -298,17 +303,15 @@ namespace dxvk {
298303
if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name()))
299304
devExtensions.amdMemoryOverallocationBehaviour.setMode(DxvkExtMode::Optional);
300305

301-
DxvkNameSet extensionsEnabled;
302-
303306
if (!m_deviceExtensions.enableExtensions(
304307
devExtensionList.size(),
305308
devExtensionList.data(),
306309
&extensionsEnabled))
307-
throw DxvkError("DxvkAdapter: Failed to create device");
310+
return false;
308311

309312
// Enable additional extensions if necessary
310313
extensionsEnabled.merge(m_extraExtensions);
311-
DxvkNameList extensionNameList = extensionsEnabled.toNameList();
314+
extensionNameList = extensionsEnabled.toNameList();
312315

313316
// Always enable robust buffer access
314317
enabledFeatures.core.features.robustBufferAccess = VK_TRUE;
@@ -443,34 +446,22 @@ namespace dxvk {
443446
// Create pNext chain for additional device features
444447
initFeatureChain(enabledFeatures, devExtensions, instance->extensions());
445448

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-
455449
// Report the desired overallocation behaviour to the driver
456450
VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD };
457451
overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD;
458452

459453
// Create the requested queues
460-
float queuePriority = 1.0f;
461-
std::vector<VkDeviceQueueCreateInfo> queueInfos;
454+
static const float queuePriority = 1.0f;
462455

463456
std::unordered_set<uint32_t> queueFamiliySet;
464457

465-
DxvkAdapterQueueIndices queueFamilies = findQueueFamilies();
458+
queueFamilies = findQueueFamilies();
466459
queueFamiliySet.insert(queueFamilies.graphics);
467460
queueFamiliySet.insert(queueFamilies.transfer);
468461

469462
if (queueFamilies.sparse != VK_QUEUE_FAMILY_IGNORED)
470463
queueFamiliySet.insert(queueFamilies.sparse);
471464

472-
this->logQueueFamilies(queueFamilies);
473-
474465
for (uint32_t family : queueFamiliySet) {
475466
VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
476467
graphicsQueue.queueFamilyIndex = family;
@@ -479,7 +470,8 @@ namespace dxvk {
479470
queueInfos.push_back(graphicsQueue);
480471
}
481472

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;
483475
info.queueCreateInfoCount = queueInfos.size();
484476
info.pQueueCreateInfos = queueInfos.data();
485477
info.enabledExtensionCount = extensionNameList.count();
@@ -489,6 +481,34 @@ namespace dxvk {
489481
if (devExtensions.amdMemoryOverallocationBehaviour)
490482
overallocInfo.pNext = std::exchange(info.pNext, &overallocInfo);
491483

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!
492512
VkDevice device = VK_NULL_HANDLE;
493513
VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device);
494514

@@ -661,11 +681,17 @@ namespace dxvk {
661681
// Create device loader
662682
Rc<vk::DeviceFn> vkd = new vk::DeviceFn(m_vki, false, args.device);
663683

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.
665685
DxvkDeviceQueueSet queues = { };
666686
queues.graphics = { args.queue, args.queueFamily };
667687
queues.transfer = queues.graphics;
668688

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+
669695
return new DxvkDevice(instance, this, vkd, enabledFeatures, queues, args.queueCallback);
670696
}
671697

@@ -992,7 +1018,7 @@ namespace dxvk {
9921018

9931019

9941020
std::vector<DxvkExt*> DxvkAdapter::getExtensionList(
995-
DxvkDeviceExtensions& devExtensions) {
1021+
DxvkDeviceExtensions& devExtensions) const {
9961022
return {{
9971023
&devExtensions.amdMemoryOverallocationBehaviour,
9981024
&devExtensions.amdShaderFragmentMask,

src/dxvk/dxvk_adapter.h

+53-9
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,41 @@ namespace dxvk {
7070
};
7171

7272

73+
/**
74+
* \brief Device creation extension info
75+
*/
76+
struct DxvkDeviceCreateExtInfo {
77+
DxvkDeviceExtensions deviceExtensions;
78+
DxvkNameSet extensionsEnabled;
79+
DxvkNameList extensionNameList;
80+
bool enableCudaInterop;
81+
};
82+
83+
/**
84+
* \brief Device creation queue info
85+
*/
86+
struct DxvkDeviceCreateQueueInfo {
87+
DxvkAdapterQueueIndices queueFamilies;
88+
std::vector<VkDeviceQueueCreateInfo> queueInfos;
89+
};
90+
7391
/**
7492
* \brief Device import info
7593
*/
7694
struct DxvkDeviceImportInfo {
77-
VkDevice device;
78-
VkQueue queue;
79-
uint32_t queueFamily;
80-
uint32_t extensionCount;
81-
const char** extensionNames;
82-
const VkPhysicalDeviceFeatures2* features;
83-
DxvkQueueCallback queueCallback;
95+
VkDevice device;
96+
VkQueue queue;
97+
uint32_t queueFamily;
98+
uint32_t extensionCount;
99+
const char** extensionNames;
100+
const VkPhysicalDeviceFeatures2* features;
101+
DxvkQueueCallback queueCallback;
102+
103+
// Optional additional queues
104+
VkQueue transferQueue = VK_NULL_HANDLE;
105+
uint32_t transferQueueFamily = VK_QUEUE_FAMILY_IGNORED;
106+
VkQueue sparseQueue = VK_NULL_HANDLE;
107+
uint32_t sparseQueueFamily = VK_QUEUE_FAMILY_IGNORED;
84108
};
85109

86110
/**
@@ -212,12 +236,32 @@ namespace dxvk {
212236
void enableExtensions(
213237
const DxvkNameSet& extensions);
214238

239+
/**
240+
* \brief Gets DXVK device creation info
241+
*
242+
* Gets device creation info required for DXVK
243+
* to function based on enabledFeatures
244+
*
245+
* \param [in] instance Parent instance
246+
* \param [out] info Device create info
247+
* \param [in,out] enabledFeatures Device features
248+
* \param [out] extInfo Device extension list
249+
* \param [out] queueInfo Device queue list
250+
* \returns true if succeeded
251+
*/
252+
bool getDeviceCreateInfo(
253+
const Rc<DxvkInstance>& instance,
254+
VkDeviceCreateInfo& info,
255+
DxvkDeviceFeatures& enabledFeatures,
256+
DxvkDeviceCreateExtInfo& extInfo,
257+
DxvkDeviceCreateQueueInfo& queueInfo) const;
258+
215259
/**
216260
* \brief Creates a DXVK device
217261
*
218262
* Creates a logical device for this adapter.
219263
* \param [in] instance Parent instance
220-
* \param [in] enabledFeatures Device features
264+
* \param [in] requestedFeatures Device features
221265
* \returns Device handle
222266
*/
223267
Rc<DxvkDevice> createDevice(
@@ -343,7 +387,7 @@ namespace dxvk {
343387
VkQueueFlags flags) const;
344388

345389
std::vector<DxvkExt*> getExtensionList(
346-
DxvkDeviceExtensions& devExtensions);
390+
DxvkDeviceExtensions& devExtensions) const;
347391

348392
static void initFeatureChain(
349393
DxvkDeviceFeatures& enabledFeatures,

0 commit comments

Comments
 (0)