DirectX怪象之二, 程式很吃CPU

2021-09-08 14:46:48 字數 2561 閱讀 1000

學習directx程式設計的兄弟們可能經常遇到的乙個情況是,程式經常莫名奇妙的占用大量的cpu資源,其實吃cpu的問題並不是directx程式所特有的,幾乎任何程式都可能,只不過directx程式更加容易產生而已,總結了一下,主要有以下幾個方面

這種情況的現象多發生在程式執行的時候,也就是視窗處於active狀態時,大家都知道,dx是基於com的,這也就意味著,你需要手動釋放com物件,如果沒有及時釋放的話,cpu就會吃緊,尤其是當在render函式中建立物件的時候更是如此。至於哪些需要釋放,哪些不需要釋放,需要視具體情況而定,這裡有乙個簡單的方法,如果建立該物件的函式形如create***,那麼基本都需要釋放,這種物件一般都有乙個release方法,直接呼叫這個方法即可。給大家分享乙個巨集定義,來自於dx sdk,這個巨集可以很方便的釋放com物件

#define

safe_release(p) if(p)

我們在程式設計時應該遵循一些好的程式設計習慣,這樣就會避免錯誤發生,比如

1 對於那些只需要一次建立的物件,通通放到render函式之外,所以我們通常設定乙個函式名叫initd3d,可以把一次性初始化的**都放到這裡。切記不可把非渲染操作放到render函式裡面,因為render函式就是用來做渲染的,而且呼叫頻率極高,幾乎是時時刻刻都在呼叫,如果把其他操作資源的過程也放到這裡,勢必會影響效率。

2 在開發的時候盡量使用debug版本的庫,這樣可以及時發現資源洩露。

這種情況多發生在視窗處於inactive狀態時,比如被遮擋或者最小化到工作列。先看一段windows下的渲染框架,下面的**邏輯很簡單,有訊息則處理訊息,無訊息則渲染,如果你使用了這段**,那麼你可以試著將視窗最小化,你將會看到cpu使用率上公升一大截,為什麼呢?這是由於peekmessage的機制造成的,說到peekmessage就不得不說getmessage,這二者都是用於從訊息佇列中取得訊息,不同的是,peekmessage如果沒取到訊息,會立即返回0,而getmessage如果沒取到訊息,則會一直等待有訊息可取。也就是說peekmessage是非同步的,而getmessage是同步的。下面的**就是利用沒有訊息處理的時間進行渲染,而當視窗最小化時,peekmessage一直取不到訊息,所以程式一直在渲染,這樣就占用了大量的cpu時間。

msg msg ;

zeromemory( &msg, sizeof

(msg) );

peekmessage( &msg, null, 0u, 0u

, pm_noremove );

//get latest time

static dword lasttime =timegettime();

while (msg.message !=wm_quit)

else

//render the scene if there is no message to handle

}

有了上面的分析,我們可以分兩種情況來處理,一是程式處於active狀態時,我們按照上面的方法渲染。二是程式處於inactive狀態時,我們可以使用getmessage來等待乙個訊息,因為此時程式不需要渲染(已經最小化了,還渲染啥呀?)。對應的**如下

bool bgotmsg;

msg msg;

peekmessage( &msg, null, 0u, 0u

, pm_noremove );

while( wm_quit !=msg.message )

}else}}

下面的問題就是如何處理m_bactive這個變數了,可以響應wm_size訊息,size_maxhide表示有其他視窗最大化了,這樣就意味著本視窗被完全遮擋了,size_minimized表示視窗最小化了。這兩種情況我們將視窗視為inactive狀態。

case

wm_size:

//check to see if we are losing our window...

if( size_maxhide

==wparam

||size_minimized

==wparam )

m_bactive

=false;

else

m_bactive

=true;

break;

由於我對場景管理不是很熟練,所以只能簡單說說,場景管理應該屬於中高層次的技術,在剛學directx的時候,根本不會考慮這些,但是隨著知識的深入,程式**的增大,邏輯越來越複雜,模型越來越多,難免會涉及到場景管理,什麼是場景管理呢,如果從渲染的角度來講,就是區分哪些應該渲染,哪些不用渲染,就是說要提高渲染的速度,場景管理中最基本的就是frustum剪裁,四叉樹,bsp場景管理,八叉樹等。

frustum,中文翻譯成視錐,視錐剪裁是最基本的場景管理,也就是只渲染在視野內的模型,其他的一律剪裁掉。

四叉樹多用於地形渲染

bsp多用於室內場景管理,著名的quake系列使用的就是bsp樹

八叉樹比較通用

如果你的場景中有大量的模型,而又沒有做場景管理,也就意味著,一次性將所有的模型都渲染一遍,不管模型是否在視野裡,這勢必很浪費cpu資源。

開發Metro應用程式之二 C 程式

1.每乙個xaml元素型別 對應於乙個 windows runtime type 當新增新的elements 到xaml檔案中,vs2012會自動產生對應的 這樣就可以通過code的方式處理介面元素的操作了。這些生成的和xaml對應的vc class 在宣告時都被冠以partial ref,沒有這種...

使用Code blocks 編譯QT程式之二

在上篇的使用code blocks 編譯qt程式的文章中,我們使用了一種常見的方法來compile qt program.上篇的基本原理就是使用qmake來生成makefile,然後costomize makefile.這樣就能編譯好qt程式了。但是在這裡有乙個問題,那就是如果我們要引用qt中的其它...

程式猿如何預估工時之二

說著麼多,就是想說客戶端和服務端是不同的 最近幾年 那麼用20年前,15年前那種工時統計方法,去量度乙個程式猿,而不管他的客戶端還是服務端,是否合適?再說,服務端寫的todo,是不是意味著未實現呢?功能未做好,工時怎麼算呢?客戶端可以很簡單明確地細分乙個個小任務,服務端需要持續改善,事先最好有計畫,...