青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

麒麟子

~~

導(dǎo)航

<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

統(tǒng)計(jì)

常用鏈接

留言簿(12)

隨筆分類

隨筆檔案

Friends

WebSites

積分與排名

最新隨筆

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

OGRE3D 渲染系統(tǒng)線程化

先前研究渲染系統(tǒng)線程化的時(shí)候翻到了這篇文章,于是一邊看一邊寫出了漢語(yǔ)。 文中寫多地方翻譯得很不通順,見(jiàn)諒。

 

譯者序:偶然在網(wǎng)上看到這篇文章,自己很想仔細(xì)研究一下。但搜尋半天不見(jiàn)中文版。于是自己斗膽翻譯了一下。文中不免有漏洞百出,甚至可以說(shuō)有些地方不及Google翻譯得好。但這樣總的來(lái)說(shuō)是出了一個(gè)中文版,而我自己在翻譯過(guò)程中也會(huì)停下來(lái)仔細(xì)思考。

OGRE這個(gè)線程化的文章很老了。因?yàn)镺GRE目前已經(jīng)支持多線程渲染。 這篇文章貌似是某些人研究出來(lái)的三個(gè)線程化方案,并給出了測(cè)試結(jié)果。以向OGRE社區(qū)證明線程化方案的可行性。 對(duì)于許多想研究渲染線程化的人來(lái)說(shuō),是一篇值得參考的文章。文中提出了許多在不同情況下線程化時(shí)遇到的問(wèn)題,以及需要注意的問(wèn)題。值得一讀/

介紹

OGRE3D(a.k.a. Ogre)是目前最常用的開(kāi)放源代碼 3D 引擎之一。它是一款功能完善的通用 3D 引擎,可應(yīng)用于從游戲到科學(xué)模擬等多種商用產(chǎn)品。該引擎由來(lái)自開(kāi)放源代碼社區(qū)的數(shù)百名技術(shù)人員歷經(jīng)五年時(shí)間而開(kāi)發(fā)成功。如欲了解 Ogre 的詳細(xì)信息,請(qǐng)?jiān)L問(wèn)網(wǎng)站 www.ogre3d.org 。

然而,盡管 Ogre 功能強(qiáng)大,但是它卻在技術(shù)上存在一個(gè)重要缺憾,那就是它無(wú)法在系統(tǒng)中充分利用多個(gè)處理器的優(yōu)勢(shì)。目前,英特爾已經(jīng)有多款雙核產(chǎn)品上市,而超線程(HT)技術(shù)更是在多年前就已應(yīng)用在英特爾&reg; 奔騰&reg; 4 處理器中。將 Ogre 線程化所實(shí)現(xiàn)的性能增益將絲毫不遜色于添加第二枚處理器所實(shí)現(xiàn)的性能增益。

本文將向您介紹將 Ogre 渲染系統(tǒng)線程化的三種不同處理方法,并且我們將根據(jù)下文所描述的線程化目的,選擇一種方法進(jìn)行完整實(shí)施。

線程化目標(biāo)

當(dāng)我們?cè)趯?duì)OGRE線程化時(shí),需要實(shí)現(xiàn)以下幾個(gè)目標(biāo):

·通過(guò)改動(dòng)最少的OGRE源碼以使OGRE社區(qū)接受。

·在雙核處理器上,相對(duì)于非線程化渲染的OGRE系統(tǒng)來(lái)說(shuō),提升25%的FPS,以平衡應(yīng)用程序的CPU和GPU使用率

·在用戶不知道的情況下對(duì)SDK包中的DEMO進(jìn)行必要的變動(dòng),而不讓用戶在畫(huà)面上有任何察覺(jué)。

假設(shè)

本文提及了OGRE中的許多類,以及使用了OGRE中的許多程序片段。所以,這里假設(shè)讀者都是對(duì)OGRE的源碼非常了解或者已經(jīng)對(duì)源碼進(jìn)行過(guò)快速的查閱,否則將很難理解這些OGRE的特性。同樣,讀者也應(yīng)該對(duì)線程的概念有所了解。這里就不再介紹更多關(guān)于線程的內(nèi)容。

限制

這里所討論的所有實(shí)現(xiàn),都沒(méi)有在超過(guò)兩個(gè)處理器的機(jī)器上實(shí)驗(yàn)過(guò)。因此,這些技術(shù)對(duì)于雙核處理器或雙核心系統(tǒng)最適合不過(guò)。以后的文章中將會(huì)討論如何在OGRE中創(chuàng)建一個(gè)線程隊(duì)列,使OGRE以及使用OGRE的應(yīng)用程序都能夠在雙核處理器以及多核上得到性能的提升。

