From 200c9286b4a82c5c4ffb041ff7588e8013fc4d72 Mon Sep 17 00:00:00 2001 From: Amer Koleci Date: Wed, 4 Jan 2023 17:49:58 +0100 Subject: [PATCH] D3D12: improve various CheckFeatureSupport calls and StaticSamplerDescription. --- Directory.Build.props | 2 +- .../ID3D12Device.cs | 148 ++++++++++++++++++ .../StaticSamplerDescription.cs | 93 +++++++---- 3 files changed, 214 insertions(+), 29 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 2515fe4..5a31711 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,7 +14,7 @@ true $(MSBuildThisFileDirectory)NuGet.config - 1.9.9 + 1.9.10 true diff --git a/src/Vortice.Win32.Graphics.Direct3D12/ID3D12Device.cs b/src/Vortice.Win32.Graphics.Direct3D12/ID3D12Device.cs index 4fe80f2..32e4530 100644 --- a/src/Vortice.Win32.Graphics.Direct3D12/ID3D12Device.cs +++ b/src/Vortice.Win32.Graphics.Direct3D12/ID3D12Device.cs @@ -1,6 +1,8 @@ // Copyright © Amer Koleci and Contributors. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information. +using Win32.Graphics.Direct3D; +using Win32.Graphics.Dxgi.Common; using static Win32.Apis; namespace Win32.Graphics.Direct3D12; @@ -35,4 +37,150 @@ public static unsafe partial class ID3D12DeviceExtensions HeapProperties heapProperties = new(heapType); return self.CreateCommittedResource(&heapProperties, HeapFlags.None, pDesc, InitialResourceState, pOptimizedClearValue, riidResource, ppvResource); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FeatureLevel CheckMaxSupportedFeatureLevel(ref this TD3D12Device self) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + ReadOnlySpan featureLevels = stackalloc FeatureLevel[4] + { + FeatureLevel.Level_12_2, + FeatureLevel.Level_12_1, + FeatureLevel.Level_11_1, + FeatureLevel.Level_11_0 + }; + + fixed (FeatureLevel* pFeatureLevels = featureLevels) + { + var featureData = new FeatureDataFeatureLevels + { + NumFeatureLevels = (uint)featureLevels.Length, + pFeatureLevelsRequested = pFeatureLevels, + MaxSupportedFeatureLevel = FeatureLevel.Level_11_0 + }; + + if (self.CheckFeatureSupport(Feature.FeatureLevels, &featureData, sizeof(FeatureDataFeatureLevels)).Success) + { + return featureData.MaxSupportedFeatureLevel; + } + + return FeatureLevel.Level_11_0; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FeatureLevel CheckMaxSupportedFeatureLevel( + ref this TD3D12Device self, ReadOnlySpan featureLevels) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + fixed (FeatureLevel* pFeatureLevels = featureLevels) + { + var featureData = new FeatureDataFeatureLevels + { + NumFeatureLevels = (uint)featureLevels.Length, + pFeatureLevelsRequested = pFeatureLevels, + MaxSupportedFeatureLevel = FeatureLevel.Level_11_0 + }; + + if (self.CheckFeatureSupport(Feature.FeatureLevels, &featureData, sizeof(FeatureDataFeatureLevels)).Success) + { + return featureData.MaxSupportedFeatureLevel; + } + + return FeatureLevel.Level_11_0; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RootSignatureVersion CheckHighestRootSignatureVersionl( + ref this TD3D12Device self, + RootSignatureVersion highestVersion = RootSignatureVersion.V1_1) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + var featureData = new FeatureDataRootSignature + { + HighestVersion = highestVersion + }; + + if (self.CheckFeatureSupport(Feature.RootSignature, &featureData, sizeof(FeatureDataRootSignature)).Success) + { + return featureData.HighestVersion; + } + + return RootSignatureVersion.V1_0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ShaderModel CheckHighestShaderModel(ref this TD3D12Device self, ShaderModel highestShaderModel) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + var featureData = new FeatureDataShaderModel + { + HighestShaderModel = highestShaderModel + }; + + if (self.CheckFeatureSupport(Feature.ShaderModel, &featureData, sizeof(FeatureDataShaderModel)).Success) + { + return featureData.HighestShaderModel; + } + + return ShaderModel.SM_5_1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool CheckFormatSupport(ref this TD3D12Device self, + Format format, out FormatSupport1 formatSupport1, out FormatSupport2 formatSupport2) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + FeatureDataFormatSupport featureData = new() + { + Format = format + }; + + if (self.CheckFeatureSupport(Feature.FormatSupport, &featureData, sizeof(FeatureDataFormatSupport)).Failure) + { + formatSupport1 = FormatSupport1.None; + formatSupport2 = FormatSupport2.None; + return false; + } + + formatSupport1 = featureData.Support1; + formatSupport2 = featureData.Support2; + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte GetFormatPlaneCount(ref this TD3D12Device self, Format format) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + var featureData = new FeatureDataFormatInfo + { + Format = format + }; + + if (self.CheckFeatureSupport(Feature.FormatInfo, &featureData, sizeof(FeatureDataFormatInfo)).Failure) + { + return 0; + } + + return featureData.PlaneCount; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FeatureDataCommandQueuePriority CheckCommandQueuePriority(ref this TD3D12Device self, CommandListType commandListType) + where TD3D12Device : unmanaged, ID3D12Device.Interface + { + FeatureDataCommandQueuePriority featureData = new() + { + CommandListType = commandListType, + }; + + if (self.CheckFeatureSupport(Feature.CommandQueuePriority, &featureData, sizeof(FeatureDataFormatInfo)).Failure) + { + return default; + } + + return featureData; + } + } diff --git a/src/Vortice.Win32.Graphics.Direct3D12/StaticSamplerDescription.cs b/src/Vortice.Win32.Graphics.Direct3D12/StaticSamplerDescription.cs index 86326c3..5907e81 100644 --- a/src/Vortice.Win32.Graphics.Direct3D12/StaticSamplerDescription.cs +++ b/src/Vortice.Win32.Graphics.Direct3D12/StaticSamplerDescription.cs @@ -7,33 +7,6 @@ namespace Win32.Graphics.Direct3D12; public unsafe partial struct StaticSamplerDescription { - /// - /// Initializes a new instance of the struct. - /// - /// The shader visibility. - /// The shader register. - /// The register space. - public StaticSamplerDescription( - ShaderVisibility shaderVisibility, - uint shaderRegister, - uint registerSpace) - { - Filter = Filter.MinMagMipLinear; - AddressU = TextureAddressMode.Clamp; - AddressV = TextureAddressMode.Clamp; - AddressW = TextureAddressMode.Clamp; - MipLODBias = 0.0f; - MaxAnisotropy = 1; - ComparisonFunc = ComparisonFunction.Never; - BorderColor = StaticBorderColor.TransparentBlack; - MinLOD = float.MinValue; - MaxLOD = float.MaxValue; - - ShaderRegister = shaderRegister; - RegisterSpace = registerSpace; - ShaderVisibility = shaderVisibility; - } - /// /// Initializes a new instance of the struct. /// @@ -46,7 +19,7 @@ public unsafe partial struct StaticSamplerDescription in SamplerDescription samplerDescription, ShaderVisibility shaderVisibility, uint shaderRegister, - uint registerSpace, + uint registerSpace = 0, StaticBorderColor borderColor = StaticBorderColor.OpaqueWhite) : this() { ShaderVisibility = shaderVisibility; @@ -63,4 +36,68 @@ public unsafe partial struct StaticSamplerDescription MaxAnisotropy = samplerDescription.MaxAnisotropy; ComparisonFunc = samplerDescription.ComparisonFunc; } + + public StaticSamplerDescription( + uint shaderRegister, + Filter filter = Filter.Anisotropic, + TextureAddressMode addressU = TextureAddressMode.Wrap, + TextureAddressMode addressV = TextureAddressMode.Wrap, + TextureAddressMode addressW = TextureAddressMode.Wrap, + float mipLODBias = 0, + uint maxAnisotropy = 16, + ComparisonFunction comparisonFunc = ComparisonFunction.LessEqual, + StaticBorderColor borderColor = StaticBorderColor.OpaqueWhite, + float minLOD = 0, + float maxLOD = D3D12_FLOAT32_MAX, + ShaderVisibility shaderVisibility = ShaderVisibility.All, + uint registerSpace = 0) + { + Init(out this, shaderRegister, filter, addressU, addressV, addressW, mipLODBias, maxAnisotropy, comparisonFunc, borderColor, minLOD, maxLOD, shaderVisibility, registerSpace); + } + + public static void Init(out StaticSamplerDescription samplerDesc, + uint shaderRegister, + Filter filter = Filter.Anisotropic, + TextureAddressMode addressU = TextureAddressMode.Wrap, + TextureAddressMode addressV = TextureAddressMode.Wrap, + TextureAddressMode addressW = TextureAddressMode.Wrap, + float mipLODBias = 0, + uint maxAnisotropy = 16, + ComparisonFunction comparisonFunc = ComparisonFunction.LessEqual, + StaticBorderColor borderColor = StaticBorderColor.OpaqueWhite, + float minLOD = 0, + float maxLOD = D3D12_FLOAT32_MAX, + ShaderVisibility shaderVisibility = ShaderVisibility.All, + uint registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + + public void Init(uint shaderRegister, + Filter filter = Filter.Anisotropic, + TextureAddressMode addressU = TextureAddressMode.Wrap, + TextureAddressMode addressV = TextureAddressMode.Wrap, + TextureAddressMode addressW = TextureAddressMode.Wrap, + float mipLODBias = 0, uint maxAnisotropy = 16, + ComparisonFunction comparisonFunc = ComparisonFunction.LessEqual, + StaticBorderColor borderColor = StaticBorderColor.OpaqueWhite, + float minLOD = 0, + float maxLOD = D3D12_FLOAT32_MAX, + ShaderVisibility shaderVisibility = ShaderVisibility.All, + uint registerSpace = 0) + { + Init(out this, shaderRegister, filter, addressU, addressV, addressW, mipLODBias, maxAnisotropy, comparisonFunc, borderColor, minLOD, maxLOD, shaderVisibility, registerSpace); + } }