1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/dxvk_adapter.cpp

391 lines
17 KiB
C++
Raw Normal View History

2017-10-10 23:32:13 +02:00
#include <cstring>
#include "dxvk_adapter.h"
#include "dxvk_device.h"
#include "dxvk_instance.h"
#include "dxvk_surface.h"
namespace dxvk {
DxvkAdapter::DxvkAdapter(
DxvkInstance* instance,
2017-10-10 23:32:13 +02:00
VkPhysicalDevice handle)
: m_instance (instance),
m_vki (instance->vki()),
m_handle (handle) {
this->queryExtensions();
this->queryDeviceInfo();
this->queryDeviceFeatures();
this->queryDeviceQueues();
2017-10-10 23:32:13 +02:00
}
DxvkAdapter::~DxvkAdapter() {
2017-11-26 14:01:41 +01:00
2017-10-10 23:32:13 +02:00
}
Rc<DxvkInstance> DxvkAdapter::instance() const {
return m_instance;
}
2017-10-10 23:32:13 +02:00
VkPhysicalDeviceMemoryProperties DxvkAdapter::memoryProperties() const {
VkPhysicalDeviceMemoryProperties memoryProperties;
m_vki->vkGetPhysicalDeviceMemoryProperties(m_handle, &memoryProperties);
return memoryProperties;
}
VkFormatProperties DxvkAdapter::formatProperties(VkFormat format) const {
VkFormatProperties formatProperties;
m_vki->vkGetPhysicalDeviceFormatProperties(m_handle, format, &formatProperties);
return formatProperties;
}
2017-12-09 14:41:37 +01:00
VkResult DxvkAdapter::imageFormatProperties(
VkFormat format,
VkImageType type,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkImageCreateFlags flags,
VkImageFormatProperties& properties) const {
return m_vki->vkGetPhysicalDeviceImageFormatProperties(
m_handle, format, type, tiling, usage, flags, &properties);
2017-10-10 23:32:13 +02:00
}
uint32_t DxvkAdapter::graphicsQueueFamily() const {
for (uint32_t i = 0; i < m_queueFamilies.size(); i++) {
if (m_queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
return i;
}
throw DxvkError("DxvkAdapter: No graphics queue found");
2017-10-10 23:32:13 +02:00
}
uint32_t DxvkAdapter::presentQueueFamily() const {
// TODO Implement properly
return this->graphicsQueueFamily();
}
bool DxvkAdapter::checkFeatureSupport(const DxvkDeviceFeatures& required) const {
return (m_deviceFeatures.core.features.robustBufferAccess
|| !required.core.features.robustBufferAccess)
&& (m_deviceFeatures.core.features.fullDrawIndexUint32
|| !required.core.features.fullDrawIndexUint32)
&& (m_deviceFeatures.core.features.imageCubeArray
|| !required.core.features.imageCubeArray)
&& (m_deviceFeatures.core.features.independentBlend
|| !required.core.features.independentBlend)
&& (m_deviceFeatures.core.features.geometryShader
|| !required.core.features.geometryShader)
&& (m_deviceFeatures.core.features.tessellationShader
|| !required.core.features.tessellationShader)
&& (m_deviceFeatures.core.features.sampleRateShading
|| !required.core.features.sampleRateShading)
&& (m_deviceFeatures.core.features.dualSrcBlend
|| !required.core.features.dualSrcBlend)
&& (m_deviceFeatures.core.features.logicOp
|| !required.core.features.logicOp)
&& (m_deviceFeatures.core.features.multiDrawIndirect
|| !required.core.features.multiDrawIndirect)
&& (m_deviceFeatures.core.features.drawIndirectFirstInstance
|| !required.core.features.drawIndirectFirstInstance)
&& (m_deviceFeatures.core.features.depthClamp
|| !required.core.features.depthClamp)
&& (m_deviceFeatures.core.features.depthBiasClamp
|| !required.core.features.depthBiasClamp)
&& (m_deviceFeatures.core.features.fillModeNonSolid
|| !required.core.features.fillModeNonSolid)
&& (m_deviceFeatures.core.features.depthBounds
|| !required.core.features.depthBounds)
&& (m_deviceFeatures.core.features.wideLines
|| !required.core.features.wideLines)
&& (m_deviceFeatures.core.features.largePoints
|| !required.core.features.largePoints)
&& (m_deviceFeatures.core.features.alphaToOne
|| !required.core.features.alphaToOne)
&& (m_deviceFeatures.core.features.multiViewport
|| !required.core.features.multiViewport)
&& (m_deviceFeatures.core.features.samplerAnisotropy
|| !required.core.features.samplerAnisotropy)
&& (m_deviceFeatures.core.features.textureCompressionETC2
|| !required.core.features.textureCompressionETC2)
&& (m_deviceFeatures.core.features.textureCompressionASTC_LDR
|| !required.core.features.textureCompressionASTC_LDR)
&& (m_deviceFeatures.core.features.textureCompressionBC
|| !required.core.features.textureCompressionBC)
&& (m_deviceFeatures.core.features.occlusionQueryPrecise
|| !required.core.features.occlusionQueryPrecise)
&& (m_deviceFeatures.core.features.pipelineStatisticsQuery
|| !required.core.features.pipelineStatisticsQuery)
&& (m_deviceFeatures.core.features.vertexPipelineStoresAndAtomics
|| !required.core.features.vertexPipelineStoresAndAtomics)
&& (m_deviceFeatures.core.features.fragmentStoresAndAtomics
|| !required.core.features.fragmentStoresAndAtomics)
&& (m_deviceFeatures.core.features.shaderTessellationAndGeometryPointSize
|| !required.core.features.shaderTessellationAndGeometryPointSize)
&& (m_deviceFeatures.core.features.shaderImageGatherExtended
|| !required.core.features.shaderImageGatherExtended)
&& (m_deviceFeatures.core.features.shaderStorageImageExtendedFormats
|| !required.core.features.shaderStorageImageExtendedFormats)
&& (m_deviceFeatures.core.features.shaderStorageImageMultisample
|| !required.core.features.shaderStorageImageMultisample)
&& (m_deviceFeatures.core.features.shaderStorageImageReadWithoutFormat
|| !required.core.features.shaderStorageImageReadWithoutFormat)
&& (m_deviceFeatures.core.features.shaderStorageImageWriteWithoutFormat
|| !required.core.features.shaderStorageImageWriteWithoutFormat)
&& (m_deviceFeatures.core.features.shaderUniformBufferArrayDynamicIndexing
|| !required.core.features.shaderUniformBufferArrayDynamicIndexing)
&& (m_deviceFeatures.core.features.shaderSampledImageArrayDynamicIndexing
|| !required.core.features.shaderSampledImageArrayDynamicIndexing)
&& (m_deviceFeatures.core.features.shaderStorageBufferArrayDynamicIndexing
|| !required.core.features.shaderStorageBufferArrayDynamicIndexing)
&& (m_deviceFeatures.core.features.shaderStorageImageArrayDynamicIndexing
|| !required.core.features.shaderStorageImageArrayDynamicIndexing)
&& (m_deviceFeatures.core.features.shaderClipDistance
|| !required.core.features.shaderClipDistance)
&& (m_deviceFeatures.core.features.shaderCullDistance
|| !required.core.features.shaderCullDistance)
&& (m_deviceFeatures.core.features.shaderFloat64
|| !required.core.features.shaderFloat64)
&& (m_deviceFeatures.core.features.shaderInt64
|| !required.core.features.shaderInt64)
&& (m_deviceFeatures.core.features.shaderInt16
|| !required.core.features.shaderInt16)
&& (m_deviceFeatures.core.features.shaderResourceResidency
|| !required.core.features.shaderResourceResidency)
&& (m_deviceFeatures.core.features.shaderResourceMinLod
|| !required.core.features.shaderResourceMinLod)
&& (m_deviceFeatures.core.features.sparseBinding
|| !required.core.features.sparseBinding)
&& (m_deviceFeatures.core.features.sparseResidencyBuffer
|| !required.core.features.sparseResidencyBuffer)
&& (m_deviceFeatures.core.features.sparseResidencyImage2D
|| !required.core.features.sparseResidencyImage2D)
&& (m_deviceFeatures.core.features.sparseResidencyImage3D
|| !required.core.features.sparseResidencyImage3D)
&& (m_deviceFeatures.core.features.sparseResidency2Samples
|| !required.core.features.sparseResidency2Samples)
&& (m_deviceFeatures.core.features.sparseResidency4Samples
|| !required.core.features.sparseResidency4Samples)
&& (m_deviceFeatures.core.features.sparseResidency8Samples
|| !required.core.features.sparseResidency8Samples)
&& (m_deviceFeatures.core.features.sparseResidency16Samples
|| !required.core.features.sparseResidency16Samples)
&& (m_deviceFeatures.core.features.sparseResidencyAliased
|| !required.core.features.sparseResidencyAliased)
&& (m_deviceFeatures.core.features.variableMultisampleRate
|| !required.core.features.variableMultisampleRate)
&& (m_deviceFeatures.core.features.inheritedQueries
|| !required.core.features.inheritedQueries)
&& (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor
|| !required.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor)
&& (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor
|| !required.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor);
}
Rc<DxvkDevice> DxvkAdapter::createDevice(DxvkDeviceFeatures enabledFeatures) {
DxvkDeviceExtensions devExtensions;
std::array<DxvkExt*, 12> devExtensionList = {{
&devExtensions.extShaderViewportIndexLayer,
&devExtensions.extTransformFeedback,
&devExtensions.extVertexAttributeDivisor,
&devExtensions.khrDedicatedAllocation,
&devExtensions.khrDescriptorUpdateTemplate,
&devExtensions.khrGetMemoryRequirements2,
&devExtensions.khrImageFormatList,
&devExtensions.khrMaintenance1,
&devExtensions.khrMaintenance2,
&devExtensions.khrSamplerMirrorClampToEdge,
&devExtensions.khrShaderDrawParameters,
&devExtensions.khrSwapchain,
}};
DxvkNameSet extensionsEnabled;
if (!m_deviceExtensions.enableExtensions(
devExtensionList.size(),
devExtensionList.data(),
extensionsEnabled))
throw DxvkError("DxvkAdapter: Failed to create device");
// Enable additional extensions if necessary
extensionsEnabled.merge(g_vrInstance.getDeviceExtensions(getAdapterIndex()));
DxvkNameList extensionNameList = extensionsEnabled.toNameList();
2017-10-10 23:32:13 +02:00
Logger::info("Enabled device extensions:");
this->logNameList(extensionNameList);
// Create pNext chain for additional device features
enabledFeatures.core.pNext = nullptr;
if (devExtensions.extVertexAttributeDivisor.revision() >= 3) {
enabledFeatures.extVertexAttributeDivisor.pNext = enabledFeatures.core.pNext;
enabledFeatures.core.pNext = &enabledFeatures.extVertexAttributeDivisor;
}
// Create one single queue for graphics and present
2017-10-10 23:32:13 +02:00
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueInfos;
uint32_t gIndex = this->graphicsQueueFamily();
uint32_t pIndex = this->presentQueueFamily();
2017-10-10 23:32:13 +02:00
VkDeviceQueueCreateInfo graphicsQueue;
graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
graphicsQueue.pNext = nullptr;
graphicsQueue.flags = 0;
graphicsQueue.queueFamilyIndex = gIndex;
graphicsQueue.queueCount = 1;
graphicsQueue.pQueuePriorities = &queuePriority;
queueInfos.push_back(graphicsQueue);
if (pIndex != gIndex) {
VkDeviceQueueCreateInfo presentQueue = graphicsQueue;
presentQueue.queueFamilyIndex = pIndex;
queueInfos.push_back(presentQueue);
}
2017-10-10 23:32:13 +02:00
VkDeviceCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
info.pNext = enabledFeatures.core.pNext;
2017-10-10 23:32:13 +02:00
info.flags = 0;
info.queueCreateInfoCount = queueInfos.size();
info.pQueueCreateInfos = queueInfos.data();
info.enabledLayerCount = 0;
info.ppEnabledLayerNames = nullptr;
info.enabledExtensionCount = extensionNameList.count();
info.ppEnabledExtensionNames = extensionNameList.names();
info.pEnabledFeatures = &enabledFeatures.core.features;
2017-10-10 23:32:13 +02:00
VkDevice device = VK_NULL_HANDLE;
if (m_vki->vkCreateDevice(m_handle, &info, nullptr, &device) != VK_SUCCESS)
throw DxvkError("DxvkAdapter: Failed to create device");
Rc<DxvkDevice> result = new DxvkDevice(this,
new vk::DeviceFn(m_vki->instance(), device),
devExtensions, enabledFeatures);
result->initResources();
return result;
2017-10-10 23:32:13 +02:00
}
Rc<DxvkSurface> DxvkAdapter::createSurface(HINSTANCE instance, HWND window) {
return new DxvkSurface(this, instance, window);
}
2018-03-07 00:23:06 +01:00
void DxvkAdapter::logAdapterInfo() const {
VkPhysicalDeviceProperties deviceInfo = this->deviceProperties();
VkPhysicalDeviceMemoryProperties memoryInfo = this->memoryProperties();
2018-03-07 00:23:06 +01:00
Logger::info(str::format(deviceInfo.deviceName, ":"));
Logger::info(str::format(" Driver: ",
VK_VERSION_MAJOR(deviceInfo.driverVersion), ".",
VK_VERSION_MINOR(deviceInfo.driverVersion), ".",
VK_VERSION_PATCH(deviceInfo.driverVersion)));
Logger::info(str::format(" Vulkan: ",
VK_VERSION_MAJOR(deviceInfo.apiVersion), ".",
VK_VERSION_MINOR(deviceInfo.apiVersion), ".",
VK_VERSION_PATCH(deviceInfo.apiVersion)));
for (uint32_t i = 0; i < memoryInfo.memoryHeapCount; i++) {
constexpr VkDeviceSize mib = 1024 * 1024;
Logger::info(str::format(" Memory Heap[", i, "]: "));
Logger::info(str::format(" Size: ", memoryInfo.memoryHeaps[i].size / mib, " MiB"));
Logger::info(str::format(" Flags: ", "0x", std::hex, memoryInfo.memoryHeaps[i].flags));
for (uint32_t j = 0; j < memoryInfo.memoryTypeCount; j++) {
if (memoryInfo.memoryTypes[j].heapIndex == i) {
Logger::info(str::format(
" Memory Type[", j, "]: ",
"Property Flags = ", "0x", std::hex, memoryInfo.memoryTypes[j].propertyFlags));
}
}
}
2018-03-07 00:23:06 +01:00
}
void DxvkAdapter::queryExtensions() {
m_deviceExtensions = DxvkNameSet::enumDeviceExtensions(m_vki, m_handle);
}
void DxvkAdapter::queryDeviceInfo() {
m_deviceInfo = DxvkDeviceInfo();
m_deviceInfo.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
m_deviceInfo.core.pNext = nullptr;
if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) {
m_deviceInfo.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
m_deviceInfo.extTransformFeedback.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extTransformFeedback);
}
if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
m_deviceInfo.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
m_deviceInfo.extVertexAttributeDivisor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extVertexAttributeDivisor);
}
m_vki->vkGetPhysicalDeviceProperties2KHR(m_handle, &m_deviceInfo.core);
// Nvidia reports the driver version in a slightly different format
if (DxvkGpuVendor(m_deviceInfo.core.properties.vendorID) == DxvkGpuVendor::Nvidia) {
m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION(
VK_VERSION_MAJOR(m_deviceInfo.core.properties.driverVersion),
VK_VERSION_MINOR(m_deviceInfo.core.properties.driverVersion >> 0) >> 2,
VK_VERSION_PATCH(m_deviceInfo.core.properties.driverVersion >> 2) >> 4);
}
}
void DxvkAdapter::queryDeviceFeatures() {
m_deviceFeatures = DxvkDeviceFeatures();
m_deviceFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
m_deviceFeatures.core.pNext = nullptr;
if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) {
m_deviceFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
m_deviceFeatures.extVertexAttributeDivisor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extVertexAttributeDivisor);
}
m_vki->vkGetPhysicalDeviceFeatures2KHR(m_handle, &m_deviceFeatures.core);
}
void DxvkAdapter::queryDeviceQueues() {
uint32_t numQueueFamilies = 0;
m_vki->vkGetPhysicalDeviceQueueFamilyProperties(
m_handle, &numQueueFamilies, nullptr);
m_queueFamilies.resize(numQueueFamilies);
m_vki->vkGetPhysicalDeviceQueueFamilyProperties(
m_handle, &numQueueFamilies, m_queueFamilies.data());
}
uint32_t DxvkAdapter::getAdapterIndex() const {
for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++) {
if (m_instance->enumAdapters(i).ptr() == this)
return i;
}
return ~0u;
}
void DxvkAdapter::logNameList(const DxvkNameList& names) {
for (uint32_t i = 0; i < names.count(); i++)
Logger::info(str::format(" ", names.name(i)));
}
}