線程化OGRE渲染系統(tǒng)使用到的技術(shù)

OGRE中有很多地方都可以被線程化,但線程化最能在多核上提升性能的是渲染系統(tǒng)。渲染系統(tǒng)在OGRE占據(jù)了巨大的一塊,并且從某種意義上講,它能單獨(dú)地被外部程序訪問(wèn)。下面介紹三種將OGRE渲染系統(tǒng)線程化的例子。

1、 在OGRE中對(duì)于渲染的調(diào)用可以被放在他自己的線程中。

2、 一個(gè)線程化層可以被放在OgreMain和渲染系統(tǒng)插件之間。

3、 渲染系統(tǒng)插件可以單開(kāi)一個(gè)線程來(lái)調(diào)用圖形API。

上面這三種方案都有各自的優(yōu)缺點(diǎn),本文將會(huì)一一討論。

線程化并不會(huì)對(duì)每個(gè)應(yīng)用程序有利

注意,線程化只對(duì)那種花費(fèi)在圖形調(diào)用API和邏輯處理上的時(shí)間很接近的應(yīng)用程序有好處。若其中一個(gè)較另一個(gè)差別很大,則看不到明顯的效果。

技術(shù)方案1:線程化OgreMain(高級(jí)線程化手段)

在OgreMain中進(jìn)行線程化是一種最高級(jí)的線程化手段,也表示能獲得最高級(jí)的潛在性能。這是因?yàn)镺gre在做一次渲染的時(shí)候,需要做很多事情,并且不僅僅是提交某些命令或數(shù)據(jù)到顯卡。比如,決定哪個(gè)攝相機(jī)是活動(dòng)攝相機(jī),遍歷場(chǎng)景中所有可見(jiàn)物體,標(biāo)志所有可見(jiàn)物體去渲染,等等。 下面的插圖展示了一個(gè)Ogre渲染過(guò)程(為了簡(jiǎn)化起見(jiàn),一些東西被忽略)。高級(jí)線程化將導(dǎo)致這里所有的過(guò)程被放置在他自己的線程里。

clip_image002

線程化問(wèn)題

采用這種方案有一個(gè)主要的問(wèn)題就是,兩個(gè)線程中將會(huì)發(fā)生代碼重疊。打個(gè)比方,主線程和渲染線程都需要訪問(wèn)場(chǎng)景中某個(gè)場(chǎng)景對(duì)象的相同數(shù)據(jù)。主線程要更新它的位置和方向,然而此時(shí)渲染線程要讀這些信息或者在渲染線程渲染前主線程修改了這些內(nèi)容。從而導(dǎo)致渲染幀的內(nèi)容與實(shí)際不符,會(huì)相差一幀。特別地,當(dāng)渲染在渲染一個(gè)對(duì)象時(shí)主線程卻要把它刪除,就會(huì)出問(wèn)題。如下圖所示:

clip_image004

除了剛剛提到的線程自身的問(wèn)題外,同樣也存在處理器共享失敗的問(wèn)題。當(dāng)一個(gè)變量被一個(gè)線程更新的時(shí)候,這個(gè)變量是處于這個(gè)線程所在的CPU緩存行中的,而另外一個(gè)線程也會(huì)訪問(wèn)這個(gè)緩存行中的內(nèi)容的相同數(shù)據(jù)。由于它們共享緩存行,一個(gè)處理器需要清空整個(gè)緩存行,不管其它處理器是否做了修改。這就是這個(gè)高級(jí)線程方方案的問(wèn)題所在。因?yàn)橹骶€程和渲染線程使用同樣的類的實(shí)例。 由于類體變量被相繼地放置在內(nèi)存中,因此他們要共享同樣的緩存行。關(guān)于更多緩存行共享失敗的問(wèn)題。可以查看相關(guān)文章。

避免問(wèn)題

為了避免上面提到的線程問(wèn)題,這里提供了兩個(gè)可以安全訪問(wèn)和更新對(duì)象的解決方案。

1、 使用一個(gè)更新隊(duì)列。

2、 復(fù)制對(duì)象

更新隊(duì)列的方案通過(guò)維持一個(gè)對(duì)象的更新隊(duì)列來(lái)防止訪問(wèn)重疊。見(jiàn)下圖。 更新將只發(fā)生一次,即當(dāng)主線程準(zhǔn)備讓渲染線程開(kāi)始渲染的時(shí)候。當(dāng)然,你需要等待渲染線程完成后才能進(jìn)行第二次啟用。這個(gè)方案有一個(gè)缺點(diǎn),就是單處理系統(tǒng)上的CPU反而會(huì)承受這個(gè)更新隊(duì)列的額外負(fù)擔(dān),而享受不到這個(gè)更新隊(duì)列的好處。另一個(gè)缺點(diǎn)就是,當(dāng)對(duì)硬件資源(如索引,頂點(diǎn)緩沖等)改變時(shí)。排隊(duì)改變這些資源將會(huì)很困難,因?yàn)檫@些數(shù)據(jù)都非常大。

