设备、交换链和设备环境如何创建

  1. 设备环境是什么?创建设备、交换链和设备环境通过什么方法调用?

    设备和交换链能够通过Direct3D函数全部创建,这个函数就是D3D11CreateDeviceAndSwapChain。当然你也可以调用每一具体类型的D3D函数创建(如CreateSwapChain仅仅创建交换链)。这个函数最后一个参数也会返回创建的设备环境(渲染环境),Direct3D渲染环境是一种告诉设备怎样绘制的渲染环境,它包括渲染状态和其它的绘制信息。
    D3D11CreateDeviceAndSwapChain函数的参数值如下:

    1. [in]一个用于创建设备的视频适配器(即显卡)的指针。如果传进NULL,则D3D使用默认显卡。如果在机器上装有多个显卡,就可启用该参数。
    2. [in]我们希望创建的驱动设备类型(例如:硬件设备,WARP设备,软件设备或参考设备)。
    3. [in]实现软件渲染设备的动态库句柄。如果使用的驱动设备类型是软件设备,则该参数不能为NULL。
    4. [in]创建标志。D3D中的创建标志0用于我们的游戏发布,而标志D3D11_CREATE_DEVICE_DEBUG则允许我们创建可供调试的设备,在开发中这是比较有用的。
    5. [in]我们所希望创建的特性级别(也称特征级别),以我们的希望值排序进行安排。因为这个参数是一个指针,所以你可以传一个数组进来。
    6. [in]特性级别数组中的特性数量。(例如数组中有D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1的话,特性数量就是数组大小3。)
    7. [in]SDK 版本号。因为我们只使用DirectX 11 SDK,所以书中都是D3D11_SDK_VERSION。
    8. [in]用于描述交换链的对象。(就是用于描述我们将创建的交换链的一个结构体,我们依赖这个结构体的内容来创建交换链)
    9. [out]该函数调用成功后保存我们创建好的设备。
    10. [out]该函数调用成功后保存我们成功创建的特征级别。
    11. [out]该函数调用成功后保存设备的渲染环境。
  2. 第二个参数,如何创建出条件允许下,我们最希望的设备类型?

    我们可以采用循环,循环中依次遍历按我们希望的设备类型排序的数组,循环体中调用D3D11CreateDeviceAndSwapChain函数,如果调用失败则继续循环,调用成功则退出循环。
    首先我们创建一个按我们希望的设备类型排序的数组:

    D3D_DRIVER_TYPE driverTypes[] =
    {
    D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,
    D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE
    };
    

    接着再保存这个数组大小,以便我们用来做循环的条件,ARRAYSIZE是windows的api,可以得到数组的大小:

    unsigned int totalDriverTypes = ARRAYSIZE( driverTypes );
    

    每次调用D3D11CreateDeviceAndSwapChain函数时,第二个参数就依次填这个数组的元素值。

  3. 第四个参数,如何让编译器根据是否在debug调试状态,来传进不同的实参?

    我们可以用一个宏判断编译器是否在debug调试状态。
    首先我们创建一个用于保存状态标记的变量:

    unsigned int creationFlags = 0;
    

    然后通过宏来让编译器是否在调试状态来决定creationFlags的值:

    ifdef _DEBUG
    creationFlags |= D3D11_CREATE_DEVICE_DEBUG; //按位与或
    #endif
    
  4. 特性级别也需要用一个循环遍历吗?

    不需要,因为该函数已经提供一个可以传入数组的参数(第5个参数)和一个指定数组大小的参数(第6个参数),我们只需要填好这两个参数,该函数在内部就会我们依次遍历特性级别。
    这和我们上面写的创建最希望的设备数组步骤一样。
    首先,我们创建一个特性级别数组:

    D3D_FEATURE_LEVEL featureLevels[] =
    {
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0
    }
    

    然后保存数组大小:

    unsigned int totalFeatureLevels = ARRAYSIZE( featureLevels );
    
  5. 需要描述一个交换链的什么内容?

    一个交换链的描述用于我们想创建怎样的交换链,该描述交换链的结构体有如下成员:

    1. 缓存页数量(用于页面翻转的主/辅助缓存)。
    2. 缓存页的宽度和高度。
    3. 我们交换链中缓存的用法被设置为
      DXGI_USGAE_RENDER_TARGET_OUTPUT,意味着该交换链能够用于输出,即它能够被渲染。
    4. 缓存格式。
        有时你会被要求提供具体的DXGI格式。不同格式用于描述不同的事物,比如描述图像的布局,每一颜色使用的bits数,或者对于顶点缓存的顶点布局。最常见的是,DXGI格式用于描述交换链中的缓存布局。DXGI格式不是具体的某一类型的数据,只是描述它们是什么结构。
        一个DXGI格式的例子是,DXGI_FORMAT_R8G8B8A8_UNORM用于描述数据对于RGBA的每一部分用8bits来存储。当定义顶点,使用DXGI_FORMAT_R32G32B32_FLOAT格式时,将对于三个部分都用32bits来存储。尽管格式可以是RGB,它只是描述数据的布局,而不管数据用于何处。
        有时你可以看到对于每部分有相同的比特数但是后缀不同的格式。例如DXGI_FORMAT_R32G32B32A32_FLOAT 和DXGI_FORMAT_R32G32B32A32_UINT,这表示它们描述的对象的每一部分使用两种格式都使用相同数量的bit,但 是包含这些bit 的数据类型不同。这里考虑全部类型的格式。
        对于没有声明类型的对象可以用无类型的格式。使用此种格式表明对象的每一部分使用的bits 数量而不关心所包含的数据类型,例如DXGI_FORMAT_R32G32B32A32_TYPELESS格式。公共格式列表见于表2.1 中。

      表2.1:Direct3D 公共格式
      格式 描述
      DXGI_FORMAT_R32G32B32A32_TYPELESS 组成无类型RGBA 分量的128 位格式
      DXGI_FORMAT_R32G32B32A32_FLOAT 浮点类型RGBA 分量的128 位格式
      DXGI_FORMAT_R32G32B32A32_UINT 无符号整型RGBA 分量的128 位格式
      DXGI_FORMAT_R32G32B32A32_SINT 有符号整型RGBA 分量的128 位格式
      DXGI_FORMAT_R8G8B8A8_TYPELESS 组成无类型RGBA 分量的32 位格式
      DXGI_FORMAT_R8G8B8A8_UINT 无符号整型RGBA 分量的32 位格式
      DXGI_FORMAT_R8G8B8A8_SINT 有符号整型RGBA 分量的32 位格式

    5. 刷新率,用于决定刷新显示的频率(使用60/1表示60Hz的刷新频率,这也是交换链的交换频率)

    6. 窗口句柄(与CreateWindow函数创建的一样,指定我们要绘制的窗口)
    7. 用于是否应用窗口模式,true表示窗口模式,false当然表示全屏模式。
    8. 取样描述中的取样数量和质量。取样描述定义了D3D中多重取样性质,多重取样是一种用于像素间的取样和利用平均值渲染来创建在形状颜色间平滑过渡的技术。我们试图使用多重取样来减少所谓的锯齿边(即阶梯效果)。如果锯齿边很多,那游戏看起来就像“我的世界”那样,除非是游戏风格故意这样设定,锯齿边往往会使玩家感觉游戏画面不美观、不逼真。如下图:

    下面我们就创建一个交换链描述对象:

    RECT dimensions;
    GetClientRect( hwnd, &dimensions );
    unsigned int width = dimensions.right - dimensions.left;
    unsigned int height = dimensions.bottom - dimensions.top;
    DXGI_SWAP_CHAIN_DESC swapChainDesc;
    ZeroMemory( &swapChainDesc, sizeof( swapChainDesc ) );
    swapChainDesc.BufferCount = 1; //
    swapChainDesc.BufferDesc.Width = width;
    swapChainDesc.BufferDesc.Height = height;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow = hwnd;
    swapChainDesc.Windowed = true;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
    

