在x_jun 的DX11 入门教程里面留了一些作业,本篇文章是第一篇文章的课后作业
原文链接 :DirectX11 With Windows SDK--01 DirectX11初始化

  1. 尝试修改项目代码,让窗口内的显示变红
    这个问题比较简单 我们找到 DrawScene() 函数把 static float blue[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; 这个代码段改为 static float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; 即可,记得修改参数

  2. 某些电脑可能有多于一个的显示适配器(显卡)。首先要通过CreateDXGIFactory创建IDXGIFactory,然后使用IDXGIFactory::EnumAdapters来枚举显示适配器。尝试通过这种方式查看你的电脑有多少个显示适配器(IDXGIAdapter),并察看它们的信息。
    这个问题首先我在D3DApp::InitDirect3D()函数的最后,按照问题的提示 添加了如下代码

     // 先创建Factory 和 adapter
     ComPtr<IDXGIFactory> Factory = nullptr;
     ComPtr<IDXGIAdapter> adapter = nullptr;
     // 根据函数的要求添加参数
     CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(Factory.GetAddressOf()));
     // 枚举显示适配器  可以修改一下 数字 枚举
     Factory->EnumAdapters(0, adapter.GetAddressOf());
     // 通过 GetDesc函数去获取 adapter的描述,需要填充一个 DXGI_ADAPTER_DESC
     DXGI_ADAPTER_DESC apDesc;
     adapter->GetDesc(&apDesc);
     // 输出 Description
     // 把WCHAR 类型转为char 需要添加 #include <comdef.h>头文件
     _bstr_t b(apDesc.Description);
     const char* s = b;
     // 这个是格式化输出 可以在输出中打印字符 要是用这个先要添加 最下面的宏
     OUTINFO_1_PARAM("IDXGIAdapter----DEBUG----%s\n", s);
     // OUTINFO 系列的宏定义 (百度的)
     //输出调试信息--在DebugView软件里面看调试信息
     #define OUTINFO_0_PARAM(fmt) {CHAR sOut[256];CHAR sfmt[50];sprintf_s(sfmt,"%s%s","INFO--",fmt);sprintf_s(sOut,(sfmt));OutputDebugStringA(sOut);}
     #define OUTINFO_1_PARAM(fmt,var) {CHAR sOut[256];CHAR sfmt[50];sprintf_s(sfmt,"%s%s","INFO--",fmt);sprintf_s(sOut,(sfmt),var);OutputDebugStringA(sOut);}
     #define OUTINFO_2_PARAM(fmt,var1,var2) {CHAR sOut[256];CHAR sfmt[50];sprintf_s(sfmt,"%s%s","INFO--",fmt);sprintf_s(sOut,(sfmt),var1,var2);OutputDebugStringA(sOut);}
     #define OUTINFO_3_PARAM(fmt,var1,var2,var3) {CHAR sOut[256];CHAR sfmt[50];sprintf_s(sfmt,"%s%s","INFO--",fmt);sprintf_s(sOut,(sfmt),var1,var2,var3);OutputDebugStringA(sOut);}

    运行程序我们就能到看详细信息了 如图所示:
    图片说明

  3. 一个显示适配器可能关联了多个输出设备(IDXGIOutput),你可以使用IDXGIAdapter::EnumOutputs方法来枚举出特定的输出,尝试观察它们的信息
    紧跟着在上一个问题的代码后面添加

        ComPtr<IDXGIOutput> output = nullptr;
     // 尝试修改函数中的数字 观察控制台输出
     adapter->EnumOutputs(0, output.GetAddressOf());
     DXGI_OUTPUT_DESC outDesc;
     output->GetDesc(&outDesc);
     _bstr_t out(outDesc.DeviceName);
     const char* o = out;
     OUTINFO_1_PARAM("IDXGIOutput---DEBUG----- %s\n", o);

    我的输出如下
    图片说明

  4. 对于给定的像素格式,一个输出设备可以支持许多种显示模式(DXGI_MODE_DESC),通过它可以看到全屏宽度、高度、刷新率。尝试使用IDXGIOutput::GetDisplayModeList方法观察所有支持的模式(传递DXGI_FORMAT_R8G8B8A8_UNORM格式进去)。
    在下面添加代码

     UINT num = 0;
     DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
     UINT flags = DXGI_ENUM_MODES_INTERLACED;
     output->GetDisplayModeList(format, flags, &num, 0);
    
     DXGI_MODE_DESC* pDescs = new DXGI_MODE_DESC[num];
     output->GetDisplayModeList(format, flags, &num, pDescs);
     OUTINFO_1_PARAM("dasda-%d\n",pDescs->Width);

    通过debug 断点调试我们可以发现如图
    图片说明

  5. 默认情况下的窗口程序是可以通过ALT+ENTER来进入/退出全屏的。此外,我们可以通过IDXGISwapChain来动态设置窗口全屏属性,找到对应的方法并尝试一下。

     m_pSwapChain->SetFullscreenState(true, nullptr);
  6. 现在尝试指定显示适配器来创建D3D设备。通过CreateDXGIFactory函数来创建IDXGIFactory,通常它会包含接口IDXGIFactory1,但有可能它也会包含接口IDXGIFactory2。在没有创建D3D设备的情况下,这种方式就可以帮助我们了解是否可以创建出Direct3D 11.1的设备。为了能够指定显示适配器来创建D3D11设备,我们需要将D3D_DRIVER_TYPE强行设置为D3D_DRIVER_TYPE_UNKNOWN,否则在创建设备的时候会得到如下报错信息:

      DX ERROR: D3D11CreateDevice: When creating a device from an existing adapter (i.e. pAdapter is non-NULL), DriverType must be D3D_DRIVER_TYPE_UNKNOWN. [ INITIALIZATION ERROR #3146141: ]

找到InitDirect3D() 函数在遍历驱动类型数组的for循环上面添加

```cpp
ComPtr<IDXGIAdapter> dxgiAdapter = nullptr;
ComPtr<IDXGIFactory> dxgiFactory = nullptr;
CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(dxgiFactory.GetAddressOf()));
dxgiFactory->EnumAdapters(0, dxgiAdapter.GetAddressOf());
//修改D3D11CreateDevice() 函数 将第一个参数设置为 dxgiAdapter.Get()
```