clip_image006

復(fù)制對(duì)象的方案從本質(zhì)上講,就是為一個(gè)經(jīng)常變動(dòng)的對(duì)象復(fù)制副本。在這種方案下,使用OGRE的應(yīng)用程序?qū)⒈灰髲?fù)制一個(gè)經(jīng)常需要更新的對(duì)象,因?yàn)橹挥兴滥男?duì)象是需要經(jīng)常更新的。應(yīng)用程序也不得不按照一定的方式來(lái)寫:對(duì)象的處理是在對(duì)象被顯示后的下一幀。(這點(diǎn)沒(méi)有太明白,貌似意思是說(shuō),對(duì)象的處理和渲染為兩個(gè)幀,一個(gè)幀拿來(lái)渲染,一個(gè)幀拿來(lái)處理,看到下面那圖應(yīng)該是這個(gè)意思)。當(dāng)然,如果你的應(yīng)用程序并不每幀更新對(duì)象,這也是一個(gè)問(wèn)題,在這種情況下,你的對(duì)象有可能是在幾幀后才被訪問(wèn),這樣就會(huì)導(dǎo)致沖突。也可以對(duì)其做一些優(yōu)化,如只有對(duì)象中主線程和渲染線程要共享的數(shù)據(jù)才被復(fù)制,以此來(lái)減少負(fù)擔(dān)。在這樣的情況下對(duì)象將不再是一個(gè)復(fù)制品,但是將會(huì)有一個(gè)雙緩沖用于存放你復(fù)制的這些東西。

在下圖中,注意那個(gè)object X 將保持一致性(假設(shè)更新速度大于30FPS)。但是object Y將不會(huì),因?yàn)樵谇耙粠M(jìn)行了縮放,但是這個(gè)數(shù)據(jù)并沒(méi)有被體現(xiàn)在復(fù)制對(duì)象中。

clip_image008

圖里有許多關(guān)于同步的東西被我刪掉了,但是上面著實(shí)能夠反應(yīng)這個(gè)技術(shù)的實(shí)現(xiàn)形式。

上面說(shuō)到的兩個(gè)技術(shù)中,并沒(méi)有任何一個(gè)技術(shù)被OGRE社區(qū)接受,它們都需要大量修改OGRE代碼,因此并未繼續(xù)。一個(gè)需要復(fù)制對(duì)象數(shù)據(jù)來(lái)控制數(shù)據(jù)修改的例子便是Frustum::updataView函數(shù)和_update函數(shù),對(duì)于實(shí)現(xiàn)這個(gè)函數(shù)的所有類,都需要在渲染中被調(diào)用,以及OGRE的其它地方(渲染以外的地方)。

在哪里進(jìn)行線程化

在OgreMain中進(jìn)行線程化的一個(gè)理想的地方便是在Root::renderOneFrame中。這個(gè)函數(shù)調(diào)用了主渲染_Root::_updateAllRenderTargets,這個(gè)函數(shù)可以輕易地被封裝一次。

下面是一些實(shí)現(xiàn)上面想法的示例代碼。



_beginthreadex(
0,0,Root::renderThreadFuc,0,0,0);



/*static*/ unsigned int Root::renderThreadFunc( )



    
while(1)

    
{

        waitForStartRendering( );

        _setStartRendering(flase);

        _updateAllRenderTargets( );

        _setRenderingComplete(
true);

    }


}


bool Root::renderOneFrame( )

{

    
if(!_fireFrameStarted( ) )

        
return false;

    
if(mThreadedRendering)

    


        _waitForRenderingComplete( );

        _setRenderingComplete(
false);

        _setStartRendering(
true);

    }


    
else

    
{

        _updateAllRenderTargets( );

    }


}


_wait 和_set函數(shù)演示了操作系統(tǒng)依賴的同步函數(shù)調(diào)用,例如,WINDOWS版本的_waitForRenderingComplete將會(huì)包含一個(gè)WaitForSingleObject調(diào)用。注意當(dāng)多線程開(kāi)啟的時(shí)候,應(yīng)該在真正渲染完成之前調(diào)用_fireFrameEnded函數(shù)。

技術(shù)方案2:創(chuàng)建一個(gè)線程渲染系統(tǒng)層(中級(jí)線程化手段)

