DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色( 三 )


// 创建完成,那就显示ShowWindow(hWnd, SW_NORMAL);获取实际的窗口大小 , 这将用来决定后续交换链的创建 。什么是交换链?自己去了解
RECT windowRect;GetClientRect(hWnd, &windowRect);clientSize = new SizeI(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);以上代码就完成了创建 Win32 窗口
获取显示适配器接口这一步是可选的,通过枚举 DX 提供的抽象的显示适配器接口,可以用来后续创建 D3D 设备 。本文这里是给大家演示如何获取抽象的显示适配器接口的方法 , 没有指定显示适配器接口也是可以创建 D3D 设备
显示适配器接口 IDXGIAdapter 是对硬件或软件的一个抽象,可以是一个显卡 , 也可以是一个软件渲染器 。这里获取到的抽象的显示适配器接口,在大部分情况下都是和具体的显卡相关的,但是不代表着一定就是真实的显卡
下图是从官方文档拷贝的 , 一个电脑加两个显卡的对象关系

DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色

文章插图
先尝试使用 IDXGIFactory6 提供的 EnumAdapterByGpuPreference 方法枚举显卡,这个方法的功能是可以按照给定的参数进行排序,特别方便开发时,获取首个可用显卡
想要使用 EnumAdapterByGpuPreference 方法,需要先获取 IDXGIFactory6 对象 。而 IDXGIFactory6 对象可以通过工厂创建 IDXGIFactory2 对象间接获取
接下来咱也会用到 IDXGIFactory2 提供的功能
// 开始创建工厂创建 D3D 的逻辑var dxgiFactory2 = DXGI.DXGI.CreateDXGIFactory1<DXGI.IDXGIFactory2>();为了让大家方便阅读获取显卡的代码,将获取显卡的代码放入到 GetHardwareAdapter 方法
private static IEnumerable<DXGI.IDXGIAdapter1> GetHardwareAdapter(DXGI.IDXGIFactory2 factory) { }先尝试从 IDXGIFactory2 对象获取 IDXGIFactory6 对象
在 DX 的设计上 , 接口都是一个个版本迭代的,为了保持兼容性,只是新加接口 , 而不是更改原来的接口定义 。也就是获取到的对象,也许有在这台设备上的 DX 版本,能支持到 IDXGIFactory6 版本 , 通用的做法是调用 QueryInterface* 方法,例如 QueryInterfaceOrNull 方法,尝试获取到更新的版本的接口对象 。使用封装的 QueryInterfaceOrNull 方法,可以在不支持时返回空,通过判断返回值即可了解是否支持
DXGI.IDXGIFactory6? factory6 = factory.QueryInterfaceOrNull<DXGI.IDXGIFactory6>();if (factory6 != null){// 这个系统的 DX 支持 IDXGIFactory6 类型}else{// 不支持就不支持咯 , 用旧版本的方式获取显示适配器接口}在 IDXGIFactory6 新加的 EnumAdapterByGpuPreference 方法可以支持传入参数,通过参数按照顺序返回显示适配器接口
传入高性能参数开始获?。岚凑账承蚧袢〉?DX 认为的高性能排列的顺序
// 先告诉系统,要高性能的显卡for (int adapterIndex = 0;factory6.EnumAdapterByGpuPreference(adapterIndex, DXGI.GpuPreference.HighPerformance,out DXGI.IDXGIAdapter1? adapter).Success;adapterIndex++){if (adapter == null){continue;}}再扔掉使用软渲染的 , 扔掉软渲染的这一步只是为了演示如何判断获取到的显示适配器接口是采用软渲染的
// 先告诉系统,要高性能的显卡for (int adapterIndex = 0;factory6.EnumAdapterByGpuPreference(adapterIndex, DXGI.GpuPreference.HighPerformance,out DXGI.IDXGIAdapter1? adapter).Success;adapterIndex++){if (adapter == null){continue;}DXGI.AdapterDescription1 desc = adapter.Description1;if ((desc.Flags & DXGI.AdapterFlags.Software) != DXGI.AdapterFlags.None){// Don't select the Basic Render Driver adapter.adapter.Dispose();continue;}}这里可以输出获取到的显示适配器接口的描述,可以看看在不同的设备上的输出
Console.WriteLine($"枚举到 {adapter.Description1.Description} 显卡");所有的获取的代码如下
DXGI.IDXGIFactory6? factory6 = factory.QueryInterfaceOrNull<DXGI.IDXGIFactory6>();if (factory6 != null){// 先告诉系统 , 要高性能的显卡for (int adapterIndex = 0;factory6.EnumAdapterByGpuPreference(adapterIndex, DXGI.GpuPreference.HighPerformance,out DXGI.IDXGIAdapter1? adapter).Success;adapterIndex++){if (adapter == null){continue;}DXGI.AdapterDescription1 desc = adapter.Description1;if ((desc.Flags & DXGI.AdapterFlags.Software) != DXGI.AdapterFlags.None){// Don't select the Basic Render Driver adapter.adapter.Dispose();continue;}//factory6.Dispose();Console.WriteLine($"枚举到 {adapter.Description1.Description} 显卡");yield return adapter;}factory6.Dispose();}

推荐阅读