利用D3DQUERY實現簡單的GPU計時器

2022-04-29 12:36:09 字數 2956 閱讀 5729

最近想給引擎加乙個準確定位各渲染模組消耗的功能,因此翻閱資料,自己實現了乙個簡短的gpu時鐘。在引擎中整合如下:

值得注意的是,使用硬體查詢後,回讀顯示卡中的值會導致cpu/gpu的等待,因而會損失一些時間。因此這個功能只能算作開發時的除錯工具之用(真正產品不會有人關心gpu時間...)

我昨晚花了少量時間做了乙個簡單的實現,現在在這裡貼出來,基本是全部**,摘回去可直接使用~ 如有設計上的疏忽還請見諒!

改計時器使用十分方便,整合好之後,測量每個階段的時間,只需補上3條**,即可~

d3d文件中提到了有這樣乙個硬體查詢型別:d3dquerytype_timestamp

改硬體查詢會在查詢的地方,返回乙個uint64型別的當前的gpu tick值,因此,可以使用這個來取得每個模組的開始和結束tick,在每幀結束的時候getdata,計算出每乙個階段的耗時

此外,d3dquerytype_timestampfreq這個查詢型別,可以返回時鐘頻率,這時我們便可以通過  (結束tick - 開始tick) / 時鐘頻率 來得出gpu中這一段的耗時了。

因此,我們可以實現乙個簡單的gputimer類:

class gkgputimer

float gettime()

//init d3dquery

void init(idirect3ddevice9* pdevice);

void destroy();

//mark the timestamp

void start();

void stop();

//get timestep when finish a frame

void update();

private:

idirect3dquery9* m_peventstart;

idirect3dquery9* m_peventstop;

idirect3dquery9* m_peventfreq;

float m_felapsedtime;

bool m_skip; // judge if should get data

};

很簡單一對init(),destroy(),在裝置建立和丟失的時候對d3d物件進行重建和釋放

一對start(),stop(),在需要測量的**段兩邊放置,分別取得開始和結束的timestamp和freq

乙個update(),在每幀結束的時候,從gpu取得測量值,計算之後儲存於m_felapsedtime中

m_skip用於判斷是否應該從gpu取值,因為由於渲染流程的改變,有些計時器可能在一些情況下並不會測量。

下面看一下簡單的實現

(注: genv->pcvmanager->r_profilegpu == 1 是我引擎中的引數,為1時表示開啟gpu計時)

gkgputimer::gkgputimer()

void gkgputimer::init(idirect3ddevice9* pdevice)

void gkgputimer::destroy()

void gkgputimer::start()

m_skip = false;

}void gkgputimer::stop()

m_skip = false;

}void gkgputimer::update()

else

}m_skip = true;

}

最後,就是整合到渲染流程中了,我實現了幾個簡單函式,在渲染流程的恰當階段呼叫即可

(注:ms_gputimers為我渲染器的乙個靜態成員)

typedef std::mapgkgputimermap;
//

build gpu timers when init renderer

void gkrendererd3d9::buildgputimers()

//init gpu timers when device reset

void gkrendererd3d9::initgputimers(idirect3ddevice9* pdevice)}//

release gpu timers when device lost

void gkrendererd3d9::destorygputimers()}//

getdata from gpu when a frame end

void gkrendererd3d9::updategputimers()

}}

使用了map結構,因此在設定計時器的時候就特別方便了,比如:

gkrendererd3d9::ms_gputimers[l"

ssao

"].start();

//

ssao render process...

gkrendererd3d9::ms_gputimers[l"

ssao

"].stop();

新增完畢後,在想要拿時間的地方,

gkrendererd3d9::ms_gputimers[l"

ssao

"].gettime()

即可。自此,gputimer全部完成,用了不到200行**。

使用上,就是

ms_gputimers.insert( gkgputimermap::value_type( l"

測量名", gkgputimer()) );

gkrendererd3d9::ms_gputimers[l"

測量名"].start();

gkrendererd3d9::ms_gputimers[l"

測量名"].stop();

三條**,當然如果加上一些巨集技巧,可以更加工程化一些~

利用D3DQUERY實現簡單的GPU計時器

最近想給引擎加乙個準確定位各渲染模組消耗的功能,因此翻閱資料,自己實現了乙個簡短的gpu時鐘。在引擎中整合如下 值得注意的是,使用硬體查詢後,回讀顯示卡中的值會導致cpu gpu的等待,因而會損失一些時間。因此這個功能只能算作開發時的除錯工具之用 真正產品不會有人關心gpu時間.我昨晚花了少量時間做...

D3的簡單語法

選擇 選擇單個元素用 select 選擇第乙個元素 選擇多個元素用 selectall 選擇 插入 刪除元素 insert 在選擇集前面插入元素 d3.select body insert p moon remove 刪除元素 d3.select moon remove 文字屬性樣式操作 資料連線 ...

用unity3d實現簡單chat對話

本文是解釋鷹大的多人聯網例項example1思路,由於自己理解的問題,不足地方請斧正。華麗的分割線 主線流程 1.awake 設計遊戲視窗 獲取玩家名字 function awake 2.ongui 判斷是否顯示聊天視窗建立聊天視窗處理回車 獲取輸入焦點 function ongui gui.ski...