創(chuàng)建一個(gè)線程化的渲染系統(tǒng)層對(duì)OGRE渲染系統(tǒng)來(lái)說(shuō)是一個(gè)很不顯眼的方案。但是由于OGRE渲染系統(tǒng)的復(fù)雜性,它也是最困難的方案。渲染層從本質(zhì)上講是對(duì)渲染系統(tǒng)插件(如D3D,OPENGL)的一個(gè)封裝。想要在OGRE中創(chuàng)建和集成一個(gè)這樣的附加渲染系統(tǒng),只需要對(duì)OGRE進(jìn)行較少的改動(dòng)。但是創(chuàng)建創(chuàng)建一個(gè)線程化的渲染系統(tǒng)層,又是另一回事了。

clip_image010

為了創(chuàng)建一個(gè)線程化的渲染系統(tǒng)層,你至少需要在OgreMain中實(shí)現(xiàn)Ogre::RenderSystem 類和Ogre:RenderWindow類。這兩個(gè)類僅僅是界于Ogre和實(shí)際的渲染器插件之間的一個(gè)層。這個(gè)層的工作并不是簡(jiǎn)單的將對(duì)插件的函數(shù)調(diào)用進(jìn)行封裝。需要決定要做哪些什么,以便調(diào)用渲染器插件,因?yàn)檫@個(gè)方案的目標(biāo)是將渲染的工作分離到另一個(gè)線程中。在實(shí)面這些類的函數(shù)時(shí),有幾事情需要思考。

·習(xí)慣性地(如,所有函數(shù)調(diào)用僅僅是在開(kāi)始渲染之前調(diào)用。)可以僅是對(duì)渲染器插件的直接調(diào)用,(相當(dāng)于函數(shù)轉(zhuǎn)發(fā))。也可以在包裝的同時(shí)進(jìn)行一些必要的初始化。

·在調(diào)用渲染器插件進(jìn)行創(chuàng)建操作時(shí),將需要等待前一幀渲染完成。并且需要一個(gè)包裝類來(lái)包裝那個(gè)渲染器返回(提供一個(gè)已經(jīng)存在的實(shí)例)的與創(chuàng)建相當(dāng)?shù)念悺R粋€(gè)需要包裝類的好例子便是渲染器插件返回的RenderWindow類。這個(gè)類的實(shí)例通過(guò)RenderWindow:createRenderWindow創(chuàng)建并返回。

·某些函數(shù)需要訪問(wèn)基類。RenderSystem和RenderWindow類需要調(diào)用一些基類方法來(lái)完成一些內(nèi)部事情。在OGRE中不這樣做,會(huì)導(dǎo)致不正確的行為。

·渲染用的函數(shù)需要被排隊(duì),以便享受到多線程的好處。渲染線程將會(huì)遍歷那個(gè)隊(duì)列,并按順序調(diào)用那些函數(shù)。 RenderWindow中的swapBuffers函數(shù)是一個(gè)例外。它的包裝函數(shù)既要加入渲染隊(duì)列管理,但它又是向渲染線程發(fā)出信號(hào),執(zhí)行渲染隊(duì)列中的函數(shù)的地方。

上面提到的幾點(diǎn)描述了實(shí)現(xiàn)這個(gè)方案需要做的事情,也還有其它一些小問(wèn)題需要考慮,并且一些問(wèn)題需要在實(shí)現(xiàn)的時(shí)候處理。

線程化的問(wèn)題

這個(gè)實(shí)現(xiàn)和“方案1:高級(jí)線程化方案”一樣,存在同樣的問(wèn)題。除開(kāi)這種情況,最好的解決方案就是復(fù)制需要共享的數(shù)據(jù)。因?yàn)檫@個(gè)中間層不擁有Ogre中的類。也有其它一些從“低級(jí)線程化方案”中借鑒而來(lái)的解決辦法來(lái)完成這個(gè)實(shí)現(xiàn),從而對(duì)顯卡資源提供一個(gè)線程安全訪問(wèn)手段。

在哪里線程化

正如先前提到的,這將是線程化Ogre渲染系統(tǒng)的一個(gè)最不顯眼的方案。所需要對(duì)Ogre做的輕微改變僅是對(duì)Ogre現(xiàn)有的渲染系統(tǒng)增加一個(gè)線程化的渲染系統(tǒng)層。像這樣

void Root::AddRenderSystem(RenderSystem *newRender)

{

    mRenderers.push_back(newRender);

#ifdef __THEARDRENDERSYSTEM__

    
if(mThreadRenderSystem)

    
{

        RenderSystem
* newTRender = 

            
new ThreadedRenderSystem(newRender);

        
if(newTRender != NULL)

            mRenderers.push_back( newTRender);

    }


#endif

}




