D3D9学习笔记(三) Device
2.1架构
2.2类型
基本的device类型:hal:硬件渲染(发布)。这也不是直接访问硬件驱动,而是访问在上一层的hal。(在顶点处理过程中,如果硬件处理失败,可尝试混合处理及纯软处理,设定标志D3DCREATE_MIXED_VERTEXPROCESSING)
soft软件渲染(但是这种软渲染并不一定拥有同当前硬件相同的渲染能力,所以要经常检查)
ref完全精密的实现所有特征的软渲染可以,可用于验证feature,使用那些还没被做到硬件的feature,也可以用来验证是不是硬件驱动有bug,因为它是最规范完整的按feature来渲染。
2.3一些问题
xp与vista的显示的一些问题
1.在安全桌面下:如屏保、锁定、未登入状态等,hal device是不能访问的,D3D9的device会创建失败。但是vista可以使用系统service来创建
2.远程桌面:XP下不能再远程桌面上创建DEVICE vista可以通过remote desktop session来创建
2.4选择硬件设备
1 枚举硬件
IDirect3D9:: GetAdapterCount()获取显卡数量,D3D9中的显卡表示为0-GetAdapterCount()-1的整数,主显卡也可用D3DADAPTER_DEFAULT表示。
另外可以用IDirect3D9::GetAdapterIdentifier
获取显卡的厂商类型等信息。
2.获取指定显卡支持的显示模式
IDirect3D9::GetAdapterDisplayMode可获取硬件当前的显示模式
3.(可选)查询设备是否支持要用到的一些硬件加速,他还能查询设备是否支持swap chain
IDirect3D9::CheckDeviceType(窗口模式可省)
4.获取当前硬件的渲染能力
5,当渲染到一个surface时,通常要检查这个surface的格式是是否可以用于texture、rendertarget、depth-stenil buffer
IDirect3D9::CheckDeviceFormat.(窗口模式可省)
6.查询一个硬件是否支持某种多采样技术(反走样)
IDirect3D9::CheckDeviceMultiSampleType(窗口模式可省)
较高的多采样和多backbuffer会严重增加显存的使用
2.5创建device
创建操作只能在当前激活的窗口显示的同一个线程中
1.创建一个D3D object,(这个创建多个会严重影响性能)。
IDirect3D9 *Direct3DCreate9(UINT SDKVersion),失败返回null。参数永远是D3D_SDK_VERSION
2.创建device
IDirect3D9::CreateDevice(
[in] UINT Adapter,--显卡
[in] D3DDEVTYPE DeviceType, --类型
[in] HWND hFocusWindow,--窗口
[in] DWORD BehaviorFlags,
[in, out] D3DPRESENT_PARAMETERS *pPresentationParameters,--设备的主要参数
[out, retval] IDirect3DDevice9 **ppReturnedDeviceInterface
)
*UINT Adapter显卡:D3DADAPTER_DEFAULT为主显卡
* D3DDEVTYPE:
D3DDEVTYPE_HAL = 1, hal
D3DDEVTYPE_NULLREF = 4,--只创建资源,所有要求传入D3DDEVTYPE类型参数的函数都会失败
D3DDEVTYPE_REF = 2,ref
D3DDEVTYPE_SW = 3,使用插件的软渲染,插件要用,IDirect3D9::RegisterSoftwareDevice注册
* BehaviorFlags:
D3DCREATE_ADAPTERGROUP_DEVICE只对主显卡有效,让设备驱动输出给它所拥有的所有显示输出
D3DCREATE_DISABLE_DRIVER_MANAGEMENT代替设备驱动来管理资源,这样在发生资源不足时D3D调用不会失败
D3DCREATE_DISABLE_PRINTSCREEN:不注册截屏快捷键,只对Direct3D 9Ex
D3DCREATE_DISABLE_PSGP_THREADING:强制计算工作必须在主线程上,vista以上有效
D3DCREATE_ENABLE_PRESENTSTATS:允许GetPresentStatistics收集统计信息只对Direct3D 9Ex
D3DCREATE_FPU_PRESERVE;强制D3D与线程使用相同的浮点精度,会降低性能
D3DCREATE_HARDWARE_VERTEXPROCESSING:指定硬件进行顶点处理,必须跟随D3DCREATE_PUREDEVICE
D3DCREATE_MIXED_VERTEXPROCESSING:指定混合顶点处理
D3DCREATE_SOFTWARE_VERTEXPROCESSING:指定纯软的顶点处理
D3DCREATE_MULTITHREADED:要求D3D是线程安全的,多线程时
D3DCREATE_NOWINDOWCHANGES:拥有不改变窗口焦点
D3DCREATE_PUREDEVICE:只试图使用纯硬件的渲染
D3DCREATE_SCREENSAVER:允许被屏保打断只对Direct3D 9Ex
D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DCREATE_MIXED_VERTEXPROCESSING, and D3DCREATE_SOFTWARE_VERTEXPROCESSING中至少有一个一定要设置
*D3DPRESENT_PARAMETERS pPresentationParameters
typedef struct D3DPRESENT_PARAMETERS {
UINT BackBufferWidth;
UINT BackBufferHeight; --back buffer的长宽注意如果是全屏模式必须等于显卡的其中一种分辨率如果是窗口不填就用这个窗口的大小
D3DFORMAT BackBufferFormat; --backbuffer的格式(主要是颜色格式),必须与当前的render target相同。在窗口模式D3DFMT_UNKNOWN可以直接使用去匹配当前的显示格式,全屏不行
UINT BackBufferCount; --backbuffer的数量0 -D3DPRESENT_BACK_BUFFERS_MAX之间,0代表创建一个(就是创建到0号缓存),函数调用返回失败时,将返回实际可以创建的backbuffer的数量
D3DMULTISAMPLE_TYPE MultiSampleType;--只有swapchain是D3DSWAPEFFECT_DISCARD才能使用多采样(用于反走样),否则都必须设置D3DMULTISAMPLE_TYPE
DWORD MultiSampleQuality; -多采样的质量,0-CheckDeviceMultiSampleType之间,越大越高质量
D3DSWAPEFFECT SwapEffect;--swapchain在交换buffer时的参数,swapchain要按照顺序从backbuffer n 往前到front buffer 交换数据
HWND hDeviceWindow; --窗口;窗口模式,就是显示的窗口,如果null,则使用当前的激活窗口。全屏模式,主显示器使用当前的激活窗口,其他显示器必须使用一个确定的窗口。当窗口重置时back buffer不会被重置。
BOOL Windowed; --是否全屏
BOOL EnableAutoDepthStencil;--是否让D3D自动管理depth buffer,如果true则下一个参数必须是个正确的参数
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags; --一些在present显示时的参数
UINT FullScreen_RefreshRateInHz;--全屏时硬件刷新屏幕的频率,EnumAdapterModes返回的模式中选其一,窗口模式要填0,
UINT PresentationInterval; backbuffer交换给frontbuffer的最大频率
}
*D3DSWAPEFFECT 交换链参数
D3DSWAPEFFECT_DISCARD = 1,
当使用flip和copy的时候,present会保证不影响每个buffer的内容,这会带来大量的显存开销,同时使用这个标记可以采取效率最高的交换方式,当buffer的东西被有效显示后,某些buffer里的数据就不保证正确性了,所以在present之前一定要先update整个backbuffer。如果采样方式不是用的D3DMULTISAMPLE_NONE一定都要用这个标记。
D3DSWAPEFFECT_FLIP = 2,见1.3.1
D3DSWAPEFFECT_COPY = 3,见1.3.1
D3DSWAPEFFECT_OVERLAY = 4,
使用显存中特定的一块区域(overlay)当使用这块区域时不会发生从显存copy到内存中的操作,效率高,这只可以用于win7之后并且是D3D9ex的
D3DSWAPEFFECT_FLIPEX = 5,
D3DSWAPEFFECT_FLIP的更高效模式只可以用于win7之后并且是D3D9ex的
*DWORD Flags
D3DPRESENTFLAG_DEVICECLIP
限制了window模式下客户端区域present操作的结构,暗示了back buffer包含有video。
D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
在调用present后discard depth/stencil surface里面的内容。这样就使depth/stencil surface是一个可写的surface。如果depth/stencil surface的格式是D3DFMT_D16_LOCKABLE或者 D3DFMT_D32_LOCKABLE设置这个标记将会返回一个错误。
D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
backbuffer可以被锁定
D3DPRESENTFLAG_NOAUTOROTATE
不允许自动旋转显示器自动选择显示内容提高效率 D3D9ex可用
D3DPRESENTFLAG_VIDEO
说明backbuffer 有video
*UINT PresentationInterval它说明了硬件的显示刷新率与present进行缓存swap的频率的二者的关系,这个参数会影响屏幕的实际的FPS等属性。显卡的刷新率不是真的FPS,那只是显卡给屏幕的重绘频率,真正的FPS是实际的swap的频率结合显卡的刷新频率,要看屏幕上最终是每秒显示了几次SWAP交换。
这里是为了解决gpu和显示输出对frontbuffer的冲突解决方式
present不被hal device处理,如果硬件在忙于处理或等待垂直同步(防止被撕裂),那么执行present会马上失败返回,即不发生交换缓存操作。也就是硬件忙的时候会保证垂直同步而不进行重绘制,它可能是可以保证画面不会出现撕裂,但是是以卡帧为代价。它的意思也是不要去锁定FPS。
D3DPRESENT_INTERVAL_ONE/~FOUR present等待垂直同步,但是保证present最多每1~4帧被打扰一次。这里是提高帧率与放置撕裂的权衡
D3DPRESENT_INTERVAL_IMMEDIATE
能present 就立即present,完全不管垂直同步了,最贴近实际的swap帧率。
D3DPRESENT_LINEAR_CONTENT
back buffer format is X8R8G8B8.
其中
D3DPRESENT_INTERVAL_DEFAULT 基本机遇是D3DPRESENT_INTERVAL_ONE
垂直同步质量与FPS的关系(越往下FPS变高,垂直同步变差)
D3DPRESENT_DONOTWAIT
D3DPRESENT_INTERVAL_ONE
D3DPRESENT_INTERVAL_TWO
D3DPRESENT_INTERVAL_。。
D3DPRESENT_INTERVAL_IMMEDIATE
2.6清理资源
当程序要退出或者需要废弃当前device重建新的时候,要清理D3D9资源,调用
VOID Cleanup()
{
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}