mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
Adding an extension will now require an additional step, but this evolved version of the extension list code is more sane and the structures can be more easily copied around.
294 lines
12 KiB
C++
294 lines
12 KiB
C++
#include <cstring>
|
|
|
|
#include "dxvk_adapter.h"
|
|
#include "dxvk_device.h"
|
|
#include "dxvk_instance.h"
|
|
#include "dxvk_surface.h"
|
|
|
|
namespace dxvk {
|
|
|
|
DxvkAdapter::DxvkAdapter(
|
|
const Rc<DxvkInstance>& instance,
|
|
VkPhysicalDevice handle)
|
|
: m_instance (instance),
|
|
m_vki (instance->vki()),
|
|
m_handle (handle) {
|
|
uint32_t numQueueFamilies = 0;
|
|
m_vki->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
m_handle, &numQueueFamilies, nullptr);
|
|
|
|
m_queueFamilies.resize(numQueueFamilies);
|
|
m_vki->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
m_handle, &numQueueFamilies, m_queueFamilies.data());
|
|
}
|
|
|
|
|
|
DxvkAdapter::~DxvkAdapter() {
|
|
|
|
}
|
|
|
|
|
|
Rc<DxvkInstance> DxvkAdapter::instance() const {
|
|
return m_instance;
|
|
}
|
|
|
|
|
|
VkPhysicalDeviceProperties DxvkAdapter::deviceProperties() const {
|
|
VkPhysicalDeviceProperties properties;
|
|
m_vki->vkGetPhysicalDeviceProperties(m_handle, &properties);
|
|
|
|
if (DxvkGpuVendor(properties.vendorID) == DxvkGpuVendor::Nvidia) {
|
|
properties.driverVersion = VK_MAKE_VERSION(
|
|
VK_VERSION_MAJOR(properties.driverVersion),
|
|
VK_VERSION_MINOR(properties.driverVersion >> 0) >> 2,
|
|
VK_VERSION_PATCH(properties.driverVersion >> 2) >> 4);
|
|
}
|
|
|
|
return properties;
|
|
}
|
|
|
|
|
|
VkPhysicalDeviceMemoryProperties DxvkAdapter::memoryProperties() const {
|
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
|
m_vki->vkGetPhysicalDeviceMemoryProperties(m_handle, &memoryProperties);
|
|
return memoryProperties;
|
|
}
|
|
|
|
|
|
VkPhysicalDeviceFeatures DxvkAdapter::features() const {
|
|
VkPhysicalDeviceFeatures features;
|
|
m_vki->vkGetPhysicalDeviceFeatures(m_handle, &features);
|
|
return features;
|
|
}
|
|
|
|
|
|
VkFormatProperties DxvkAdapter::formatProperties(VkFormat format) const {
|
|
VkFormatProperties formatProperties;
|
|
m_vki->vkGetPhysicalDeviceFormatProperties(m_handle, format, &formatProperties);
|
|
return formatProperties;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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");
|
|
}
|
|
|
|
|
|
uint32_t DxvkAdapter::presentQueueFamily() const {
|
|
// TODO Implement properly
|
|
return this->graphicsQueueFamily();
|
|
}
|
|
|
|
|
|
bool DxvkAdapter::checkFeatureSupport(
|
|
const VkPhysicalDeviceFeatures& required) const {
|
|
const VkPhysicalDeviceFeatures supported = this->features();
|
|
|
|
return (supported.robustBufferAccess || !required.robustBufferAccess)
|
|
&& (supported.fullDrawIndexUint32 || !required.fullDrawIndexUint32)
|
|
&& (supported.imageCubeArray || !required.imageCubeArray)
|
|
&& (supported.independentBlend || !required.independentBlend)
|
|
&& (supported.geometryShader || !required.geometryShader)
|
|
&& (supported.tessellationShader || !required.tessellationShader)
|
|
&& (supported.sampleRateShading || !required.sampleRateShading)
|
|
&& (supported.dualSrcBlend || !required.dualSrcBlend)
|
|
&& (supported.logicOp || !required.logicOp)
|
|
&& (supported.multiDrawIndirect || !required.multiDrawIndirect)
|
|
&& (supported.drawIndirectFirstInstance || !required.drawIndirectFirstInstance)
|
|
&& (supported.depthClamp || !required.depthClamp)
|
|
&& (supported.depthBiasClamp || !required.depthBiasClamp)
|
|
&& (supported.fillModeNonSolid || !required.fillModeNonSolid)
|
|
&& (supported.depthBounds || !required.depthBounds)
|
|
&& (supported.wideLines || !required.wideLines)
|
|
&& (supported.largePoints || !required.largePoints)
|
|
&& (supported.alphaToOne || !required.alphaToOne)
|
|
&& (supported.multiViewport || !required.multiViewport)
|
|
&& (supported.samplerAnisotropy || !required.samplerAnisotropy)
|
|
&& (supported.textureCompressionETC2 || !required.textureCompressionETC2)
|
|
&& (supported.textureCompressionASTC_LDR || !required.textureCompressionASTC_LDR)
|
|
&& (supported.textureCompressionBC || !required.textureCompressionBC)
|
|
&& (supported.occlusionQueryPrecise || !required.occlusionQueryPrecise)
|
|
&& (supported.pipelineStatisticsQuery || !required.pipelineStatisticsQuery)
|
|
&& (supported.vertexPipelineStoresAndAtomics || !required.vertexPipelineStoresAndAtomics)
|
|
&& (supported.fragmentStoresAndAtomics || !required.fragmentStoresAndAtomics)
|
|
&& (supported.shaderTessellationAndGeometryPointSize || !required.shaderTessellationAndGeometryPointSize)
|
|
&& (supported.shaderImageGatherExtended || !required.shaderImageGatherExtended)
|
|
&& (supported.shaderStorageImageExtendedFormats || !required.shaderStorageImageExtendedFormats)
|
|
&& (supported.shaderStorageImageMultisample || !required.shaderStorageImageMultisample)
|
|
&& (supported.shaderStorageImageReadWithoutFormat || !required.shaderStorageImageReadWithoutFormat)
|
|
&& (supported.shaderStorageImageWriteWithoutFormat || !required.shaderStorageImageWriteWithoutFormat)
|
|
&& (supported.shaderUniformBufferArrayDynamicIndexing || !required.shaderUniformBufferArrayDynamicIndexing)
|
|
&& (supported.shaderSampledImageArrayDynamicIndexing || !required.shaderSampledImageArrayDynamicIndexing)
|
|
&& (supported.shaderStorageBufferArrayDynamicIndexing || !required.shaderStorageBufferArrayDynamicIndexing)
|
|
&& (supported.shaderStorageImageArrayDynamicIndexing || !required.shaderStorageImageArrayDynamicIndexing)
|
|
&& (supported.shaderClipDistance || !required.shaderClipDistance)
|
|
&& (supported.shaderCullDistance || !required.shaderCullDistance)
|
|
&& (supported.shaderFloat64 || !required.shaderFloat64)
|
|
&& (supported.shaderInt64 || !required.shaderInt64)
|
|
&& (supported.shaderInt16 || !required.shaderInt16)
|
|
&& (supported.shaderResourceResidency || !required.shaderResourceResidency)
|
|
&& (supported.shaderResourceMinLod || !required.shaderResourceMinLod)
|
|
&& (supported.sparseBinding || !required.sparseBinding)
|
|
&& (supported.sparseResidencyBuffer || !required.sparseResidencyBuffer)
|
|
&& (supported.sparseResidencyImage2D || !required.sparseResidencyImage2D)
|
|
&& (supported.sparseResidencyImage3D || !required.sparseResidencyImage3D)
|
|
&& (supported.sparseResidency2Samples || !required.sparseResidency2Samples)
|
|
&& (supported.sparseResidency4Samples || !required.sparseResidency4Samples)
|
|
&& (supported.sparseResidency8Samples || !required.sparseResidency8Samples)
|
|
&& (supported.sparseResidency16Samples || !required.sparseResidency16Samples)
|
|
&& (supported.sparseResidencyAliased || !required.sparseResidencyAliased)
|
|
&& (supported.variableMultisampleRate || !required.variableMultisampleRate)
|
|
&& (supported.inheritedQueries || !required.inheritedQueries);
|
|
}
|
|
|
|
|
|
Rc<DxvkDevice> DxvkAdapter::createDevice(const VkPhysicalDeviceFeatures& enabledFeatures) {
|
|
DxvkDeviceExtensions devExtensions;
|
|
|
|
std::array<DxvkExt*, 11> devExtensionList = {{
|
|
&devExtensions.extShaderViewportIndexLayer,
|
|
&devExtensions.extVertexAttributeDivisor,
|
|
&devExtensions.khrDedicatedAllocation,
|
|
&devExtensions.khrDescriptorUpdateTemplate,
|
|
&devExtensions.khrGetMemoryRequirements2,
|
|
&devExtensions.khrImageFormatList,
|
|
&devExtensions.khrMaintenance1,
|
|
&devExtensions.khrMaintenance2,
|
|
&devExtensions.khrSamplerMirrorClampToEdge,
|
|
&devExtensions.khrShaderDrawParameters,
|
|
&devExtensions.khrSwapchain,
|
|
}};
|
|
|
|
DxvkNameSet extensionsEnabled;
|
|
DxvkNameSet extensionsAvailable = DxvkNameSet::enumDeviceExtensions(m_vki, m_handle);
|
|
|
|
if (!extensionsAvailable.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();
|
|
|
|
Logger::info("Enabled device extensions:");
|
|
this->logNameList(extensionNameList);
|
|
|
|
float queuePriority = 1.0f;
|
|
std::vector<VkDeviceQueueCreateInfo> queueInfos;
|
|
|
|
uint32_t gIndex = this->graphicsQueueFamily();
|
|
uint32_t pIndex = this->presentQueueFamily();
|
|
|
|
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);
|
|
}
|
|
|
|
VkDeviceCreateInfo info;
|
|
info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
info.pNext = nullptr;
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
Rc<DxvkSurface> DxvkAdapter::createSurface(HINSTANCE instance, HWND window) {
|
|
return new DxvkSurface(this, instance, window);
|
|
}
|
|
|
|
|
|
void DxvkAdapter::logAdapterInfo() const {
|
|
VkPhysicalDeviceProperties deviceInfo = this->deviceProperties();
|
|
VkPhysicalDeviceMemoryProperties memoryInfo = this->memoryProperties();
|
|
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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)));
|
|
}
|
|
|
|
}
|