技術(shù)方案3:線程化渲染插件(低級(jí)線程化手段)

線程化一個(gè)特定的渲染插件帶來(lái)了最低級(jí)的適應(yīng)性,因?yàn)樗吞囟ǖ募夹g(shù)(如D3D,OPENGL)綁定起來(lái)。但是它也使你能夠最大限度地操縱硬件資源。

實(shí)現(xiàn)這個(gè)方案最干凈利落的辦法就是創(chuàng)建一個(gè)介于API和渲染插件之間的層,用來(lái)處理線程化。(如下圖)

clip_image012

在這種方法下,它僅僅是用你的層來(lái)替換API接口。并且每個(gè)一調(diào)用從渲染插件的調(diào)用都是線程安全的,因?yàn)槟愕倪@個(gè)層處理了所有的調(diào)用。為D3D做這個(gè),僅僅是用你自己的包裝類和方法替換了IDirect3D的接口。對(duì)于OPENGL,你將移除所有的OPENGL頭文件,并用你自己包裝好后的頭文件替換掉它們。有可能你需要用一個(gè)命名空間來(lái)包裝OPENGL函數(shù),以免出現(xiàn)名詞沖突。

這個(gè)方案依然和“中級(jí)線程化手段”一樣需要考慮些線程化相關(guān)的東西。

·初始化不需要多線程

·創(chuàng)建函數(shù)以及一些get函數(shù)需要在渲染完一幀前等待。

·渲染命令,和伴隨參數(shù)將需要加入隊(duì)列中。

關(guān)于索引和頂點(diǎn)緩沖的加鎖

對(duì)于所有的方案,都存在一個(gè)使用硬件資源時(shí)的潛在線程問(wèn)題。對(duì)索引頂點(diǎn)緩沖區(qū)的加鎖就是一個(gè)很大的挑戰(zhàn),因?yàn)槟承?yīng)用程序在執(zhí)行的時(shí)候總是會(huì)反復(fù)對(duì)這些緩沖區(qū)進(jìn)行加鎖和解鎖。比如對(duì)于動(dòng)態(tài)緩沖區(qū),總是會(huì)每幀都改變它的內(nèi)容來(lái)實(shí)現(xiàn)畫(huà)面的變化。一些應(yīng)用程序也會(huì)重用緩沖區(qū)以使多個(gè)對(duì)象每幀都能夠共享同樣的頂點(diǎn)和索引緩沖區(qū)。為了解決這個(gè)問(wèn)題,我們需要緩沖這些緩沖區(qū)。然而,可以通過(guò)很多方法來(lái)實(shí)現(xiàn),下面有兩種緩沖辦法:

1、 部分緩沖區(qū)加鎖,這是一個(gè)類似于雙緩沖的緩沖技術(shù)。我們將在顯卡中創(chuàng)建兩個(gè)緩沖區(qū),而不是一個(gè)。在這種情況下,當(dāng)應(yīng)用程序在寫一個(gè)緩沖區(qū)的時(shí)候,渲染線程將使用另一個(gè)緩沖區(qū)中的數(shù)據(jù)進(jìn)行渲染。這個(gè)方案可以提升渲染速度但是有一個(gè)缺點(diǎn),就是會(huì)消耗更多的顯存。并且不能處理應(yīng)用程序在每一幀對(duì)同一緩沖區(qū)連續(xù)寫兩次的情況。

clip_image014

2、 完全緩沖區(qū)加鎖,這個(gè)技術(shù)保持一個(gè)對(duì)于緩沖區(qū)的所有鎖的副本。保留一個(gè)本地緩沖區(qū)并在上面進(jìn)行所有的修改。當(dāng)解鎖它的時(shí)候,那些數(shù)據(jù)就會(huì)被放入一個(gè)參數(shù)隊(duì)列,這樣就可以對(duì)每次加鎖/解鎖維護(hù)一個(gè)唯一的副本。雖然這樣可以對(duì)緩沖區(qū)數(shù)據(jù)進(jìn)行精確的維護(hù),但當(dāng)某些應(yīng)用程序在鎖較大的數(shù)據(jù)的時(shí)候效果會(huì)大打折扣。

clip_image016

為什么鎖表面的時(shí)候不用緩沖

