您的位置:首页 > 其它

Ogre线程渲染,渲染设备无法恢复窗口停止响应的案例及解决办法

2013-11-21 11:41 375 查看
问题比较简单:

我在主线程Main中创建了WIN32窗口,并初始化好了Ogre相关资源。独立开启一个线程Render进行Ogre的渲染以及场景挂接、移除等渲染循环操作。

正常情况下不会有任何问题,但是一旦我们改变了WIN32窗口的大小时,这时候会触发Ogre重置渲染设备,但是重置失败了,渲染循环也就崩溃了....

跟着Ogre源代码到,bool D3D9Device::reset()里面发现是调用hr = mDevice->Reset(mPresentationParams);时返回了一个错误的值,也就是说在非创建窗口消息循环的线程调用void WorkSearchContext::Reset(VirtualProcessor *pVirtualProcessor, Algorithm algorithm)时没有正常执行(这里有位是Release也就没有深入跟踪调试)

试过很多种改变窗口style和styleEx的方法,都没用。这里还要说明一下,使用FireBreath控件封装好的WIN32窗口不存在之类的问题,这说明问题原因不是出自Ogre本身渲染部分,而是WIN32窗口默认不支持在其他线程修改渲染设备(个人猜测)。

至于具体解决方案,暂时还没有找到,这里记录一下问题!

2013.11.21 15:37 临时解决办法

void RenderWindow::WindowMoveOrResize()

{

//暂停渲染

UGlobe::Base::MessageSender::SendRenderMessage(UGlobe::Base::PAUSE_RENDER);

//暂时用renderOneFrame来恢复渲染设备,以后需要进一步改进

//用于在异步线程渲染的时候重置渲染设备

RenderEngine::GetRenderEngine().GetRoot()->renderOneFrame(10);

//恢复渲染

UGlobe::Base::MessageSender::SendRenderMessage(UGlobe::Base::RECOVER_RENDER);

}

在创建窗口的Main线程里面监听窗口Resize消息,获得消息后立马暂停渲染线程的渲染。此时主线程进行一帧渲染,在这一帧里面,D3D Reset被正常执行了,也就是设备正常恢复了,然后恢复渲染线程的渲染。

但是这样造成了一个新的问题,就是主线程【暂停——渲染一帧——恢复】这个过程可能会产生线程互斥上的问题,而我的确遇到了(虽然概率很小)

虽然这样不能作为最终定论,但是这里给了我一个解决办法的思路,就是窗口改变大小的时候,暂停渲染线程,让主线程手动调用恢复设备。。。然后继续渲染

————接来下继续探索完美的解决方案!

2013.11.22 10:00

经过半天的探究结果:结合MSDN对D3D Device的解释【http://msdn.microsoft.com/en-us/library/microsoft.windowsmobile.directx.direct3d.device.reset(v=vs.85).aspx
“A call to Reset fails
if made on a different thread than the one used to create the device being reset.”】,我们必须把创建渲染设备,也就是renderwindow放在渲染线程里面。

解决方式:将创建renderwindow的过程封装成一个即时任务发送到渲染线程,主线程必须等待任务做完再返回创建好的RenderWindow*指针,即同步

下面验证结果!

2013.11.22 11:35

代码:

第一步:

boost::condition_variable_any cond_callback_complete;//定义条件变量

boost::mutex muCreate; //定义互斥锁

第二步:

boost::mutex::scoped_lock lock(muCreate);//锁住互斥锁

proxyPtr->PostTask(FROM_HERE,

boost::bind(&RenderWindow::InitRenderTask,this));//向渲染线程发送Create渲染设备任务

cond_callback_complete.wait(muCreate);//等待上诉任务执行完成的信号

第三步:

void RenderWindow::InitRenderTask()//向渲染线程发送的任务函数

{

......//创建渲染设备相关操作

......

cond_callback_complete.notify_one();//发出创建完成信号,让主线程wait结束

}

通过以上三步,已经完美解决了上诉一系列问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