Skip to content

Commit

Permalink
[dxvk] Support getting device create info without creating device
Browse files Browse the repository at this point in the history
  • Loading branch information
AlpyneDreams committed Dec 28, 2024
1 parent 1eb0c68 commit 9eb346f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 35 deletions.
78 changes: 52 additions & 26 deletions src/dxvk/dxvk_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,21 @@ namespace dxvk {
}


Rc<DxvkDevice> DxvkAdapter::createDevice(
const Rc<DxvkInstance>& instance,
DxvkDeviceFeatures enabledFeatures) {
DxvkDeviceExtensions devExtensions;
bool DxvkAdapter::getDeviceCreateInfo(
const Rc<DxvkInstance>& instance,
VkDeviceCreateInfo& info,
DxvkDeviceFeatures& enabledFeatures,
DxvkDeviceCreateExtInfo& extInfo,
DxvkDeviceCreateQueueInfo& queueInfo) const {
auto& [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo;
auto& [queueFamilies, queueInfos] = queueInfo;

auto devExtensionList = getExtensionList(devExtensions);

// Only enable Cuda interop extensions in 64-bit builds in
// order to avoid potential driver or address space issues.
// 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.nvxImageViewHandle.name()) &&
m_deviceFeatures.vk12.bufferDeviceAddress;
Expand All @@ -298,17 +303,15 @@ namespace dxvk {
if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name()))
devExtensions.amdMemoryOverallocationBehaviour.setMode(DxvkExtMode::Optional);

DxvkNameSet extensionsEnabled;

if (!m_deviceExtensions.enableExtensions(
devExtensionList.size(),
devExtensionList.data(),
&extensionsEnabled))
throw DxvkError("DxvkAdapter: Failed to create device");
return false;

// Enable additional extensions if necessary
extensionsEnabled.merge(m_extraExtensions);
DxvkNameList extensionNameList = extensionsEnabled.toNameList();
extensionNameList = extensionsEnabled.toNameList();

// Always enable robust buffer access
enabledFeatures.core.features.robustBufferAccess = VK_TRUE;
Expand Down Expand Up @@ -443,34 +446,22 @@ namespace dxvk {
// Create pNext chain for additional device features
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
VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD };
overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD;

// Create the requested queues
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueInfos;
static const float queuePriority = 1.0f;

std::unordered_set<uint32_t> queueFamiliySet;

DxvkAdapterQueueIndices queueFamilies = findQueueFamilies();
queueFamilies = findQueueFamilies();
queueFamiliySet.insert(queueFamilies.graphics);
queueFamiliySet.insert(queueFamilies.transfer);

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

this->logQueueFamilies(queueFamilies);

for (uint32_t family : queueFamiliySet) {
VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
graphicsQueue.queueFamilyIndex = family;
Expand All @@ -479,7 +470,8 @@ namespace dxvk {
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.queueCreateInfoCount = queueInfos.size();
info.pQueueCreateInfos = queueInfos.data();
info.enabledExtensionCount = extensionNameList.count();
Expand All @@ -489,6 +481,34 @@ namespace dxvk {
if (devExtensions.amdMemoryOverallocationBehaviour)
overallocInfo.pNext = std::exchange(info.pNext, &overallocInfo);

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;
VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device);

Expand Down Expand Up @@ -661,11 +681,17 @@ namespace dxvk {
// Create device loader
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 = { };
queues.graphics = { args.queue, args.queueFamily };
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);
}

Expand Down Expand Up @@ -992,7 +1018,7 @@ namespace dxvk {


std::vector<DxvkExt*> DxvkAdapter::getExtensionList(
DxvkDeviceExtensions& devExtensions) {
DxvkDeviceExtensions& devExtensions) const {
return {{
&devExtensions.amdMemoryOverallocationBehaviour,
&devExtensions.amdShaderFragmentMask,
Expand Down
62 changes: 53 additions & 9 deletions src/dxvk/dxvk_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
struct DxvkDeviceImportInfo {
VkDevice device;
VkQueue queue;
uint32_t queueFamily;
uint32_t extensionCount;
const char** extensionNames;
const VkPhysicalDeviceFeatures2* features;
DxvkQueueCallback queueCallback;
VkDevice device;
VkQueue queue;
uint32_t queueFamily;
uint32_t extensionCount;
const char** extensionNames;
const VkPhysicalDeviceFeatures2* features;
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;
};

/**
Expand Down Expand Up @@ -212,12 +236,32 @@ namespace dxvk {
void enableExtensions(
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
*
* Creates a logical device for this adapter.
* \param [in] instance Parent instance
* \param [in] enabledFeatures Device features
* \param [in] requestedFeatures Device features
* \returns Device handle
*/
Rc<DxvkDevice> createDevice(
Expand Down Expand Up @@ -343,7 +387,7 @@ namespace dxvk {
VkQueueFlags flags) const;

std::vector<DxvkExt*> getExtensionList(
DxvkDeviceExtensions& devExtensions);
DxvkDeviceExtensions& devExtensions) const;

static void initFeatureChain(
DxvkDeviceFeatures& enabledFeatures,
Expand Down

0 comments on commit 9eb346f

Please sign in to comment.