表面(如前臺(tái)緩沖,后臺(tái)緩沖,紋理等)通常消耗大量的存儲(chǔ)空間。 所以,在對(duì)表面加鎖時(shí)緩沖是無(wú)用的,也是不必要的。為什么沒(méi)有用呢,因?yàn)樵谏厦娴募渔i緩沖技術(shù)中,一個(gè)顯卡會(huì)瞬間消耗掉大量的存儲(chǔ)空間,因?yàn)檫@個(gè)時(shí)候我們需要?jiǎng)?chuàng)建兩個(gè)表面。 例如:一個(gè)1024X1024 32bpp的紋理通常會(huì)消耗掉4MB的顯存,但是如果采用了上面的緩沖鎖技術(shù),那么將會(huì)占用8MB的顯存。這個(gè)技術(shù)將會(huì)導(dǎo)致紋理可用的顯存資源直接減半。而對(duì)于完全緩沖區(qū)鎖技術(shù)。則會(huì)消耗了大量的系統(tǒng)內(nèi)存并且花費(fèi)較多時(shí)間來(lái)拷貝數(shù)據(jù)。因?yàn)檫@個(gè)技術(shù)在系統(tǒng)內(nèi)存中維護(hù)了一個(gè)數(shù)據(jù)的副本。所以它將會(huì)一次性地為這個(gè)表面分配大量的空間。當(dāng)解鎖的時(shí)候,又會(huì)將數(shù)據(jù)拷貝到參數(shù)隊(duì)列里,并且參數(shù)隊(duì)列在必要的時(shí)候,也會(huì)分配較大的空間。在渲染時(shí),渲染線程同樣需要將數(shù)據(jù)從參數(shù)隊(duì)列中取出,并拷貝到真正的表面上。所有的這些拷貝操作,都會(huì)導(dǎo)致加鎖和解鎖的速度大大降低。

表面加鎖時(shí)緩沖不必要是因?yàn)閼?yīng)用程序不需要直接對(duì)表面(紋理除外)進(jìn)行讀寫,為了取得更好的性能,可以使用顯卡直接對(duì)表面進(jìn)行操作。紋理,從另一方面講,僅會(huì)被加鎖一次,然后從文件中加載信息到它的表面。所以,對(duì)于紋理的加鎖,可以讓主線程等待渲染線程返回,然后再進(jìn)行加鎖,而不用對(duì)其進(jìn)行緩沖。注意,等待渲染線程返回并加鎖有可能導(dǎo)致錯(cuò)誤。因?yàn)橛锌赡茱@卡正在填充這個(gè)表面資源。記住,頻繁的對(duì)表面進(jìn)行加鎖將會(huì)導(dǎo)致因?yàn)橹骶€程的強(qiáng)制等待而使效率降低。

在哪里進(jìn)行線程化

這個(gè)方案的實(shí)現(xiàn)只能是在包裝圖形API的那個(gè)包裝類中。每一個(gè)函數(shù)都會(huì)有不同的實(shí)現(xiàn),因?yàn)樗鼈冇锌赡苁侵苯诱{(diào)用圖形API,而有可能是要在調(diào)用圖形API前等待前一幀繪制完成。或者是將數(shù)據(jù)放入渲染線程的隊(duì)列,讓渲染線程去調(diào)用API。也可以對(duì)其進(jìn)行一些優(yōu)化,采用在包裝類中做一些緩存來(lái)緩存那些需要等待的調(diào)用(譯注:個(gè)人理解是因?yàn)槊恳粠枰却恼{(diào)用可能不止一個(gè),將他們緩存起來(lái)。這樣當(dāng)渲染線程返回時(shí),一并調(diào)用這些函數(shù),就能少了許多等待)。你還需要的就是修改渲染系統(tǒng)插件的代碼,用你的包裝類函數(shù)替換掉所有的圖形API調(diào)用。

下面的代碼演示了如何進(jìn)行IUnknown接口的包裝。

 


D3D9WrapperUnknown:: D3D9WrapperUnknown

D3D9WrapperDevice
* pD3DDevice)

:m_pD3DDevice(pD3DDevice)

,m_RefCount(
1)

{

}


D3D9WrapperUnknown:: 
~D3D9WrapperUnknown

{

    
if(m_RefCount>0)

    
{

        
//輸出信息,因?yàn)殄e(cuò)了。

    }


}


ULONG D3D9WrapperUnknown::AddRef( )

{

    
return ++m_RefCount;

}


ULONG D3D9WrapperUnknown::Release( )

{

    
if(!(--m_RefCount))

    
{

        
if(m_pUnknown != NULL)

        
{

            m_pD3DDevice
->SubmitRelease(m_pUnKown);

        }


        delete 
this;

    }


    
return m_RefCount;

}



這個(gè)技術(shù)達(dá)到了本文介紹中的所有目標(biāo),并且也是最終的選擇方案。D3D9渲染系統(tǒng)被選擇來(lái)實(shí)現(xiàn)這個(gè)方案,伴隨本文的代碼可以從Intel Developer website上下載。

OGRE分析以及結(jié)果

