Direct3D

     这一章我们首先将描述direct3D的通用的架构,并且讨论Direct3D与windows GDI的联系,然后再引入Direct3D的一些抽象概念:devices, swap chains , surfaces和resources。 接下来,我们将描述IDirect3D接口,这个接口揭露了系统里面的图形devices。   

    当一个图形应用程序初始化的时候,它首先probe系统里面的图形设备,然后再选择一个合适的设备来满足应用程序的display需求。这个过程称作“device enumeration”。IDirect3D使枚举设备过程非常容易,能够让我们检查出现在系统里面的设备是否符合我们的需要。

    每一个monitor都是由一个adapter驱动的,它能够支持很多种显示模式和刷新率。每个adapterd都拥有运行在windowed 和exclusive模式下的的硬件和软件设备对象。应用程序列举出每个adapter上的可用的设备,检查他们的capability和支持的显示模式,找到一个合适的设备。当这个设备找到之后,应用程序需要检查这个设备是否支持render target 格式,resource格式以及multisampling。

   Direct3D能够枚举默认adapter上的所有设备或者所有adapters上的所有设备。 多个monitor的系统开始很通用,应用程序能充分利用多个monitor的附加的显示空间。

 

Direct3D Architecture

     Direct3D是windows系统里面与GDI相同层级的组件。Direct3D 设备驱动直接与图形硬件打交到,并且可以直接与显卡驱动程序通信。Direct3D的抽象概念包括devices, swap chains和resources。 设备封装了硬件渲染操作方法,设备属性控制渲染行为并且提供渲染信息,设备方法用于执行渲染。设备至少包括一个swap chain和多个用于渲染的资源。资源存放在设备硬件里或者其附近,用于提供图形渲染所需要的特定数据。Direct3D提供的资源包括场景几何体(顶点和索引)以及外观数据(图片,纹理和volumes)。

     surface也是一种资源,它包含一个矩形集合的像素数据,如color, alpha, depth/stencil以及纹理信息。一个swap chain 包含了一个和多个back buffer surface。设备的render target也是back buffer surface,并且还可能携带一个depth/stencil  surface。

     所有的back buffer都是合理的render target,但是并不是所有render target都是back buffer。我们也可以让一个纹理surface作为render target,来实现动态的渲染效果。

     为了获得设备对象,Direct3D提供了设备枚举和创建的方法。所有的其他对象就可以由设备来创建。应用程序首先获取runtime的接口,选择和创建一个设备。接着使用设备创建其他的资源对象。

 

Windowed and Exclusive mode

 

     Direct3D 设备两种不同的操作模式:windowed 和exclusive。在windowed下,图形渲染在桌面窗口的客户端区域进行。Direct3D 将跟GDI一起工作,使用::stretchBlt方法在windows的客户端区域present一个back buffer。在Exclusive模式下,Direct3D直接调用显卡驱动,而并不通过GDI。当一个exclusive模式的应用程序运行的时候,其他应用程序都不可以再访问显卡了。

 

Devices Type

 

     每个adapter支持几种类型的设备。Direct3D支持的三种类型:包括HAL 设备,reference设备以及可插拔的软件设备。D3DDEVTYPE定义了设备类型。

typedef enum _D3DDEVTYPE

{

      D3DDEVTYPE_HAL = 1,

      D3DDEVTYPE_NULLREF = 4,

      D3DDEVTYPE_REF = 2,

      D3DDEVTYPE_SW = 3
} D3DDEVTYPE;

     HAL(hardware abstraction layer)设备使用了图形渲染的硬件加速,所以是速度最快的设备类型。reference设备只有在SDK的安装版本里面才有,它包括了对整个图形的pipeline进行软件实现。这个设备虽然速度很慢,但是它易于图形应用程序的调试。null referece 设备将什么都不做,所有的渲染只是一个黑屏。当系统没有装SDK,但是应用程序请求一个reference设备的时候,它就返回一个null reference。可插拔的软件设备通过RegisterDevice设备方法提供,Direct3D 9.0c还没有可插拔的软件设备。

 

Resources

 

     每种资源都有Type,Pool, Format和Usage属性。这些属性都是在资源创建的时候一次性指定。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   

}

 

Pool属性描述了Direct3D怎么管理它,定义在D3DPOOL枚举类型里面。资源默认是在设备内存里面的。managed 池里面资源是在系统内存里面,当需要使用他的时候它将copy到设备内存里面。系统内存池的资源只存在于系统内存里面。scratch池里面的资源只存在与系统内存里面,并且它不受设备格式限制。当一个设备lost的时候,它的默认池里面的资源都会lost。

typedef enum _D3DPOOL

{

D3DPOOL_DEFAULT = 0,

D3DPOOL_MANAGED = 1,

D3DPOOL_SYSTEMMEM=2,

D3DPOOL_SCRATCH = 3

}D3DPOOL;

