Skip to content

Commit

Permalink
review.
Browse files Browse the repository at this point in the history
  • Loading branch information
lijipeng787 committed Mar 17, 2018
1 parent 1804eb0 commit ea792ae
Showing 1 changed file with 44 additions and 47 deletions.
91 changes: 44 additions & 47 deletions Chapter 4 Direct3D Initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
我们通常用接口`Interface`的形式引用一个`COM`组件,使得我们能够将其视为`C++`里面的类,并且当作类使用。
大多数的`COM`细节在我们使用`C++`编写`DirectX`程序的时候就被隐藏了。
唯一需要注意的是我们是通过指定的函数或者另外一个接口去实例化一个`Interface`,而不是通过使用`C++`的关键字`new`。(**Interface通常声明为一个指针**)。
`COM`组件是引用计数的,也就是说当我们不需要使用一个接口的时候,不必使用delete释放内存而是必须通过`Release`方法去释放它(**所有的Interface都是继承自IUnknown的**)。
当一个`COM`组件的引用次数是0的时候我们才会真正释放组件所占内存。
`COM`组件是引用计数的,也就是说当我们不需要使用一个接口的时候,不必使用delete释放内存而是必须通过`Release`方法去释放它(**所有的Interface都是继承自IUnknown的**)。当一个`COM`组件的引用次数是0的时候我们才会真正释放组件所占内存。

为了帮助我们管理`COM`组件的生命期,`Windows Runtime Library`提供了`Microsoft::WRL::ComPtr`这个类,使我们以智能指针的形式使用`COM`组件。
当一个`ComPtr`实例再也不会被使用的时候,它就会自己调用`Release`释放自己。这样的话我们就不需要关心`COM`组件的释放问题了。
Expand Down Expand Up @@ -203,12 +202,14 @@
![Image4.5](Images/4.5.png)
> 图片4.5
我们看到一个穿过多边形边缘的像素(a),有3个像素的颜色是绿色的,还有一个像素因为在多边形外面,他的颜色并没有被改变,因此他还是以前的颜色
然后我们计算最后的颜色,即一组像素作为最后的一个像素,我们通常是取平均值来作为最后的颜色。这样的话他就会比原本的锯齿状平滑很多
我们可以看到一个穿过多边形边缘的像素(a),经过多重采样的计算,前三个象限的像素颜色是绿色,而第四象限的像素出现在多边形外面,因此他的颜色并没有被改变,还是上一次绘制颜色或Clear命令的颜色
(b)为了计算该像素最后的颜色,我们对四个子像素颜色(三个绿色,一个白色)求和取平均值。这样结果会更加平滑,在多边形的边缘锯齿效果也会得到抑制

在图片$4.5$中,我们将4个像素分为一个网格模式(即将一个像素组分成4个小矩形)。
但是具体的模式却是由硬件来决定的,即一个像素组里面的子像素在这个像素组中的位置。
`Direct3D`并没有要求子像素的位置在像素组的哪里。
注意:超级采样与多重采样的关键区别在于:超级采样以子像素为单位计算,因此子像素的颜色可能不同;多重采样以像素为单位计算,而被多边形覆盖的可见子像素使用该像素的颜色。由于计算图像颜色是渲染管线中耗费最大的几个操作之一,所以对比超级采样,多重采样的性能提升是巨大的,另一方面,超级采样的结果更加精确。

在图片$4.5$中,我们使用一种将一个像素分为四个子像素的统一网格模式。
但是具体的模式由硬件决定(即一个像素组里面的子像素在这个像素组中的位置)。
`Direct3D`对此没有做出明确定义,在一些情况下,某些模式性能、质量会更高。

### 4.1.8 Multisampling in Direct3D

