mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-29 17:52:18 +01:00
[d3d11] Implemented proper feature tests
This commit is contained in:
parent
e051498621
commit
ac2d16599c
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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)))
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user