格式属性描述了资源在内存里面的layout,它定义在D3DFORMAT枚举类型里面。所有的资源都有一种格式,但是大部分格式枚举都是像素数据的格式。

typedef enum _D3DFORMAT

{

D3DFMT_UNKNOWN = 0,

D3DFMT_INDEX16 = 101,

D3DFMT_INDEX32 = 102,

D3DFMT_VERTEXDATA = 100,

D3DFMT_A4L4 = 52,

D3DFMT_A8 = 28,

D3DFMT_L8 = 50,

D3DFMT_P8=41,

D3DFMT_R3G3B2 = 27,

D3DFMT_A1R5G5B5 = 25

D3DFMT_A4R4G4B4= 26,

D3DFMT_A8L8 = 51,

D3DFMT_A8P8 = 40,

D3DFMT_A8R3G3B2 = 29,

D3DFMT_L16 = 81,

D3DFMT_L6V5U5= 61,

D3DFMT_R16F = 111,

D3DFMT_R5G6B5 = 23,

D3DFMT_V8U8= 60,

D3DFMT_X1R5G5B5 = 24,

D3DFMT_X4R4G4B4 = 30,

 

D3DFMT_R8G8B8 = 20,

D3DFMT_A2R10G10B10= 35,

D3DFMT_A2W10V10U10= 31,

D3DFMT_A2W10V10U10 = 67,

D3DFMT_A8B8G8R8 = 32,

D3DFMT_A8R8G8B8 = 21,

D3DFMT_CxV8U8 = 117,

D3DFMT_G16R16 = 34,

D3DFMT_Q8W8V8U8 = 63,

D3DFMT_R32F = 114,

D3DFMT_V16U16 = 64,

D3DFMT_W11V11U10 = 65,

D3DFMT_X8L8V8U8 = 62,

D3DFMT_X8B8G8R8 = 33,

D3DFMT_X8R8G8B8=22,

 

D3DFMT_A16B16G16R16= 36,

D3DFMT_A16B16G16R16F = 113,

D3DFMT_G32R32F = 115,

D3DFMT_Q16W16V16U16 = 110,

 

D3DFMT_A32B32G32R32F = 116,

 

D3DFMT_DXT1 = MAKEFOURCC('D','X','T','1');

D3DFMT_DXT2 = MAKEFOURCC('D','X','T','2');

D3DFMT_DXT3 = MAKEFOURCC('D','X','T','3');

D3DFMT_DXT4 = MAKEFOURCC('D','X','T','4');

D3DFMT_DXT5 = MAKEFOURCC('D','X','T','5');

D3DFMT_G8R8_G8B8 = MAKEFOURCC('G','R','G','B');

D3DFMT_R8G8_B8G8 = MAKEFOURCC('R','G','B','G');

D3DFMT_UYVY = MAKEFOURCC('U','Y','V','Y');

D3DFMT_YUY2 =MAKEFOURCC('Y','U','Y','2');

D3DFMT_MULT2_ARGB8 = MAKEFOURCC('M','E','T','1');

D3DFMT_D15S1 = 73,

D3DFMT_D16 = 80,

D3DFMT_D16_LOCKABLE = 70,

D3DFMT_D32F_LOCKABLE = 82,

D3DFMT_D24S8  = 75,

D3DFMT_D24FS8 = 83,

D3DFMT_D24X4S4 = 79,

D3DFMT_D24X8 = 77,

D3DFMT_D32 = 71

}D3DFORMAT;

 

    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互换。

   Usage 包括D3DUSAGE_AUTOGENMIPMAP,D3DUSAGE_DEPTHSTENCIL,D3DUSAGE_DMAP,D3DUSAGE_DONOTCLIP,D3DUSAGE_DYNAMIC,D3DUSAGE_NPATCHES,D3DUSAGE_POINTS,D3DUSAGE_RENDERTARGET,D3DUSAGE_RTPATCHES,D3DUSAGE_SOFTWAREPROCESSING,D3DUSAGE_WRITEONLY。

 

IDirect3D9

    可以通过Direct3D的全局核心函数来获取IDirect3D9接口。

#define D3DSDK_VERSION 31

IDirect3D9 * WINAPI  ::Direct3DCreate9(UINT sdk_version);

    版本参数必须是D3D_SDK_VERSION。当direct3D头文件改变时,这个数字将增加。如果传了错误的版本号码,这个函数将失败,并且返回NULL。

   IDirect3D提供了一个图形硬件模型。在这个模型里,每个monitor都连接一个adapter(它被一个无符号整数所标识)。一个Apdater并不完全与一张显卡等同,近些年,有些显卡上可以支持两个apdater,称作"dual head" display,IDirect3D9认为他们是不同的apdaters。

   接口提供了统一的方式检查连接到系统的所有的适配器,并且选择最适合的一个来完成渲染任务。

