diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-09-13 03:17:35 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-09-13 03:17:35 +0000 |
| commit | 83acbd6c353255f478164018a357637fb2f11cb5 (patch) | |
| tree | c685b67b63185cd47d397a0d2dc423c9a8032421 /Graphics | |
| parent | Fixed shader error log + fixed tests in Win8.1 (diff) | |
| download | DiligentCore-83acbd6c353255f478164018a357637fb2f11cb5.tar.gz DiligentCore-83acbd6c353255f478164018a357637fb2f11cb5.zip | |
Added option to enable/disable device features during initialization (API 240069)
Diffstat (limited to 'Graphics')
19 files changed, 647 insertions, 503 deletions
diff --git a/Graphics/GLSLTools/include/GLSLSourceBuilder.hpp b/Graphics/GLSLTools/include/GLSLSourceBuilder.hpp index 99710eaf..ffe36a4e 100644 --- a/Graphics/GLSLTools/include/GLSLSourceBuilder.hpp +++ b/Graphics/GLSLTools/include/GLSLSourceBuilder.hpp @@ -28,7 +28,7 @@ #pragma once #include "BasicTypes.h" -#include "DeviceCaps.h" +#include "GraphicsTypes.h" #include "Shader.h" namespace Diligent diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index 1de30eab..b99138ca 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -38,7 +38,6 @@ set(INTERFACE interface/CommandList.h interface/Constants.h interface/DepthStencilState.h - interface/DeviceCaps.h interface/DeviceContext.h interface/DeviceObject.h interface/EngineFactory.h diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 713faca8..7d297e0c 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240068 +#define DILIGENT_API_VERSION 240069 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/DeviceCaps.h b/Graphics/GraphicsEngine/interface/DeviceCaps.h deleted file mode 100644 index b5bb866a..00000000 --- a/Graphics/GraphicsEngine/interface/DeviceCaps.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2019-2020 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -// clang-format off - -/// \file -/// Definition of the device capabilities - -#include "GraphicsTypes.h" - -DILIGENT_BEGIN_NAMESPACE(Diligent) - -/// Device type -enum RENDER_DEVICE_TYPE -{ - RENDER_DEVICE_TYPE_UNDEFINED = 0, ///< Undefined device - RENDER_DEVICE_TYPE_D3D11, ///< D3D11 device - RENDER_DEVICE_TYPE_D3D12, ///< D3D12 device - RENDER_DEVICE_TYPE_GL, ///< OpenGL device - RENDER_DEVICE_TYPE_GLES, ///< OpenGLES device - RENDER_DEVICE_TYPE_VULKAN, ///< Vulkan device - RENDER_DEVICE_TYPE_METAL ///< Metal device (not yet implemented) -}; - -/// Texture sampler capabilities -struct SamplerCaps -{ - /// Indicates if device supports border texture addressing mode - Bool BorderSamplingModeSupported DEFAULT_INITIALIZER(False); - - /// Indicates if device supports anisotrpoic filtering - Bool AnisotropicFilteringSupported DEFAULT_INITIALIZER(False); - - /// Indicates if device supports MIP load bias - Bool LODBiasSupported DEFAULT_INITIALIZER(False); -}; -typedef struct SamplerCaps SamplerCaps; - -/// Texture capabilities -struct TextureCaps -{ - /// Maximum dimension (width) of a 1D texture, or 0 if 1D textures are not supported. - Uint32 MaxTexture1DDimension DEFAULT_INITIALIZER(0); - - /// Maximum number of slices in a 1D texture array, or 0 if 1D texture arrays are not supported. - Uint32 MaxTexture1DArraySlices DEFAULT_INITIALIZER(0); - - /// Maximum dimension (width or height) of a 2D texture. - Uint32 MaxTexture2DDimension DEFAULT_INITIALIZER(0); - - /// Maximum number of slices in a 2D texture array, or 0 if 2D texture arrays are not supported. - Uint32 MaxTexture2DArraySlices DEFAULT_INITIALIZER(0); - - /// Maximum dimension (width, height, or depth) of a 3D texture, or 0 if 3D textures are not supported. - Uint32 MaxTexture3DDimension DEFAULT_INITIALIZER(0); - - /// Maximum dimension (width or height) of a cubemap face, or 0 if cubemap textures are not supported. - Uint32 MaxTextureCubeDimension DEFAULT_INITIALIZER(0); - - /// Indicates if device supports 2D multisampled textures - Bool Texture2DMSSupported DEFAULT_INITIALIZER(False); - - /// Indicates if device supports 2D multisampled texture arrays - Bool Texture2DMSArraySupported DEFAULT_INITIALIZER(False); - - /// Indicates if device supports texture views - Bool TextureViewSupported DEFAULT_INITIALIZER(False); - - /// Indicates if device supports cubemap arrays - Bool CubemapArraysSupported DEFAULT_INITIALIZER(False); -}; -typedef struct TextureCaps TextureCaps; - -/// Describes supported device features -struct DeviceFeatures -{ - /// Indicates if device supports separable programs - Bool SeparablePrograms DEFAULT_INITIALIZER(False); - - /// Indicates if device supports indirect draw commands - Bool IndirectRendering DEFAULT_INITIALIZER(False); - - /// Indicates if device supports wireframe fill mode - Bool WireframeFill DEFAULT_INITIALIZER(False); - - /// Indicates if device supports multithreaded resource creation - Bool MultithreadedResourceCreation DEFAULT_INITIALIZER(False); - - /// Indicates if device supports compute shaders - Bool ComputeShaders DEFAULT_INITIALIZER(False); - - /// Indicates if device supports geometry shaders - Bool GeometryShaders DEFAULT_INITIALIZER(False); - - /// Indicates if device supports tessellation - Bool Tessellation DEFAULT_INITIALIZER(False); - - /// Indicates if device supports mesh and amplification shaders - Bool MeshShaders DEFAULT_INITIALIZER(False); - - /// Indicates if device supports bindless resources - Bool BindlessResources DEFAULT_INITIALIZER(False); - - /// Indicates if device supports occlusion queries (see Diligent::QUERY_TYPE_OCCLUSION). - Bool OcclusionQueries DEFAULT_INITIALIZER(False); - - /// Indicates if device supports binary occlusion queries (see Diligent::QUERY_TYPE_BINARY_OCCLUSION). - Bool BinaryOcclusionQueries DEFAULT_INITIALIZER(False); - - /// Indicates if device supports timestamp queries (see Diligent::QUERY_TYPE_TIMESTAMP). - Bool TimestampQueries DEFAULT_INITIALIZER(False); - - /// Indicates if device supports pipeline statistics queries (see Diligent::QUERY_TYPE_PIPELINE_STATISTICS). - Bool PipelineStatisticsQueries DEFAULT_INITIALIZER(False); - - /// Indicates if device supports duration queries (see Diligent::QUERY_TYPE_DURATION). - Bool DurationQueries DEFAULT_INITIALIZER(False); - - /// Indicates if device supports depth bias clamping - Bool DepthBiasClamp DEFAULT_INITIALIZER(False); - - /// Indicates if device supports depth clamping - Bool DepthClamp DEFAULT_INITIALIZER(False); - - /// Indicates if device supports depth clamping - Bool IndependentBlend DEFAULT_INITIALIZER(False); - - /// Indicates if device supports dual-source blend - Bool DualSourceBlend DEFAULT_INITIALIZER(False); - - /// Indicates if device supports multiviewport - Bool MultiViewport DEFAULT_INITIALIZER(False); - - /// Indicates if device supports all BC-compressed formats - Bool TextureCompressionBC DEFAULT_INITIALIZER(False); - - /// Indicates if device supports writes to UAVs as well as atomic operations in vertex, - /// tessellation, and geometry shader stages. - Bool VertexPipelineUAVWritesAndAtomics DEFAULT_INITIALIZER(False); - - /// Indicates if device supports writes to UAVs as well as atomic operations in pixel - /// shader stage. - Bool PixelUAVWritesAndAtomics DEFAULT_INITIALIZER(False); - - /// Specifies whether all the extended UAV texture formats are available in shader code. - Bool TextureUAVExtendedFormats DEFAULT_INITIALIZER(False); -}; -typedef struct DeviceFeatures DeviceFeatures; - -/// Device capabilities -struct DeviceCaps -{ - /// Device type. See Diligent::DeviceType. - enum RENDER_DEVICE_TYPE DevType DEFAULT_INITIALIZER(RENDER_DEVICE_TYPE_UNDEFINED); - - /// Major revision of the graphics API supported by the graphics adapter. - /// Note that this value indicates the maximum supported feature level, so, - /// for example, if the device type is D3D11, this value will be 10 when - /// the maximum supported Direct3D feature level of the graphics adapter is 10.0. - Int32 MajorVersion DEFAULT_INITIALIZER(0); - - /// Minor revision of the graphics API supported by the graphics adapter. - /// Similar to MajorVersion, this value indicates the maximum supported feature level. - Int32 MinorVersion DEFAULT_INITIALIZER(0); - - /// Adapter type. See Diligent::ADAPTER_TYPE. - ADAPTER_TYPE AdaterType DEFAULT_INITIALIZER(ADAPTER_TYPE_UNKNOWN); - - /// Texture sampling capabilities. See Diligent::SamplerCaps. - SamplerCaps SamCaps; - - /// Texture capabilities. See Diligent::TextureCaps. - TextureCaps TexCaps; - - /// Device features. See Diligent::DeviceFeatures. - DeviceFeatures Features; - -#if DILIGENT_CPP_INTERFACE - bool IsGLDevice()const - { - return DevType == RENDER_DEVICE_TYPE_GL || DevType == RENDER_DEVICE_TYPE_GLES; - } - bool IsD3DDevice()const - { - return DevType == RENDER_DEVICE_TYPE_D3D11 || DevType == RENDER_DEVICE_TYPE_D3D12; - } - bool IsVulkanDevice()const - { - return DevType == RENDER_DEVICE_TYPE_VULKAN; - } - - struct NDCAttribs - { - const float MinZ; // Minimum z value of normalized device coordinate space - const float ZtoDepthScale; // NDC z to depth scale - const float YtoVScale; // Scale to transform NDC y coordinate to texture V coordinate - - float GetZtoDepthBias() const - { - // Returns ZtoDepthBias such that given NDC z coordinate, depth value can be - // computed as follows: - // d = z * ZtoDepthScale + ZtoDepthBias - return -MinZ * ZtoDepthScale; - } - }; - - const NDCAttribs& GetNDCAttribs()const - { - if (IsVulkanDevice()) - { - // Note that Vulkan itself does not invert Y coordinate when transforming - // normalized device Y to window space. However, we use negative viewport - // height which achieves the same effect as in D3D, thererfore we need to - // invert y (see comments in DeviceContextVkImpl::CommitViewports() for details) - static constexpr const NDCAttribs NDCAttribsVk {0.0f, 1.0f, -0.5f}; - return NDCAttribsVk; - } - else if (IsD3DDevice()) - { - static constexpr const NDCAttribs NDCAttribsD3D {0.0f, 1.0f, -0.5f}; - return NDCAttribsD3D; - } - else if (IsGLDevice()) - { - static constexpr const NDCAttribs NDCAttribsGL {-1.0f, 0.5f, 0.5f}; - return NDCAttribsGL; - } - else - { - static constexpr const NDCAttribs NDCAttribsDefault {0.0f, 1.0f, 0.5f}; - return NDCAttribsDefault; - } - } -#endif -}; -typedef struct DeviceCaps DeviceCaps; - -DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 272c2cd5..6320f947 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -34,7 +34,7 @@ #include "../../../Primitives/interface/Object.h" #include "../../../Primitives/interface/FlagEnum.h" -#include "DeviceCaps.h" +#include "GraphicsTypes.h" #include "Constants.h" #include "Buffer.h" #include "InputLayout.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 323a3fd1..c8514a65 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1453,6 +1453,297 @@ enum QUERY_TYPE }; + +/// Device type +enum RENDER_DEVICE_TYPE +{ + RENDER_DEVICE_TYPE_UNDEFINED = 0, ///< Undefined device + RENDER_DEVICE_TYPE_D3D11, ///< D3D11 device + RENDER_DEVICE_TYPE_D3D12, ///< D3D12 device + RENDER_DEVICE_TYPE_GL, ///< OpenGL device + RENDER_DEVICE_TYPE_GLES, ///< OpenGLES device + RENDER_DEVICE_TYPE_VULKAN, ///< Vulkan device + RENDER_DEVICE_TYPE_METAL ///< Metal device (not yet implemented) +}; + + +/// Texture sampler capabilities +struct SamplerCaps +{ + /// Indicates if device supports border texture addressing mode + Bool BorderSamplingModeSupported DEFAULT_INITIALIZER(False); + + /// Indicates if device supports anisotrpoic filtering + Bool AnisotropicFilteringSupported DEFAULT_INITIALIZER(False); + + /// Indicates if device supports MIP load bias + Bool LODBiasSupported DEFAULT_INITIALIZER(False); +}; +typedef struct SamplerCaps SamplerCaps; + + +/// Texture capabilities +struct TextureCaps +{ + /// Maximum dimension (width) of a 1D texture, or 0 if 1D textures are not supported. + Uint32 MaxTexture1DDimension DEFAULT_INITIALIZER(0); + + /// Maximum number of slices in a 1D texture array, or 0 if 1D texture arrays are not supported. + Uint32 MaxTexture1DArraySlices DEFAULT_INITIALIZER(0); + + /// Maximum dimension (width or height) of a 2D texture. + Uint32 MaxTexture2DDimension DEFAULT_INITIALIZER(0); + + /// Maximum number of slices in a 2D texture array, or 0 if 2D texture arrays are not supported. + Uint32 MaxTexture2DArraySlices DEFAULT_INITIALIZER(0); + + /// Maximum dimension (width, height, or depth) of a 3D texture, or 0 if 3D textures are not supported. + Uint32 MaxTexture3DDimension DEFAULT_INITIALIZER(0); + + /// Maximum dimension (width or height) of a cubemap face, or 0 if cubemap textures are not supported. + Uint32 MaxTextureCubeDimension DEFAULT_INITIALIZER(0); + + /// Indicates if device supports 2D multisampled textures + Bool Texture2DMSSupported DEFAULT_INITIALIZER(False); + + /// Indicates if device supports 2D multisampled texture arrays + Bool Texture2DMSArraySupported DEFAULT_INITIALIZER(False); + + /// Indicates if device supports texture views + Bool TextureViewSupported DEFAULT_INITIALIZER(False); + + /// Indicates if device supports cubemap arrays + Bool CubemapArraysSupported DEFAULT_INITIALIZER(False); +}; +typedef struct TextureCaps TextureCaps; + + +/// Device feature state +DILIGENT_TYPED_ENUM(DEVICE_FEATURE_STATE, Uint8) +{ + /// Device feature is disabled. + DEVICE_FEATURE_STATE_DISABLED = 0, + + /// Device feature is enabled. + + /// If a feature is requested to be enabled during the initialization through + /// EngineCreateInfo::Feautures, but is not supported by the device/driver/platform, + /// the engine will fail to initialize. + DEVICE_FEATURE_STATE_ENABLED = 1, + + /// Device feature is optional. + + /// During the initialization the engine will attempt to enable the feature. + /// If the feature is not supported by the device/driver/platform, + /// the engine will successfully be initialized, but the feature will be disabled. + /// The actual feature state can be queried from DeviceCaps structure. + DEVICE_FEATURE_STATE_OPTIONAL = 2 +}; + + +/// Describes the device features +struct DeviceFeatures +{ + /// Indicates if device supports separable programs + DEVICE_FEATURE_STATE SeparablePrograms DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports indirect draw commands + DEVICE_FEATURE_STATE IndirectRendering DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports wireframe fill mode + DEVICE_FEATURE_STATE WireframeFill DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports multithreaded resource creation + DEVICE_FEATURE_STATE MultithreadedResourceCreation DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports compute shaders + DEVICE_FEATURE_STATE ComputeShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports geometry shaders + DEVICE_FEATURE_STATE GeometryShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports tessellation + DEVICE_FEATURE_STATE Tessellation DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports mesh and amplification shaders + DEVICE_FEATURE_STATE MeshShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports bindless resources + DEVICE_FEATURE_STATE BindlessResources DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports occlusion queries (see Diligent::QUERY_TYPE_OCCLUSION). + DEVICE_FEATURE_STATE OcclusionQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports binary occlusion queries (see Diligent::QUERY_TYPE_BINARY_OCCLUSION). + DEVICE_FEATURE_STATE BinaryOcclusionQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports timestamp queries (see Diligent::QUERY_TYPE_TIMESTAMP). + DEVICE_FEATURE_STATE TimestampQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports pipeline statistics queries (see Diligent::QUERY_TYPE_PIPELINE_STATISTICS). + DEVICE_FEATURE_STATE PipelineStatisticsQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports duration queries (see Diligent::QUERY_TYPE_DURATION). + DEVICE_FEATURE_STATE DurationQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports depth bias clamping + DEVICE_FEATURE_STATE DepthBiasClamp DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports depth clamping + DEVICE_FEATURE_STATE DepthClamp DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports depth clamping + DEVICE_FEATURE_STATE IndependentBlend DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports dual-source blend + DEVICE_FEATURE_STATE DualSourceBlend DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports multiviewport + DEVICE_FEATURE_STATE MultiViewport DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports all BC-compressed formats + DEVICE_FEATURE_STATE TextureCompressionBC DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports writes to UAVs as well as atomic operations in vertex, + /// tessellation, and geometry shader stages. + DEVICE_FEATURE_STATE VertexPipelineUAVWritesAndAtomics DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports writes to UAVs as well as atomic operations in pixel + /// shader stage. + DEVICE_FEATURE_STATE PixelUAVWritesAndAtomics DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Specifies whether all the extended UAV texture formats are available in shader code. + DEVICE_FEATURE_STATE TextureUAVExtendedFormats DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + +#if DILIGENT_CPP_INTERFACE + DeviceFeatures() noexcept {} + + explicit DeviceFeatures(DEVICE_FEATURE_STATE State) noexcept : + SeparablePrograms {State}, + IndirectRendering {State}, + WireframeFill {State}, + MultithreadedResourceCreation {State}, + ComputeShaders {State}, + GeometryShaders {State}, + Tessellation {State}, + MeshShaders {State}, + BindlessResources {State}, + OcclusionQueries {State}, + BinaryOcclusionQueries {State}, + TimestampQueries {State}, + PipelineStatisticsQueries {State}, + DurationQueries {State}, + DepthBiasClamp {State}, + DepthClamp {State}, + IndependentBlend {State}, + DualSourceBlend {State}, + MultiViewport {State}, + TextureCompressionBC {State}, + VertexPipelineUAVWritesAndAtomics {State}, + PixelUAVWritesAndAtomics {State}, + TextureUAVExtendedFormats {State} + { +# if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(*this) == 23, "Did you add a new feature to DeviceFeatures? Please handle its satus above."); +# endif + } +#endif +}; +typedef struct DeviceFeatures DeviceFeatures; + + +/// Device capabilities +struct DeviceCaps +{ + /// Device type. See Diligent::DeviceType. + enum RENDER_DEVICE_TYPE DevType DEFAULT_INITIALIZER(RENDER_DEVICE_TYPE_UNDEFINED); + + /// Major revision of the graphics API supported by the graphics adapter. + /// Note that this value indicates the maximum supported feature level, so, + /// for example, if the device type is D3D11, this value will be 10 when + /// the maximum supported Direct3D feature level of the graphics adapter is 10.0. + Int32 MajorVersion DEFAULT_INITIALIZER(0); + + /// Minor revision of the graphics API supported by the graphics adapter. + /// Similar to MajorVersion, this value indicates the maximum supported feature level. + Int32 MinorVersion DEFAULT_INITIALIZER(0); + + /// Adapter type. See Diligent::ADAPTER_TYPE. + ADAPTER_TYPE AdaterType DEFAULT_INITIALIZER(ADAPTER_TYPE_UNKNOWN); + + /// Texture sampling capabilities. See Diligent::SamplerCaps. + SamplerCaps SamCaps; + + /// Texture capabilities. See Diligent::TextureCaps. + TextureCaps TexCaps; + + /// Device features. See Diligent::DeviceFeatures. + + /// \note For optional features requested during the initialization, the + /// struct will indicate the actual feature state (enabled or disabled). + DeviceFeatures Features; + +#if DILIGENT_CPP_INTERFACE + bool IsGLDevice()const + { + return DevType == RENDER_DEVICE_TYPE_GL || DevType == RENDER_DEVICE_TYPE_GLES; + } + bool IsD3DDevice()const + { + return DevType == RENDER_DEVICE_TYPE_D3D11 || DevType == RENDER_DEVICE_TYPE_D3D12; + } + bool IsVulkanDevice()const + { + return DevType == RENDER_DEVICE_TYPE_VULKAN; + } + + struct NDCAttribs + { + const float MinZ; // Minimum z value of normalized device coordinate space + const float ZtoDepthScale; // NDC z to depth scale + const float YtoVScale; // Scale to transform NDC y coordinate to texture V coordinate + + float GetZtoDepthBias() const + { + // Returns ZtoDepthBias such that given NDC z coordinate, depth value can be + // computed as follows: + // d = z * ZtoDepthScale + ZtoDepthBias + return -MinZ * ZtoDepthScale; + } + }; + + const NDCAttribs& GetNDCAttribs()const + { + if (IsVulkanDevice()) + { + // Note that Vulkan itself does not invert Y coordinate when transforming + // normalized device Y to window space. However, we use negative viewport + // height which achieves the same effect as in D3D, thererfore we need to + // invert y (see comments in DeviceContextVkImpl::CommitViewports() for details) + static constexpr const NDCAttribs NDCAttribsVk {0.0f, 1.0f, -0.5f}; + return NDCAttribsVk; + } + else if (IsD3DDevice()) + { + static constexpr const NDCAttribs NDCAttribsD3D {0.0f, 1.0f, -0.5f}; + return NDCAttribsD3D; + } + else if (IsGLDevice()) + { + static constexpr const NDCAttribs NDCAttribsGL {-1.0f, 0.5f, 0.5f}; + return NDCAttribsGL; + } + else + { + static constexpr const NDCAttribs NDCAttribsDefault {0.0f, 1.0f, 0.5f}; + return NDCAttribsDefault; + } + } +#endif +}; +typedef struct DeviceCaps DeviceCaps; + + /// Engine creation attibutes struct EngineCreateInfo { @@ -1472,6 +1763,17 @@ struct EngineCreateInfo /// Pointer to the user-specified debug message callback function DebugMessageCallbackType DebugMessageCallback DEFAULT_INITIALIZER(nullptr); + + /// Requested device features. + + /// \remarks If a feature is requested to be enabled, but is not supported + /// by the device/driver/platform, the engine will fail to initialize. + /// + /// If a feature is requested to be optioanl, the engine will attempt to enable the feature. + /// If the feature is not supported by the device/driver/platform, + /// the engine will successfully be initialized, but the feature will be disabled. + /// The actual feature state can be queried from DeviceCaps structure. + DeviceFeatures Features; }; typedef struct EngineCreateInfo EngineCreateInfo; diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index ddbc75b2..0cea79eb 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -33,7 +33,6 @@ #include "../../../Primitives/interface/Object.h" #include "EngineFactory.h" #include "GraphicsTypes.h" -#include "DeviceCaps.h" #include "Constants.h" #include "Buffer.h" #include "InputLayout.h" diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index 55c2e0ba..d0d16ad9 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -30,7 +30,7 @@ #include "Buffer.h" #include "BufferView.h" #include "DepthStencilState.h" -#include "DeviceCaps.h" +#include "GraphicsTypes.h" #include "DeviceContext.h" #include "InputLayout.h" #include "PipelineState.h" diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp index f041806c..8003615e 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -48,7 +48,7 @@ public: IEngineFactory* pEngineFactory, const EngineD3D11CreateInfo& EngineAttribs, ID3D11Device* pd3d11Device, - Uint32 NumDeferredContexts); + Uint32 NumDeferredContexts) noexcept(false); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; /// Implementation of IRenderDevice::CreateBuffer() in Direct3D11 backend. diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index c8c26d80..d5671816 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -143,12 +143,25 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo } } +#define UNSUPPORTED_FEATURE(Feature, Name) \ + do \ + { \ + if (EngineAttribs.Features.Feature == DEVICE_FEATURE_STATE_ENABLED) \ + LOG_ERROR_AND_THROW(Name " not supported by Direct3D11 device"); \ + m_DeviceCaps.Features.Feature = DEVICE_FEATURE_STATE_DISABLED; \ + } while (false) + // Direct3D11 only supports shader model 5.0 even if the device feature level is // above 11.0 (for example, 11.1 or 12.0), so bindless resources are never available. // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro#overview-for-each-feature-level - m_DeviceCaps.Features.BindlessResources = False; - - m_DeviceCaps.Features.VertexPipelineUAVWritesAndAtomics = False; + UNSUPPORTED_FEATURE(BindlessResources, "Bindless resources are"); + UNSUPPORTED_FEATURE(VertexPipelineUAVWritesAndAtomics, "Vertex pipeline UAV writes and atomics are"); + UNSUPPORTED_FEATURE(MeshShaders, "Mesh shaders are"); +#undef UNSUPPORTED_FEATURE + +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(DeviceFeatures) == 23, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); +#endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 710db2ef..5c077497 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -57,7 +57,7 @@ public: const EngineD3D12CreateInfo& EngineCI, ID3D12Device* pD3D12Device, size_t CommandQueueCount, - ICommandQueueD3D12** ppCmdQueues); + ICommandQueueD3D12** ppCmdQueues) noexcept(false); ~RenderDeviceD3D12Impl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 76e8aa07..b91ac760 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -154,113 +154,141 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo m_pDxCompiler {CreateDXCompiler(DXCompilerTarget::Direct3D12, EngineCI.pDxCompilerPath)} // clang-format on { - m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_D3D12; - auto FeatureLevel = GetD3DFeatureLevel(); - switch (FeatureLevel) + try { - case D3D_FEATURE_LEVEL_12_0: - case D3D_FEATURE_LEVEL_12_1: - m_DeviceCaps.MajorVersion = 12; - m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_12_1 ? 1 : 0; - break; - - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_11_1: - m_DeviceCaps.MajorVersion = 11; - m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_11_1 ? 1 : 0; - break; - - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_10_1: - m_DeviceCaps.MajorVersion = 10; - m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_10_1 ? 1 : 0; - break; - - default: - UNEXPECTED("Unexpected D3D feature level"); - } + m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_D3D12; + auto FeatureLevel = GetD3DFeatureLevel(); + switch (FeatureLevel) + { + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: + m_DeviceCaps.MajorVersion = 12; + m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_12_1 ? 1 : 0; + break; - if (auto pDXGIAdapter1 = DXGIAdapterFromD3D12Device(pd3d12Device)) - { - DXGI_ADAPTER_DESC1 AdapterDesc = {}; + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_11_1: + m_DeviceCaps.MajorVersion = 11; + m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_11_1 ? 1 : 0; + break; - auto hr = pDXGIAdapter1->GetDesc1(&AdapterDesc); - if (SUCCEEDED(hr)) - { - m_DeviceCaps.AdaterType = (AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? ADAPTER_TYPE_SOFTWARE : ADAPTER_TYPE_HARDWARE; - } - else - { - LOG_ERROR_MESSAGE("Failed to get DXGIDevice adapter desc. Adapter type will be unknown."); + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_10_1: + m_DeviceCaps.MajorVersion = 10; + m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_10_1 ? 1 : 0; + break; + + default: + UNEXPECTED("Unexpected D3D feature level"); } - } - // Direct3D12 supports shader model 5.1 on all feature levels (even on 11.0), - // so bindless resources are always available. - // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support - m_DeviceCaps.Features.BindlessResources = True; + if (auto pDXGIAdapter1 = DXGIAdapterFromD3D12Device(pd3d12Device)) + { + DXGI_ADAPTER_DESC1 AdapterDesc = {}; - m_DeviceCaps.Features.VertexPipelineUAVWritesAndAtomics = True; + auto hr = pDXGIAdapter1->GetDesc1(&AdapterDesc); + if (SUCCEEDED(hr)) + { + m_DeviceCaps.AdaterType = (AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? ADAPTER_TYPE_SOFTWARE : ADAPTER_TYPE_HARDWARE; + } + else + { + LOG_ERROR_MESSAGE("Failed to get DXGIDevice adapter desc. Adapter type will be unknown."); + } + } - // Detect maximum shader model. - { - // Direct3D12 supports shader model 5.1 on all feature levels. + // Direct3D12 supports shader model 5.1 on all feature levels (even on 11.0), + // so bindless resources are always available. // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support - m_MaxShaderModel = D3D_SHADER_MODEL_5_1; + m_DeviceCaps.Features.BindlessResources = DEVICE_FEATURE_STATE_ENABLED; - // Header may not have constants for D3D_SHADER_MODEL_6_1 and above. - const D3D_SHADER_MODEL Models[] = // - { - static_cast<D3D_SHADER_MODEL>(0x65), // minimum required for mesh shader - static_cast<D3D_SHADER_MODEL>(0x64), - static_cast<D3D_SHADER_MODEL>(0x63), - static_cast<D3D_SHADER_MODEL>(0x62), - static_cast<D3D_SHADER_MODEL>(0x61), - D3D_SHADER_MODEL_6_0 // - }; - - for (auto Model : Models) + m_DeviceCaps.Features.VertexPipelineUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; + + // Detect maximum shader model. { - D3D12_FEATURE_DATA_SHADER_MODEL ShaderModel = {Model}; - if (SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &ShaderModel, sizeof(ShaderModel)))) + // Direct3D12 supports shader model 5.1 on all feature levels. + // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support + m_MaxShaderModel = D3D_SHADER_MODEL_5_1; + + // Header may not have constants for D3D_SHADER_MODEL_6_1 and above. + const D3D_SHADER_MODEL Models[] = // + { + static_cast<D3D_SHADER_MODEL>(0x65), // minimum required for mesh shader + static_cast<D3D_SHADER_MODEL>(0x64), + static_cast<D3D_SHADER_MODEL>(0x63), + static_cast<D3D_SHADER_MODEL>(0x62), + static_cast<D3D_SHADER_MODEL>(0x61), + D3D_SHADER_MODEL_6_0 // + }; + + for (auto Model : Models) { - m_MaxShaderModel = ShaderModel.HighestShaderModel; - break; + D3D12_FEATURE_DATA_SHADER_MODEL ShaderModel = {Model}; + if (SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &ShaderModel, sizeof(ShaderModel)))) + { + m_MaxShaderModel = ShaderModel.HighestShaderModel; + break; + } } + LOG_INFO_MESSAGE("Max device shader model: ", (m_MaxShaderModel >> 4) & 0xF, '_', m_MaxShaderModel & 0xF); } - } - // Check if mesh shader is supported. + // Check if mesh shader is supported. + bool MeshShadersSupported = false; #ifdef D3D12_H_HAS_MESH_SHADER - { - D3D12_FEATURE_DATA_D3D12_OPTIONS7 FeatureData = {}; + { + D3D12_FEATURE_DATA_D3D12_OPTIONS7 FeatureData = {}; - bool SupportsMeshShader = - SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &FeatureData, sizeof(FeatureData))) && - FeatureData.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; + MeshShadersSupported = + SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &FeatureData, sizeof(FeatureData))) && + FeatureData.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; - m_DeviceCaps.Features.MeshShaders = (m_MaxShaderModel >= D3D_SHADER_MODEL_6_5 && SupportsMeshShader); - } + MeshShadersSupported = (m_MaxShaderModel >= D3D_SHADER_MODEL_6_5 && MeshShadersSupported); + } +#else + if (EngineCI.Features.MeshShaders == DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_AND_THROW("Mesh shaders are requested to be enabled, but the engine was built with the Windows SDK that does " + "not support the feature. Please update the SDK to version 10.0.19041.0 or later and rebuild the engine."); + } #endif - auto& TexCaps = m_DeviceCaps.TexCaps; + if (EngineCI.Features.MeshShaders == DEVICE_FEATURE_STATE_ENABLED && !MeshShadersSupported) + { + LOG_ERROR_AND_THROW("This device/driver does not support mesh shaders. Please make sure that you have compatible GPU and that your " + "Winodws is up to date (version 2004 or later is required)"); + } + + m_DeviceCaps.Features.MeshShaders = MeshShadersSupported ? DEVICE_FEATURE_STATE_ENABLED : DEVICE_FEATURE_STATE_DISABLED; + +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(DeviceFeatures) == 23, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); +#endif - TexCaps.MaxTexture1DDimension = D3D12_REQ_TEXTURE1D_U_DIMENSION; - TexCaps.MaxTexture1DArraySlices = D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION; - TexCaps.MaxTexture2DDimension = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; - TexCaps.MaxTexture2DArraySlices = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - TexCaps.MaxTexture3DDimension = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - TexCaps.MaxTextureCubeDimension = D3D12_REQ_TEXTURECUBE_DIMENSION; - TexCaps.Texture2DMSSupported = True; - TexCaps.Texture2DMSArraySupported = True; - TexCaps.TextureViewSupported = True; - TexCaps.CubemapArraysSupported = True; + auto& TexCaps = m_DeviceCaps.TexCaps; - auto& SamCaps = m_DeviceCaps.SamCaps; + TexCaps.MaxTexture1DDimension = D3D12_REQ_TEXTURE1D_U_DIMENSION; + TexCaps.MaxTexture1DArraySlices = D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION; + TexCaps.MaxTexture2DDimension = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; + TexCaps.MaxTexture2DArraySlices = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + TexCaps.MaxTexture3DDimension = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + TexCaps.MaxTextureCubeDimension = D3D12_REQ_TEXTURECUBE_DIMENSION; + TexCaps.Texture2DMSSupported = True; + TexCaps.Texture2DMSArraySupported = True; + TexCaps.TextureViewSupported = True; + TexCaps.CubemapArraysSupported = True; - SamCaps.BorderSamplingModeSupported = True; - SamCaps.AnisotropicFilteringSupported = True; - SamCaps.LODBiasSupported = True; + auto& SamCaps = m_DeviceCaps.SamCaps; + + SamCaps.BorderSamplingModeSupported = True; + SamCaps.AnisotropicFilteringSupported = True; + SamCaps.LODBiasSupported = True; + } + catch (...) + { + m_DynamicMemoryManager.Destroy(); + throw; + } } RenderDeviceD3D12Impl::~RenderDeviceD3D12Impl() diff --git a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp index fc73814d..61e5fb12 100644 --- a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp @@ -157,26 +157,26 @@ public: auto& Features = this->m_DeviceCaps.Features; - Features.SeparablePrograms = True; - Features.IndirectRendering = True; - Features.WireframeFill = True; - Features.MultithreadedResourceCreation = True; - Features.ComputeShaders = True; - Features.GeometryShaders = True; - Features.Tessellation = True; - Features.OcclusionQueries = True; - Features.BinaryOcclusionQueries = True; - Features.TimestampQueries = True; - Features.PipelineStatisticsQueries = True; - Features.DurationQueries = True; - Features.DepthBiasClamp = True; - Features.DepthClamp = True; - Features.IndependentBlend = True; - Features.DualSourceBlend = True; - Features.MultiViewport = True; - Features.TextureCompressionBC = True; - Features.PixelUAVWritesAndAtomics = True; - Features.TextureUAVExtendedFormats = True; + Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; + Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED; + Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED; + Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED; + Features.GeometryShaders = DEVICE_FEATURE_STATE_ENABLED; + Features.Tessellation = DEVICE_FEATURE_STATE_ENABLED; + Features.OcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.BinaryOcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.TimestampQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.PipelineStatisticsQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.DepthBiasClamp = DEVICE_FEATURE_STATE_ENABLED; + Features.DepthClamp = DEVICE_FEATURE_STATE_ENABLED; + Features.IndependentBlend = DEVICE_FEATURE_STATE_ENABLED; + Features.DualSourceBlend = DEVICE_FEATURE_STATE_ENABLED; + Features.MultiViewport = DEVICE_FEATURE_STATE_ENABLED; + Features.TextureCompressionBC = DEVICE_FEATURE_STATE_ENABLED; + Features.PixelUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; + Features.TextureUAVExtendedFormats = DEVICE_FEATURE_STATE_ENABLED; } }; diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp index dbdb51c8..1dcb37d4 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp @@ -63,7 +63,7 @@ public: IMemoryAllocator& RawMemAllocator, IEngineFactory* pEngineFactory, const EngineGLCreateInfo& InitAttribs, - const SwapChainDesc* pSCDesc = nullptr); + const SwapChainDesc* pSCDesc = nullptr) noexcept(false); ~RenderDeviceGLImpl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override; @@ -188,7 +188,6 @@ private: virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; bool CheckExtension(const Char* ExtensionString); void FlagSupportedTexFormats(); - void QueryDeviceCaps(); }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp index 4d4b2916..524250d6 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp @@ -28,7 +28,7 @@ #include "pch.h" #include "GLContextWindows.hpp" -#include "DeviceCaps.h" +#include "GraphicsTypes.h" #include "GLTypeConversions.hpp" #include "GraphicsAccessories.hpp" diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 6d0948ae..0ae5204c 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -98,7 +98,6 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, } FlagSupportedTexFormats(); - QueryDeviceCaps(); std::basic_string<GLubyte> glstrVendor = glGetString(GL_VENDOR); std::string Vendor = StrToLower(std::string(glstrVendor.begin(), glstrVendor.end())); @@ -139,7 +138,49 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &MaxLayers); CHECK_GL_ERROR("Failed to get maximum number of texture array layers"); - Features.VertexPipelineUAVWritesAndAtomics = False; +#define SET_FEATURE_STATE(Feature, IsSupported, FeatureName) \ + do \ + { \ + switch (InitAttribs.Features.Feature) \ + { \ + case DEVICE_FEATURE_STATE_ENABLED: \ + { \ + if (!(IsSupported)) \ + LOG_ERROR_AND_THROW(FeatureName, " not supported by this device"); \ + else \ + Features.Feature = DEVICE_FEATURE_STATE_ENABLED; \ + } \ + break; \ + case DEVICE_FEATURE_STATE_DISABLED: \ + case DEVICE_FEATURE_STATE_OPTIONAL: \ + Features.Feature = (IsSupported) ? \ + DEVICE_FEATURE_STATE_ENABLED : \ + DEVICE_FEATURE_STATE_DISABLED; \ + break; \ + default: UNEXPECTED("Unexpected feature state"); \ + } \ + } while (false) + + SET_FEATURE_STATE(VertexPipelineUAVWritesAndAtomics, false, "Vertex pipeline UAV writes and atomics are"); + SET_FEATURE_STATE(MeshShaders, false, "Mesh shaders are"); + + { + bool WireframeFillSupported = (glPolygonMode != nullptr); + if (WireframeFillSupported) + { + // Test glPolygonMode() function to check if it fails + // (It does fail on NVidia Shield tablet, but works fine + // on Intel hw) + VERIFY(glGetError() == GL_NO_ERROR, "Unhandled gl error encountered"); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (glGetError() != GL_NO_ERROR) + WireframeFillSupported = false; + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + if (glGetError() != GL_NO_ERROR) + WireframeFillSupported = false; + } + SET_FEATURE_STATE(WireframeFill, WireframeFillSupported, "Wireframe fill is"); + } if (m_DeviceCaps.DevType == RENDER_DEVICE_TYPE_GL) { @@ -148,27 +189,30 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, const bool IsGL42OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 2); const bool IsGL41OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 1); - Features.SeparablePrograms = True; - Features.IndirectRendering = True; - Features.WireframeFill = True; - Features.MultithreadedResourceCreation = False; - Features.ComputeShaders = IsGL43OrAbove || CheckExtension("GL_ARB_compute_shader"); - Features.GeometryShaders = MajorVersion >= 4 || CheckExtension("GL_ARB_geometry_shader4"); - Features.Tessellation = MajorVersion >= 4 || CheckExtension("GL_ARB_tessellation_shader"); - Features.BindlessResources = False; - Features.OcclusionQueries = True; // Present since 3.3 - Features.BinaryOcclusionQueries = True; // Present since 3.3 - Features.TimestampQueries = True; // Present since 3.3 - Features.PipelineStatisticsQueries = True; // Present since 3.3 - Features.DurationQueries = True; // Present since 3.3 - Features.DepthBiasClamp = False; // There is no depth bias clamp in OpenGL - Features.DepthClamp = MajorVersion >= 4 || CheckExtension("GL_ARB_depth_clamp"); - Features.IndependentBlend = True; - Features.DualSourceBlend = IsGL41OrAbove || CheckExtension("GL_ARB_blend_func_extended"); - Features.MultiViewport = IsGL41OrAbove || CheckExtension("GL_ARB_viewport_array"); - Features.PixelUAVWritesAndAtomics = IsGL42OrAbove || CheckExtension("GL_ARB_shader_image_load_store"); - Features.TextureUAVExtendedFormats = False; - + Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; + Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED; + // clang-format off + SET_FEATURE_STATE(MultithreadedResourceCreation, false, "Multithreaded resource creation is"); + SET_FEATURE_STATE(ComputeShaders, IsGL43OrAbove || CheckExtension("GL_ARB_compute_shader"), "Compute shaders are"); + SET_FEATURE_STATE(GeometryShaders, MajorVersion >= 4 || CheckExtension("GL_ARB_geometry_shader4"), "Geometry shaders are"); + SET_FEATURE_STATE(Tessellation, MajorVersion >= 4 || CheckExtension("GL_ARB_tessellation_shader"), "Tessellation is"); + SET_FEATURE_STATE(BindlessResources, false, "Bindless resources are"); + // clang-format on + Features.OcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; // Present since 3.3 + Features.BinaryOcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; // Present since 3.3 + Features.TimestampQueries = DEVICE_FEATURE_STATE_ENABLED; // Present since 3.3 + Features.PipelineStatisticsQueries = DEVICE_FEATURE_STATE_ENABLED; // Present since 3.3 + Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; // Present since 3.3 + // clang-format off + SET_FEATURE_STATE(DepthBiasClamp, false, "Depth bias clamp is"); // There is no depth bias clamp in OpenGL + SET_FEATURE_STATE(DepthClamp, MajorVersion >= 4 || CheckExtension("GL_ARB_depth_clamp"), "Depth clamp is"); + SET_FEATURE_STATE(IndependentBlend, true, "Independent blend is"); + SET_FEATURE_STATE(DualSourceBlend, IsGL41OrAbove || CheckExtension("GL_ARB_blend_func_extended"), "Dual source blend is"); + SET_FEATURE_STATE(MultiViewport, IsGL41OrAbove || CheckExtension("GL_ARB_viewport_array"), "Multi viewport is"); + SET_FEATURE_STATE(PixelUAVWritesAndAtomics, IsGL42OrAbove || CheckExtension("GL_ARB_shader_image_load_store"), "Pixel UAV writes and atomics are"); + SET_FEATURE_STATE(TextureUAVExtendedFormats, false, "Texture UAV extended formats are"); + // clang-format on TexCaps.MaxTexture1DDimension = MaxTextureSize; TexCaps.MaxTexture1DArraySlices = MaxLayers; @@ -195,32 +239,33 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, bool IsGLES31OrAbove = (MajorVersion >= 4) || (MajorVersion == 3 && MinorVersion >= 1); bool IsGLES32OrAbove = (MajorVersion >= 4) || (MajorVersion == 3 && MinorVersion >= 2); - Features.SeparablePrograms = IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects"); - Features.IndirectRendering = IsGLES31OrAbove || strstr(Extensions, "draw_indirect"); - Features.WireframeFill = False; - Features.MultithreadedResourceCreation = False; - Features.ComputeShaders = IsGLES31OrAbove || strstr(Extensions, "compute_shader"); - Features.GeometryShaders = IsGLES32OrAbove || strstr(Extensions, "geometry_shader"); - Features.Tessellation = IsGLES32OrAbove || strstr(Extensions, "tessellation_shader"); - Features.BindlessResources = False; - Features.OcclusionQueries = False; - Features.BinaryOcclusionQueries = True; // Supported in GLES3.0 + // clang-format off + SET_FEATURE_STATE(SeparablePrograms, IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects"), "Separable programs are"); + SET_FEATURE_STATE(IndirectRendering, IsGLES31OrAbove || strstr(Extensions, "draw_indirect"), "Indirect rendering is"); + SET_FEATURE_STATE(WireframeFill, false, "Wireframe fill is"); + SET_FEATURE_STATE(MultithreadedResourceCreation, false, "Multithreaded resource creation is"); + SET_FEATURE_STATE(ComputeShaders, IsGLES31OrAbove || strstr(Extensions, "compute_shader"), "Compute shaders are"); + SET_FEATURE_STATE(GeometryShaders, IsGLES32OrAbove || strstr(Extensions, "geometry_shader"), "Geometry shaders are"); + SET_FEATURE_STATE(Tessellation, IsGLES32OrAbove || strstr(Extensions, "tessellation_shader"), "Tessellation is"); + SET_FEATURE_STATE(BindlessResources, false, "Bindless resources are"); + SET_FEATURE_STATE(OcclusionQueries, false, "Occlusion queries are"); + SET_FEATURE_STATE(BinaryOcclusionQueries, true, "Binary occlusion queries are"); // Supported in GLES3.0 #if GL_TIMESTAMP - Features.TimestampQueries = strstr(Extensions, "disjoint_timer_query"); - Features.DurationQueries = Features.TimestampQueries; + SET_FEATURE_STATE(TimestampQueries, strstr(Extensions, "disjoint_timer_query"), "Timestamp queries are"); + SET_FEATURE_STATE(DurationQueries, Features.TimestampQueries, "Duration queries are"); #else - Features.TimestampQueries = False; - Features.DurationQueries = False; + SET_FEATURE_STATE(TimestampQueries, false, "Timestamp queries are"); + SET_FEATURE_STATE(DurationQueries, false, "Duration queries are"); #endif - Features.PipelineStatisticsQueries = False; - Features.DepthBiasClamp = False; // There is no depth bias clamp in OpenGL - Features.DepthClamp = strstr(Extensions, "depth_clamp"); - Features.IndependentBlend = IsGLES32OrAbove; - Features.DualSourceBlend = strstr(Extensions, "blend_func_extended"); - Features.MultiViewport = strstr(Extensions, "viewport_array"); - Features.PixelUAVWritesAndAtomics = IsGLES31OrAbove || strstr(Extensions, "shader_image_load_store"); - Features.TextureUAVExtendedFormats = False; - + SET_FEATURE_STATE(PipelineStatisticsQueries, false, "Pipeline atatistics queries are"); + SET_FEATURE_STATE(DepthBiasClamp, false, "Depth bias clamp is"); // There is no depth bias clamp in OpenGL + SET_FEATURE_STATE(DepthClamp, strstr(Extensions, "depth_clamp"), "Depth clamp is"); + SET_FEATURE_STATE(IndependentBlend, IsGLES32OrAbove, "Independent blend is"); + SET_FEATURE_STATE(DualSourceBlend, strstr(Extensions, "blend_func_extended"), "Dual source blend"); + SET_FEATURE_STATE(MultiViewport, strstr(Extensions, "viewport_array"), "Multi viewport"); + SET_FEATURE_STATE(PixelUAVWritesAndAtomics, IsGLES31OrAbove || strstr(Extensions, "shader_image_load_store"), "Pixel UAV writes and atomics"); + SET_FEATURE_STATE(TextureUAVExtendedFormats, false, "Texture UAV extended formats"); + // clang-format on TexCaps.MaxTexture1DDimension = 0; // Not supported in GLES 3.2 TexCaps.MaxTexture1DArraySlices = 0; // Not supported in GLES 3.2 @@ -242,7 +287,9 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, const bool bBPTC = CheckExtension("GL_ARB_texture_compression_bptc"); const bool bS3TC = CheckExtension("GL_EXT_texture_compression_s3tc"); - Features.TextureCompressionBC = bRGTC && bBPTC && bS3TC; + SET_FEATURE_STATE(TextureCompressionBC, bRGTC && bBPTC && bS3TC, "BC texture compression is"); + +#undef SET_FEATURE_STATE } RenderDeviceGLImpl::~RenderDeviceGLImpl() @@ -945,28 +992,6 @@ void RenderDeviceGLImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat) } } -void RenderDeviceGLImpl::QueryDeviceCaps() -{ - if (glPolygonMode == nullptr) - m_DeviceCaps.Features.WireframeFill = false; - - if (m_DeviceCaps.Features.WireframeFill) - { - // Test glPolygonMode() function to check if it fails - // (It does fail on NVidia Shield tablet, but works fine - // on Intel hw) - VERIFY(glGetError() == GL_NO_ERROR, "Unhandled gl error encountered"); - m_DeviceCaps.Features.WireframeFill = True; - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (glGetError() != GL_NO_ERROR) - m_DeviceCaps.Features.WireframeFill = False; - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - if (glGetError() != GL_NO_ERROR) - m_DeviceCaps.Features.WireframeFill = False; - } -} - - FBOCache& RenderDeviceGLImpl::GetFBOCache(GLContext::NativeGLContextType Context) { ThreadingTools::LockHelper FBOCacheLock(m_FBOCacheLockFlag); diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 9f18c99c..caf198cd 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -67,7 +67,7 @@ public: ICommandQueueVk** pCmdQueues, std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice, - std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice); + std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice) noexcept(false); ~RenderDeviceVkImpl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index a2304bfe..4dee23de 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -167,33 +167,58 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; DeviceCreateInfo.flags = 0; // Reserved for future use // https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#extended-functionality-device-layer-deprecation - DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored. - DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored - DeviceCreateInfo.queueCreateInfoCount = 1; - DeviceCreateInfo.pQueueCreateInfos = &QueueInfo; - VkPhysicalDeviceFeatures DeviceFeatures = {}; - -#define ENABLE_FEATURE(Feature) DeviceFeatures.Feature = PhysicalDeviceFeatures.Feature - ENABLE_FEATURE(geometryShader); - ENABLE_FEATURE(tessellationShader); - ENABLE_FEATURE(pipelineStatisticsQuery); - ENABLE_FEATURE(occlusionQueryPrecise); - ENABLE_FEATURE(imageCubeArray); - ENABLE_FEATURE(fillModeNonSolid); - ENABLE_FEATURE(samplerAnisotropy); - ENABLE_FEATURE(depthBiasClamp); - ENABLE_FEATURE(depthClamp); - ENABLE_FEATURE(independentBlend); - ENABLE_FEATURE(dualSrcBlend); - ENABLE_FEATURE(multiViewport); - ENABLE_FEATURE(textureCompressionBC); - ENABLE_FEATURE(vertexPipelineStoresAndAtomics); - ENABLE_FEATURE(fragmentStoresAndAtomics); - ENABLE_FEATURE(shaderStorageImageExtendedFormats); + DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored. + DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored + DeviceCreateInfo.queueCreateInfoCount = 1; + DeviceCreateInfo.pQueueCreateInfos = &QueueInfo; + VkPhysicalDeviceFeatures EnabledFeatures = {}; + EnabledFeatures.fullDrawIndexUint32 = PhysicalDeviceFeatures.fullDrawIndexUint32; + +#define ENABLE_FEATURE(Feature, RequestedState, FeatureName) \ + do \ + { \ + switch (RequestedState) \ + { \ + case DEVICE_FEATURE_STATE_DISABLED: \ + EnabledFeatures.Feature = VK_FALSE; \ + break; \ + case DEVICE_FEATURE_STATE_ENABLED: \ + { \ + if (PhysicalDeviceFeatures.Feature == VK_FALSE) \ + LOG_ERROR_AND_THROW(FeatureName, " not supported by this device"); \ + else \ + EnabledFeatures.Feature = VK_TRUE; \ + } \ + break; \ + case DEVICE_FEATURE_STATE_OPTIONAL: \ + EnabledFeatures.Feature = PhysicalDeviceFeatures.Feature; \ + break; \ + default: UNEXPECTED("Unexpected feature state"); \ + } \ + } while (false) + + // clang-format off + ENABLE_FEATURE(geometryShader, EngineCI.Features.GeometryShaders, "Geometry shaders are"); + ENABLE_FEATURE(tessellationShader, EngineCI.Features.Tessellation, "Tessellation is"); + ENABLE_FEATURE(pipelineStatisticsQuery, EngineCI.Features.PipelineStatisticsQueries, "Pipeline statistics queries are"); + ENABLE_FEATURE(occlusionQueryPrecise, EngineCI.Features.OcclusionQueries, "Occlusion queries are"); + ENABLE_FEATURE(imageCubeArray, DEVICE_FEATURE_STATE_OPTIONAL, "Image cube arrays"); + ENABLE_FEATURE(fillModeNonSolid, EngineCI.Features.WireframeFill, "Wireframe fill is"); + ENABLE_FEATURE(samplerAnisotropy, DEVICE_FEATURE_STATE_OPTIONAL, "Anisotropic texture filtering is"); + ENABLE_FEATURE(depthBiasClamp, EngineCI.Features.DepthBiasClamp, "Depth bias clamp is"); + ENABLE_FEATURE(depthClamp, EngineCI.Features.DepthClamp, "Depth clamp is"); + ENABLE_FEATURE(independentBlend, EngineCI.Features.IndependentBlend, "Independent blend is"); + ENABLE_FEATURE(dualSrcBlend, EngineCI.Features.DualSourceBlend, "Dual-source blend is"); + ENABLE_FEATURE(multiViewport, EngineCI.Features.MultiViewport, "Multiviewport is"); + ENABLE_FEATURE(textureCompressionBC, EngineCI.Features.TextureCompressionBC, "BC texture compression is"); + ENABLE_FEATURE(vertexPipelineStoresAndAtomics, EngineCI.Features.VertexPipelineUAVWritesAndAtomics, "Vertex pipeline UAV writes and atomics are"); + ENABLE_FEATURE(fragmentStoresAndAtomics, EngineCI.Features.PixelUAVWritesAndAtomics, "Pixel UAV writes and atomics are"); + ENABLE_FEATURE(shaderStorageImageExtendedFormats, EngineCI.Features.TextureUAVExtendedFormats, "Texture UAV extended formats are"); + // clang-format on #undef ENABLE_FEATURE - DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains - // boolean indicators of all the features to be enabled. + DeviceCreateInfo.pEnabledFeatures = &EnabledFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains + // boolean indicators of all the features to be enabled. std::vector<const char*> DeviceExtensions = { @@ -211,17 +236,26 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E (void)NextExt; // Enable mesh shader extension. + bool MeshShadersSupported = false; #ifdef VK_NV_mesh_shader VkPhysicalDeviceMeshShaderFeaturesNV MeshShaderFeats = PhysicalDevice->GetExtFeatures().MeshShader; if (SupportsFeatures2 && PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME)) { + MeshShadersSupported = true; DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME); *NextExt = &MeshShaderFeats; NextExt = &MeshShaderFeats.pNext; } #endif + if (EngineCI.Features.MeshShaders == DEVICE_FEATURE_STATE_ENABLED && !MeshShadersSupported) + LOG_ERROR_AND_THROW("Mesh shaders are not supported by this device"); + +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(DeviceFeatures) == 23, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); +#endif + DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size()); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index c619dc59..01ef7447 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -166,34 +166,43 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* // May be unused if extensions are disabled. (void)(vkExtFeatures); - Features.SeparablePrograms = True; - Features.IndirectRendering = True; - Features.WireframeFill = vkDeviceFeatures.fillModeNonSolid != VK_FALSE; - Features.MultithreadedResourceCreation = True; - Features.ComputeShaders = True; - Features.GeometryShaders = vkDeviceFeatures.geometryShader != VK_FALSE; - Features.Tessellation = vkDeviceFeatures.tessellationShader != VK_FALSE; - Features.BindlessResources = True; - Features.OcclusionQueries = vkDeviceFeatures.occlusionQueryPrecise != VK_FALSE; - Features.BinaryOcclusionQueries = True; - Features.TimestampQueries = True; - Features.DurationQueries = True; - Features.PipelineStatisticsQueries = vkDeviceFeatures.pipelineStatisticsQuery != VK_FALSE; - Features.DepthBiasClamp = vkDeviceFeatures.depthBiasClamp != VK_FALSE; - Features.DepthClamp = vkDeviceFeatures.depthClamp != VK_FALSE; - Features.IndependentBlend = vkDeviceFeatures.independentBlend != VK_FALSE; - Features.DualSourceBlend = vkDeviceFeatures.dualSrcBlend != VK_FALSE; - Features.MultiViewport = vkDeviceFeatures.multiViewport != VK_FALSE; - Features.TextureCompressionBC = vkDeviceFeatures.textureCompressionBC != VK_FALSE; - Features.VertexPipelineUAVWritesAndAtomics = vkDeviceFeatures.vertexPipelineStoresAndAtomics != VK_FALSE; - Features.PixelUAVWritesAndAtomics = vkDeviceFeatures.fragmentStoresAndAtomics != VK_FALSE; - Features.TextureUAVExtendedFormats = vkDeviceFeatures.shaderStorageImageExtendedFormats != VK_FALSE; + auto GetFeatureState = [](VkBool32 vkFeatureState) // + { + return vkFeatureState != VK_FALSE ? DEVICE_FEATURE_STATE_ENABLED : DEVICE_FEATURE_STATE_DISABLED; + }; + + Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; + Features.WireframeFill = GetFeatureState(vkDeviceFeatures.fillModeNonSolid); + Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED; + Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED; + Features.GeometryShaders = GetFeatureState(vkDeviceFeatures.geometryShader); + Features.Tessellation = GetFeatureState(vkDeviceFeatures.tessellationShader); + Features.BindlessResources = DEVICE_FEATURE_STATE_ENABLED; + Features.OcclusionQueries = GetFeatureState(vkDeviceFeatures.occlusionQueryPrecise); + Features.BinaryOcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.TimestampQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.PipelineStatisticsQueries = GetFeatureState(vkDeviceFeatures.pipelineStatisticsQuery); + Features.DepthBiasClamp = GetFeatureState(vkDeviceFeatures.depthBiasClamp); + Features.DepthClamp = GetFeatureState(vkDeviceFeatures.depthClamp); + Features.IndependentBlend = GetFeatureState(vkDeviceFeatures.independentBlend); + Features.DualSourceBlend = GetFeatureState(vkDeviceFeatures.dualSrcBlend); + Features.MultiViewport = GetFeatureState(vkDeviceFeatures.multiViewport); + Features.TextureCompressionBC = GetFeatureState(vkDeviceFeatures.textureCompressionBC); + Features.VertexPipelineUAVWritesAndAtomics = GetFeatureState(vkDeviceFeatures.vertexPipelineStoresAndAtomics); + Features.PixelUAVWritesAndAtomics = GetFeatureState(vkDeviceFeatures.fragmentStoresAndAtomics); + Features.TextureUAVExtendedFormats = GetFeatureState(vkDeviceFeatures.shaderStorageImageExtendedFormats); #ifdef VK_NV_mesh_shader - // All devices that supports mesh shader also supports task shader, so it is not necessary to use two separate features. - Features.MeshShaders = vkExtFeatures.MeshShader.meshShader != VK_FALSE && vkExtFeatures.MeshShader.taskShader != VK_FALSE; + // All devices that support mesh shaders also support task shaders, so it is not necessary to use two separate features. + Features.MeshShaders = GetFeatureState(vkExtFeatures.MeshShader.meshShader != VK_FALSE && vkExtFeatures.MeshShader.taskShader != VK_FALSE); #else - Features.MeshShaders = False; + Features.MeshShaders = DEVICE_FEATURE_STATE_DISABLED; +#endif + +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(DeviceFeatures) == 23, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits; |