最后,附上一个创建设备、交换链和设备环境的示例:

    //创建设备和交换链m_hInstance = hInstance;m_hwnd = hwnd;RECT dimensions;GetClientRect( hwnd, &dimensions );unsigned int width = dimensions.right - dimensions.left;unsigned int height = dimensions.bottom - dimensions.top;D3D_DRIVER_TYPE driverTypes[] ={D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE};unsigned int totalDriverTypes = ARRAYSIZE( driverTypes );D3D_FEATURE_LEVEL featureLevels[] ={D3D_FEATURE_LEVEL_11_0,D3D_FEATURE_LEVEL_10_1,D3D_FEATURE_LEVEL_10_0};unsigned int totalFeatureLevels = ARRAYSIZE( featureLevels );DXGI_SWAP_CHAIN_DESC swapChainDesc;ZeroMemory( &swapChainDesc, sizeof( swapChainDesc ) );swapChainDesc.BufferCount = 1;swapChainDesc.BufferDesc.Width = width;swapChainDesc.BufferDesc.Height = height;swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;swapChainDesc.OutputWindow = hwnd;swapChainDesc.Windowed = true;swapChainDesc.SampleDesc.Count = 1;swapChainDesc.SampleDesc.Quality = 0;unsigned int creationFlags = 0;#ifdef _DEBUGcreationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endifHRESULT result;unsigned int driver = 0;for( driver = 0; driver < totalDriverTypes; ++driver ){result = D3D11CreateDeviceAndSwapChain( 0, driverTypes[driver], 0, creationFlags,featureLevels, totalFeatureLevels,D3D11_SDK_VERSION, &swapChainDesc, &m_pSwapChain,&m_pD3DDevice, &m_featureLevel, &m_pD3DContext );if( SUCCEEDED( result ) ){m_driverType = driverTypes[driver];break;}}if( FAILED( result ) ){DXTRACE_MSG( L"Failed to create the Direct3D device!" );return false;}