這個(gè)部分我們將討論采用“低級(jí)線程化手段”時(shí),運(yùn)行OGRE的例子程序的情況。下面的數(shù)據(jù)是在2.4GHz Core 2 雙核處理器,NVIDIA 7800顯卡上測(cè)試的結(jié)果。這些數(shù)據(jù)顯示了兩個(gè)不同的緩沖加鎖方案,以及在沒(méi)有開(kāi)啟多線程時(shí)DirectX包裝類的負(fù)載。綠色背景指明了使用這個(gè)方案時(shí)提升到了1.1倍,甚至更多。 黃色部分指明了運(yùn)用該方案時(shí),降低到了1.0倍以下,但是并無(wú)太大損耗。而紅色部分指明了動(dòng)用此方案時(shí),出現(xiàn)了沖突情況。

clip_image018

注意,這里有太多的1。0左右的元素,當(dāng)然也有一些稍微低于1。0的。但是不會(huì)太多。可以看到,這里也有許多綠色的元素,表明運(yùn)行良好。但要注意,這些測(cè)試?yán)佣际荗GRE的DEMO,DEMO并不使用CPU處理太多的東西。只有兩個(gè)元素是紅的。都是處于“完全緩沖加鎖”方案中。因?yàn)檫@些DEMO經(jīng)常更新很大的頂點(diǎn)緩沖。導(dǎo)致很多時(shí)間花費(fèi)在等待復(fù)制完成,從而出現(xiàn)問(wèn)題。

需要特別說(shuō)明的是“Shadow Demo”。有兩種陰影方案,模版和紋理。只有模版陰影在“部分緩沖加鎖”方案時(shí)會(huì)出現(xiàn)問(wèn)題,而紋理陰影則工作良好。

同時(shí)也要注意的時(shí),一些例子在“完全緩沖加鎖”方案中運(yùn)行的效果比“部分緩沖加鎖”方案要好。在這種情況下,應(yīng)用程序取得一個(gè)可以讀寫的緩沖區(qū)。在這種情況下,主要是負(fù)載在于應(yīng)用程序會(huì)將顯存中的數(shù)據(jù)復(fù)制到系統(tǒng)內(nèi)存中。而“完全緩沖加鎖”方案通過(guò)將加鎖和解鎖放到渲染線程中,而將這個(gè)負(fù)擔(dān)消除了。

結(jié)論:

將一個(gè)3D渲染引擎線程化是一項(xiàng)具有挑戰(zhàn)性的工作,但事實(shí)證明,它是可行的。正如先前所展示的一樣,將OGRE渲染引擎線程化是很成功的,并且在某些DEMO上運(yùn)行出了良好的效果。有三種線程化方案,但最終只選擇了“低級(jí)優(yōu)化方案“來(lái)實(shí)現(xiàn)。因?yàn)槠錆M足了本文最初提出的目標(biāo)。在OGRE社區(qū)的共同努力下,OGRE可以在CPU和GPU資源都密集型的應(yīng)用程序中,運(yùn)行出更多幀數(shù)和更平滑的顯示效果。

