diff --git a/AIDevGallery.SourceGenerator/AIDevGallery.SourceGenerator.csproj b/AIDevGallery.SourceGenerator/AIDevGallery.SourceGenerator.csproj index 09eaedcd..899ddd64 100644 --- a/AIDevGallery.SourceGenerator/AIDevGallery.SourceGenerator.csproj +++ b/AIDevGallery.SourceGenerator/AIDevGallery.SourceGenerator.csproj @@ -27,6 +27,7 @@ + diff --git a/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs b/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs index 456dd89d..e2adb299 100644 --- a/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs +++ b/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs @@ -63,6 +63,7 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im } filePaths.Add("NativeMethods.txt"); + filePaths.Add("NativeMethods.json"); foreach (var filePath in filePaths) { @@ -82,6 +83,11 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im } else { + if (fileName.StartsWith("NativeMethods")) + { + fileName = GetNameWithExtension(filePath); + } + sourceBuilder.AppendLine($" {fileName},"); } } @@ -113,7 +119,13 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im } else { - sourceBuilder.AppendLine($" SharedCodeEnum.{fileName} => \"{Path.GetFileName(filePath)}\","); + var name = Path.GetFileName(filePath); + if (name.StartsWith("NativeMethods")) + { + fileName = GetNameWithExtension(filePath); + } + + sourceBuilder.AppendLine($" SharedCodeEnum.{fileName} => \"{name}\","); } } @@ -153,10 +165,11 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im } string fileContent; - if (fileName == "NativeMethods") + if (filePath.StartsWith("NativeMethods")) { + fileName = GetNameWithExtension(filePath); var assembly = Assembly.GetExecutingAssembly(); - using (Stream stream = assembly.GetManifestResourceStream("AIDevGallery.SourceGenerator.NativeMethods.txt")) + using (Stream stream = assembly.GetManifestResourceStream($"AIDevGallery.SourceGenerator.{filePath}")) { using (StreamReader reader = new(stream)) { @@ -186,6 +199,13 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im sourceBuilder.AppendLine("}"); context.AddSource("SharedCodeEnum.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); + + static string GetNameWithExtension(string filePath) + { + return Path.GetFileName(filePath) + .Replace(".txt", "_Txt") + .Replace(".json", "_Json"); + } } private static readonly Regex UsingAIDevGalleryTelemetryNamespace = new(@"using AIDevGallery.Telemetry\S*;\r?\n", RegexOptions.Multiline | RegexOptions.Compiled); diff --git a/AIDevGallery.Utils/AIDevGallery.Utils.csproj b/AIDevGallery.Utils/AIDevGallery.Utils.csproj index acf5a60c..f6ea4caa 100644 --- a/AIDevGallery.Utils/AIDevGallery.Utils.csproj +++ b/AIDevGallery.Utils/AIDevGallery.Utils.csproj @@ -8,6 +8,7 @@ true + true diff --git a/AIDevGallery/AIDevGallery.csproj b/AIDevGallery/AIDevGallery.csproj index 85ec00cb..7da2374e 100644 --- a/AIDevGallery/AIDevGallery.csproj +++ b/AIDevGallery/AIDevGallery.csproj @@ -13,11 +13,10 @@ enable preview CS8305;WMC1501 - - $(NoWarn);IL2050 $(NoWarn);IL2026 true + true SamplesRoots.xml TELEMETRYEVENTSOURCE_PUBLIC diff --git a/AIDevGallery/Helpers/SamplesHelper.cs b/AIDevGallery/Helpers/SamplesHelper.cs index 16a93fa0..7b2e2a4b 100644 --- a/AIDevGallery/Helpers/SamplesHelper.cs +++ b/AIDevGallery/Helpers/SamplesHelper.cs @@ -41,7 +41,8 @@ public static List GetAllSharedCode(this Sample sample, Dictiona if (sharedCode.Contains(SharedCodeEnum.DeviceUtils)) { - AddUnique(SharedCodeEnum.NativeMethods); + AddUnique(SharedCodeEnum.NativeMethods_Txt); + AddUnique(SharedCodeEnum.NativeMethods_Json); } return sharedCode; @@ -79,7 +80,8 @@ public static List GetAllNugetPackageReferences(this Sample sample, Dict var sharedCode = sample.GetAllSharedCode(models); - if (sharedCode.Contains(SharedCodeEnum.NativeMethods)) + if (sharedCode.Contains(SharedCodeEnum.NativeMethods_Txt) || + sharedCode.Contains(SharedCodeEnum.NativeMethods_Json)) { AddUnique("Microsoft.Windows.CsWin32"); } diff --git a/AIDevGallery/MainWindow.xaml b/AIDevGallery/MainWindow.xaml index 6c1e8deb..2df923b4 100644 --- a/AIDevGallery/MainWindow.xaml +++ b/AIDevGallery/MainWindow.xaml @@ -139,6 +139,7 @@ searchResults = []; + public MainWindow(object? obj = null) { this.InitializeComponent(); @@ -217,7 +220,11 @@ private void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChan if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput && !string.IsNullOrWhiteSpace(SearchBox.Text)) { var filteredSearchResults = App.SearchIndex.Where(sr => sr.Label.Contains(sender.Text, StringComparison.OrdinalIgnoreCase)).ToList(); - SearchBox.ItemsSource = filteredSearchResults.OrderByDescending(i => i.Label.StartsWith(sender.Text, StringComparison.CurrentCultureIgnoreCase)).ThenBy(i => i.Label); + searchResults.Clear(); + foreach (var result in filteredSearchResults.OrderByDescending(i => i.Label.StartsWith(sender.Text, StringComparison.CurrentCultureIgnoreCase)).ThenBy(i => i.Label)) + { + searchResults.Add(result); + } } } diff --git a/AIDevGallery/NativeMethods.json b/AIDevGallery/NativeMethods.json new file mode 100644 index 00000000..f39dcf9d --- /dev/null +++ b/AIDevGallery/NativeMethods.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://aka.ms/CsWin32.schema.json", + "allowMarshaling": false, + "public": false +} \ No newline at end of file diff --git a/AIDevGallery/Pages/APIs/APIPage.xaml b/AIDevGallery/Pages/APIs/APIPage.xaml index c49ccf6c..fceccf98 100644 --- a/AIDevGallery/Pages/APIs/APIPage.xaml +++ b/AIDevGallery/Pages/APIs/APIPage.xaml @@ -111,6 +111,7 @@ HorizontalAlignment="Stretch" AutomationProperties.Name="Samples" IsItemInvokedEnabled="True" + ItemsSource="{x:Bind samples}" ItemInvoked="SampleList_ItemInvoked" SelectionMode="None"> diff --git a/AIDevGallery/Pages/APIs/APIPage.xaml.cs b/AIDevGallery/Pages/APIs/APIPage.xaml.cs index 21ec8578..85991719 100644 --- a/AIDevGallery/Pages/APIs/APIPage.xaml.cs +++ b/AIDevGallery/Pages/APIs/APIPage.xaml.cs @@ -11,6 +11,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using System; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -25,6 +26,7 @@ internal sealed partial class APIPage : Page private ModelDetails? modelDetails; private string? readmeContents; private string? codeSnippet; + private ObservableCollection samples = []; public APIPage() { @@ -118,14 +120,20 @@ private void GetSamples() // if we don't have a modelType, we are in a user added language model, use same samples as Phi var modelType = modelFamilyType ?? ModelType.Phi3Mini; - var samples = SampleDetails.Samples.Where(s => s.Model1Types.Contains(modelType) || s.Model2Types?.Contains(modelType) == true).ToList(); + samples.Clear(); + foreach (var sample in SampleDetails.Samples.Where(s => s.Model1Types.Contains(modelType) || s.Model2Types?.Contains(modelType) == true)) + { + samples.Add(sample); + } + if (ModelTypeHelpers.ParentMapping.Values.Any(parent => parent.Contains(modelType))) { var parent = ModelTypeHelpers.ParentMapping.FirstOrDefault(parent => parent.Value.Contains(modelType)).Key; - samples.AddRange(SampleDetails.Samples.Where(s => s.Model1Types.Contains(parent) || s.Model2Types?.Contains(parent) == true)); + foreach (var sample in SampleDetails.Samples.Where(s => s.Model1Types.Contains(parent) || s.Model2Types?.Contains(parent) == true)) + { + samples.Add(sample); + } } - - SampleList.ItemsSource = samples; } private void LoadCodeSnippet(string? snippet) diff --git a/AIDevGallery/Pages/Models/ModelPage.xaml b/AIDevGallery/Pages/Models/ModelPage.xaml index 5c8f3200..ae0bc184 100644 --- a/AIDevGallery/Pages/Models/ModelPage.xaml +++ b/AIDevGallery/Pages/Models/ModelPage.xaml @@ -164,6 +164,7 @@ AutomationProperties.Name="Samples" IsEnabled="False" IsItemInvokedEnabled="True" + ItemsSource="{x:Bind samples}" ItemInvoked="SampleList_ItemInvoked" SelectionMode="None"> diff --git a/AIDevGallery/Pages/Models/ModelPage.xaml.cs b/AIDevGallery/Pages/Models/ModelPage.xaml.cs index 37e84f0b..d73e7a8f 100644 --- a/AIDevGallery/Pages/Models/ModelPage.xaml.cs +++ b/AIDevGallery/Pages/Models/ModelPage.xaml.cs @@ -12,6 +12,7 @@ using Microsoft.UI.Xaml.Navigation; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -25,6 +26,7 @@ internal sealed partial class ModelPage : Page private ModelType? modelFamilyType; private List models = new(); private string? readme; + private ObservableCollection samples = []; public ModelPage() { @@ -278,14 +280,20 @@ private void ModelSelectionControl_SelectedModelChanged(object sender, ModelDeta // if we don't have a modelType, we are in a user added language model, use same samples as Phi var modelType = modelFamilyType ?? ModelType.Phi3Mini; - var samples = SampleDetails.Samples.Where(s => s.Model1Types.Contains(modelType) || s.Model2Types?.Contains(modelType) == true).ToList(); + samples.Clear(); + foreach (var sample in SampleDetails.Samples.Where(s => s.Model1Types.Contains(modelType) || s.Model2Types?.Contains(modelType) == true)) + { + samples.Add(sample); + } + if (ModelTypeHelpers.ParentMapping.Values.Any(parent => parent.Contains(modelType))) { var parent = ModelTypeHelpers.ParentMapping.FirstOrDefault(parent => parent.Value.Contains(modelType)).Key; - samples.AddRange(SampleDetails.Samples.Where(s => s.Model1Types.Contains(parent) || s.Model2Types?.Contains(parent) == true)); + foreach (var sample in SampleDetails.Samples.Where(s => s.Model1Types.Contains(parent) || s.Model2Types?.Contains(parent) == true)) + { + samples.Add(sample); + } } - - SampleList.ItemsSource = samples; } private void CopyButton_Click(object sender, RoutedEventArgs e) diff --git a/AIDevGallery/Pages/Scenarios/ScenarioSelectionPage.xaml.cs b/AIDevGallery/Pages/Scenarios/ScenarioSelectionPage.xaml.cs index 16573584..e2b70999 100644 --- a/AIDevGallery/Pages/Scenarios/ScenarioSelectionPage.xaml.cs +++ b/AIDevGallery/Pages/Scenarios/ScenarioSelectionPage.xaml.cs @@ -15,7 +15,8 @@ namespace AIDevGallery.Pages; internal sealed partial class ScenarioSelectionPage : Page { - internal record FilterRecord(string? Tag, string Text); + [WinRT.GeneratedBindableCustomProperty] + internal partial record FilterRecord(string? Tag, string Text); private readonly List filters = [ diff --git a/AIDevGallery/ProjectGenerator/Generator.cs b/AIDevGallery/ProjectGenerator/Generator.cs index 6385cb9c..8b2b392f 100644 --- a/AIDevGallery/ProjectGenerator/Generator.cs +++ b/AIDevGallery/ProjectGenerator/Generator.cs @@ -394,7 +394,8 @@ private async Task AddFilesFromSampleAsync( { string directory = outputPath; - if (sharedCodeEnum != SharedCodeEnum.NativeMethods) + if (sharedCodeEnum != SharedCodeEnum.NativeMethods_Txt && + sharedCodeEnum != SharedCodeEnum.NativeMethods_Json) { if (!Directory.Exists(Path.Join(outputPath, "Utils"))) { diff --git a/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.cs b/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.cs index d93b7d41..6934cebf 100644 --- a/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.cs +++ b/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.cs @@ -8,11 +8,13 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; namespace AIDevGallery.Samples.SharedCode; +[WinRT.GeneratedBindableCustomProperty] internal sealed partial class SemanticComboBox : Control { private IVectorStore? _vectorStore; @@ -31,6 +33,8 @@ public IEmbeddingGenerator>? EmbeddingGenerator typeof(SemanticComboBox), new PropertyMetadata(null, OnEmbeddingGeneratorChanged)); + public ObservableCollection SearchResults { get; } = []; + public List Items { get { return (List)GetValue(ItemsProperty); } @@ -98,8 +102,11 @@ private async void SuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxT // only listen to changes caused by user entering text. if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) { - var searchResults = await Search(sender.Text); - sender.ItemsSource = searchResults.Select(item => item.Text); + SearchResults.Clear(); + foreach (var item in await Search(sender.Text)) + { + SearchResults.Add(item.Text); + } } } diff --git a/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.xaml b/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.xaml index 8e5cc591..9047e5ee 100644 --- a/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.xaml +++ b/AIDevGallery/Samples/SharedCode/Controls/SemanticComboBox.xaml @@ -12,6 +12,7 @@ x:Name="SemanticSuggestBox" HorizontalAlignment="Stretch" VerticalAlignment="Top" + ItemsSource="{Binding SearchResults, RelativeSource={RelativeSource TemplatedParent}}" PlaceholderText="Start typing to semantically search categories..." /> diff --git a/AIDevGallery/Samples/SharedCode/Controls/SmartPasteForm.cs b/AIDevGallery/Samples/SharedCode/Controls/SmartPasteForm.cs index 250f7429..05c09358 100644 --- a/AIDevGallery/Samples/SharedCode/Controls/SmartPasteForm.cs +++ b/AIDevGallery/Samples/SharedCode/Controls/SmartPasteForm.cs @@ -18,6 +18,7 @@ namespace AIDevGallery.Samples.SharedCode; +[WinRT.GeneratedBindableCustomProperty] internal sealed partial class SmartPasteForm : Control { private const int _defaultMaxLength = 1024; @@ -207,7 +208,8 @@ private void PasteValuesToForm(Dictionary values) new PropertyMetadata(default(List), new PropertyChangedCallback(OnFieldLabelsChanged))); } -internal class FormField : ObservableObject +[WinRT.GeneratedBindableCustomProperty] +internal partial class FormField : ObservableObject { private string? label; private string? value; diff --git a/AIDevGallery/Utils/AppUtils.cs b/AIDevGallery/Utils/AppUtils.cs index c99326e2..cf82c9a5 100644 --- a/AIDevGallery/Utils/AppUtils.cs +++ b/AIDevGallery/Utils/AppUtils.cs @@ -279,41 +279,41 @@ public static StyleDictionary GetCodeHighlightingStyleFromElementTheme(ElementTh } } - public static bool HasNpu() + public static unsafe bool HasNpu() { if (_hasNpu.HasValue) { return _hasNpu.Value; } - IDXCoreAdapterFactory adapterFactory; - if (PInvoke.DXCoreCreateAdapterFactory(typeof(IDXCoreAdapterFactory).GUID, out var adapterFactoryObj) != HRESULT.S_OK) + IDXCoreAdapterFactory* adapterFactory; + if (PInvoke.DXCoreCreateAdapterFactory(typeof(IDXCoreAdapterFactory).GUID, out void* adapterFactoryObj) != HRESULT.S_OK) { throw new InvalidOperationException("Failed to create adapter factory"); } - adapterFactory = (IDXCoreAdapterFactory)adapterFactoryObj; + adapterFactory = (IDXCoreAdapterFactory*)adapterFactoryObj; // First try getting all GENERIC_ML devices, which is the broadest set of adapters // and includes both GPUs and NPUs; however, running this sample on an older build of // Windows may not have drivers that report GENERIC_ML. - IDXCoreAdapterList adapterList; + IDXCoreAdapterList* adapterList; - adapterFactory.CreateAdapterList([DXCORE_ADAPTER_ATTRIBUTE_D3D12_GENERIC_ML], typeof(IDXCoreAdapterList).GUID, out var adapterListObj); - adapterList = (IDXCoreAdapterList)adapterListObj; + adapterFactory->CreateAdapterList([DXCORE_ADAPTER_ATTRIBUTE_D3D12_GENERIC_ML], typeof(IDXCoreAdapterList).GUID, out var adapterListObj); + adapterList = (IDXCoreAdapterList*)adapterListObj; // Fall back to CORE_COMPUTE if GENERIC_ML devices are not available. This is a more restricted // set of adapters and may filter out some NPUs. - if (adapterList.GetAdapterCount() == 0) + if (adapterList->GetAdapterCount() == 0) { - adapterFactory.CreateAdapterList( + adapterFactory->CreateAdapterList( [PInvoke.DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE], typeof(IDXCoreAdapterList).GUID, out adapterListObj); - adapterList = (IDXCoreAdapterList)adapterListObj; + adapterList = (IDXCoreAdapterList*)adapterListObj; } - if (adapterList.GetAdapterCount() == 0) + if (adapterList->GetAdapterCount() == 0) { throw new InvalidOperationException("No compatible adapters found."); } @@ -325,17 +325,15 @@ public static bool HasNpu() DXCoreAdapterPreference.HighPerformance ]; - adapterList.Sort(preferences); + adapterList->Sort(preferences); - List adapters = []; - - for (uint i = 0; i < adapterList.GetAdapterCount(); i++) + for (uint i = 0; i < adapterList->GetAdapterCount(); i++) { - IDXCoreAdapter adapter; - adapterList.GetAdapter(i, typeof(IDXCoreAdapter).GUID, out var adapterObj); - adapter = (IDXCoreAdapter)adapterObj; + IDXCoreAdapter* adapter; + adapterList->GetAdapter(i, typeof(IDXCoreAdapter).GUID, out var adapterObj); + adapter = (IDXCoreAdapter*)adapterObj; - adapter.GetPropertySize( + adapter->GetPropertySize( DXCoreAdapterProperty.DriverDescription, out var descriptionSize); @@ -344,13 +342,10 @@ public static bool HasNpu() try { buffer = Marshal.AllocHGlobal((int)descriptionSize); - unsafe - { - adapter.GetProperty( - DXCoreAdapterProperty.DriverDescription, - descriptionSize, - buffer.ToPointer()); - } + adapter->GetProperty( + DXCoreAdapterProperty.DriverDescription, + descriptionSize, + buffer.ToPointer()); adapterDescription = Marshal.PtrToStringAnsi(buffer) ?? string.Empty; } @@ -365,7 +360,6 @@ public static bool HasNpu() adapterDescription = adapterDescription[..^1]; } - adapters.Add(adapter); if (adapterDescription.Contains("NPU") || adapterDescription.Contains("AI Boost")) { _hasNpu = true; diff --git a/AIDevGallery/Utils/DeviceUtils.cs b/AIDevGallery/Utils/DeviceUtils.cs index 6943dd9a..9192e806 100644 --- a/AIDevGallery/Utils/DeviceUtils.cs +++ b/AIDevGallery/Utils/DeviceUtils.cs @@ -9,22 +9,23 @@ namespace AIDevGallery.Utils; internal static class DeviceUtils { - public static int GetBestDeviceId() + public static unsafe int GetBestDeviceId() { int deviceId = 0; nuint maxDedicatedVideoMemory = 0; try { DXGI_CREATE_FACTORY_FLAGS createFlags = 0; - Windows.Win32.PInvoke.CreateDXGIFactory2(createFlags, typeof(IDXGIFactory2).GUID, out object dxgiFactoryObj).ThrowOnFailure(); - IDXGIFactory2? dxgiFactory = (IDXGIFactory2)dxgiFactoryObj; + Windows.Win32.PInvoke.CreateDXGIFactory2(createFlags, typeof(IDXGIFactory2).GUID, out void* dxgiFactoryObj).ThrowOnFailure(); + IDXGIFactory2* dxgiFactory = (IDXGIFactory2*)dxgiFactoryObj; - IDXGIAdapter1? selectedAdapter = null; + IDXGIAdapter1* selectedAdapter = null; var index = 0u; do { - var result = dxgiFactory.EnumAdapters1(index, out IDXGIAdapter1? dxgiAdapter1); + IDXGIAdapter1* dxgiAdapter1 = null; + var result = dxgiFactory->EnumAdapters1(index, &dxgiAdapter1); if (result.Failed) { @@ -37,7 +38,7 @@ public static int GetBestDeviceId() } else { - DXGI_ADAPTER_DESC1 dxgiAdapterDesc = dxgiAdapter1.GetDesc1(); + DXGI_ADAPTER_DESC1 dxgiAdapterDesc = dxgiAdapter1->GetDesc1(); if (selectedAdapter == null || dxgiAdapterDesc.DedicatedVideoMemory > maxDedicatedVideoMemory) { @@ -59,21 +60,22 @@ public static int GetBestDeviceId() return deviceId; } - public static ulong GetVram() + public static unsafe ulong GetVram() { nuint maxDedicatedVideoMemory = 0; try { DXGI_CREATE_FACTORY_FLAGS createFlags = 0; - Windows.Win32.PInvoke.CreateDXGIFactory2(createFlags, typeof(IDXGIFactory2).GUID, out object dxgiFactoryObj).ThrowOnFailure(); - IDXGIFactory2? dxgiFactory = (IDXGIFactory2)dxgiFactoryObj; + Windows.Win32.PInvoke.CreateDXGIFactory2(createFlags, typeof(IDXGIFactory2).GUID, out void* dxgiFactoryObj).ThrowOnFailure(); + IDXGIFactory2* dxgiFactory = (IDXGIFactory2*)dxgiFactoryObj; - IDXGIAdapter1? selectedAdapter = null; + IDXGIAdapter1* selectedAdapter = null; var index = 0u; do { - var result = dxgiFactory.EnumAdapters1(index, out IDXGIAdapter1? dxgiAdapter1); + IDXGIAdapter1* dxgiAdapter1 = null; + var result = dxgiFactory->EnumAdapters1(index, &dxgiAdapter1); if (result.Failed) { @@ -86,7 +88,7 @@ public static ulong GetVram() } else { - DXGI_ADAPTER_DESC1 dxgiAdapterDesc = dxgiAdapter1.GetDesc1(); + DXGI_ADAPTER_DESC1 dxgiAdapterDesc = dxgiAdapter1->GetDesc1(); if (selectedAdapter == null || dxgiAdapterDesc.DedicatedVideoMemory > maxDedicatedVideoMemory) {