查看: 2543|回复: 10

请教GPU与Renderer::draw()的同步问题

[复制链接]

该用户从未签到

发表于 2008-11-30 22:30:36 | 显示全部楼层 |阅读模式
大家好
    请问下Renderer::draw()在分发opengl指令之后,GPU还没有完成绘制,会不会Renderer::draw()又开始分发指令啊

该用户从未签到

发表于 2008-11-30 23:31:03 | 显示全部楼层
不会的,因为有Barrier栅栏的同步处理。可以参看《最长的一帧》

该用户从未签到

 楼主| 发表于 2008-12-1 09:37:44 | 显示全部楼层
对于DrawThreadPerContext线程模型:
numThreadsOnStartBarrier = 1;
numThreadsOnEndBarrier = 1;
startRenderingBarrier以及endRenderingDispatchBarrier栅栏就不会同步了吧。
swapReadyBarrier它的作用是在交换双缓存之前对所有GC线程执行一次同步,能同步GPU吗。
数据全是static类型,那样endDynamicDrawBlock也不起作用了吧
还有其他的Barrier栅栏不

[ 本帖最后由 forest37 于 2008-12-1 09:55 编辑 ]

该用户从未签到

发表于 2008-12-1 10:30:01 | 显示全部楼层
我对GPU编程还不是很了解,不过下一步准备深入集中地学习一下。我不知道如果分发指令的时候GPU的命令执行还没有结束会发生什么事情。会发生系统崩溃吗?还是仅仅将新加进来的OpenGL命令排在队列的后面?如果是后者的话那没必要对GPU进行同步。

有关GPU数据的操作可以参看OpenGLQuerySupport::checkQuery函数,这里使用了query object的机制,计算GPU中的渲染命令执行所耗费的时间。如果愿意的话,完全可以在这里使用GL_QUERY_RESULT_AVAILABLE来延迟主进程直到GPU渲染完成,但是OSG没有这样做,相信一定有其原因。

该用户从未签到

 楼主| 发表于 2008-12-1 10:40:11 | 显示全部楼层
对于DrawThreadPerContext线程模型,且数据全是static类型时,我发现如果GPU执行的时间大于CULL+Draw的时间,一个CULL执行完后并不会立即执行第二个阶段的APP/CULL,但如果GPU执行的时间小于CULL+Draw的时间,一个CULL执行完后会立即执行第二个阶段的APP/CULL,只是我还没找到相应的控制代码

该用户从未签到

发表于 2008-12-1 10:45:58 | 显示全部楼层
没有别的栅栏了,如果您的GPU执行时间是从OSG的StatHandler中得到的,那么强烈建议您深入阅读一下OpenGLQuerySupport::checkQuery及其相关函数,相信必有斩获。也希望您将自己的测试和分析结果继续与大家分享

该用户从未签到

发表于 2008-12-1 11:01:28 | 显示全部楼层
此外,另一个值得注意的地方就是ThreadSafeQueue::takeFront,OSG的cull和draw函数在执行过程中对场景视图sceneView玩了一个“踢皮球”的游戏

CULL:将场景视图从_availableQueue中取出,筛选结束后传到_drawQueue中;
DRAW:将场景视图从_drawQueue中取出,绘制结束后传到_availableQueue中;

如果在这个过程中,takeFront没有从队列中得到场景视图的话,那么会立即阻塞线程,等待有场景视图从正在执行的CULL或DRAW过程返回。这种保护机制可能也是您测试结果的诱因之一

该用户从未签到

 楼主| 发表于 2008-12-1 13:27:31 | 显示全部楼层
好像GPU的绘制不会影响_drawQueue吧
以下是我测试的代码 cow.osg 中的数据被修改为static
在好一点的显卡上一个CULL执行完后会立即执行第二个阶段的APP/CULL,差一点的显卡上两个CULL之间会有间隔。而且在DrawThreadPerContext线程模型下的CULL的时间会远大于单线程的CULL,当然如果StatHandler显示的时间准确的话。也许在看了OpenGLQuerySupport::checkQuery之后,我会有些新的想法吧
int main()
{
    osgViewer::Viewer viewer;
        osg::Group *mRoot=new osg::Group();
        osg::Node* m1=osgDB::readNodeFile("D:\\OSG\\data\\cow.osg");       
        for (int i=0;i<600;i++)
        {
                osg:ositionAttitudeTransform* pat=new osg::PositionAttitudeTransform;
                pat->addChild(m1);
                pat->setPosition(osg::Vec3(i*5,0,0));
                mRoot->addChild(pat);
        }

        viewer.setSceneData(mRoot);
        mRoot->setDataVariance(osg::Object::STATIC);
        viewer.addEventHandler(new osgViewer::StatsHandler);
        //viewer.setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
        return viewer.run();
}

该用户从未签到

 楼主| 发表于 2008-12-1 13:36:35 | 显示全部楼层
也许问题就出在ThreadSafeQueue::takeFront,我以为是drawQueue的takeFront

该用户从未签到

发表于 2008-12-1 13:38:46 | 显示全部楼层
谢谢,很有意思,有空我也研究一下。

forest37有兴趣的话不妨把自己的见解与osg-users的专家们也讨论讨论。很高兴看到国内的很多OSG同行不再局限于某个具体功能实现的求助以及大段代码调试的问题,而是进一步着眼于仿真系统本身的隐患和改善方案,这也是论坛和邮件组设立的初衷,可喜可贺~~

该用户从未签到

 楼主| 发表于 2008-12-3 09:27:32 | 显示全部楼层
robert:
The GPU draw time is just that the GPU draw time, it is unrelated to
anything on the CPU unless the OpenGL fifo is full, and if this is the
case then the draw dispatch will block and then CPU draw dispatch and
GPU draw times will be rather similar, but this isn't the case - you
are absolutely GPU limited.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表