posted on 2010-12-20 23:14 麒麟子 閱讀(2380) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Game and Engine

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            伊人婷婷久久| 亚洲欧美三级在线| 久久国产视频网| 亚洲免费av观看| 国产色爱av资源综合区| 欧美乱妇高清无乱码| 久久岛国电影| 中文精品99久久国产香蕉| 亚洲大片在线| 久久久久女教师免费一区| 亚洲视频在线观看一区| 亚洲第一区在线观看| 国产区二精品视| 国产精品www色诱视频| 欧美成人在线免费视频| 久久精品论坛| 性久久久久久| 中文日韩电影网站| 亚洲精品久久久久久一区二区| 久久性色av| 欧美在线综合| 午夜精品久久久久久| 一区二区欧美视频| 亚洲美女中文字幕| 亚洲黄色免费电影| 在线观看欧美日本| 韩国欧美一区| 国产视频一区二区在线观看 | 亚洲视频日本| 亚洲美女中出| 亚洲日本视频| 亚洲日本中文字幕| 亚洲清纯自拍| 亚洲欧洲日产国产综合网| 亚洲第一福利视频| 亚洲高清影视| 最新日韩在线| 999亚洲国产精| 亚洲毛片av在线| 99pao成人国产永久免费视频| 亚洲精品免费在线观看| 亚洲精品一区在线观看| 日韩西西人体444www| 一本色道久久综合亚洲精品婷婷| 99精品热6080yy久久| 国产精品99久久久久久久女警| 一区二区三区日韩| 亚洲免费在线视频| 午夜精品久久久久久久久| 欧美影院在线播放| 久久一二三四| 欧美国产亚洲视频| 欧美性猛交视频| 国产伦精品一区二区三区| 国产日韩欧美精品在线| 在线电影一区| 99精品国产99久久久久久福利| 亚洲视频1区2区| 久久精品72免费观看| 久久久伊人欧美| 欧美福利电影网| 日韩西西人体444www| 亚洲综合日本| 久色成人在线| 欧美亚男人的天堂| 国产综合自拍| 亚洲精品一区二区三区福利| 亚洲一区免费观看| 久久久久成人精品| 欧美www视频在线观看| 亚洲美女视频在线观看| 亚洲欧美国产毛片在线| 久久一区二区视频| 欧美视频在线观看免费网址| 国产日韩亚洲欧美| 亚洲精品一区二区三区樱花| 午夜视频精品| 亚洲高清不卡av| 亚洲欧美日韩在线综合| 美女在线一区二区| 国产精品久久久一区二区三区| 激情成人亚洲| 亚洲欧美美女| 亚洲第一中文字幕| 香蕉久久夜色精品| 欧美片在线播放| 国内精品免费在线观看| 在线亚洲自拍| 欧美va亚洲va日韩∨a综合色| 在线视频日韩| 欧美福利专区| 极品少妇一区二区三区精品视频| 99re8这里有精品热视频免费 | 久久精品人人做人人爽| 欧美日韩国产综合视频在线观看 | 亚洲精品网址在线观看| 久久国产精品黑丝| 亚洲精品综合久久中文字幕| 久久aⅴ国产紧身牛仔裤| 欧美日精品一区视频| 亚洲国产国产亚洲一二三| 欧美亚洲在线播放| 日韩午夜免费| 欧美v日韩v国产v| 激情成人av在线| 欧美亚洲免费| 99精品视频免费在线观看| 久久综合伊人77777尤物| 国产色爱av资源综合区| 亚洲永久在线| 亚洲精品一区二| 欧美大片在线观看| 亚洲国产精品成人综合色在线婷婷| 欧美一级大片在线观看| 一区二区福利| 欧美日韩精品久久久| 最新国产乱人伦偷精品免费网站| 久久婷婷av| 香蕉成人啪国产精品视频综合网| 国产精品国产三级国产aⅴ浪潮| 亚洲美女视频| 亚洲国内高清视频| 欧美www视频| 最新高清无码专区| 欧美激情一级片一区二区| 久久久激情视频| 一区在线播放视频| 久久综合精品一区| 久久久久国产精品午夜一区| 国内精品免费在线观看| 久久久久久久国产| 欧美在线视频导航| 国外视频精品毛片| 久久夜色精品国产欧美乱极品| 欧美一区国产二区| 国产一区二区精品久久99| 久久精品一区蜜桃臀影院 | 美女视频黄a大片欧美| 一区精品在线| 免费久久99精品国产自| 久久久美女艺术照精彩视频福利播放| 国产亚洲精品aa午夜观看| 久久精品亚洲一区二区| 欧美影院成人| 在线日韩电影| 亚洲高清视频中文字幕| 欧美精品尤物在线| 亚洲影院色无极综合| 亚洲在线黄色| 黄色成人精品网站| 欧美国产日韩二区| 欧美精品一区二区视频| 亚洲一区视频在线观看视频| 亚洲夜间福利| 国产偷自视频区视频一区二区| 久久露脸国产精品| 欧美成年人在线观看| 一区二区三区欧美成人| 亚洲欧美国产va在线影院| 在线观看av一区| 亚洲国产片色| 国产精品私人影院| 老司机精品久久| 欧美国产丝袜视频| 欧美亚洲视频在线看网址| 久久久精品一区| 99re国产精品| 性色一区二区| 亚洲精品老司机| 亚洲自拍啪啪| 亚洲欧洲综合| 亚洲欧美日韩电影| 91久久精品美女| 亚洲男人第一网站| 91久久在线观看| 亚洲专区免费| 亚洲精品一区二区三区99| 亚洲一区二区三区精品动漫| 在线免费高清一区二区三区| 一本一本久久| 亚洲国产婷婷香蕉久久久久久99| 一区二区免费在线播放| 亚洲第一精品影视| 亚洲一级在线观看| 亚洲精品午夜精品| 欧美一区二区日韩一区二区| 99热精品在线| 久久偷看各类wc女厕嘘嘘偷窃| 亚洲午夜小视频| 蜜臀91精品一区二区三区| 欧美亚洲一区二区在线观看| 欧美激情1区2区3区| 久久久久99精品国产片| 欧美丝袜一区二区| 欧美激情四色| 狠狠色综合色区| 亚洲免费小视频| 一区二区三区视频在线看| 另类图片综合电影| 久久久久久夜|