首页 > 代码库 > Direct3D基础概念和模型整理
Direct3D基础概念和模型整理
转自:http://blog.csdn.net/blues1021/article/details/41099705
参考整理自文章:
http://zh.wikipedia.org/zh/Direct3D
http://blog.csdn.net/weili_2007/article/details/1907066
http://msdn.microsoft.com/en-us/library/windows/desktop/bb219679(v=vs.85).aspx#Direct3D_System_Integration
概念主要包括IDirect3D, Adapter, Device, swap chain(surface后台缓存、前台缓存、深度和模板缓存),资源(资源类型_D3DRESOURCETYPE、格式_D3DFORMAT、资源存放的内存区域Pool、资源的使用标识Usage)。模型就是这些概念形成的Direct3D对象接口模型。
一、图形模型基础
1)显卡物理组成:
(1)显卡的BIOS用于驱动显卡.
(2)GPU,
(3)显存RAM,
(4)RAMDAC数模转换器
(5)接口PCI/AGP/TV输出。
2)图形数据传输模型:
显卡BIOS初始化,数据从磁盘读取或来自程序内部(CPU&RAM) ->(1)主板PCI/AGP高级图形端口输入->(2)DeviceGPU复杂的数学和几何运算的图形渲染管道->(3)显存RAM存放GPU运算需要的数据和完成后的信息(像素+位置)显存低端1GB/2GB高端4GB/6GB->(4)VGA(CRT)/PCIe/ViVo等端口输出Monitor监视器。
Direct3D图形管道渲染过程:
Direct3D 10 API定义了vertices(顶点), textures(纹理), buffers(缓冲区),以及state群组转换到屏幕上的流程。这样的流程被描述成rendering pipeline(渲染流水线),其中有着許多不同的阶段. Direct3D 10 渲染流水线的各阶段包括:
- 输入组装(Input Assembler):程序从美术磁盘文件CPU/系统RAM取得顶点,并将程序提供的数据装进流水线。
- 顶点著色引擎(Vertex Shader): 每次处理一个顶点,比如变换、贴图、光照。
- 几何著色器(Geometry Shader): Shader Model 4.0引进了几何著色器,使用Shader资源来处理点、线、面的几何坐标变换,一次最多处理六个点,快速地将模型类似的顶点结合起来进行运算。此一过程无需CPU参与。
- 流输出(Stream Output):将Vertex Shader和Pixel Shader处理完成的数据输出给使用者。
- 光栅化(Rasterizer): 把算完的顶点转成像素,再将像素(pixels)输出给pixel shader. 这里亦可执行其他工作,像是切割非视锥区域的像素,或者对顶点进行插值以得到像素数据。
- 像素著色引擎(Pixel Shader):決定最后要往渲染目标(render targe)写入的像素颜色,同时也可以计算一个准备写到深度缓冲区的深度值。
- 输出混合(Output Merger):接收來自于pixel shader的slice,进行传统的Stencil测试和Depth测试,整合各种不同的输出资料(颜色和位置),用以建立最后之结果。
CPU和GPU,内存和显存的分工,进而提高计算和内存使用效率,优化程序的性能:
在固定渲染管道中,编程的图形文件读取,硬件设备性能的检测,由显卡适配器运行类型和后台缓存表面参数等指定的设备的生成,设备创建的各种资源贴图动画光照,设备状态的设置,设备的转换操作设置等,会在CPU代码中进行非渲染中的计算和对Dircet3D/OPENGL的渲染状态设置。
实际在CPU提交渲染后,还需要GPU真正对裁剪,背面消隐,变换,光照等进行计算,纹理像素深度测试,模板测试,像素融合,光栅化;显存进行存储,并由显卡进行渲染出来。
所以CPU层面的资源量,运算量也要控制好;GPU各种计算的开启控制,尽量让显存的命中率高不需要频繁请求CPU, 这样才能有比较好的程序图形计算性能和内存开销。
注:Shader编程把更多的计算交付给的GPU处理,可以处理计算量比较大的效果实现,且程序也获得比较好的性能。
3)渲染管道中的坐标转换:
局部坐标系->世界坐标系->观察坐标系
->背面消隐->光照->裁剪
->投影->视口坐标系->光栅化。
二、IDirect3D统一接口
IDirect3D对象是支持Direct3D图形设备驱动的统一接口,可以用来得到系统的adapter(显卡)的硬件及软件特性。
IDirect3D提供了一个图形硬件模型。在这个模型里,一个Adapter(它被一个无符号整数所标识)可以创建一个或多个Device, 一个adapter连接一个或多个monitor。
注:一个Apdater并不完全与一张显卡等同,近些年,有些显卡上可以支持两个apdater,称作"dual head" display,IDirect3D9认为他们是不同的apdaters。
三、Adapter显卡适配器标识号和枚举Adapter的功能:
Adapter用无符号整数的标识号表示,是显卡适配器(AGP,PCI接口,GPU,显存,Monitor)的软件抽象对象,通过枚举adapter可以获取指定类型的Device对象(一个adapter可以创建多个Device),及获取Monitor的特征。
每一个monitor都是由一个adapter驱动的,它能够支持很多种显示模式和刷新频率,用Adapter ID(需要IDirct3D对象)获取用户的硬件特性支持情况的判断,用于创建特定的Device, 例如:是否支持render target 格式,resource格式以及multisampling。
IDirect3D对象枚举Adapter的功能:
GetAdapterCount()
GetAdapterDisplayMode
GetAdapterIdentifier //得到适配器描述
CheckDeviceType //判断指定适配器上的设备是否支持硬件加速
GetDeviceCaps //指定设备的性能,主要判断是否支持硬件顶点处理(T&L)
GetAdapterModeCount //得到适配器上指定缓冲格式所有可用的显示模式
EnumAdapterModes //枚举所有显示模式
CheckDeviceFormat
CheckDeviceMultiSampleType
创建设备注意:
Direct3D 设备两种不同的操作模式:windowed 和exclusive。
在windowed下,图形渲染在桌面窗口的客户端区域进行。Direct3D 将跟GDI一起工作,使用::stretchBlt方法在windows的客户端区域present一个back buffer。
在Exclusive模式下,Direct3D直接调用显卡驱动,而并不通过GDI。当一个exclusive模式的应用程序运行的时候,其他应用程序都不可以再访问显卡了。
使用:
1)CheckDeviceFormat :
每个adapter有多种显示模式。每个显示模式包含screen dimension,refresh rate 和像素格式,Direct3D使用结构体D3DDISPLAYMODE定义。
back buffer surface格式必须与显示模式格式兼容, 使用CheckDeviceFormat 发现兼容的格式。一般情况下,back buffer格式与显示格式有着相同的像素深度和颜色layout。
一个XRGB显示格式能与同样深度的ARGB back buffer一起使用。
2)GetDeviceCaps:
找到了合适的设备,我们就可以通过GetDeviceCaps来检查设备的渲染功能。
3)CheckDeviceType:
告诉我们显示格式和back buffer格式对一个指定类型的设备是否合理。
4)CheckDeviceFormat:
接下来,我们可以使用CheckDeviceFormat更新所有的资源(back buffer surfaces, depth/stencilsurfaces,texture surfaces和volume texture 格式)。
再接下来,如果应用程序需要做深度可视性检测,它应该使用CheckDepthStencilMatch发现一个深度buffer。
最后,需要使用multisampling应用程序需要通过CheckDeviceMultisampling来检测。
注意:CheckDeviceType 用于检测Adapter允许的颜色Format与与它的某个设备支持的backbuffer颜色格式是否兼容。
CheckDeviceFormat用于检测是否某个adapter的设备支持某种资源格式。
5)GetAdapterIdentifier:
用于识别某个品牌的adapter。GetAdapterIdentifier返回一个D3DADAPTER_IDENTIFIER9的结构体。
Driver和Description用于图形界面对设备的选择。DriverVersion 指示了Direct3D的版本号码。
VendorId, DeviceId,SubSysId,Revision 用来区分不同的硬件芯片。WHQLLEVEL就是这个驱动的WHQL(Windows hardware quality Laboratory) 信息。
这个值如果是0表示它没有过这个认证,如果是1表示过了,但是没有日期信息。决定WHQL LEVEL是一个很费时的操作,通常一般都是避免做这个操作。
将GetAdapterIdentifier的flag参数为0,就可以避免这个操作。
6)CreateDevice:
有些显卡可以在单张卡上提供多个视频output。D3DCREATE_ADAPTERGROUP_DEVICE 允许应用程序通过单个设备接口驱动两个video output,允许资源在两个output上共享。D3DCREATE_DISABLE_DRIVER_MANAGEMENT和D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EXdisable设备资源管理,强迫所有的资源管理发生在运行时。使用ex 形式当创建资源内存不足的时候会返回错误,non-ex形式将不会返回错误。
Direct3D使用单精度浮点计算。如果一个应用程序需要FPU更高的精度,有两种选择。或者应用程序保证FPU运行在单精度模式下,或者应用程序在执行浮点运算之前预先保存应用程序的FPU精度,当返回时再恢复FPU。
pure device flag 让是被使用最少的内部状态跟踪,可以提高应用程序的performance。
Presentation参数描述了设备显示在monitor上的渲染参数。presentation的每个成员描述了设备的presentation的行为,所以在这个函数返回的时候有可能会修改里面的值,所以presentation必须是可写的。
D3DPRESENTFLAG_DEVICECLIP 限制了window模式下客户端区域present操作的结构,它在WindowXP和Windows 2000下支持。D3DPRESENTFLG_VIDEO flag暗示了back buffer包含有video。D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL 在调用present后discard depth/stencil surface里面的内容。这样就使depth/stencil surface是一个可写的surface。如果depth/stencil surface的格式是D3DFMT_D16_LOCKABLE 或者 D3DFMT_D32_LOCKABLE设置这个标记将会返回一个错误。
在window模式下,hDeviceWindow指定了渲染窗口的句柄。如果hDeviceWindow为null,则focus窗口将是被渲染的窗口。FullScreen_RefreshRateInHz必须是0。
在exclusive模式下,hDeviceWindow指定了应用程序使用的top-level窗口。如果系统里面有多个设备,只有一个设备能使用hDeviceWindow的focus_window。
BackBufferWidth, BackBufferHeight, BackBufferFormat必须等于这个适配器的D3DDISPLAYMODE的相关成员。
FullScreen_PresentationInterval指定了presentation rate和屏幕refresh rate期望的关系。
FullScreen_RefreshRateInHz是一个很里的refresh rate 或者是D3DPRESENT_RATE_DEFUALT默认值。
D3DPRESENT_RATE_DEFUALT 指示exclusive 模式下runtime选择一个合适的refresh rate, window模式下使用当前的refresh rate。
7)GetAdapterMonitor:
对于多个monitor的系统来说,虚拟桌面由一个包含了所有参与到windows桌面的adapters的有边界的矩形组成。
其他没有参与进来的adapters也可以附着在这个系统上面。桌面上所有的adapters至少共享一个像素边界。
应用程序可能想要某个monitor的全屏的显示,GetAdapterMonitor返回一个Adapter的HMonitor句柄。
一旦你有这个句柄,你就可以决定虚拟桌面的哪部分被这个moniter占用。
8)NumberOfAdaptersInGroup:
多个adapter能从单张卡里面提供多个不同的video output。当使用D3DCREATE_ADAPTERGROUP_DEVICE创建设备时,需要提供一组D3DPRESENT_PARAMETERS。
这个数组的数目不能少于D3DCAPS的NumberOfAdaptersInGroup成员。只有一个D3DPRESENT_PARAMETERS 能使用focus窗口作为它的设备窗口,
剩下的必须使用他们自己的top-level窗口作为设备窗口。无论创建多少个swap chain,只有一个depth/stencil面被创建。
四、Device设备对象
Device是通过IDirct3D对象,Adapter的类型D3DDEVTYPE,表面特性D3DPRESENT_PARAMETERS指定的设备对象(比Adapter具体),Adapter偏硬件,Device更加软件具体化的"实际设备对象"。Direct3D提供了设备枚举和创建的方法。所有的其他对象就可以由设备来创建。
Device创建各种资源(CPU/RAM/AGP RAM/ 显存),对资源的各种状态设置和操作(变换\光照\光栅化),新版的D3D11中用Content负责资源的操作。
DEVICE则是D3D的核心,它包装了整个图形流水管线,包括变换、光照和光栅化(着色),根据D3D版本不同,流水线也有区别,比如最新的D3D10就包含了新的GS几何处理。因此Device创建和管理swap chains , surfaces和resources,执行转换各种设置,且负责渲染数据。
Device至少包括一个swap chain和多个用于渲染的resources资源。
HAL(hardware abstraction layer)设备使用了图形渲染的硬件加速,所以是速度最快的设备类型。
reference设备只有在SDK的安装版本里面才有,它包括了对整个图形的pipeline进行软件实现。这个设备虽然速度很慢,但是它易于图形应用程序的调试。
null referece 设备将什么都不做,所有的渲染只是一个黑屏。当系统没有装SDK,但是应用程序请求一个reference设备的时候,它就返回一个null reference。
可插拔的软件设备通过RegisterDevice设备方法提供,Direct3D 9.0c还没有可插拔的软件设备。
Architecturally, Direct3D devices contain a transformation module, a lighting module, and a rasterizing module, as the following diagram shows.
五、Swap chain交换链和各种surface表面缓存
swap chain和surface也是资源,会在PRESENT_PRAMETERS指定,在CreateDevice时候和Device一起被创建。也可以创建多个后台缓存,形成交换链,交换链会在Present时候按照队列挪动的方式进行轮换。
一个swap chain 包含了一个和多个back buffer surface, surface也是一种资源,它包含一个矩形集合的像素数据,如color, alpha, depth/stencil以及纹理信息。
所有的back buffer都是合理的render target,但是并不是所有render target都是back buffer。我们也可以让一个纹理surface作为render target,来实现动态的渲染效果。
拓展:
DX11:
1.device 作为 “实际对象”, 管理存储各种数据(当然也负责与 hardwar的沟通), 和硬件交互, 用来创建资源,操作资源。
2.context 更多的是 “提供操作的接口”,device将很多数据操作委托给了context接口,通常用来操作各种缓存数据,从而告知 device 进行如何绘图 how to draw。
3.swapchain 实现了一个或多个的 surface 用来存储 输出到输出设备output device 之前的各种 “渲染数据”, 做得数据后台加速,大部分 函数都是 与 buffer的状态相关。
六、RUNTIME(Device)
Device内部由RUNTIME运行时管理调度Device的各种操作,有重要的命令结构Command Buffer(应该在系统RAM中),实现命名的分发。
七、Driver(GPU)
RUNTIME需要通过Adapter(GPU)的Driver来实现,Driver分为HAL Driver和REF Driver,Driver是硬件显卡或硬件显卡预定义的驱动和图形操作指令。
翻译RUNTIME过来的各种Device的命令,进行物理的执行操作,当然Driver也有一个命令结构Driver Buffer(应该在显存中)。
八、Resource各种资源
resources资源存放在设备硬件里或者其附近,用于提供图形渲染所需要的特定数据。
Direct3D提供的资源包括场景几何体(顶点和索引)以及外观数据(图片,纹理和volumes)。
每种资源都有Type,Pool, Format和Usage属性。这些属性都是在资源创建的时候一次性指定。
1)Type:
Type属性指定了资源的类型,定义在D3DRESOURCETYPE枚举类型里面。
typedef enum _D3DRESOURCETYPE
{
D3DRTYPE_SURFACE = 1,
D3DRTYPE_VOLUME = 2,
D3DRTYPE_TEXTURE = 3,
D3DRTYPE_VOLUMETEXTURE = 4,
D3DRTYPE_CUBETEXTURE = 5,
D3DRTYPE_VERTEXBUFFER= 6,
D3DRTYPE_INDEXBUFFER = 7
}
2)Pool:
Pool属性描述了Direct3D怎么管理它,定义在D3DPOOL枚举类型里面。
当一个设备lost的时候,它的默认池里面的资源都会lost。
typedef enum _D3DPOOL
{
D3DPOOL_DEFAULT = 0,// 资源默认是在设备内存里面的。
D3DPOOL_MANAGED = 1,// managed 池里面资源是在系统内存里面,当需要使用他的时候它将copy到设备内存里面。
D3DPOOL_SYSTEMMEM=2,// 系统内存池的资源只存在于系统内存里面,CPU RAM。
D3DPOOL_SCRATCH = 3 // scratch池里面的资源只存在与系统内存里面,并且它不受设备格式限制。
}D3DPOOL;
注意:
应用程序可用的内存与当前使用的diplay mode 有关。如果设备申请的video mode与桌面显示的video mode不一致时,
创建一个exclusive模式的设备可能引起不一致显示模式的变化。为了避免在应用程序启动时这种失常的效果,应用程序最好能在安装的时候执行内存测试,然后保存这个结果。
这个操作是安全的,因为在某种特殊的显示模式可用内存量不会改变,除非硬件被更换。
3)Format:
格式属性描述了资源在内存里面的layout,它定义在D3DFORMAT枚举类型里面。所有的资源都有一种格式,但是大部分格式枚举都是像素数据的格式。
typedef enum _D3DFORMAT
{
D3DFMT_UNKNOWN = 0,
D3DFMT_INDEX16 = 101,
D3DFMT_INDEX32 = 102,
D3DFMT_VERTEXDATA = http://www.mamicode.com/100,
D3DFMT_A4L4 = 52,
D3DFMT_A8 = 28,
...
}
An,Ln,Bn,Pn,Rn,Gn和Bn都是无符号的,Un,Vn,Wn,Qn是有符号的。Dn和Sn设备指定的depth/stencil surface数据。
MAKEFOURCC宏用来生成一个四字符码。附加的vendor指定的格式可以通过MAKEFOURCC定义。DXTn格式是压缩纹理格式。
D3DCOLOR的像素格式是D3DFMT_A8R8G8B8,然而PALETTEENTRY和COLORREF 却让R和G互换。
4)Usage:
标记怎么样去使用资源,挪动,压缩,纹理方式,模板方式;怎么样使用会根据不同的资源类型,不同的内存存放,会有关联,所以标记会仅限某种资源类型或某种内存类型下使用。
包括D3DUSAGE_AUTOGENMIPMAP,D3DUSAGE_DEPTHSTENCIL,
D3DUSAGE_DMAP,D3DUSAGE_DONOTCLIP,D3DUSAGE_DYNAMIC,D3DUSAGE_NPATCHES,
D3DUSAGE_POINTS,D3DUSAGE_RENDERTARGET,D3DUSAGE_RTPATCHES
,D3DUSAGE_SOFTWAREPROCESSING,D3DUSAGE_WRITEONLY。
Direct3D基础概念和模型整理