DirectX11 设备、交换链和设备环境如何创建相关推荐

  1. [Vulkan教程]绘制一个三角形/呈现/交换链(Swip chain)

    文章目录 检查交换链支持 启用设备扩展 查询交换链支持详情 为交换链选择正确的设置 表面格式 呈现模式 交换范围 创建交换链 检索交换链中的图像 Vulkan没有默认缓冲区的概念,因此需要一个东西提供 ...

  2. 初始Vulkun(7):交换链

    08/02/2020,03/22/2021 文章目录 交换链 显卡是否支持交换链(VK_KHR_swapchain) 逻辑设备需要扩展交换链 配置交换链环境 获取surface的设置细节 保持与sur ...

  3. Vulkan填坑学习Day06—交换链

    Vulkan 交换链 Vulkan 交换链,在这一章节,我们了解一下将渲染图像提交到屏幕的基本机制.这种机制称为交换链,并且需要在Vulkan上下文中被明确创建.从屏幕的角度观察,交换链本质上是一个图 ...

  4. Vulkan 交换链详解

    大家好,接下来将为大家介绍Vulkan 交换链详解. 在这一章节,我们了解一下将渲染图像提交到屏幕的基本机制.这种机制称为交换链,并且需要在Vulkan上下文中被明确创建.从屏幕的角度观察,交换链本质 ...

  5. Vulkan入门(四)-Surface和交换链.md

    文章目录 参考资料 简述 一. Window Surface 1.1 创建窗口Surface 二. Swap Chain-交换链 2.1 检查GPU是否支持交换链 2.2 使能设备扩展 2.3 获取关 ...

  6. Vulkan学习--5.创建一个窗口表面和交换链

    • 创建一个窗口,窗口表面和交换链 1.检测交换链是否支持 2.启用交换链扩展 3.选择适当的表面格式 4.查找最佳的可用呈现模式 5.设置交换范围 6.创建窗口表面 7.创建交换链 8.查询交换链支 ...

  7. Oculus VR SDK实现-Oculus针对双眼显示的交换链设计

    目录 一.创建交换链 二.创建DepthBuffer和FrameBuffer 三.基于交换链对Buffer的使用 一.创建交换链 首先我们关注一下ovrFramebuffer这个结构体: typede ...

  8. Vulkan Cookbook 第二章 14 使用R8G8B8A8格式和邮箱呈现模式创建交换链

    使用R8G8B8A8格式和邮箱呈现模式创建交换链 译者注:示例代码点击此处 要创建交换链,需要获取大量附加信息并准备想到多的参数.为了呈现准备阶段所需的所有步骤的顺序以及如何使用所获得的信息,我们将创 ...

  9. 问一个AddDevice和设备符号链的问题??

    问一个AddDevice和设备符号链的问题?? UNICODE_STRING ntDeviceName;      UNICODE_STRING win32DeviceName;      RtlIn ...

最新文章

  1. 数据性能调校——查看最耗资源的各种SQL
  2. DL:深度学习算法(神经网络模型集合)概览之《THE NEURAL NETWORK ZOO》的中文解释和感悟(二)
  3. 数论分块专题复习(余数求和+模积和+Ice Rain+The Fool)
  4. Juice Extractor dp
  5. Java高并发BlockingQueue重要的实现类二
  6. 交换排序图解_排序算法(一):初级比较排序
  7. list元素求和_C# lamda =gt;与 数组 list,简单应用
  8. UEFI学习 (一) ——下载与编译
  9. c++ primer 5学习小结
  10. android6.0 framework修改使用两个声卡
  11. Mybatis对Double类型的字符串进行范围查询
  12. 前端工程师的前途与价值体现
  13. NIO源码解析-FileChannel
  14. mysql自增列防止恢复初始_重置mysql的自增列 AUTO_INCREMENT初时值 | 瑕疵学院 – 学习无瑕疵,成就有保障...
  15. WebSocket 获取客户端的IP
  16. IDEA设置背景和定时更换背景
  17. (实验一)十进制整数的原反补移码实现
  18. 前端 实现数据的分批加载
  19. Jenkins自动化部署详细教程
  20. python中ret是什么意思_python 代码中 ret=True 代表什么意思?

热门文章

  1. java boolean空_什么时候应该使用Boolean的null值?
  2. VRay 3.6 for SketchUp 混合材质之艺术背景制作教程
  3. 如果让你来设计网络,如何让电脑互联?
  4. 广域网优化仍是容灾和云接入的关键
  5. 2020年中国经济(第二部分)
  6. 使用UltraISO制作U盘启动盘+重装win10操作系统
  7. php phantomjs 安装_php phantomjs怎么安装
  8. Python 排列组合的计算
  9. 头歌--Java入门 - Java初体验
  10. 为你详解Linux安装GCC方法