调试最长的一帧(第27天)

对于几个多线程渲染中的成员变量

 

继续抄一抄,

 

Block阻塞器

BlockCount;计数器类。它与阻塞器类的使用方法基本相同。block()阻塞线程

release()释放线程

不过除此之外,BlockCount的构造函数还可以设置一个阻塞计数值。

计数的作用是,每当阻塞器的completed()函数被执行一次,计数器就减1,直至减到0就释放被阻塞的线程。

Barrier类,线程栅栏类。这是一个对于线程颇为重要的阻塞器接口。

它的构造函数与BlockCount类似,可以设置为一个整数值,我们可以把这个值理解为栅栏的强度。

每个执行了Barrier::block()函数的线程都将被阻塞。当被阻塞在栅栏处的线程达到指定的数目时,就好比栅栏无法支撑那么大的强度一样,展览将被冲开,所有的线程将被释放。重要的是,这些线程是几乎同时释放的,也就保证了线程执行的同步性。

从代码中,也很容易看到。BlockCount是由其他任意线程执行指定次数的completed()函数,即可释放被阻塞的线程;而Barrier则是必须阻塞指定个数的线程之后,所有的线程才会同时被释放。

其实这些都不用死记硬背,看看源码就一目了然了。

OSG多线程渲染实现的关键在于以下三个变量,用与对线程阻塞与同步的操作,

 

osg::BarrierOperation类在定义时会传入两个参数。整型参数定义了这个栅栏可阻塞的线程数,或者说它的强度(达到这一数值时将自动释放所有线程),另一个则定义是否需要在阻塞前执行固定的操作(通常不用,即BarrierOperation::NO_OPERATION)

osg::EndOfDynamicDrawBlock在定义时会传入一个参数,表示阻塞的最大计数值。当阻塞器对象的completed()函数执行次数达到这一数值时,才会释放被阻塞的线程。

 

这边都+1,是因为在主进程中block一下,以便释放所有block的线程。如不需要等待所有线程完成即可下一帧,则只需要主进程的这1个block即可。在渲染开始时,需要同步其他线程,设定为contexts.size()+1或者camera.size()+1即可。主线程的为1,其他线程为context.size()或者camera.size();

 

 

上面两个开启线程的方法,会在后面的电子书介绍,所以暂时放在这里,不扩展。

 

在这两者之间,其实就是单线程渲染方式顺序执行各个图形设备的筛选和绘制工作,概括起来就是

在CullDrawThreadPerContext和DrawThreadContext方式下,由于gc->getGraphicsThread()为真,因此不再执行GraphicsContext::runOperations(),也就是不再从主进程的renderingTraversals函数中执行场景绘制;而在更加高效也更加复杂的cullThreadPercameraDrawThreadPercontext方式下,不只场景绘制不再由主进程来进行,由于camera->getCameraThread()也为真,因此筛选动作也是由摄像机线程来完成的。

这点可以验证下,看看走哪里

 

 

 

可见绘制是摄像机线程完成的。具体不展开,因为电子书后面还有,到时候再根据电子书内容慢慢调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值