mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-06 20:58:37 +01:00
[dxvk] Support getting device create info without creating device
This commit is contained in:
parent
33981e6a21
commit
68aff5ded5
2 changed files with 106 additions and 35 deletions
|
@ -272,16 +272,21 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkDevice> DxvkAdapter::createDevice(
|
bool DxvkAdapter::getDeviceCreateInfo(
|
||||||
const Rc<DxvkInstance>& instance,
|
const Rc<DxvkInstance>& instance,
|
||||||
DxvkDeviceFeatures enabledFeatures) {
|
VkDeviceCreateInfo& info,
|
||||||
DxvkDeviceExtensions devExtensions;
|
DxvkDeviceFeatures& enabledFeatures,
|
||||||
|
DxvkDeviceCreateExtInfo& extInfo,
|
||||||
|
DxvkDeviceCreateQueueInfo& queueInfo) const {
|
||||||
|
auto& [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo;
|
||||||
|
auto& [queueFamilies, queueInfos] = queueInfo;
|
||||||
|
|
||||||
auto devExtensionList = getExtensionList(devExtensions);
|
auto devExtensionList = getExtensionList(devExtensions);
|
||||||
|
|
||||||
// Only enable Cuda interop extensions in 64-bit builds in
|
// Only enable Cuda interop extensions in 64-bit builds in
|
||||||
// order to avoid potential driver or address space issues.
|
// order to avoid potential driver or address space issues.
|
||||||
// VK_KHR_buffer_device_address is expensive on some drivers.
|
// VK_KHR_buffer_device_address is expensive on some drivers.
|
||||||
bool enableCudaInterop = !env::is32BitHostPlatform() &&
|
enableCudaInterop = !env::is32BitHostPlatform() &&
|
||||||
m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) &&
|
m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) &&
|
||||||
m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) &&
|
m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) &&
|
||||||
m_deviceFeatures.vk12.bufferDeviceAddress;
|
m_deviceFeatures.vk12.bufferDeviceAddress;
|
||||||
|
@ -298,17 +303,15 @@ namespace dxvk {
|
||||||
if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name()))
|
if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name()))
|
||||||
devExtensions.amdMemoryOverallocationBehaviour.setMode(DxvkExtMode::Optional);
|
devExtensions.amdMemoryOverallocationBehaviour.setMode(DxvkExtMode::Optional);
|
||||||
|
|
||||||
DxvkNameSet extensionsEnabled;
|
|
||||||
|
|
||||||
if (!m_deviceExtensions.enableExtensions(
|
if (!m_deviceExtensions.enableExtensions(
|
||||||
devExtensionList.size(),
|
devExtensionList.size(),
|
||||||
devExtensionList.data(),
|
devExtensionList.data(),
|
||||||
&extensionsEnabled))
|
&extensionsEnabled))
|
||||||
throw DxvkError("DxvkAdapter: Failed to create device");
|
return false;
|
||||||
|
|
||||||
// Enable additional extensions if necessary
|
// Enable additional extensions if necessary
|
||||||
extensionsEnabled.merge(m_extraExtensions);
|
extensionsEnabled.merge(m_extraExtensions);
|
||||||
DxvkNameList extensionNameList = extensionsEnabled.toNameList();
|
extensionNameList = extensionsEnabled.toNameList();
|
||||||
|
|
||||||
// Always enable robust buffer access
|
// Always enable robust buffer access
|
||||||
enabledFeatures.core.features.robustBufferAccess = VK_TRUE;
|
enabledFeatures.core.features.robustBufferAccess = VK_TRUE;
|
||||||
|
@ -443,34 +446,22 @@ namespace dxvk {
|
||||||
// Create pNext chain for additional device features
|
// Create pNext chain for additional device features
|
||||||
initFeatureChain(enabledFeatures, devExtensions, instance->extensions());
|
initFeatureChain(enabledFeatures, devExtensions, instance->extensions());
|
||||||
|
|
||||||
// Log feature support info an extension list
|
|
||||||
Logger::info(str::format("Device properties:"
|
|
||||||
"\n Device : ", m_deviceInfo.core.properties.deviceName,
|
|
||||||
"\n Driver : ", m_deviceInfo.vk12.driverName, " ", m_deviceInfo.driverVersion.toString()));
|
|
||||||
|
|
||||||
Logger::info("Enabled device extensions:");
|
|
||||||
this->logNameList(extensionNameList);
|
|
||||||
this->logFeatures(enabledFeatures);
|
|
||||||
|
|
||||||
// Report the desired overallocation behaviour to the driver
|
// Report the desired overallocation behaviour to the driver
|
||||||
enabledFeatures.amdOverallocation = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD };
|
enabledFeatures.amdOverallocation = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD };
|
||||||
enabledFeatures.amdOverallocation.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD;
|
enabledFeatures.amdOverallocation.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD;
|
||||||
|
|
||||||
// Create the requested queues
|
// Create the requested queues
|
||||||
float queuePriority = 1.0f;
|
static const float queuePriority = 1.0f;
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueInfos;
|
|
||||||
|
|
||||||
std::unordered_set<uint32_t> queueFamiliySet;
|
std::unordered_set<uint32_t> queueFamiliySet;
|
||||||
|
|
||||||
DxvkAdapterQueueIndices queueFamilies = findQueueFamilies();
|
queueFamilies = findQueueFamilies();
|
||||||
queueFamiliySet.insert(queueFamilies.graphics);
|
queueFamiliySet.insert(queueFamilies.graphics);
|
||||||
queueFamiliySet.insert(queueFamilies.transfer);
|
queueFamiliySet.insert(queueFamilies.transfer);
|
||||||
|
|
||||||
if (queueFamilies.sparse != VK_QUEUE_FAMILY_IGNORED)
|
if (queueFamilies.sparse != VK_QUEUE_FAMILY_IGNORED)
|
||||||
queueFamiliySet.insert(queueFamilies.sparse);
|
queueFamiliySet.insert(queueFamilies.sparse);
|
||||||
|
|
||||||
this->logQueueFamilies(queueFamilies);
|
|
||||||
|
|
||||||
for (uint32_t family : queueFamiliySet) {
|
for (uint32_t family : queueFamiliySet) {
|
||||||
VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
|
VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
|
||||||
graphicsQueue.queueFamilyIndex = family;
|
graphicsQueue.queueFamilyIndex = family;
|
||||||
|
@ -479,7 +470,9 @@ namespace dxvk {
|
||||||
queueInfos.push_back(graphicsQueue);
|
queueInfos.push_back(graphicsQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceCreateInfo info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, enabledFeatures.core.pNext };
|
info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
info.pNext = enabledFeatures.core.pNext;
|
||||||
|
info.flags = 0;
|
||||||
info.queueCreateInfoCount = queueInfos.size();
|
info.queueCreateInfoCount = queueInfos.size();
|
||||||
info.pQueueCreateInfos = queueInfos.data();
|
info.pQueueCreateInfos = queueInfos.data();
|
||||||
info.enabledExtensionCount = extensionNameList.count();
|
info.enabledExtensionCount = extensionNameList.count();
|
||||||
|
@ -489,6 +482,34 @@ namespace dxvk {
|
||||||
if (devExtensions.amdMemoryOverallocationBehaviour)
|
if (devExtensions.amdMemoryOverallocationBehaviour)
|
||||||
enabledFeatures.amdOverallocation.pNext = std::exchange(info.pNext, &enabledFeatures.amdOverallocation);
|
enabledFeatures.amdOverallocation.pNext = std::exchange(info.pNext, &enabledFeatures.amdOverallocation);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rc<DxvkDevice> DxvkAdapter::createDevice(
|
||||||
|
const Rc<DxvkInstance>& instance,
|
||||||
|
DxvkDeviceFeatures enabledFeatures) {
|
||||||
|
VkDeviceCreateInfo info;
|
||||||
|
DxvkDeviceCreateExtInfo extInfo;
|
||||||
|
DxvkDeviceCreateQueueInfo queueInfo;
|
||||||
|
|
||||||
|
// Get device creation info
|
||||||
|
if (!getDeviceCreateInfo(instance, info, enabledFeatures, extInfo, queueInfo))
|
||||||
|
throw DxvkError("DxvkAdapter: Failed to create device");
|
||||||
|
|
||||||
|
auto& [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo;
|
||||||
|
auto& [queueFamilies, queueInfos] = queueInfo;
|
||||||
|
|
||||||
|
// Log feature support info, extension list, and queue families
|
||||||
|
Logger::info(str::format("Device properties:"
|
||||||
|
"\n Device : ", m_deviceInfo.core.properties.deviceName,
|
||||||
|
"\n Driver : ", m_deviceInfo.vk12.driverName, " ", m_deviceInfo.driverVersion.toString()));
|
||||||
|
|
||||||
|
Logger::info("Enabled device extensions:");
|
||||||
|
this->logNameList(extensionNameList);
|
||||||
|
this->logFeatures(enabledFeatures);
|
||||||
|
this->logQueueFamilies(queueFamilies);
|
||||||
|
|
||||||
|
// Create device!
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device);
|
VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device);
|
||||||
|
|
||||||
|
@ -661,11 +682,17 @@ namespace dxvk {
|
||||||
// Create device loader
|
// Create device loader
|
||||||
Rc<vk::DeviceFn> vkd = new vk::DeviceFn(m_vki, false, args.device);
|
Rc<vk::DeviceFn> vkd = new vk::DeviceFn(m_vki, false, args.device);
|
||||||
|
|
||||||
// We only support one queue when importing devices, and no sparse.
|
// By default, we only use one queue when importing devices, and no sparse.
|
||||||
DxvkDeviceQueueSet queues = { };
|
DxvkDeviceQueueSet queues = { };
|
||||||
queues.graphics = { args.queue, args.queueFamily };
|
queues.graphics = { args.queue, args.queueFamily };
|
||||||
queues.transfer = queues.graphics;
|
queues.transfer = queues.graphics;
|
||||||
|
|
||||||
|
if (args.transferQueue != VK_NULL_HANDLE && args.transferQueueFamily != VK_QUEUE_FAMILY_IGNORED)
|
||||||
|
queues.transfer = { args.transferQueue, args.transferQueueFamily };
|
||||||
|
|
||||||
|
if (args.sparseQueue != VK_NULL_HANDLE && args.sparseQueueFamily != VK_QUEUE_FAMILY_IGNORED)
|
||||||
|
queues.sparse = { args.sparseQueue, args.sparseQueueFamily };
|
||||||
|
|
||||||
return new DxvkDevice(instance, this, vkd, enabledFeatures, queues, args.queueCallback);
|
return new DxvkDevice(instance, this, vkd, enabledFeatures, queues, args.queueCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,7 +1019,7 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
std::vector<DxvkExt*> DxvkAdapter::getExtensionList(
|
std::vector<DxvkExt*> DxvkAdapter::getExtensionList(
|
||||||
DxvkDeviceExtensions& devExtensions) {
|
DxvkDeviceExtensions& devExtensions) const {
|
||||||
return {{
|
return {{
|
||||||
&devExtensions.amdMemoryOverallocationBehaviour,
|
&devExtensions.amdMemoryOverallocationBehaviour,
|
||||||
&devExtensions.amdShaderFragmentMask,
|
&devExtensions.amdShaderFragmentMask,
|
||||||
|
|
|
@ -70,17 +70,41 @@ namespace dxvk {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device creation extension info
|
||||||
|
*/
|
||||||
|
struct DxvkDeviceCreateExtInfo {
|
||||||
|
DxvkDeviceExtensions deviceExtensions;
|
||||||
|
DxvkNameSet extensionsEnabled;
|
||||||
|
DxvkNameList extensionNameList;
|
||||||
|
bool enableCudaInterop;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device creation queue info
|
||||||
|
*/
|
||||||
|
struct DxvkDeviceCreateQueueInfo {
|
||||||
|
DxvkAdapterQueueIndices queueFamilies;
|
||||||
|
std::vector<VkDeviceQueueCreateInfo> queueInfos;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Device import info
|
* \brief Device import info
|
||||||
*/
|
*/
|
||||||
struct DxvkDeviceImportInfo {
|
struct DxvkDeviceImportInfo {
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkQueue queue;
|
VkQueue queue;
|
||||||
uint32_t queueFamily;
|
uint32_t queueFamily;
|
||||||
uint32_t extensionCount;
|
uint32_t extensionCount;
|
||||||
const char** extensionNames;
|
const char** extensionNames;
|
||||||
const VkPhysicalDeviceFeatures2* features;
|
const VkPhysicalDeviceFeatures2* features;
|
||||||
DxvkQueueCallback queueCallback;
|
DxvkQueueCallback queueCallback;
|
||||||
|
|
||||||
|
// Optional additional queues
|
||||||
|
VkQueue transferQueue = VK_NULL_HANDLE;
|
||||||
|
uint32_t transferQueueFamily = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
VkQueue sparseQueue = VK_NULL_HANDLE;
|
||||||
|
uint32_t sparseQueueFamily = VK_QUEUE_FAMILY_IGNORED;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,12 +236,32 @@ namespace dxvk {
|
||||||
void enableExtensions(
|
void enableExtensions(
|
||||||
const DxvkNameSet& extensions);
|
const DxvkNameSet& extensions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets DXVK device creation info
|
||||||
|
*
|
||||||
|
* Gets device creation info required for DXVK
|
||||||
|
* to function based on enabledFeatures
|
||||||
|
*
|
||||||
|
* \param [in] instance Parent instance
|
||||||
|
* \param [out] info Device create info
|
||||||
|
* \param [in,out] enabledFeatures Device features
|
||||||
|
* \param [out] extInfo Device extension list
|
||||||
|
* \param [out] queueInfo Device queue list
|
||||||
|
* \returns true if succeeded
|
||||||
|
*/
|
||||||
|
bool getDeviceCreateInfo(
|
||||||
|
const Rc<DxvkInstance>& instance,
|
||||||
|
VkDeviceCreateInfo& info,
|
||||||
|
DxvkDeviceFeatures& enabledFeatures,
|
||||||
|
DxvkDeviceCreateExtInfo& extInfo,
|
||||||
|
DxvkDeviceCreateQueueInfo& queueInfo) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a DXVK device
|
* \brief Creates a DXVK device
|
||||||
*
|
*
|
||||||
* Creates a logical device for this adapter.
|
* Creates a logical device for this adapter.
|
||||||
* \param [in] instance Parent instance
|
* \param [in] instance Parent instance
|
||||||
* \param [in] enabledFeatures Device features
|
* \param [in] requestedFeatures Device features
|
||||||
* \returns Device handle
|
* \returns Device handle
|
||||||
*/
|
*/
|
||||||
Rc<DxvkDevice> createDevice(
|
Rc<DxvkDevice> createDevice(
|
||||||
|
@ -343,7 +387,7 @@ namespace dxvk {
|
||||||
VkQueueFlags flags) const;
|
VkQueueFlags flags) const;
|
||||||
|
|
||||||
std::vector<DxvkExt*> getExtensionList(
|
std::vector<DxvkExt*> getExtensionList(
|
||||||
DxvkDeviceExtensions& devExtensions);
|
DxvkDeviceExtensions& devExtensions) const;
|
||||||
|
|
||||||
static void initFeatureChain(
|
static void initFeatureChain(
|
||||||
DxvkDeviceFeatures& enabledFeatures,
|
DxvkDeviceFeatures& enabledFeatures,
|
||||||
|
|
Loading…
Add table
Reference in a new issue