[d3d11] Implemented proper feature tests

This commit is contained in:
Philip Rebohle 2017-12-02 16:47:06 +01:00
parent e051498621
commit ac2d16599c
11 changed files with 208 additions and 36 deletions

View File

@ -516,8 +516,74 @@ namespace dxvk {
bool D3D11Device::CheckFeatureLevelSupport(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
return featureLevel <= D3D_FEATURE_LEVEL_11_0;
// We currently only support 11_0 interfaces
if (featureLevel > D3D_FEATURE_LEVEL_11_0)
return false;
// Check whether all features are supported
const VkPhysicalDeviceFeatures features
= GetDeviceFeatures(adapter, featureLevel);
if (!adapter->checkFeatureSupport(features))
return false;
// TODO also check for required limits
return true;
}
VkPhysicalDeviceFeatures D3D11Device::GetDeviceFeatures(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
VkPhysicalDeviceFeatures supported = adapter->features();
VkPhysicalDeviceFeatures enabled;
std::memset(&enabled, 0, sizeof(enabled));
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
enabled.alphaToOne = VK_TRUE;
enabled.depthClamp = VK_TRUE;
enabled.depthBiasClamp = VK_TRUE;
enabled.depthBounds = VK_TRUE;
enabled.fillModeNonSolid = VK_TRUE;
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
enabled.samplerAnisotropy = VK_TRUE;
enabled.shaderClipDistance = VK_TRUE;
enabled.shaderCullDistance = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
enabled.occlusionQueryPrecise = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
enabled.multiViewport = VK_TRUE;
enabled.independentBlend = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
enabled.fullDrawIndexUint32 = VK_TRUE;
enabled.fragmentStoresAndAtomics = VK_TRUE;
enabled.geometryShader = VK_TRUE;
enabled.logicOp = supported.logicOp;
enabled.shaderImageGatherExtended = VK_TRUE;
enabled.textureCompressionBC = VK_TRUE;
enabled.vertexPipelineStoresAndAtomics = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
enabled.imageCubeArray = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
enabled.shaderFloat64 = supported.shaderFloat64;
enabled.shaderInt64 = supported.shaderInt64;
enabled.tessellationShader = VK_TRUE;
enabled.variableMultisampleRate = VK_TRUE;
}
return enabled;
}
}

View File

@ -221,6 +221,11 @@ namespace dxvk {
}
static bool CheckFeatureLevelSupport(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel);
static VkPhysicalDeviceFeatures GetDeviceFeatures(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel);
private:

View File

