From 1ee2b40c53c459105e3a913eb955fed92cdcf928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 13 Dec 2020 19:21:33 +0100 Subject: [PATCH] Vk: fetching of supported device features. This is what I needed BigEnumSet for -- good thing I didn't even try to have 128-bit enums because I'm now at 110 values and it's still far from complete. Next step is enabling those features when creating a device, which should hopefully be a lot less code, reusing most of what was here. --- doc/vulkan-mapping.dox | 47 +- doc/vulkan-support.dox | 2 +- src/Magnum/Vk/CMakeLists.txt | 4 + src/Magnum/Vk/DeviceFeatures.cpp | 63 + src/Magnum/Vk/DeviceFeatures.h | 1032 +++++++++++++++++ src/Magnum/Vk/DeviceProperties.cpp | 97 ++ src/Magnum/Vk/DeviceProperties.h | 89 +- src/Magnum/Vk/Implementation/DeviceFeatures.h | 61 + .../Implementation/deviceFeatureMapping.hpp | 186 +++ src/Magnum/Vk/Test/CMakeLists.txt | 2 + src/Magnum/Vk/Test/DeviceFeaturesTest.cpp | 110 ++ src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp | 71 ++ src/Magnum/Vk/Vk.h | 2 + 13 files changed, 1738 insertions(+), 28 deletions(-) create mode 100644 src/Magnum/Vk/DeviceFeatures.cpp create mode 100644 src/Magnum/Vk/DeviceFeatures.h create mode 100644 src/Magnum/Vk/Implementation/DeviceFeatures.h create mode 100644 src/Magnum/Vk/Implementation/deviceFeatureMapping.hpp create mode 100644 src/Magnum/Vk/Test/DeviceFeaturesTest.cpp diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index d355e1eba..ea157a339 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -205,7 +205,7 @@ Vulkan function | Matching API @fn_vk{GetPhysicalDeviceExternalBufferProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceExternalFenceProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceExternalSemaphoreProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@fn_vk{GetPhysicalDeviceFeatures}, \n @fn_vk{GetPhysicalDeviceFeatures2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | +@fn_vk{GetPhysicalDeviceFeatures}, \n @fn_vk{GetPhysicalDeviceFeatures2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties::features() @fn_vk{GetPhysicalDeviceFormatProperties}, \n @fn_vk{GetPhysicalDeviceFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceMemoryProperties}, \n @fn_vk{GetPhysicalDeviceMemoryProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties::memoryProperties() @@ -499,56 +499,55 @@ Vulkan structure | Matching API Vulkan structure | Matching API --------------------------------------- | ------------ -@type_vk{PhysicalDevice8bitStorageFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDevice16bitStorageFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceBufferDeviceAddressFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{PhysicalDevice8bitStorageFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDevice16bitStorageFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceFeatures +@type_vk{PhysicalDeviceBufferDeviceAddressFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures @type_vk{PhysicalDeviceDepthStencilResolveProperties} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceDescriptorIndexingFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | | +@type_vk{PhysicalDeviceDescriptorIndexingFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DeviceFeatures @type_vk{PhysicalDeviceDescriptorIndexingProperties} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{PhysicalDeviceDriverProperties} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{PhysicalDeviceExternalBufferInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceExternalFenceInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceExternalImageFormatInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceExternalSemaphoreInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceFeatures}, \n @type_vk{PhysicalDeviceFeatures2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceFloat16Int8Features} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{PhysicalDeviceFeatures}, \n @type_vk{PhysicalDeviceFeatures2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceFeatures @type_vk{PhysicalDeviceFloatControlsProperties} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{PhysicalDeviceGroupProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceHostQueryResetFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | | +@type_vk{PhysicalDeviceHostQueryResetFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DeviceFeatures @type_vk{PhysicalDeviceIDProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceImageFormatInfo2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceImagelessFramebufferFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceIndexTypeUint8FeaturesEXT} @m_class{m-label m-flat m-warning} **EXT** | | -@type_vk{PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT} @m_class{m-label m-flat m-warning} **EXT** | | +@type_vk{PhysicalDeviceImagelessFramebufferFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceIndexTypeUint8FeaturesEXT} @m_class{m-label m-flat m-warning} **EXT** | @ref DeviceFeatures +@type_vk{PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT} @m_class{m-label m-flat m-warning} **EXT** | @ref DeviceFeatures @type_vk{PhysicalDeviceLimits} | | @type_vk{PhysicalDeviceMaintenance3Properties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceMemoryProperties}, \n @type_vk{PhysicalDeviceMemoryProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties -@type_vk{PhysicalDeviceMultiviewFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | | +@type_vk{PhysicalDeviceMultiviewFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceFeatures @type_vk{PhysicalDeviceMultiviewProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDevicePointClippingProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceProperties}, \n @type_vk{PhysicalDeviceProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties -@type_vk{PhysicalDeviceProtectedMemoryFeatures} @m_class{m-label m-flat m-success} **1.1** | | +@type_vk{PhysicalDeviceProtectedMemoryFeatures} @m_class{m-label m-flat m-success} **1.1** | @ref DeviceFeatures @type_vk{PhysicalDeviceProtectedMemoryProperties} @m_class{m-label m-flat m-success} **1.1** | | @type_vk{PhysicalDeviceSamplerFilterMinmaxProperties} @m_class{m-label m-flat m-success} **EXT, 1.2** | | -@type_vk{PhysicalDeviceSamplerYcbcrConversionFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{PhysicalDeviceSeparateDepthStencilLayoutsFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceScalarBlockLayoutFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | | -@type_vk{PhysicalDeviceShaderAtomicInt64Features} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceShaderDrawParametersFeatures} @m_class{m-label m-flat m-success} **1.1** | | -@type_vk{PhysicalDeviceShaderFloat16Int8Features} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceShaderSubgroupExtendedTypesFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{PhysicalDeviceSamplerYcbcrConversionFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceFeatures +@type_vk{PhysicalDeviceSeparateDepthStencilLayoutsFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceScalarBlockLayoutFeatures} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceShaderAtomicInt64Features} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceShaderDrawParametersFeatures} @m_class{m-label m-flat m-success} **1.1** | @ref DeviceFeatures +@type_vk{PhysicalDeviceShaderFloat16Int8Features} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceShaderSubgroupExtendedTypesFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures @type_vk{PhysicalDeviceSparseImageFormatInfo2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PhysicalDeviceSparseProperties} | | @type_vk{PhysicalDeviceSubgroupProperties} @m_class{m-label m-flat m-success} **1.1** | | -@type_vk{PhysicalDeviceTimelineSemaphoreFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{PhysicalDeviceTimelineSemaphoreFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures @type_vk{PhysicalDeviceTimelineSemaphoreProperties} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceUniformBufferStandardLayoutFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | -@type_vk{PhysicalDeviceVariablePointersFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | | +@type_vk{PhysicalDeviceUniformBufferStandardLayoutFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures +@type_vk{PhysicalDeviceVariablePointersFeatures} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceFeatures @type_vk{PhysicalDeviceVulkan11Features} @m_class{m-label m-flat m-success} **1.2** | ignored for compatibility reasons @type_vk{PhysicalDeviceVulkan11Properties} @m_class{m-label m-flat m-success} **1.2** | ignored for compatibility reasons @type_vk{PhysicalDeviceVulkan12Features} @m_class{m-label m-flat m-success} **1.2** | ignored for compatibility reasons @type_vk{PhysicalDeviceVulkan12Properties} @m_class{m-label m-flat m-success} **1.2** | ignored for compatibility reasons -@type_vk{PhysicalDeviceVulkanMemoryModelFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{PhysicalDeviceVulkanMemoryModelFeatures} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceFeatures @type_vk{PipelineCacheCreateInfo} | | @type_vk{PipelineColorBlendAttachmentState} | | @type_vk{PipelineColorBlendStateCreateInfo} | | diff --git a/doc/vulkan-support.dox b/doc/vulkan-support.dox index a1173fd77..36dbbef2a 100644 --- a/doc/vulkan-support.dox +++ b/doc/vulkan-support.dox @@ -55,7 +55,7 @@ See the @ref vulkan-mapping page for a list of already implemented functions. Extension | Status --------------------------------------------------- | ------ @vk_extension{KHR,multiview} | | -@vk_extension{KHR,get_physical_device_properties2} @m_class{m-label m-info} **instance** | device, memory and queue properties only +@vk_extension{KHR,get_physical_device_properties2} @m_class{m-label m-info} **instance** | device, feature, memory and queue properties only @vk_extension{KHR,device_group} | | @vk_extension{KHR,shader_draw_parameters} | | @vk_extension{KHR,maintenance1} | | diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 9a6bc0623..3656adacb 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -44,6 +44,7 @@ set(MagnumVk_GracefulAssert_SRCS Buffer.cpp Device.cpp DeviceProperties.cpp + DeviceFeatures.cpp Enums.cpp ExtensionProperties.cpp Image.cpp @@ -60,6 +61,7 @@ set(MagnumVk_HEADERS CommandPoolCreateInfo.h Device.h DeviceCreateInfo.h + DeviceFeatures.h DeviceProperties.h Enums.h Extensions.h @@ -88,10 +90,12 @@ set(MagnumVk_HEADERS set(MagnumVk_PRIVATE_HEADERS Implementation/Arguments.h + Implementation/DeviceFeatures.h Implementation/DeviceState.h Implementation/InstanceState.h Implementation/compressedPixelFormatMapping.hpp + Implementation/deviceFeatureMapping.hpp Implementation/pixelFormatMapping.hpp Implementation/structureHelpers.h Implementation/vertexFormatMapping.hpp) diff --git a/src/Magnum/Vk/DeviceFeatures.cpp b/src/Magnum/Vk/DeviceFeatures.cpp new file mode 100644 index 000000000..3cd7e0301 --- /dev/null +++ b/src/Magnum/Vk/DeviceFeatures.cpp @@ -0,0 +1,63 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "DeviceFeatures.h" + +#include +#include + +namespace Magnum { namespace Vk { + +namespace { + +#ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */ +constexpr const char* FeatureNames[] { + #define _c(value, field) #value, + #define _cver(value, field, suffix, version) _c(value, field) + #define _cext(value, field, suffix, extension) _c(value, field) + #include "Magnum/Vk/Implementation/deviceFeatureMapping.hpp" + #undef _c + #undef _cver + #undef _cext +}; +#endif + +} + +Debug& operator<<(Debug& debug, const DeviceFeature value) { + debug << "Vk::DeviceFeature" << Debug::nospace; + + if(UnsignedInt(value) < Containers::arraySize(FeatureNames)) { + return debug << "::" << Debug::nospace << FeatureNames[UnsignedInt(value)]; + } + + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, const DeviceFeatures& value) { + return Containers::bigEnumSetDebugOutput(debug, value, "Vk::DeviceFeatures{}"); +} + +}} diff --git a/src/Magnum/Vk/DeviceFeatures.h b/src/Magnum/Vk/DeviceFeatures.h new file mode 100644 index 000000000..9c1687fe9 --- /dev/null +++ b/src/Magnum/Vk/DeviceFeatures.h @@ -0,0 +1,1032 @@ +#ifndef Magnum_Vk_DeviceFeatures_h +#define Magnum_Vk_DeviceFeatures_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Enum @ref Magnum::Vk::DeviceFeature, enum set @ref Magnum::Vk::DeviceFeatures + * @m_since_latest + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +/** +@brief Device feature +@m_since_latest + +Contains information stored in the @type_vk{PhysicalDeviceFeatures2} structure +chain. Values correspond to equivalently named structure fields, usually just +with the first letter uppercase instead of lowercase. +@see @ref DeviceFeatures, @ref DeviceProperties::features() + +@todo @type_vk{PhysicalDeviceVulkan12Features} additionally has + `samplerMirrorClampToEdge`, `drawIndirectCount`, `descriptorIndexing`, + `samplerFilterMinMax`, `shaderOutputViewportIndex`, `shaderOutputLayer`, `subgroupBroadcastDynamicId` that aren't exposed in any extension -- does + that mean we have to enable such extension even on 1.2 in order to enable + those? Provide some compatibility, as in show them as supported when + the exts are present and enable corresponding exts when those get enabled + on device creation? +*/ +enum class DeviceFeature: UnsignedShort { + /** + * Whether accesses to buffers are bounds-checked against the range of the + * buffer descriptor. + * @todo expose @vk_extension{EXT,robustness2}, reference from here + */ + RobustBufferAccess, + + /** + * Whether the full 32-bit range is supported for indexed draw calls when + * using @val_vk{INDEX_TYPE_UINT32,IndexType}. + * @see @ref DeviceFeature::IndexTypeUint8 + * @todo expose the `maxDrawIndexedIndexValue` limit + */ + FullDrawIndexUint32, + + /** + * Whether image views with @val_vk{IMAGE_VIEW_TYPE_CUBE_ARRAY,ImageViewType} + * can be created and used in shaders. + */ + ImageCubeArray, + + /** Whether blend state can be different per attachment. */ + IndependentBlend, + + /** Whether geometry shaders are supported. */ + GeometryShader, + + /** Whether tessellation control and evaluation shaders are supported. */ + TessellationShader, + + /** Whether sample shading and multisample interpolation is supported. */ + SampleRateShading, + + /** Whether blend operations which take two sources are supported. */ + DualSrcBlend, + + /** Whether logic operations are supported. */ + LogicOp, + + /** Whether multiple draw indirect is supported. */ + MultiDrawIndirect, + + /** Whether indirect draw calls support the first instance parameter. */ + DrawIndirectFirstInstance, + + /** Whether depth clamping is supported. */ + DepthClamp, + + /** Whether depth bias clamping is supported. */ + DepthBiasClamp, + + /** Whether point and wireframe fill modes are supported. */ + FillModeNonSolid, + + /** Whether depth bound tests are supported. */ + DepthBounds, + + /** Whether lines with a width other than @cpp 1.0f @ce are supported. */ + WideLines, + + /** Whether points with size greater than @cpp 1.0f @ce are supported. */ + LargePoints, + + /** + * Whether replacing the alpha of color fragment output from the fragment + * shader with @cpp 1.0f @ce is supported. + */ + AlphaToOne, + + /** Whether rendering to more than one viewport is supported. */ + MultiViewport, + + /** Whether anisotropic filtering is supported. */ + SamplerAnisotropy, + + /** + * Whether *all* ETC2 and EAC compressed texture formats are supported. + * @todoc link to the formats once we have our own PixelFormat enum + */ + TextureCompressionEtc2, + + /** + * Whether *all* ASTC LDR compressed texture formats are supported. + * @todoc link to the formats once we have our own PixelFormat enum + * @see @ref DeviceFeature::TextureCompressionAstcHdr + */ + TextureCompressionAstcLdr, + + /** + * Whether *all* BC compressed texture formats are supported. + * @todoc link to the formats once we have our own PixelFormat enum + */ + TextureCompressionBc, + + /** + * Whether occlusion queries returning actual sample counts are supported. + */ + OcclusionQueryPrecise, + + /** Whether pipeline statistics queries are supported. */ + PipelineStatisticsQuery, + + /** + * Whether storage buffers and images support stores and atomic operations + * in the vertex, tessellation and geometry shader stages. + */ + VertexPipelineStoresAndAtomics, + + /** + * Whether storage buffers and images support stores and atomic operations + * in the fragment shader stage. + */ + FragmentStoresAndAtomics, + + /** + * Whether point size is accessible in tessellation control, tessellation + * evaluation and geometry shader stages. + */ + ShaderTessellationAndGeometryPointSize, + + /** + * Whether the extended set of image gather instructions is available in + * shader code. + */ + ShaderImageGatherExtended, + + /** + * Whether *all* shader storage image extended formats are supported. + * @todoc link to the formats once we have our own PixelFormat enum + */ + ShaderStorageImageExtendedFormats, + + /** + * Whether multisampled storage images are supported. + * @see @ref ImageUsage::Storage + */ + ShaderStorageImageMultisample, + + /** + * Whether storage images require a format qualifier to be specified when + * reading from storage images. + * @see @ref DeviceFeature::ShaderStorageImageWriteWithoutFormat + */ + ShaderStorageImageReadWithoutFormat, + + /** + * Whether storage images require a format qualifier to be specified when + * writing to storage images. + * @see @ref DeviceFeature::ShaderStorageImageReadWithoutFormat + */ + ShaderStorageImageWriteWithoutFormat, + + /** + * Whether arrays of uniform buffers can be indexed by dynamically uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + */ + ShaderUniformBufferArrayDynamicIndexing, + + /** + * Whether arrays of samplers or sampled images can be indexed by + * dynamically uniform integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + */ + ShaderSampledImageArrayDynamicIndexing, + + /** + * Whether arrays of storage buffers can be indexed by dynamically uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + */ + ShaderStorageBufferArrayDynamicIndexing, + + /** + * Whether arrays of storage images can be indexed by dynamically uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + */ + ShaderStorageImageArrayDynamicIndexing, + + /** Whether clip distances are supported in shader code. */ + ShaderClipDistance, + + /** Whether cull distances are supported in shader code. */ + ShaderCullDistance, + + /** + * Whether 64-bit floats are supported in shader code. + * @see @ref DeviceFeature::ShaderFloat16 + */ + ShaderFloat64, + + /** + * Whether 64-bit integers are supported in shader code. + * @see @ref DeviceFeature::ShaderInt16, @ref DeviceFeature::ShaderInt8, + * @ref DeviceFeature::ShaderSubgroupExtendedTypes + */ + ShaderInt64, + + /** + * Whether 16-bit integers are supported in shader code. + * @see @ref DeviceFeature::ShaderInt64, @ref DeviceFeature::ShaderInt8, + * @ref DeviceFeature::StorageBuffer16BitAccess, + * @ref DeviceFeature::UniformAndStorageBuffer16BitAccess, + * @ref DeviceFeature::StoragePushConstant16, + * @ref DeviceFeature::StorageInputOutput16, + * @ref DeviceFeature::ShaderSubgroupExtendedTypes + */ + ShaderInt16, + + /** + * Whether image operations that return resource residency information are + * supported in shader code. + */ + ShaderResourceResidency, + + /** + * Whether image operations specifying minimum resource LOD are supported + * in shader code. + */ + ShaderResourceMinLod, + + /** + * Whether resource memory can be managed at opaque sparse block level + * instead of at the object level. + */ + SparseBinding, + + /** Whether the device can access sparse buffers. */ + SparseResidencyBuffer, + + /** + * Whether the device can access sparse 2D images with 1 sample + * per pixel. + * @todo reference VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT once that's exposed + * in ImageCreateInfo + */ + SparseResidencyImage2D, + + /** Whether the device can access sparse 3D images. */ + SparseResidencyImage3D, + + /** + * Whether the device can access sparse 2D images with 2 + * samples per pixel. + * @todo reference VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT once that's exposed + * in ImageCreateInfo + */ + SparseResidency2Samples, + + /** + * Whether the device can access sparse 2D images with 4 + * samples per pixel. + * @todo reference VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT once that's exposed + * in ImageCreateInfo + */ + SparseResidency4Samples, + + /** + * Whether the device can access sparse 2D images with 8 + * samples per pixel. + * @todo reference VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT once that's exposed + * in ImageCreateInfo + */ + SparseResidency8Samples, + + /** + * Whether the device can access sparse 2D images with 16 + * samples per pixel. + * @todo reference VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT once that's exposed + * in ImageCreateInfo + */ + SparseResidency16Samples, + + /** + * Whether the device can correctly access sparse data aliased into + * multiple locations. + */ + SparseResidencyAliased, + + /** + * Whether all pipelines bound to a command buffer during a subpass which + * uses no attachment must have the same samples. + * @todoc crossreference this with PipelineCreateInfo + */ + VariableMultisampleRate, + + /** + * Whether a secondary command buffer may be executed while a query is + * active. + */ + InheritedQueries, + + /* VkPhysicalDeviceProtectedMemoryFeatures, Vk11 */ + + /** + * Whether protected memory is supported. + * @requires_vk11 Available only on Vulkan 1.1. + */ + ProtectedMemory, + + /* VkPhysicalDeviceMultiviewFeatures, #54 */ + + /** + * Whether multiview rendering within a render pass is supported. + * @requires_vk11 Extension @vk_extension{KHR,multiview} + */ + Multiview, + + /** + * Whether multiview rendering within a render pass with geometry shaders + * is supported. + * @requires_vk11 Extension @vk_extension{KHR,multiview} + */ + MultiviewGeometryShader, + + /** + * Whether multiview rendering within a render pass with tessellation + * shaders is supported. + * @requires_vk11 Extension @vk_extension{KHR,multiview} + */ + MultiviewTessellationShader, + + /* VkPhysicalDeviceShaderDrawParametersFeatures, #64 */ + + /** + * Whether shader draw parameters are supported. + * @requires_vk11 Extension @vk_extension{KHR,shader_draw_parameters} + */ + ShaderDrawParameters, + + /* VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT, #67 */ + + /** + * Whether *all* ASTC HDR compressed texture formats are supported. + * @todoc link to the formats once we have our own PixelFormat enum + * @see @ref DeviceFeature::TextureCompressionAstcLdr + * @requires_vk_extension Extension @vk_extension{EXT,texture_compression_astc_hdr} + */ + TextureCompressionAstcHdr, + + /* VkPhysicalDeviceShaderFloat16Int8Features, #83 */ + + /** + * Whether 16-bit floats are supported in shader code. + * @see @ref DeviceFeature::ShaderFloat64, + * @ref DeviceFeature::StorageBuffer16BitAccess, + * @ref DeviceFeature::UniformAndStorageBuffer16BitAccess, + * @ref DeviceFeature::StoragePushConstant16, + * @ref DeviceFeature::StorageInputOutput16, + * @ref DeviceFeature::ShaderSubgroupExtendedTypes + * @requires_vk12 Extension @vk_extension{KHR,shader_float16_int8} + */ + ShaderFloat16, + + /** + * Whether 8-bit integers are supported in shader code. + * @see @ref DeviceFeature::ShaderInt64, @ref DeviceFeature::ShaderInt16, + * @ref DeviceFeature::ShaderSubgroupExtendedTypes + * @requires_vk12 Extension @vk_extension{KHR,shader_float16_int8} + */ + ShaderInt8, + + /* VkPhysicalDevice16BitStorageFeatures, #84 */ + + /** + * Whether shader storage buffers can have 16-bit integer and 16-bit + * floating-point members. Subset of + * @ref DeviceFeature::UniformAndStorageBuffer16BitAccess. + * @see @ref DeviceFeature::StorageBuffer8BitAccess, + * @ref DeviceFeature::ShaderInt16, @ref DeviceFeature::ShaderFloat16 + * @requires_vk11 Extension @vk_extension{KHR,16bit_storage} + */ + StorageBuffer16BitAccess, + + /** + * Whether shader uniforms and storage buffers can have 16-bit integer and + * 16-bit floating-point members. Superset of + * @ref DeviceFeature::StorageBuffer16BitAccess. + * @see @ref DeviceFeature::UniformAndStorageBuffer8BitAccess, + * @ref DeviceFeature::ShaderInt16, @ref DeviceFeature::ShaderFloat16 + * @requires_vk11 Extension @vk_extension{KHR,16bit_storage} + */ + UniformAndStorageBuffer16BitAccess, + + /** + * Whether shader push constants can have 16-bit integer and 16-bit + * floating-point members. + * @see @ref DeviceFeature::StoragePushConstant8, + * @ref DeviceFeature::ShaderInt16, @ref DeviceFeature::ShaderFloat16 + * @requires_vk11 Extension @vk_extension{KHR,16bit_storage} + */ + StoragePushConstant16, + + /** + * Whether shader inputs and outputs can have 16-bit integer and 16-bit + * floating-point members. + * @see @ref DeviceFeature::ShaderInt16, @ref DeviceFeature::ShaderFloat16 + * @requires_vk11 Extension @vk_extension{KHR,16bit_storage} + */ + StorageInputOutput16, + + /* VkPhysicalDeviceImagelessFramebufferFeatures, #109 */ + + /** + * Specifying image view for attachments is possible at render pass begin + * time. + * @todoc crosslink with RenderPass::begin() when that's implemented. + * @requires_vk12 Extension @vk_extension{KHR,imageless_framebuffer} + */ + ImagelessFramebuffer, + + /* VkPhysicalDeviceVariablePointersFeatures, #121 */ + + /** + * Whether SPIR-V variable pointer storage buffers are supported. + * @requires_vk11 Extension @vk_extension{KHR,variable_pointers} + */ + VariablePointersStorageBuffer, + + /** + * Whether SPIR-V variable pointers are supported. + * @requires_vk11 Extension @vk_extension{KHR,variable_pointers} + */ + VariablePointers, + + /* VkPhysicalDeviceSamplerYcbcrConversionFeatures, #157 */ + + /** + * Whether sampler Y'CBCR conversion is supported. + * @requires_vk11 Extension @vk_extension{KHR,sampler_ycbcr_conversion} + */ + SamplerYcbcrConversion, + + /* VkPhysicalDeviceDescriptorIndexingFeatures, #162 */ + + /** + * Whether arrays of input attachment can be indexed by dynamically uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderInputAttachmentArrayDynamicIndexing, + + /** + * Whether arrays of uniform texel buffers can be indexed by dynamically + * uniform integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderUniformTexelBufferArrayDynamicIndexing, + + /** + * Whether arrays of storage texel buffers can be indexed by dynamically + * uniform integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderStorageTexelBufferArrayDynamicIndexing, + + /** + * Whether arrays of uniform buffers can be indexed by non-uniform integer + * expressions in shader code. + * @see @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderUniformBufferArrayNonUniformIndexing, + + /** + * Whether arrays of samplers or sampled images can be indexed by + * non-uniform integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderSampledImageArrayNonUniformIndexing, + + /** + * Whether arrays of storage buffers can be indexed by non-uniform integer + * expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderStorageBufferArrayNonUniformIndexing, + + /** + * Whether arrays of storage images can be indexed by non-uniform integer + * expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderStorageImageArrayNonUniformIndexing, + + /** + * Whether arrays of input attachments can be indexed by non-uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderInputAttachmentArrayNonUniformIndexing, + + /** + * Whether arrays of uniform texel buffers can be indexed by non-uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderUniformTexelBufferArrayNonUniformIndexing, + + /** + * Whether arrays of storage texel buffers can be indexed by non-uniform + * integer expressions in shader code. + * @see @ref DeviceFeature::ShaderUniformBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderSampledImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayNonUniformIndexing, + * @ref DeviceFeature::ShaderUniformBufferArrayDynamicIndexing + * @ref DeviceFeature::ShaderSampledImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageImageArrayDynamicIndexing, + * @ref DeviceFeature::ShaderInputAttachmentArrayDynamicIndexing, + * @ref DeviceFeature::ShaderUniformTexelBufferArrayDynamicIndexing, + * @ref DeviceFeature::ShaderStorageTexelBufferArrayDynamicIndexing + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + ShaderStorageTexelBufferArrayNonUniformIndexing, + + /** + * Whether uniform buffer descriptors can be updated after a set is bound. + * @see @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingUniformBufferUpdateAfterBind, + + /** + * Whether sampled image descriptors can be updated after a set is bound. + * @see @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingSampledImageUpdateAfterBind, + + /** + * Whether storage image descriptors can be updated after a set is bound. + * @see @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingStorageImageUpdateAfterBind, + + /** + * Whether storage buffer descriptors can be updated after a set is bound. + * @see @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingStorageBufferUpdateAfterBind, + + /** + * Whether uniform texel buffer descriptors can be updated after a set is + * bound. + * @see @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingUniformTexelBufferUpdateAfterBind, + + /** + * Whether storage texel buffer descriptors can be updated after a set is + * bound. + * @see @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind, + * @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingStorageTexelBufferUpdateAfterBind, + + /** + * Whether descriptors can be updated while the set is in use. + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingUpdateUnusedWhilePending, + + /** + * Whether a descriptor set binding in which some descriptors are not valid + * can be statically used. + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingPartiallyBound, + + /** + * Whether descriptor sets with a variably-sized last binding are + * supported. + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + DescriptorBindingVariableDescriptorCount, + + /** + * Whether SPIR-V runtime descriptor arrays are supported. + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + RuntimeDescriptorArray, + + /* VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures, #176 */ + + /** + * Whether subgroup operations can use 8-bit integer, 16-bit integer, + * 64-bit integer and 16-bit floating point types in group operations with + * subgroup scope, providing the types are supported. + * @see @ref DeviceFeature::ShaderInt8, @ref DeviceFeature::ShaderInt16, + * @ref DeviceFeature::ShaderInt64, @ref DeviceFeature::ShaderFloat16 + * @requires_vk12 Extension @vk_extension{KHR,shader_subgroup_extended_types} + */ + ShaderSubgroupExtendedTypes, + + /* VkPhysicalDevice8BitStorageFeatures, #178 */ + + /** + * Whether shader storage buffers can have 8-bit integer members. Subset of + * @ref DeviceFeature::UniformAndStorageBuffer8BitAccess. + * @see @ref DeviceFeature::StorageBuffer16BitAccess, + * @ref DeviceFeature::ShaderInt8 + * @requires_vk12 Extension @vk_extension{KHR,8bit_storage} + */ + StorageBuffer8BitAccess, + + /** + * Whether shader uniforms and storage buffers can have 8-bit integer + * members. Superset of @ref DeviceFeature::StorageBuffer8BitAccess. + * @see @ref DeviceFeature::UniformAndStorageBuffer16BitAccess, + * @ref DeviceFeature::ShaderInt8 + * @requires_vk12 Extension @vk_extension{KHR,8bit_storage} + */ + UniformAndStorageBuffer8BitAccess, + + /** + * Whether shader push constants can have 8-bit integer members. + * @see @ref DeviceFeature::StoragePushConstant16, + * @ref DeviceFeature::ShaderInt8 + * @requires_vk12 Extension @vk_extension{KHR,8bit_storage} + */ + StoragePushConstant8, + + /* VkPhysicalDeviceShaderAtomicInt64Features, #181 */ + + /** + * Whether shaders can perform 64-bit integer atomic operations on buffers. + * @see @ref DeviceFeature::ShaderSharedInt64Atomics + * @requires_vk12 Extension @vk_extension{KHR,shader_atomic_int64} + */ + ShaderBufferInt64Atomics, + + /** + * Whether shaders can perform 64-bit integer atomic operations on shared + * memory. + * @see @ref DeviceFeature::ShaderBufferInt64Atomics + * @requires_vk12 Extension @vk_extension{KHR,shader_atomic_int64} + */ + ShaderSharedInt64Atomics, + + /* VkPhysicalDeviceTimelineSemaphoreFeatures, #208 */ + + /** + * Whether timeline semaphores are supported. + * @requires_vk12 Extension @vk_extension{KHR,timeline_semaphore} + */ + TimelineSemaphore, + + /* VkPhysicalDeviceVulkanMemoryModelFeatures, #212 */ + + /** + * Whether the Vulkan Memory Model is supported. + * @see @ref DeviceFeature::VulkanMemoryModelDeviceScope, + * @ref DeviceFeature::VulkanMemoryModelAvailabilityVisibilityChains + * @requires_vk12 Extension @vk_extension{KHR,vulkan_memory_model} + */ + VulkanMemoryModel, + + /** + * Whether the Vulkan Memory Model can use device scope synchronization. + * @see @ref DeviceFeature::VulkanMemoryModel, + * @ref DeviceFeature::VulkanMemoryModelAvailabilityVisibilityChains + * @requires_vk12 Extension @vk_extension{KHR,vulkan_memory_model} + */ + VulkanMemoryModelDeviceScope, + + /** + * Whether the Vulkan Memory Model can use availability and visibility + * chains with more than one element. + * @see @ref DeviceFeature::VulkanMemoryModel, + * @ref DeviceFeature::VulkanMemoryModelDeviceScope + * @requires_vk12 Extension @vk_extension{KHR,vulkan_memory_model} + */ + VulkanMemoryModelAvailabilityVisibilityChains, + + /* VkPhysicalDeviceScalarBlockLayoutFeatures, #222 */ + + /** + * Whether layout of resource blocks in shaders using scalar alignment is + * supported. + * @requires_vk12 Extension @vk_extension{EXT,scalar_block_layout} + */ + ScalarBlockLayout, + + /* VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures, #242 */ + + /** + * Whether the implementation supports an image barrier for a depth/stencil + * image with only one of the depth/stencil aspects and whether separate + * depth/stencil layouts can be used. + * @requires_vk12 Extension @vk_extension{KHR,separate_depth_stencil_layouts} + * @todoc link to the actual ImageAspect and ImageLayout members once they + * exist + */ + SeparateDepthStencilLayouts, + + /* VkPhysicalDeviceUniformBufferStandardLayoutFeatures, #254 */ + + /** + * Whether same layouts for uniform buffers as for storage and other kinds + * of buffers are supported. + * @requires_vk12 Extension @vk_extension{KHR,uniform_buffer_standard_layout} + */ + UniformBufferStandardLayout, + + /* VkPhysicalDeviceBufferDeviceAddressFeatures, #258 */ + + /** + * Whether accessing buffer memory in shaders as storage buffers via an + * address queried from @fn_vk{GetBufferDeviceAddress} is supported. + * @see @ref DeviceFeature::BufferDeviceAddressCaptureReplay, + * @ref DeviceFeature::BufferDeviceAddressMultiDevice + * @requires_vk12 Extension @vk_extension{KHR,buffer_device_address} + */ + BufferDeviceAddress, + + /** + * Whether saving and reusing buffer dand device addresses for trace + * capture and replay is supported. + * @see @ref DeviceFeature::BufferDeviceAddress, + * @ref DeviceFeature::BufferDeviceAddressMultiDevice + * @requires_vk12 Extension @vk_extension{KHR,buffer_device_address} + */ + BufferDeviceAddressCaptureReplay, + + /** + * Whether @ref DeviceFeature::BufferDeviceAddress for logical devices + * created with multiple physical devices is supported. + * @requires_vk12 Extension @vk_extension{KHR,buffer_device_address} + * @todoc this also references `rayTracingPipeline`, `rayQuery`, update + * when those are exposed + */ + BufferDeviceAddressMultiDevice, + + /* VkPhysicalDeviceHostQueryResetFeatures, #262 */ + + /** + * Whether queries can be reset from the host with @fn_vk{ResetQueryPool}. + * @requires_vk12 Extension @vk_extension{EXT,host_query_reset} + */ + HostQueryReset, + + /* VkPhysicalDeviceIndexTypeUint8FeaturesEXT, #266 */ + + /** + * Whether an 8-bit type can be used in index buffers. + * @see @ref DeviceFeature::FullDrawIndexUint32 + * @requires_vk_extension Extension @vk_extension{EXT,index_type_uint8} + */ + IndexTypeUint8 +}; + +/** +@brief Device features +@m_since_latest + +Combines information stored in the @type_vk{PhysicalDeviceFeatures2} structure +chain. +@see @ref DeviceProperties::features() +*/ +typedef Containers::BigEnumSet DeviceFeatures; + +CORRADE_ENUMSET_OPERATORS(DeviceFeatures) + +/** +@debugoperatorenum{DeviceFeature} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceFeature value); + +/** +@debugoperatorenum{DeviceFeatures} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, const DeviceFeatures& value); + +}} + +#endif diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp index d9cf5952d..79ac31d8e 100644 --- a/src/Magnum/Vk/DeviceProperties.cpp +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -35,6 +35,7 @@ #include "Magnum/Math/Functions.h" #include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/ExtensionProperties.h" #include "Magnum/Vk/Extensions.h" #include "Magnum/Vk/Instance.h" @@ -42,6 +43,7 @@ #include "Magnum/Vk/Memory.h" #include "Magnum/Vk/Version.h" #include "Magnum/Vk/Implementation/Arguments.h" +#include "Magnum/Vk/Implementation/DeviceFeatures.h" #include "Magnum/Vk/Implementation/InstanceState.h" #include "Magnum/Vk/Implementation/structureHelpers.h" @@ -56,6 +58,7 @@ struct DeviceProperties::State { Containers::Optional extensions; void(*getPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&); + void(*getFeaturesImplementation)(DeviceProperties&, VkPhysicalDeviceFeatures2&); void(*getQueueFamilyPropertiesImplementation)(DeviceProperties&, UnsignedInt&, VkQueueFamilyProperties2*); void(*getMemoryPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceMemoryProperties2&); @@ -63,6 +66,11 @@ struct DeviceProperties::State { VkPhysicalDeviceDriverProperties driverProperties{}; VkPhysicalDeviceMemoryProperties2 memoryProperties{}; Containers::Array queueFamilyProperties; + + /* Not storing (a chain of) VkPhysicalDeviceFeatures structures, because + those are >32x larger than necessary and extremely annoying to operate + with. Using a big enum set instead. */ + DeviceFeatures features; }; DeviceProperties::State::State(Instance& instance, const VkPhysicalDevice handle) { @@ -117,14 +125,17 @@ DeviceProperties::State::State(Instance& instance, const VkPhysicalDevice handle /* Have to check both the instance and device version, see above */ if(instance.isVersionSupported(Version::Vk11) && Version(properties.properties.apiVersion) >= Version::Vk11) { getPropertiesImplementation = &DeviceProperties::getPropertiesImplementation11; + getFeaturesImplementation = &DeviceProperties::getFeaturesImplementation11; getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementation11; getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementation11; } else if(instance.isExtensionEnabled()) { getPropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR; + getFeaturesImplementation = &DeviceProperties::getFeaturesImplementationKHR; getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationKHR; getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationKHR; } else { getPropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault; + getFeaturesImplementation = &DeviceProperties::getFeaturesImplementationDefault; getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationDefault; getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationDefault; } @@ -214,6 +225,18 @@ void DeviceProperties::getPropertiesImplementation11(DeviceProperties& self, VkP return (**self._instance).GetPhysicalDeviceProperties2(self._handle, &properties); } +void DeviceProperties::getFeaturesImplementationDefault(DeviceProperties& self, VkPhysicalDeviceFeatures2& features) { + return (**self._instance).GetPhysicalDeviceFeatures(self._handle, &features.features); +} + +void DeviceProperties::getFeaturesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceFeatures2& features) { + return (**self._instance).GetPhysicalDeviceFeatures2KHR(self._handle, &features); +} + +void DeviceProperties::getFeaturesImplementation11(DeviceProperties& self, VkPhysicalDeviceFeatures2& features) { + return (**self._instance).GetPhysicalDeviceFeatures2(self._handle, &features); +} + ExtensionProperties DeviceProperties::enumerateExtensionProperties(Containers::ArrayView layers) { return InstanceExtensionProperties{layers, [](void* state, const char* const layer, UnsignedInt* count, VkExtensionProperties* properties) { auto& deviceProperties = *static_cast(state); @@ -236,6 +259,80 @@ template bool DeviceProperties::isOrVersionSupportedInternal() { return extensionPropertiesInternal().isSupported(); } +const DeviceFeatures& DeviceProperties::features() { + if(!_state) _state.emplace(*_instance, _handle); + + /* If a device doesn't support *any* feature, this will be fetched always. + That's rather rare though. */ + if(!_state->features) { + VkPhysicalDeviceFeatures2 features2{}; + Implementation::DeviceFeatures features{}; + + features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + Containers::Reference next = features2.pNext; + + /* Fetch extra features, if supported */ + if(isVersionSupported(Version::Vk11)) + Implementation::structureConnect(next, features.protectedMemory, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.multiview, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.shaderDrawParameters, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.textureCompressionAstcHdr, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.shaderFloat16Int8, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features._16BitStorage, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.imagelessFramebuffer, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.variablePointers, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.samplerYcbcrConversion, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.descriptorIndexing, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.shaderSubgroupExtendedTypes, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features._8BitStorage, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.shaderAtomicInt64, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.timelineSemaphore, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.vulkanMemoryModel, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.scalarBlockLayout, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.separateDepthStencilLayouts, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.uniformBufferStandardLayout, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.bufferDeviceAddress, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.hostQueryReset, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES); + if(isOrVersionSupportedInternal()) + Implementation::structureConnect(next, features.indexTypeUint8, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT); + + _state->getFeaturesImplementation(*this, features2); + + #define _c(value, field) \ + if(features2.features.field) \ + _state->features |= DeviceFeature::value; + #define _cver(value, field, suffix, version) \ + if(features.suffix.field) \ + _state->features |= DeviceFeature::value; + #define _cext _cver + #include "Magnum/Vk/Implementation/deviceFeatureMapping.hpp" + #undef _c + #undef _cver + #undef _cext + } + + return _state->features; +} + Containers::ArrayView DeviceProperties::queueFamilyProperties() { if(!_state) _state.emplace(*_instance, _handle); diff --git a/src/Magnum/Vk/DeviceProperties.h b/src/Magnum/Vk/DeviceProperties.h index 2b7e7153c..7e0eb70a5 100644 --- a/src/Magnum/Vk/DeviceProperties.h +++ b/src/Magnum/Vk/DeviceProperties.h @@ -246,9 +246,9 @@ MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, MemoryHeapFlags value); @m_since_latest Wraps a @type_vk_keyword{PhysicalDevice} along with its (lazy-populated) -properties. See the @ref Vk-Device-creation "Device creation docs" for an -example of using this class for enumerating available devices and picking one -of them. +properties and features. See the @ref Vk-Device-creation "Device creation docs" +for an example of using this class for enumerating available devices and +picking one of them. @see @ref pickDevice(), @ref enumerateDevices() */ class MAGNUM_VK_EXPORT DeviceProperties { @@ -410,6 +410,85 @@ class MAGNUM_VK_EXPORT DeviceProperties { /** @overload */ ExtensionProperties enumerateExtensionProperties(std::initializer_list layers); + /** + * @brief Device features + * + * Populated lazily on first request, extracting the booleans into a + * more compact set of @ref DeviceFeature values. If Vulkan 1.1 is not + * supported and the @vk_extension{KHR,get_physical_device_properties2} + * extension is not enabled on the originating instance, only the + * Vulkan 1.0 subset of device features is queried. Otherwise: + * + * - If Vulkan 1.1 is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceProtectedMemoryFeatures} + * - If Vulkan 1.1 or the @vk_extension{KHR,multiview} extension is + * supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceMultiviewFeatures} + * - If Vulkan 1.1 or the @vk_extension{KHR,shader_draw_parameters} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceShaderDrawParametersFeatures} + * - If the @vk_extension{EXT,texture_compression_astc_hdr} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT} + * - If Vulkan 1.2 or the @vk_extension{KHR,shader_float16_int8} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceShaderFloat16Int8Features} + * - If Vulkan 1.1 or the @vk_extension{KHR,16bit_storage} extension + * is supported by the device, the `pNext` chain contains + * @type_vk_keyword{PhysicalDevice16BitStorageFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,imageless_framebuffer} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceImagelessFramebufferFeatures} + * - If Vulkan 1.1 or the @vk_extension{KHR,variable_pointers} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceVariablePointersFeatures} + * - If Vulkan 1.1 or the @vk_extension{KHR,sampler_ycbcr_conversion} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceSamplerYcbcrConversionFeatures} + * - If Vulkan 1.2 or the @vk_extension{EXT,descriptor_indexing} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceDescriptorIndexingFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,shader_subgroup_extended_types} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceShaderSubgroupExtendedTypesFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,8bit_storage} extension is + * supported by the device, the `pNext` chain contains + * @type_vk_keyword{PhysicalDevice8BitStorageFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,shader_atomic_int64} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceShaderAtomicInt64Features} + * - If Vulkan 1.2 or the @vk_extension{KHR,timeline_semaphore} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceTimelineSemaphoreFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,vulkan_memory_model} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceVulkanMemoryModelFeatures} + * - If Vulkan 1.2 or the @vk_extension{EXT,scalar_block_layout} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceScalarBlockLayoutFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,separate_depth_stencil_layouts} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceSeparateDepthStencilLayoutsFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,uniform_buffer_standard_layout} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceUniformBufferStandardLayoutFeatures} + * - If Vulkan 1.2 or the @vk_extension{KHR,buffer_device_address} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceBufferDeviceAddressFeatures} + * - If Vulkan 1.2 or the @vk_extension{EXT,host_query_reset} + * extension is supported by the device, the `pNext` chain + * contains @type_vk_keyword{PhysicalDeviceHostQueryResetFeatures} + * - If the @vk_extension{EXT,index_type_uint8} extension is + * supported by the device, the `pNext` chain contains + * @type_vk_keyword{PhysicalDeviceIndexTypeUint8FeaturesEXT} + * + * @see @fn_vk_keyword{GetPhysicalDeviceFeatures2}, + * @fn_vk_keyword{GetPhysicalDeviceFeatures}, + * @type_vk_keyword{PhysicalDeviceFeatures2}, + * @type_vk_keyword{PhysicalDeviceFeatures} + */ + const DeviceFeatures& features(); + /** * @brief Queue family properties * @@ -640,6 +719,10 @@ class MAGNUM_VK_EXPORT DeviceProperties { MAGNUM_VK_LOCAL static void getPropertiesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); MAGNUM_VK_LOCAL static void getPropertiesImplementation11(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); + MAGNUM_VK_LOCAL static void getFeaturesImplementationDefault(DeviceProperties& self, VkPhysicalDeviceFeatures2& features); + MAGNUM_VK_LOCAL static void getFeaturesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceFeatures2& features); + MAGNUM_VK_LOCAL static void getFeaturesImplementation11(DeviceProperties& self, VkPhysicalDeviceFeatures2& features); + MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementationDefault(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties); MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementationKHR(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties); MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementation11(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties); diff --git a/src/Magnum/Vk/Implementation/DeviceFeatures.h b/src/Magnum/Vk/Implementation/DeviceFeatures.h new file mode 100644 index 000000000..c601f6f30 --- /dev/null +++ b/src/Magnum/Vk/Implementation/DeviceFeatures.h @@ -0,0 +1,61 @@ +#ifndef Magnum_Vk_Implementation_DeviceFeatures_h +#define Magnum_Vk_Implementation_DeviceFeatures_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { namespace Implementation { + +/* Everything except the top-level VkPhysicalDeviceFeatures2 structure, which + is treated differently when querying and enabling the features. Used by + DeviceProperties.cpp. */ +struct DeviceFeatures { + VkPhysicalDeviceProtectedMemoryFeatures protectedMemory; + VkPhysicalDeviceMultiviewFeatures multiview; + VkPhysicalDeviceShaderDrawParametersFeatures shaderDrawParameters; + VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT textureCompressionAstcHdr; + VkPhysicalDeviceShaderFloat16Int8Features shaderFloat16Int8; + VkPhysicalDevice16BitStorageFeatures _16BitStorage; + VkPhysicalDeviceImagelessFramebufferFeatures imagelessFramebuffer; + VkPhysicalDeviceVariablePointersFeatures variablePointers; + VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversion; + VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexing; + VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures shaderSubgroupExtendedTypes; + VkPhysicalDevice8BitStorageFeatures _8BitStorage; + VkPhysicalDeviceShaderAtomicInt64Features shaderAtomicInt64; + VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphore; + VkPhysicalDeviceVulkanMemoryModelFeatures vulkanMemoryModel; + VkPhysicalDeviceScalarBlockLayoutFeatures scalarBlockLayout; + VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures separateDepthStencilLayouts; + VkPhysicalDeviceUniformBufferStandardLayoutFeatures uniformBufferStandardLayout; + VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddress; + VkPhysicalDeviceHostQueryResetFeatures hostQueryReset; + VkPhysicalDeviceIndexTypeUint8FeaturesEXT indexTypeUint8; +}; + +}}} + +#endif diff --git a/src/Magnum/Vk/Implementation/deviceFeatureMapping.hpp b/src/Magnum/Vk/Implementation/deviceFeatureMapping.hpp new file mode 100644 index 000000000..4c5872434 --- /dev/null +++ b/src/Magnum/Vk/Implementation/deviceFeatureMapping.hpp @@ -0,0 +1,186 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* See Magnum/Vk/Device.cpp, Magnum/Vk/DeviceFeatures.cpp, + Magnum/Vk/DeviceProperties.cpp and Magnum/Vk/vk-info.cpp for actual usage + which explains what each parameter represents. Needs the _c(), _cver() and + _cext() macros defined, for core, version-dependent and extension-dependent + features respectively: + + _c(value, field) + _cver(value, field, suffix, version) + _cext(value, field, suffix, extension) + +*/ +#ifdef _c +_c(RobustBufferAccess, robustBufferAccess) +_c(FullDrawIndexUint32, fullDrawIndexUint32) +_c(ImageCubeArray, imageCubeArray) +_c(IndependentBlend, independentBlend) +_c(GeometryShader, geometryShader) +_c(TessellationShader, tessellationShader) +_c(SampleRateShading, sampleRateShading) +_c(DualSrcBlend, dualSrcBlend) +_c(LogicOp, logicOp) +_c(MultiDrawIndirect, multiDrawIndirect) +_c(DrawIndirectFirstInstance, drawIndirectFirstInstance) +_c(DepthClamp, depthClamp) +_c(DepthBiasClamp, depthBiasClamp) +_c(FillModeNonSolid, fillModeNonSolid) +_c(DepthBounds, depthBounds) +_c(WideLines, wideLines) +_c(LargePoints, largePoints) +_c(AlphaToOne, alphaToOne) +_c(MultiViewport, multiViewport) +_c(SamplerAnisotropy, samplerAnisotropy) +_c(TextureCompressionEtc2, textureCompressionETC2) +_c(TextureCompressionAstcLdr, textureCompressionASTC_LDR) +_c(TextureCompressionBc, textureCompressionBC) +_c(OcclusionQueryPrecise, occlusionQueryPrecise) +_c(PipelineStatisticsQuery, pipelineStatisticsQuery) +_c(VertexPipelineStoresAndAtomics, vertexPipelineStoresAndAtomics) +_c(FragmentStoresAndAtomics, fragmentStoresAndAtomics) +_c(ShaderTessellationAndGeometryPointSize, shaderTessellationAndGeometryPointSize) +_c(ShaderImageGatherExtended, shaderImageGatherExtended) +_c(ShaderStorageImageExtendedFormats, shaderStorageImageExtendedFormats) +_c(ShaderStorageImageMultisample, shaderStorageImageMultisample) +_c(ShaderStorageImageReadWithoutFormat, shaderStorageImageReadWithoutFormat) +_c(ShaderStorageImageWriteWithoutFormat, shaderStorageImageWriteWithoutFormat) +_c(ShaderUniformBufferArrayDynamicIndexing, shaderUniformBufferArrayDynamicIndexing) +_c(ShaderSampledImageArrayDynamicIndexing, shaderSampledImageArrayDynamicIndexing) +_c(ShaderStorageBufferArrayDynamicIndexing, shaderStorageBufferArrayDynamicIndexing) +_c(ShaderStorageImageArrayDynamicIndexing, shaderStorageImageArrayDynamicIndexing) +_c(ShaderClipDistance, shaderClipDistance) +_c(ShaderCullDistance, shaderCullDistance) +_c(ShaderFloat64, shaderFloat64) +_c(ShaderInt64, shaderInt64) +_c(ShaderInt16, shaderInt16) +_c(ShaderResourceResidency, shaderResourceResidency) +_c(ShaderResourceMinLod, shaderResourceMinLod) +_c(SparseBinding, sparseBinding) +_c(SparseResidencyBuffer, sparseResidencyBuffer) +_c(SparseResidencyImage2D, sparseResidencyImage2D) +_c(SparseResidencyImage3D, sparseResidencyImage3D) +_c(SparseResidency2Samples, sparseResidency2Samples) +_c(SparseResidency4Samples, sparseResidency4Samples) +_c(SparseResidency8Samples, sparseResidency8Samples) +_c(SparseResidency16Samples, sparseResidency16Samples) +_c(SparseResidencyAliased, sparseResidencyAliased) +_c(VariableMultisampleRate, variableMultisampleRate) +_c(InheritedQueries, inheritedQueries) + +_cver(ProtectedMemory, protectedMemory, protectedMemory, Vk11) + +#define _ce(value, field) _cext(value, field, multiview, KHR::multiview) +_ce(Multiview, multiview) +_ce(MultiviewGeometryShader, multiviewGeometryShader) +_ce(MultiviewTessellationShader, multiviewTessellationShader) +#undef _ce + +_cext(ShaderDrawParameters, shaderDrawParameters, shaderDrawParameters, KHR::shader_draw_parameters) + +_cext(TextureCompressionAstcHdr, textureCompressionASTC_HDR, textureCompressionAstcHdr, EXT::texture_compression_astc_hdr) + +#define _ce(value, field) _cext(value, field, shaderFloat16Int8, KHR::shader_float16_int8) +_ce(ShaderFloat16, shaderFloat16) +_ce(ShaderInt8, shaderInt8) +#undef _ce + +#define _ce(value, field) _cext(value, field, _16BitStorage, KHR::_16bit_storage) +_ce(StorageBuffer16BitAccess, storageBuffer16BitAccess) +_ce(UniformAndStorageBuffer16BitAccess, uniformAndStorageBuffer16BitAccess) +_ce(StoragePushConstant16, storagePushConstant16) +_ce(StorageInputOutput16, storageInputOutput16) +#undef _ce + +_cext(ImagelessFramebuffer, imagelessFramebuffer, imagelessFramebuffer, KHR::imageless_framebuffer) + +#define _ce(value, field) _cext(value, field, variablePointers, KHR::variable_pointers) +_ce(VariablePointersStorageBuffer, variablePointersStorageBuffer) +_ce(VariablePointers, variablePointers) +#undef _ce + +_cext(SamplerYcbcrConversion, samplerYcbcrConversion, samplerYcbcrConversion, KHR::sampler_ycbcr_conversion) + +#define _ce(value, field) _cext(value, field, descriptorIndexing, EXT::descriptor_indexing) +_ce(ShaderInputAttachmentArrayDynamicIndexing, shaderInputAttachmentArrayDynamicIndexing) +_ce(ShaderUniformTexelBufferArrayDynamicIndexing, shaderUniformTexelBufferArrayDynamicIndexing) +_ce(ShaderStorageTexelBufferArrayDynamicIndexing, shaderStorageTexelBufferArrayDynamicIndexing) +_ce(ShaderUniformBufferArrayNonUniformIndexing, shaderUniformBufferArrayNonUniformIndexing) +_ce(ShaderSampledImageArrayNonUniformIndexing, shaderSampledImageArrayNonUniformIndexing) +_ce(ShaderStorageBufferArrayNonUniformIndexing, shaderStorageBufferArrayNonUniformIndexing) +_ce(ShaderStorageImageArrayNonUniformIndexing, shaderStorageImageArrayNonUniformIndexing) +_ce(ShaderInputAttachmentArrayNonUniformIndexing, shaderInputAttachmentArrayNonUniformIndexing) +_ce(ShaderUniformTexelBufferArrayNonUniformIndexing, shaderUniformTexelBufferArrayNonUniformIndexing) +_ce(ShaderStorageTexelBufferArrayNonUniformIndexing, shaderStorageTexelBufferArrayNonUniformIndexing) +_ce(DescriptorBindingUniformBufferUpdateAfterBind, descriptorBindingUniformBufferUpdateAfterBind) +_ce(DescriptorBindingSampledImageUpdateAfterBind, descriptorBindingSampledImageUpdateAfterBind) +_ce(DescriptorBindingStorageImageUpdateAfterBind, descriptorBindingStorageImageUpdateAfterBind) +_ce(DescriptorBindingStorageBufferUpdateAfterBind, descriptorBindingStorageBufferUpdateAfterBind) +_ce(DescriptorBindingUniformTexelBufferUpdateAfterBind, descriptorBindingUniformTexelBufferUpdateAfterBind) +_ce(DescriptorBindingStorageTexelBufferUpdateAfterBind, descriptorBindingStorageTexelBufferUpdateAfterBind) +_ce(DescriptorBindingUpdateUnusedWhilePending, descriptorBindingUpdateUnusedWhilePending) +_ce(DescriptorBindingPartiallyBound, descriptorBindingPartiallyBound) +_ce(DescriptorBindingVariableDescriptorCount, descriptorBindingVariableDescriptorCount) +_ce(RuntimeDescriptorArray, runtimeDescriptorArray) +#undef _ce + +_cext(ShaderSubgroupExtendedTypes, shaderSubgroupExtendedTypes, shaderSubgroupExtendedTypes, KHR::shader_subgroup_extended_types) + +#define _ce(value, field) _cext(value, field, _8BitStorage, KHR::_8bit_storage) +_ce(StorageBuffer8BitAccess, storageBuffer8BitAccess) +_ce(UniformAndStorageBuffer8BitAccess, uniformAndStorageBuffer8BitAccess) +_ce(StoragePushConstant8, storagePushConstant8) +#undef _ce + +#define _ce(value, field) _cext(value, field, shaderAtomicInt64, KHR::shader_atomic_int64) +_ce(ShaderBufferInt64Atomics, shaderBufferInt64Atomics) +_ce(ShaderSharedInt64Atomics, shaderSharedInt64Atomics) +#undef _ce + +_cext(TimelineSemaphore, timelineSemaphore, timelineSemaphore, KHR::timeline_semaphore) + +#define _ce(value, field) _cext(value, field, vulkanMemoryModel, KHR::vulkan_memory_model) +_ce(VulkanMemoryModel, vulkanMemoryModel) +_ce(VulkanMemoryModelDeviceScope, vulkanMemoryModelDeviceScope) +_ce(VulkanMemoryModelAvailabilityVisibilityChains,vulkanMemoryModelAvailabilityVisibilityChains) +#undef _ce + +_cext(ScalarBlockLayout, scalarBlockLayout, scalarBlockLayout, EXT::scalar_block_layout) + +_cext(SeparateDepthStencilLayouts, separateDepthStencilLayouts, separateDepthStencilLayouts, KHR::separate_depth_stencil_layouts) + +_cext(UniformBufferStandardLayout, uniformBufferStandardLayout, uniformBufferStandardLayout, KHR::uniform_buffer_standard_layout) + +#define _ce(value, field) _cext(value, field, bufferDeviceAddress, KHR::buffer_device_address) +_ce(BufferDeviceAddress, bufferDeviceAddress) +_ce(BufferDeviceAddressCaptureReplay, bufferDeviceAddressCaptureReplay) +_ce(BufferDeviceAddressMultiDevice, bufferDeviceAddressMultiDevice) +#undef _ce + +_cext(HostQueryReset, hostQueryReset, hostQueryReset, EXT::host_query_reset) + +_cext(IndexTypeUint8, indexTypeUint8, indexTypeUint8, EXT::index_type_uint8) +#endif diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index a2ddf9c3e..5430790f3 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -29,6 +29,7 @@ corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkDeviceFeaturesTest DeviceFeaturesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkExtensionsTest ExtensionsTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkExtensionPropertiesTest ExtensionPropertiesTest.cpp LIBRARIES MagnumVk) @@ -115,6 +116,7 @@ set_target_properties( VkCommandBufferTest VkCommandPoolTest VkDeviceTest + VkDeviceFeaturesTest VkDevicePropertiesTest VkEnumsTest VkExtensionsTest diff --git a/src/Magnum/Vk/Test/DeviceFeaturesTest.cpp b/src/Magnum/Vk/Test/DeviceFeaturesTest.cpp new file mode 100644 index 000000000..886a524a1 --- /dev/null +++ b/src/Magnum/Vk/Test/DeviceFeaturesTest.cpp @@ -0,0 +1,110 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include + +#include "Magnum/Vk/DeviceFeatures.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DeviceFeaturesTest: TestSuite::Tester { + explicit DeviceFeaturesTest(); + + void mapping(); + + void debugFeature(); + void debugFeatures(); +}; + +DeviceFeaturesTest::DeviceFeaturesTest() { + addTests({&DeviceFeaturesTest::mapping, + + &DeviceFeaturesTest::debugFeature, + &DeviceFeaturesTest::debugFeatures}); +} + +void DeviceFeaturesTest::mapping() { + UnsignedInt firstUnhandled = 0xff; + UnsignedInt nextHandled = 0; + for(UnsignedInt i = 0; i <= 0xff; ++i) { + CORRADE_ITERATION(i); + const auto feature = DeviceFeature(i); + /* Each case verifies: + - that the entries are ordered by number by comparing a function to + expected result (so insertion here is done in proper place) + - that there was no gap (unhandled value inside the range) + - that the Debug output is equivalent to the name */ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(feature) { + #define _c(value, field) \ + case DeviceFeature::value: { \ + std::ostringstream out; \ + Debug{&out, Debug::Flag::NoNewlineAtTheEnd} << DeviceFeature::value; \ + CORRADE_COMPARE(out.str(), "Vk::DeviceFeature::" #value); \ + CORRADE_COMPARE(nextHandled, i); \ + CORRADE_COMPARE(firstUnhandled, 0xff); \ + ++nextHandled; \ + continue; \ + } + #define _cver(value, field, suffix, version) _c(value, field) + #define _cext(value, field, suffix, extension) _c(value, field) + #include "Magnum/Vk/Implementation/deviceFeatureMapping.hpp" + #undef _c + #undef _cver + #undef _cext + } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + + /* Not handled by any value, remember -- we might either be at the end + of the enum range (which is okay) or some value might be unhandled + here */ + firstUnhandled = i; + } + + CORRADE_COMPARE(firstUnhandled, 0xff); +} + +void DeviceFeaturesTest::debugFeature() { + std::ostringstream out; + Debug{&out} << DeviceFeature::FullDrawIndexUint32 << DeviceFeature::VulkanMemoryModel << DeviceFeature(0xab); + CORRADE_COMPARE(out.str(), "Vk::DeviceFeature::FullDrawIndexUint32 Vk::DeviceFeature::VulkanMemoryModel Vk::DeviceFeature(0xab)\n"); +} + +void DeviceFeaturesTest::debugFeatures() { + std::ostringstream out; + Debug{&out} << (DeviceFeature::FullDrawIndexUint32|DeviceFeature::VulkanMemoryModel|DeviceFeature(0xab)|DeviceFeature(0xcc)) << DeviceFeatures{}; + CORRADE_COMPARE(out.str(), "Vk::DeviceFeature::FullDrawIndexUint32|Vk::DeviceFeature::VulkanMemoryModel|Vk::DeviceFeature(0xab)|Vk::DeviceFeature(0xcc) Vk::DeviceFeatures{}\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DeviceFeaturesTest) diff --git a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp index e4a04e2ff..01ddfa246 100644 --- a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp +++ b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp @@ -32,6 +32,8 @@ #include #include +#include "Magnum/Math/Functions.h" +#include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/DeviceProperties.h" #include "Magnum/Vk/Extensions.h" #include "Magnum/Vk/ExtensionProperties.h" @@ -63,6 +65,10 @@ struct DevicePropertiesVkTest: VulkanTester { void driverProperties(); + void features(); + void featureExpectedSupported(); + void featureExpectedUnsupported(); + void queueFamilies(); void queueFamiliesOutOfRange(); void queueFamiliesPick(); @@ -111,6 +117,10 @@ DevicePropertiesVkTest::DevicePropertiesVkTest(): VulkanTester{NoCreate} { &DevicePropertiesVkTest::driverProperties, + &DevicePropertiesVkTest::features, + &DevicePropertiesVkTest::featureExpectedSupported, + &DevicePropertiesVkTest::featureExpectedUnsupported, + &DevicePropertiesVkTest::queueFamilies, &DevicePropertiesVkTest::queueFamiliesOutOfRange, &DevicePropertiesVkTest::queueFamiliesPick, @@ -210,6 +220,67 @@ void DevicePropertiesVkTest::driverProperties() { } } +void DevicePropertiesVkTest::features() { + Containers::Optional device = tryPickDevice(instance()); + CORRADE_VERIFY(device); + + std::size_t popcount = 0; + for(std::size_t i = 0; i != DeviceFeatures::Size; ++i) { + popcount += Math::popcount(device->features().data()[i]); + } + + Debug{} << "Available feature count:" << popcount; + CORRADE_VERIFY(popcount); + + /* These (and others) are guaranteed to be always present by the spec, so + verify our sanity with those. If not, then we have something shitty in + our implementation. */ + CORRADE_VERIFY(device->features() & DeviceFeature::RobustBufferAccess); + + /* These are from additional structures, which can be queried only if both + instance and device have 1.1 or if KHR_get_physical_driver_properties2 + is enabled on the instance. */ + if(instance().isVersionSupported(Version::Vk11) || instance().isExtensionEnabled()) { + if(device->isVersionSupported(Version::Vk11)) + CORRADE_VERIFY(device->features() & DeviceFeature::Multiview); + if(device->isVersionSupported(Version::Vk12)) { + CORRADE_VERIFY(device->features() & DeviceFeature::UniformBufferStandardLayout); + CORRADE_VERIFY(device->features() & DeviceFeature::ImagelessFramebuffer); + CORRADE_VERIFY(device->features() & DeviceFeature::SeparateDepthStencilLayouts); + CORRADE_VERIFY(device->features() & DeviceFeature::HostQueryReset); + CORRADE_VERIFY(device->features() & DeviceFeature::TimelineSemaphore); + CORRADE_VERIFY(device->features() & DeviceFeature::ShaderSubgroupExtendedTypes); + } + } +} + +void DevicePropertiesVkTest::featureExpectedSupported() { + Containers::Optional device = tryPickDevice(instance()); + CORRADE_VERIFY(device); + + if((!instance().isVersionSupported(Version::Vk11) || !device->isVersionSupported(Version::Vk11)) && !instance().isExtensionEnabled()) + CORRADE_SKIP("Neither Vulkan 1.1 nor KHR_get_physical_device_properties2 is supported, can't test"); + + if(!device->enumerateExtensionProperties().isSupported()) + CORRADE_SKIP("VK_KHR_sampler_ycbcr_conversion not supported, can't test."); + + CORRADE_VERIFY(device->features() & DeviceFeature::SamplerYcbcrConversion); +} + +void DevicePropertiesVkTest::featureExpectedUnsupported() { + Containers::Optional device = tryPickDevice(instance()); + CORRADE_VERIFY(device); + + if(!((instance().isVersionSupported(Version::Vk11) && device->isVersionSupported(Version::Vk11)) || instance().isExtensionEnabled())) + CORRADE_SKIP("Vulkan 1.1 or KHR_get_physical_device_properties2 not present, can't test."); + + + if(device->enumerateExtensionProperties().isSupported()) + CORRADE_SKIP("VK_EXT_texture_compression_astc_hdr supported, can't test."); + + CORRADE_VERIFY(!(device->features() & DeviceFeature::TextureCompressionAstcHdr)); +} + void DevicePropertiesVkTest::enumerateExtensions() { Containers::Array devices = enumerateDevices(instance()); CORRADE_VERIFY(!devices.empty()); diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 7af86bb02..0fb38f833 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -43,6 +43,8 @@ class CommandPool; class CommandPoolCreateInfo; class Device; class DeviceCreateInfo; +enum class DeviceFeature: UnsignedShort; +typedef Containers::BigEnumSet DeviceFeatures; class DeviceProperties; enum class DeviceType: Int; class Extension;