方法和属性描述
GetAdapterCount系统里面的adpater的数量
GetAdapterDisplayMode一个adapter的当前video  display mode
GetAdapterIdentifieradapter的标识符
GetAdapterModeCountapdater可支持的video display mode 的数目
GetAdapterMonitor一个adapter的HMONITOR
GetDeviceCaps设备通常的capabilities
CheckDepthStencilMatch检查设备使用的depth/stencil surface与render target和adpater显示格式是否匹配
CheckDeviceFormat检查设备支持的资源类型和格式
CheckDeviceFormatConversion 
CheckDeviceMultiSampleType检查设备是否支持multisample
CheckDeviceType 
EnumAdapterModes在一个adpater上创建一个设备对象
RegisterSoftwareDevice注册一个direct3D的软件设备

 

选择一个设备

 

   一般情况下,应用程序列举所有的设备,然后选择一个最合适的设备。首先,调用GetAdapterCount 来获取系统中的adapter的数目,每个adapter有多种显示模式。每个显示模式包含screen dimension,refresh rate 和像素格式,Direct3D使用结构体D3DDISPLAYMODE定义。

typedef struct _D3DDISPLAYMODE

{

UINT Width;

UINT   Height;

UINT   RefreshRate;

D3DFORMAT Format;

}D3DDISPLAYMODE;

Format 要么是RGB格式,要么是XRGB格式。 back buffer surface格式必须与显示模式格式兼容。 使用CheckDeviceFormat 发现兼容的格式。一般情况下,back buffer格式与显示格式有着相同的像素深度和颜色layout。一个XRGB显示格式能与同样深度的ARGB back buffer一起使用。GetAdapterModeCount返回apdator支持的显示模式的数目。EnumAdapterModes返回显示模式信息。adapter当前使用的显示模式可以通过GetAdapterDisplayMode取得。 使用一些支持的显示格式,我们可以查询支持的设备类型。CheckDeviceType方法告诉我们显示格式和back buffer格式对一个指定类型的设备是否合理。找到了合适的设备,我们就可以通过GetDeviceCaps来检查设备的渲染功能。接下来,我们可以使用CheckDeviceFormat更新所有的资源(back buffer surfaces, depth/stencil surfaces,texture surfaces和volume texture 格式)。再接下来,如果应用程序需要做深度可视性检测,它应该使用CheckDepthStencilMatch发现一个深度buffer。

最后,需要使用multisampling应用程序需要通过CheckDeviceMultisampling来检测。

注意:CheckDeviceType 用于检测Adapter允许的颜色Format与与它的某个设备支持的backbuffer颜色格式是否兼容。CheckDeviceFormat用于检测是否某个adapter的设备支持某种资源格式。

 

Determining Available Resource Memory

 

     当已经找到了一个能满足应用程序需要的设备后,这个时候,我们要看看设备是否能提供足够的内存资源满足应用程序的需要。如果应用程序已经有了指定的内存需求,判断备是否能够满足这个需求的唯一方式是初始化设备,并且尝试创建必需的资源。

      应用程序可用的内存与当前使用的diplay mode 有关。如果设备申请的video mode与桌面显示的video mode不一致时,创建一个exclusive模式的设备可能引起不一致显示模式的变化。为了避免在应用程序启动时这种失常的效果,应用程序最好能在安装的时候执行内存测试,然后保存这个结果。这个操作是安全的,因为在某种特殊的显示模式可用内存量不会改变,除非硬件被更换。

 

Device Capabilities

  

     图形设备一般都有很多architectures ,harware capabilities和performance range。应用程序probe硬件的capablities,然后决定合适的渲染strategy。应用程序可以在某个指定的adapter上调用GetDeviceCaps来获取它的capabilities。设备capabilities一般使用D3DCAPS9定义的。

 

Identifying a Particular Device

 

    在理想情况下,设备的支持情况和capabilities检测以后,我们可能就不使用incapable的设备。 但是,现实环境去不这样。GetAdapterIdentifier允许应用程序识别某个品牌的adapter。GetAdapterIdentifier返回一个D3DADAPTER_IDENTIFIER9的结构体。

    typedef struct _D3DADAPTER_IDENTIFIER9

   {

char  Driver[MAX_DEVICE_IDENTIFIER_STRING];

char  Description[MAX_DEVICE_IDENTIFIER_STRING];

char  DeviceName[32];

#ifdef _WIN32

     LARGE_INTEGER DriverVersion;

#else

     DWORD   DriverVersionLowPart;

     DWORD   DriverVersionHighPart;

#endif

  DWORD   VendorId;

  DWORD   DeviceId;

  DWORD   SubSysId;

  DWORD   Revision;

  GUID      DeviceIdentifier;

  DWORD  WHQLLevel;

  HMONITOR  hMonitor;

   } D3DADAPTER_IDENTIFIER9;

 

  Driver和Description用于图形界面对设备的选择。DriverVersion 指示了Direct3D的版本号码。VendorId, DeviceId,SubSysId,Revision 用来区分不同的硬件芯片。WHQLLEVEL就是这个驱动的WHQL(Windows hardware quality Laboratory) 信息。这个值如果是0表示它没有过这个认证,如果是1表示过了,但是没有日期信息。决定WHQL LEVEL是一个很费时的操作,通常一般都是避免做这个操作。将GetAdapterIdentifier的flag参数为0,就可以避免这个操作。

 