@ -4,6 +4,7 @@
#include <dxgi_device.h>
#include "d3d11_device.h"
#include "d3d11_enums.h"
extern "C" {
using namespace dxvk;
@ -76,9 +77,11 @@ extern "C" {
// Find the highest feature level supported by the device.
// This works because the feature level array is ordered.
const Rc<DxvkAdapter> adapter = dxvkAdapter->GetDXVKAdapter();
UINT flId;
for (flId = 0 ; flId < FeatureLevels; flId++) {
if (D3D11Device::CheckFeatureLevelSupport(pFeatureLevels[flId]))
if (D3D11Device::CheckFeatureLevelSupport(adapter, pFeatureLevels[flId]))
break;
}
@ -92,6 +95,8 @@ extern "C" {
try {
Logger::info(str::format("D3D11CreateDevice: Using feature level ", fl));
// Write back the actual feature level
// if the application requested it.
if (pFeatureLevel != nullptr)
@ -105,7 +110,10 @@ extern "C" {
if (ppDevice != nullptr) {
Com<IDXGIDevicePrivate> dxvkDevice = nullptr;
if (FAILED(DXGICreateDevicePrivate(dxvkAdapter.ptr(), &dxvkDevice))) {
const VkPhysicalDeviceFeatures deviceFeatures
= D3D11Device::GetDeviceFeatures(adapter, fl);
if (FAILED(DXGICreateDevicePrivate(dxvkAdapter.ptr(), &deviceFeatures, &dxvkDevice))) {
Logger::err("D3D11CreateDevice: Failed to create DXGI device");
return E_FAIL;
}

View File

@ -3,9 +3,11 @@
namespace dxvk {
DxgiDevice::DxgiDevice(IDXGIAdapterPrivate* adapter)
DxgiDevice::DxgiDevice(
IDXGIAdapterPrivate* adapter,
const VkPhysicalDeviceFeatures* features)
: m_adapter(adapter) {
m_device = m_adapter->GetDXVKAdapter()->createDevice();
m_device = m_adapter->GetDXVKAdapter()->createDevice(*features);
}
@ -92,10 +94,11 @@ namespace dxvk {
extern "C" {
DLLEXPORT HRESULT __stdcall DXGICreateDevicePrivate(
IDXGIAdapterPrivate* pAdapter,
IDXGIDevicePrivate** ppDevice) {
IDXGIAdapterPrivate* pAdapter,
const VkPhysicalDeviceFeatures* features,
IDXGIDevicePrivate** ppDevice) {
try {
*ppDevice = dxvk::ref(new dxvk::DxgiDevice(pAdapter));
*ppDevice = dxvk::ref(new dxvk::DxgiDevice(pAdapter, features));
return S_OK;
} catch (const dxvk::DxvkError& e) {
dxvk::Logger::err(e.message());

View File

@ -13,7 +13,9 @@ namespace dxvk {
public:
DxgiDevice(IDXGIAdapterPrivate* adapter);
DxgiDevice(
IDXGIAdapterPrivate* adapter,
const VkPhysicalDeviceFeatures* features);
~DxgiDevice();
HRESULT QueryInterface(
@ -65,7 +67,8 @@ namespace dxvk {
extern "C" {
DLLEXPORT HRESULT __stdcall DXGICreateDevicePrivate(
IDXGIAdapterPrivate* pAdapter,
IDXGIDevicePrivate** ppDevice);
IDXGIAdapterPrivate* pAdapter,
const VkPhysicalDeviceFeatures* features,
IDXGIDevicePrivate** ppDevice);
}

View File

@ -319,7 +319,7 @@ namespace dxvk {
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_SNORM;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent.width = m_desc.BufferDesc.Width;
imageInfo.extent.height = m_desc.BufferDesc.Height;
@ -331,9 +331,6 @@ namespace dxvk {
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
imageInfo.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
// | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
// | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
// | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
@ -345,6 +342,14 @@ namespace dxvk {
| VK_ACCESS_SHADER_READ_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
if (dxvkDevice->features().geometryShader)
imageInfo.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (dxvkDevice->features().tessellationShader) {
imageInfo.stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
}
if (FAILED(DXGICreateImageResourcePrivate(dxgiDevice.ptr(), &imageInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, DXGI_USAGE_BACK_BUFFER | m_desc.BufferUsage,
&resource)))

View File

@ -93,9 +93,70 @@ namespace dxvk {
}
Rc<DxvkDevice> DxvkAdapter::createDevice() {
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) {
auto enabledExtensions = this->enableExtensions();
auto enabledFeatures = this->enableFeatures();
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueInfos;
@ -134,7 +195,7 @@ namespace dxvk {
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));
return new DxvkDevice(this, new vk::DeviceFn(m_vki->instance(), device), enabledFeatures);
}
@ -167,11 +228,4 @@ namespace dxvk {
return extensionsEnabled;
}
VkPhysicalDeviceFeatures DxvkAdapter::enableFeatures() {
VkPhysicalDeviceFeatures features;
std::memset(&features, 0, sizeof(features));
return features;
}
}

View File

@ -107,13 +107,24 @@ namespace dxvk {
*/
uint32_t presentQueueFamily() const;
/**
* \brief Tests whether all required features are supported
*
* \param [in] features Required device features
* \returns \c true if all features are supported
*/
bool checkFeatureSupport(
const VkPhysicalDeviceFeatures& required) const;
/**
* \brief Creates a DXVK device
*
* Creates a logical device for this adapter.
* \param [in] enabledFeatures Device features
* \returns Device handle
*/
Rc<DxvkDevice> createDevice();
Rc<DxvkDevice> createDevice(
const VkPhysicalDeviceFeatures& enabledFeatures);
/**
* \brief Creates a surface
@ -136,8 +147,6 @@ namespace dxvk {
vk::NameList enableExtensions();
VkPhysicalDeviceFeatures enableFeatures();
};
}

View File

@ -4,10 +4,12 @@
namespace dxvk {
DxvkDevice::DxvkDevice(
const Rc<DxvkAdapter>& adapter,
const Rc<vk::DeviceFn>& vkd)
const Rc<DxvkAdapter>& adapter,
const Rc<vk::DeviceFn>& vkd,
const VkPhysicalDeviceFeatures& features)
: m_adapter (adapter),
m_vkd (vkd),
m_features (features),
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
m_renderPassPool (new DxvkRenderPassPool (vkd)),
m_pipelineManager (new DxvkPipelineManager(vkd)) {
@ -67,7 +69,6 @@ namespace dxvk {
Rc<DxvkImage> DxvkDevice::createImage(
const DxvkImageCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
// TODO record image initialization commands
return new DxvkImage(m_vkd,
createInfo, *m_memory, memoryType);
}

View File

@ -31,8 +31,10 @@ namespace dxvk {
public:
DxvkDevice(
const Rc<DxvkAdapter>& adapter,
const Rc<vk::DeviceFn>& vkd);
const Rc<DxvkAdapter>& adapter,
const Rc<vk::DeviceFn>& vkd,
const VkPhysicalDeviceFeatures& features);
~DxvkDevice();
/**
@ -62,6 +64,14 @@ namespace dxvk {
return m_adapter;
}
/**
* \brief Enabled device features
* \returns Enabled features
*/
const VkPhysicalDeviceFeatures& features() const {
return m_features;
}
/**
* \brief Creates a command list
* \returns The command list
@ -186,8 +196,9 @@ namespace dxvk {
private:
Rc<DxvkAdapter> m_adapter;
Rc<vk::DeviceFn> m_vkd;
Rc<DxvkAdapter> m_adapter;
Rc<vk::DeviceFn> m_vkd;
VkPhysicalDeviceFeatures m_features;
Rc<DxvkMemoryAllocator> m_memory;
Rc<DxvkRenderPassPool> m_renderPassPool;

View File

@ -68,7 +68,7 @@ public:
TriangleApp(HINSTANCE instance, HWND window)
: m_dxvkInstance (new DxvkInstance()),
m_dxvkAdapter (m_dxvkInstance->enumAdapters().at(0)),
m_dxvkDevice (m_dxvkAdapter->createDevice()),
m_dxvkDevice (m_dxvkAdapter->createDevice(getDeviceFeatures())),
m_dxvkSurface (m_dxvkAdapter->createSurface(instance, window)),
m_dxvkSwapchain (m_dxvkDevice->createSwapchain(m_dxvkSurface,
DxvkSwapchainProperties {
@ -178,6 +178,13 @@ public:
m_dxvkDevice->waitForIdle();
}
VkPhysicalDeviceFeatures getDeviceFeatures() const {
VkPhysicalDeviceFeatures features;
std::memset(&features, 0, sizeof(features));
return features;
}
private:
Rc<DxvkInstance> m_dxvkInstance;