最近在封装Direct3D 9引擎时,更新设备调用IDirect3Device::Reset()函数总是失败,查询了各种资料总是无果。后来知道了怎么开启Direct3D的调试模式(如图1,2),知道了原来创建设备和重置设备不在同一个线程就会出错(错误信息如图3)!!!
我在Direct3D的帮助文档中(如图4,5),找到了官网给予的解释(图6):
Content:
Full-screen Direct3D applications provide a window handle to the Direct3D run time. The window is hooked by the run time. This means that all messages passed to the application's window message procedure have first been examined by the Direct3D run time's own message-handling procedure.
Display mode changes are affected by support routines built into the underlying operating system. When mode changes occur, the system broadcasts several messages to all applications. In Direct3D applications, the messages are received on the window procedure thread, which is not necessarily the same thread that called IDirect3DDevice9::Reset or IDirect3D9::CreateDevice (or the final Release of IDirect3DDevice9, which can cause a display mode change). The Direct3D run time maintains several critical sections internally. Because at least one of these critical sections is held across the mode switch caused by IDirect3DDevice9::Reset or IDirect3D9::CreateDevice, these critical sections are still held when the application receives the mode-change related window messages.
This design has some implications for multithreaded applications. In particular, an application must be sure to strongly segregate its window message handling threads from its Direct3D threads. An application that causes a mode change on one thread but makes Direct3D calls on a different thread in its window procedure is in danger of deadlock.
For these reasons, Direct3D is designed so that the methods IDirect3DDevice9::Reset, IDirect3D9::CreateDevice, IDirect3DDevice9::TestCooperativeLevel, or the final Release of IDirect3DDevice9 can only be called from the same thread that handles window messages.
我在程序中的主线程(主线程主要相应上层系统调用)中创建的设备,然后在另一个线程(这个线程可以叫做“渲染线程”,它不断地执行循环调用,来保证每一帧的正常显示)中重置修改设备,这样会出错。现在我把创建设备也放置在渲染线程中,解决了这个问题。