Creating the Device

 

    通过IDirect3D9::CreateDevice(UINT adapter, D3DDEVTYPE device_kind,HWND focus_window, DWORD behavior_flags, D3DPRESENT_PARAMETERS* presentation,IDirect3DDevice8 **result); focus_window 参数表示它将是设备的focus。 对于一个工作在exclusive mode 设备来说,窗口必须是一个top-level窗口。 应用程序不应该在响应WM_CREATE的消息处理函数里创建设备。 当设备创建后并且在exclusive模式下,Direct3D 应用程序将接收focus 窗口的消息,Direct3D 将subclass这个focus的窗口。MFC 应用程序取得focus窗口句柄是通过函数::AfxGetSafeWindow。

   behavior_flags参数指定了创建设备的全局行为,这些flag包括D3DCREATE_ADAPTERGROUP_DEVICE,D3DCREATE_DISABLE_DRIVER_MANAGEMENT,D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX, D3DCREATE_FPU_PRESERVE, D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DCREATE_MIXED_VERTEXPROCESSING, D3DCREATE_MULTITHREADED, D3DCREATE_NOWINDOWCHANGES, D3DCREATE_PUREDEVICE,D3DCREATE_SOFTWARE_VERTEXPROCESSING。

    有些显卡可以在单张卡上提供多个视频output。D3DCREATE_ADAPTERGROUP_DEVICE 允许应用程序通过单个设备接口驱动两个video output,允许资源在两个output上共享。D3DCREATE_DISABLE_DRIVER_MANAGEMENT和D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX disable设备资源管理,强迫所有的资源管理发生在运行时。使用ex 形式当创建资源内存不足的时候会返回错误,non-ex形式将不会返回错误。

     Direct3D使用单精度浮点计算。如果一个应用程序需要FPU更高的精度,有两种选择。或者应用程序保证FPU运行在单精度模式下,或者应用程序在执行浮点运算之前预先保存应用程序的FPU精度,当返回时再恢复FPU。

   pure device flag 让是被使用最少的内部状态跟踪,可以提高应用程序的performance。

   Presentation参数描述了设备显示在monitor上的渲染参数。presentation的每个成员描述了设备的presentation的行为,所以在这个函数返回的时候有可能会修改里面的值,所以presentation必须是可写的。

   typedef  struct _D3DPRESENT_PARAMETERS_

{

UINT BackBufferWidth;

UINT   BackBufferHeight;

UINT  BackBufferFormat;

UINT  BackBufferCount;

D3DMULTISAMPLE_TYPE MultiSampleType;

DWORD MultiSampleQuality;

D3DSWAPEFFECT SwapEffect;

HWND     hDeviceWindow;

BOOL Windowed;

BOOL EnableAutoDepthStencil;

D3DFORMAT  AutoDepthStencilFormat;

DWORD Flags;

UINT  FullSCreen_RefreshRateInHz;

UINT  PresentationInterval;

}D3DPRESENT_PARAMETERS;

   Flags包含D3DPRESENTFLAG_DEVICECLIP, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, D3DPRESENTFLAG_VIDEO。

   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。

 

Multiple Monitors

   

      对于多个monitor的系统来说,虚拟桌面由一个包含了所有参与到windows桌面的adapters的有边界的矩形组成。其他没有参与进来的adapters也可以附着在这个系统上面。桌面上所有的adapters至少共享一个像素边界。

      应用程序可能想要某个monitor的全屏的显示,GetAdapterMonitor返回一个Adapter的HMonitor句柄。一旦你有这个句柄,你就可以决定虚拟桌面的哪部分被这个moniter占用。

 

Adapter Group Devices

    多个adapter能从单张卡里面提供多个不同的video output。当使用D3DCREATE_ADAPTERGROUP_DEVICE创建设备时,需要提供一组D3DPRESENT_PARAMETERS。这个数组的数目不能少于D3DCAPS的NumberOfAdaptersInGroup成员。只有一个D3DPRESENT_PARAMETERS 能使用focus窗口作为它的设备窗口,剩下的必须使用他们自己的top-level窗口作为设备窗口。无论创建多少个swap chain,只有一个depth/stencil面被创建。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值