mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 02:52:10 +01:00
[dxvk] Refactored device extension handling
Support for extensions can now be queried from the device object in an efficient way. This will allow the backend to use optional extensions for the purpose of optimization.
This commit is contained in:
parent
8805958736
commit
bc5dfc1cad
@ -74,7 +74,7 @@ namespace dxvk {
|
||||
return i;
|
||||
}
|
||||
|
||||
throw DxvkError("DxvkAdapter::graphicsQueueFamily: No graphics queue found");
|
||||
throw DxvkError("DxvkAdapter: No graphics queue found");
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +147,14 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkDevice> DxvkAdapter::createDevice(const VkPhysicalDeviceFeatures& enabledFeatures) {
|
||||
auto enabledExtensions = this->enableExtensions();
|
||||
const Rc<DxvkDeviceExtensions> extensions = new DxvkDeviceExtensions();
|
||||
extensions->enableExtensions(vk::NameSet::enumerateDeviceExtensions(*m_vki, m_handle));
|
||||
|
||||
if (!extensions->checkSupportStatus())
|
||||
throw DxvkError("DxvkAdapter: Failed to create device");
|
||||
|
||||
const vk::NameList enabledExtensions =
|
||||
extensions->getEnabledExtensionNames();
|
||||
|
||||
Logger::info("Enabled device extensions:");
|
||||
this->logNameList(enabledExtensions);
|
||||
@ -188,8 +195,8 @@ namespace dxvk {
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
|
||||
if (m_vki->vkCreateDevice(m_handle, &info, nullptr, &device) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkDevice::createDevice: Failed to create device");
|
||||
return new DxvkDevice(this, new vk::DeviceFn(m_vki->instance(), device), enabledFeatures);
|
||||
throw DxvkError("DxvkAdapter: Failed to create device");
|
||||
return new DxvkDevice(this, new vk::DeviceFn(m_vki->instance(), device), extensions, enabledFeatures);
|
||||
}
|
||||
|
||||
|
||||
@ -198,36 +205,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
vk::NameList DxvkAdapter::enableExtensions() {
|
||||
std::vector<const char*> extOptional = {
|
||||
VK_KHR_MAINTENANCE2_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
std::vector<const char*> extRequired = {
|
||||
VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
const vk::NameSet extensionsAvailable
|
||||
= vk::NameSet::enumerateDeviceExtensions(*m_vki, m_handle);
|
||||
vk::NameList extensionsEnabled;
|
||||
|
||||
for (auto e : extOptional) {
|
||||
if (extensionsAvailable.supports(e))
|
||||
extensionsEnabled.add(e);
|
||||
}
|
||||
|
||||
for (auto e : extRequired) {
|
||||
if (!extensionsAvailable.supports(e))
|
||||
throw DxvkError(str::format("DxvkDevice::getExtensions: Extension ", e, " not supported"));
|
||||
extensionsEnabled.add(e);
|
||||
}
|
||||
|
||||
return extensionsEnabled;
|
||||
}
|
||||
|
||||
|
||||
void DxvkAdapter::logNameList(const vk::NameList& names) {
|
||||
for (uint32_t i = 0; i < names.count(); i++)
|
||||
Logger::info(str::format(" ", names.name(i)));
|
||||
|
@ -155,8 +155,6 @@ namespace dxvk {
|
||||
|
||||
std::vector<VkQueueFamilyProperties> m_queueFamilies;
|
||||
|
||||
vk::NameList enableExtensions();
|
||||
|
||||
static void logNameList(const vk::NameList& names);
|
||||
|
||||
};
|
||||
|
@ -6,9 +6,11 @@ namespace dxvk {
|
||||
DxvkDevice::DxvkDevice(
|
||||
const Rc<DxvkAdapter>& adapter,
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkDeviceExtensions>& extensions,
|
||||
const VkPhysicalDeviceFeatures& features)
|
||||
: m_adapter (adapter),
|
||||
m_vkd (vkd),
|
||||
m_extensions (extensions),
|
||||
m_features (features),
|
||||
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
||||
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "dxvk_compute.h"
|
||||
#include "dxvk_constant_state.h"
|
||||
#include "dxvk_context.h"
|
||||
#include "dxvk_extensions.h"
|
||||
#include "dxvk_framebuffer.h"
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_memory.h"
|
||||
@ -40,6 +41,7 @@ namespace dxvk {
|
||||
DxvkDevice(
|
||||
const Rc<DxvkAdapter>& adapter,
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkDeviceExtensions>& extensions,
|
||||
const VkPhysicalDeviceFeatures& features);
|
||||
|
||||
~DxvkDevice();
|
||||
@ -71,6 +73,14 @@ namespace dxvk {
|
||||
return m_adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enabled device extensions
|
||||
* \returns Enabled device extensions
|
||||
*/
|
||||
const DxvkDeviceExtensions& extensions() const {
|
||||
return *m_extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enabled device features
|
||||
* \returns Enabled features
|
||||
@ -300,6 +310,7 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkAdapter> m_adapter;
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
Rc<DxvkDeviceExtensions> m_extensions;
|
||||
VkPhysicalDeviceFeatures m_features;
|
||||
|
||||
Rc<DxvkMemoryAllocator> m_memory;
|
||||
|
75
src/dxvk/dxvk_extensions.cpp
Normal file
75
src/dxvk/dxvk_extensions.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "dxvk_extensions.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkExtensionList:: DxvkExtensionList() { }
|
||||
DxvkExtensionList::~DxvkExtensionList() { }
|
||||
|
||||
|
||||
void DxvkExtensionList::enableExtensions(const vk::NameSet& extensions) {
|
||||
for (auto ext : m_extensions) {
|
||||
if (extensions.supports(ext->name()))
|
||||
ext->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkExtensionList::checkSupportStatus() {
|
||||
bool requiredExtensionsEnabled = true;
|
||||
|
||||
for (auto ext : m_extensions) {
|
||||
if (!ext->enabled()) {
|
||||
switch (ext->type()) {
|
||||
case DxvkExtensionType::Optional:
|
||||
// An optional extension should not have any impact on
|
||||
// the functionality of an application, so inform the
|
||||
// user only if verbose debug messages are enabled
|
||||
Logger::debug(str::format("Optional Vulkan extension ", ext->name(), " not supported"));
|
||||
break;
|
||||
|
||||
case DxvkExtensionType::Desired:
|
||||
// If a desired extension is not supported, applications
|
||||
// should keep working but may exhibit unexpected behaviour,
|
||||
// so we'll inform the user anyway
|
||||
Logger::warn(str::format("Vulkan extension ", ext->name(), " not supported"));
|
||||
break;
|
||||
|
||||
case DxvkExtensionType::Required:
|
||||
// Do not exit early so we can catch all unsupported extensions.
|
||||
requiredExtensionsEnabled = false;
|
||||
Logger::err(str::format("Required Vulkan extension ", ext->name(), " not supported"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requiredExtensionsEnabled;
|
||||
}
|
||||
|
||||
|
||||
vk::NameList DxvkExtensionList::getEnabledExtensionNames() const {
|
||||
vk::NameList names;
|
||||
|
||||
for (auto ext : m_extensions) {
|
||||
if (ext->enabled())
|
||||
names.add(ext->name());
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
void DxvkExtensionList::registerExtension(DxvkExtension* extension) {
|
||||
m_extensions.push_back(extension);
|
||||
}
|
||||
|
||||
|
||||
DxvkExtension::DxvkExtension(
|
||||
DxvkExtensionList* parent,
|
||||
const char* name,
|
||||
DxvkExtensionType type)
|
||||
: m_name(name), m_type(type), m_enabled(false) {
|
||||
parent->registerExtension(this);
|
||||
}
|
||||
|
||||
}
|
138
src/dxvk/dxvk_extensions.h
Normal file
138
src/dxvk/dxvk_extensions.h
Normal file
@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
// Forward declarations
|
||||
class DxvkExtension;
|
||||
class DxvkExtensionList;
|
||||
|
||||
/**
|
||||
* \brief Extension type
|
||||
*/
|
||||
enum class DxvkExtensionType {
|
||||
Optional, ///< Nothing will happen if not supported
|
||||
Desired, ///< A warning will be issued if not supported
|
||||
Required, ///< Device creation will fail if not supported
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Vulkan extension list
|
||||
*
|
||||
* Convenience class to manage a set of extensions
|
||||
* which can be either required or optional.
|
||||
*/
|
||||
class DxvkExtensionList : public RcObject {
|
||||
friend class DxvkExtension;
|
||||
public:
|
||||
|
||||
DxvkExtensionList();
|
||||
~DxvkExtensionList();
|
||||
|
||||
DxvkExtensionList (const DxvkExtensionList&) = delete;
|
||||
DxvkExtensionList& operator = (const DxvkExtensionList&) = delete;
|
||||
|
||||
/**
|
||||
* \brief Enables Vulkan extensions
|
||||
*
|
||||
* Marks all extension in the list as enabled.
|
||||
* \param [in] extensions Supported extensions
|
||||
*/
|
||||
void enableExtensions(
|
||||
const vk::NameSet& extensions);
|
||||
|
||||
/**
|
||||
* \brief Checks extension support status
|
||||
*
|
||||
* Checks whether all required extensions are present
|
||||
* and logs the name of any unsupported extension.
|
||||
* \returns \c true if required extensions are present
|
||||
*/
|
||||
bool checkSupportStatus();
|
||||
|
||||
/**
|
||||
* \brief Creates a list of enabled extensions
|
||||
*
|
||||
* The resulting list can be fed into the Vulkan
|
||||
* structs for device and instance creation.
|
||||
* \returns Names of enabled Vulkan extensions
|
||||
*/
|
||||
vk::NameList getEnabledExtensionNames() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<DxvkExtension*> m_extensions;
|
||||
|
||||
void registerExtension(DxvkExtension* extension);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Extension class
|
||||
*
|
||||
* Stores the name, type and support
|
||||
* status of a single Vulkan extension.
|
||||
*/
|
||||
class DxvkExtension {
|
||||
friend class DxvkExtensionList;
|
||||
public:
|
||||
|
||||
DxvkExtension(
|
||||
DxvkExtensionList* parent,
|
||||
const char* name,
|
||||
DxvkExtensionType type);
|
||||
|
||||
DxvkExtension (const DxvkExtension&) = delete;
|
||||
DxvkExtension& operator = (const DxvkExtension&) = delete;
|
||||
|
||||
/**
|
||||
* \brief Extension name
|
||||
* \returns Extension name
|
||||
*/
|
||||
const char* name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extension type
|
||||
* \returns Extension type
|
||||
*/
|
||||
DxvkExtensionType type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extension support status
|
||||
* \returns \c true if supported
|
||||
*/
|
||||
bool enabled() const {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const char* m_name;
|
||||
DxvkExtensionType m_type;
|
||||
bool m_enabled;
|
||||
|
||||
void setEnabled(bool enabled) {
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Device extensions
|
||||
*
|
||||
* Lists all Vulkan extensions that are potentially
|
||||
* used by DXVK if supported by the implementation.
|
||||
*/
|
||||
struct DxvkDeviceExtensions : public DxvkExtensionList {
|
||||
DxvkExtension khrMaintenance1 = { this, VK_KHR_MAINTENANCE1_EXTENSION_NAME, DxvkExtensionType::Required };
|
||||
DxvkExtension khrMaintenance2 = { this, VK_KHR_MAINTENANCE2_EXTENSION_NAME, DxvkExtensionType::Desired };
|
||||
DxvkExtension khrShaderDrawParameters = { this, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, DxvkExtensionType::Required };
|
||||
DxvkExtension khrSwapchain = { this, VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtensionType::Required };
|
||||
};
|
||||
|
||||
}
|
@ -14,6 +14,7 @@ dxvk_src = files([
|
||||
'dxvk_data.cpp',
|
||||
'dxvk_descriptor.cpp',
|
||||
'dxvk_device.cpp',
|
||||
'dxvk_extensions.cpp',
|
||||
'dxvk_format.cpp',
|
||||
'dxvk_framebuffer.cpp',
|
||||
'dxvk_graphics.cpp',
|
||||
|
Loading…
x
Reference in New Issue
Block a user