Expand All @@ -222,52 +223,54 @@ struct DXGI_SAMPLE_DESC
};
```

`Count`表示采样的时候几个像素一组`Quality`表示采样的质量等级(这个的支持需要看具体的硬件)。
高采样数量和采样等级的开销是很大的,所以在质量和效率上面要权衡一下
纹理格式和采样数量会影响采样等级的范围
`Count`表示对每个像素的采样次数`Quality`表示采样的质量(不同硬件支持不同的采样质量)。
高采样数量和采样等级的开销巨大,所以需要权衡质量与效率
另外,纹理格式和采样数量会影响采样等级

我们可以使用`ID3D12Device::CheckFeatureSupport`来查询采样等级的支持
我们可以使用`ID3D12Device::CheckFeatureSupport`来查询特定纹理格式和采样数量对采样等级的支持

> 这一段是代码,可以自己去原书上看
> 本部分为代码,请参考原书。
注意第二个参数既是输入的也是输出的,对于输入来说,我们必须确定纹理的格式,采样数量,我们想要查询的采样标识
然后函数填充`NumQualityLevels`作为输出。质量等级的范围就是`[0,NumQualityLevels)`.
注意第二个参数既是输入的也是输出,对于输入,我们必须确定纹理的格式,采样数量,以及我们想要查询的采样标识
然后函数填充`NumQualityLevels`作为输出。质量等级的范围为`[0,NumQualityLevels-1)`.

每个像素的最高采样次数定义如下:
```C++
#define D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT (32)
```
通常为了保证性能和空间足够,采样数量一般是4或者8就好了(逗我...)
如果你不想使用多重采样,你可以设置采样数量为1,质量等级为0。
通常为了保证性能和内存使用,采样数量可以设置为4或8
如果你不想使用多重采样,你可以设置采样数量为1,质量等级为0。最后,所有支持`DirectX 11`的设备都支持全部`render target`格式的4X多重采样。
### 4.1.9 Feature Levels
注意:交换链缓冲区和深度缓冲区都需要填充`DXGI_SAMPLE_DESC`这个结构体,并且相对应的后台缓冲区和深度缓冲区的多重采样设定必须完全相同。
这一章怎么全是`Direct3D 11`的内容,有毒,所以我来意译(YY)了。
### 4.1.9 Feature Levels
`Direct3D 12`介绍了特征等级的概念(即`D3D_FEATURE_LEVEL`类型)。
`Direct3D 11`中引入了特征等级的概念(即`D3D_FEATURE_LEVEL`类型)。
特征等级严格定义了一些功能,举个例子来说如果`GPU`支持`Direct3D 12`的特征等级的话,那么他就必须支持所有的`Direct3D 12`的功能(还有一些其他功能,例如多重采样还是需要查询,因为他对于不同的设备来可以说有差异)。
特征等级严格定义了一些功能,例如,如果`GPU`支持`Direct3D 11`的特征等级,那么他就必须支持所有的`Direct3D 11`功能(还有一些其他功能,例如多重采样还是需要查询,因为他对于不同的设备来可以说有差异)。
如果硬件并不支持现在的特征等级的话,应用就会自己使用最新的硬件支持的版本的特征等级
如果硬件并不支持现在的特征等级,应用就会使用自己硬件支持的最新版本特征等级
### 4.1.10 DirectX Graphics Infrastructure
`DirectX`图形接口是用于`Direct3D`的`API`。
这个接口是基于一些图形`API`会有很多共通的地方从而出现的。
例如2D渲染`API`中你也需要类似3D渲染中一样交换交换链,因此我们就产生了`DXGI`
`IDXGISwapChain`就是`DXGI`中的一部分,它主要用于全屏和窗口的切换,枚举图形系统信息,如显示设备,显示器,支持的显示模式等。
`DirectX`图形接口(**DXGI**)是与`Direct3D`一起使用的`API`。
这个接口抽取出了各种图形`API`中共用的操作。
例如,2D渲染`API`像3D渲染中一样需要交换链并交换页面以获得流畅的动画表现。
`IDXGISwapChain`就是`DXGI`中的一部分,它主要用于全屏和窗口的切换,枚举图形系统信息,如显示设备,显示器,及支持的显示模式等,另外,**DXGI**中定义了各种受支持的表面格式(**DXGI_FORMAT**)。
我们现在简单的介绍初始化`Direct3D`时所必须的`DXGI`接口。
`IDXGIFactory`是其中最重要的一个,主要负责创建交换链,枚举显示适配器。通常情况下,显示适配器是物理硬件的一部分(显卡),另外,系统拥有一个软件显示适配器,软件显示适配器可以模拟硬件的图形功能(当没有可用的硬件适配器时),在windows8及以上系统,默认会有一个名为**Microsoft Basic Render Driver**的软件适配器。
一个系统可以有很多适配器(显卡),一个显卡设备使用`IDXGIAdapter`接口。下面的内容是枚举设备的代码:
我们会在我们初始化`Direct3D`的时候简要的描述下`DXGI`接口。
例如`IDXGIFactory`主要是用于创建交换链,枚举显示设备。通常来说显示设备是物理硬件的一部分(显卡)。
一个系统可以有很多显卡设备,一个显卡设备使用`IDXGIAdapter`接口。下面的内容是枚举设备的代码。
一个系统可以有数个显示器,一个显示器就是一个显示输出(**display output**),接口`IDXGIOutput`代表一个输出。
每个显示适配器会和多个显示器关联,例如,你有一台带有3个显示器和两个显卡的电脑,那么肯定有一个显卡至少与两台显示器相关联。下面的代码枚举所有与显示适配器关联的输出:
一个系统可以有几个显示器,一个显示器就是一个显示输出,他被定义为`IDXGIOutput`。
每个显示设备会和多个显示器关联,例如你有3个显示器两个显卡的电脑,那么肯定有一个显卡至少管理两台显示器。下面的代码枚举显示器输出。
> 本部分为代码,请参考原书。
### 4.1.11 Checking Feature Support
我们已经使用过`ID3D12Device::CheckFeatureSupport`去检测现在使用的显卡对多重采样的支持了。
但是这只是这个函数可以检测的一部分特性。
我们已经使用过`ID3D12Device::CheckFeatureSupport`去检测当前显卡对多重采样的支持了。但是这只是这个检测函数的一部分功能。该函数的声明如下:
```C++
HRESULT ID3D12Device::CheckFeatureSupport(
Expand All @@ -282,26 +285,20 @@ struct DXGI_SAMPLE_DESC
- `D3D12_FEATURE_FEATURE_LEVELS`:检测特性等级支持。
- `D3D12_FEATURE_FORMAT_SUPPORT`:检测纹理格式支持。
- `D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS`:检测多重采样质量等级支持。
- `pFeatureSupportData`:一个存储你需要检测的特性的数据的地址的指针。他的值依据你需要检测的特性
- `FeatureSupportDataSize`:上一个参数的数据的内存大小
- `pFeatureSupportData`:该指针指向存储待检测特性的内存地址,其值依赖于待检测的特性
- `FeatureSupportDataSize`:上一个参数所指内存的大小

`ID3D12Device::CheckFeatureSupport`函数支持检测很多特性,很多高级特性并不需要在本书中检测。
建议大佬们还是去看官方文档比较好。
`ID3D12Device::CheckFeatureSupport`函数支持检测很多特性,但很多高级特性并不需要在本书中使用。建议去看官方文档。

### 4.1.12 Residency

一个复杂的游戏会使用到很多资源,例如纹理和模型网格,但是很多资源并不需要一直使用下去。
例如我们绘制一个森林和一个巨大的洞穴,在玩家们进入洞穴之前洞穴的资源是没有必要的。
当玩家进入洞穴后,森林的资源就是没有必要的了。
一个复杂的游戏会使用到很多资源,例如纹理和模型网格,但是很多资源并不需要GPU一直使用下去。例如,我们绘制一个森林和一个巨大的洞穴,在玩家们进入洞穴之前GPU并不需要洞穴的资源;同理,当玩家进入洞穴后,GPU也不需要森林的资源了。

在`Direct3D 12`中,应用通过将资源从显存中移除来管理资源。
然后在又需要这个资源的时候重新加载。
最基本的想法就是尽量减少显存的使用,因为我们可能没有办法将整个游戏的资源存到显存里面去,又或者有其他应用需要使用到显存。
性能上要注意的是不要将一个资源覆盖掉这个相同的资源。
如果你想要将一个资源从显存中移除,那么这个资源最好是一段时间不需要使用的资源。
在`Direct3D 12`中,应用通过将资源从显存中移除(**evicit**)来管理资源,而当需要这个资源的时候重新加载(**resident**)。
最基本的思想就是尽量减少显存的使用,因为我们可能无法将整个游戏的资源加载到显存中去,又或者有其他应用需要使用到显存。性能方面要注意的是不要在一个很短的帧时间内将同一资源移入或移除(可参考CPU中的缓存抖动),如果你想要将一个资源从显存中移除,那么这个资源最好在一段时间内不再需要使用。例如,游戏关卡或者区域的更换是决定资源是否驻留在显存中的好时机。

通常来说,一个资源在创建的时候就会被加入显存,丢弃的时候会从显存中移除。
但是应用也可以使用`ID3D12Device::MakeResident`来管理
但是应用也可以使用下列两个方法来手动管理

```C++
HRESULT ID3D12Device::MakeResident(
Expand All @@ -313,8 +310,8 @@ struct DXGI_SAMPLE_DESC
ID3D12Pageable *const *ppObjects);
```
第一个参数是资源个数,第二个参数是一个`ID3D12Pageable`类型的数组。
因为本书里面的东西太弱,所以不使用这个东西,你可以去看看文档里面的例子
第一个参数是资源个数,第二个参数是一个`ID3D12Pageable`类型的数组(ID3D12Resource即继承自这个接口,即第二个参数应该是你需要操作的GPU资源)
本书不涉及这两个方法的使用,详情请参考官方文档
## 4.2 CPU/GPU INTERACTION
Expand Down

1 comment on commit ea792ae

@LinkClinton
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里涉及到区间或者设计数字运算等,可以使用latex。例如这里。可以替换成 $[0, NumQualityLevels - 1)$
这是之前改用latex后忘记改正的地方了qaq

Please sign in to comment.