做推文的網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)html代碼大全
查詢對(duì)象和異步查詢(Query Objects and Asynchronous Queries)
Query Objects(查詢對(duì)象)是OpenGL中的一種機(jī)制,用于獲取有關(guān)一系列GL命令處理過(guò)程的信息。這些信息可以包括:
- 繪圖命令處理的圖元數(shù)量。
- 寫入變換反饋緩沖區(qū)的圖元數(shù)量。
- 在片段處理期間通過(guò)深度測(cè)試的樣本數(shù)量。
- 處理命令所需的時(shí)間量。
通過(guò)使用查詢對(duì)象,OpenGL應(yīng)用程序可以動(dòng)態(tài)地獲取有關(guān)圖形渲染過(guò)程的各種性能指標(biāo)和統(tǒng)計(jì)信息。這些信息對(duì)于性能優(yōu)化、調(diào)試和分析應(yīng)用程序的渲染流程非常有用。
使用查詢對(duì)象的一般步驟如下:
- 創(chuàng)建查詢對(duì)象:通過(guò)調(diào)用OpenGL的API函數(shù),可以創(chuàng)建一個(gè)查詢對(duì)象,并指定要查詢的信息類型。
- 開始查詢:在需要獲取信息的地方,通過(guò)調(diào)用OpenGL的API函數(shù),開始一個(gè)查詢操作。
- 執(zhí)行一系列GL命令:在開始查詢和結(jié)束查詢之間,執(zhí)行一系列的GL命令,這些命令可以是繪圖命令、變換反饋命令、深度測(cè)試命令等。
- 結(jié)束查詢:在執(zhí)行完一系列GL命令后,通過(guò)調(diào)用OpenGL的API函數(shù),結(jié)束查詢操作。
- 獲取查詢結(jié)果:通過(guò)調(diào)用OpenGL的API函數(shù),可以獲取查詢對(duì)象的結(jié)果,這些結(jié)果包含了在查詢期間收集的有關(guān)圖形處理過(guò)程的信息,比如處理的圖元數(shù)量、通過(guò)的樣本數(shù)量等。
使用查詢對(duì)象可以幫助開發(fā)人員更好地了解和優(yōu)化他們的OpenGL應(yīng)用程序的性能特征,從而提高圖形渲染的效率和質(zhì)量。
查詢類型
OpenGL 支持的查詢類型包括:
-
圖元生成查詢:目標(biāo)為
PRIMITIVES_GENERATED
,用于返回通過(guò) OpenGL 處理的圖元數(shù)量。同時(shí)激活的此類查詢最多可達(dá)MAX_VERTEX_STREAMS
個(gè)。 -
變換反饋寫入的圖元查詢:目標(biāo)為
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
,用于統(tǒng)計(jì)被寫入一個(gè)或多個(gè)緩沖對(duì)象中的圖元數(shù)量。同時(shí)激活的此類查詢同樣不得超過(guò)MAX_VERTEX_STREAMS
個(gè)。 -
變換反饋溢出查詢:目標(biāo)為
TRANSFORM_FEEDBACK_OVERFLOW
或TRANSFORM_FEEDBACK_STREAM_OVERFLOW
,用于報(bào)告一個(gè)或多個(gè)流是否存在變換反饋溢出情況。 -
遮擋查詢:目標(biāo)為
SAMPLES_PASSED
、ANY_SAMPLES_PASSED
或ANY_SAMPLES_PASSED_CONSERVATIVE
,用于計(jì)數(shù)通過(guò)深度測(cè)試的片段或樣本數(shù)量,或者設(shè)置布爾值以表示是否至少有一個(gè)片段或樣本通過(guò)了深度測(cè)試。同時(shí)只能激活一個(gè)此類查詢。 -
時(shí)間流逝查詢:目標(biāo)為
TIME_ELAPSED
,記錄完成一系列命令所需的完整時(shí)間。同時(shí)只能激活一個(gè)此類查詢。 -
時(shí)間戳查詢:目標(biāo)為
TIMESTAMP
,記錄當(dāng)前 OpenGL 的時(shí)間。同時(shí)只能激活一個(gè)此類查詢。 -
提交查詢:目標(biāo)為
VERTICES_SUBMITTED
和PRIMITIVES_SUBMITTED
分別返回傳輸?shù)?OpenGL 的頂點(diǎn)數(shù)量和圖元數(shù)量信息。 -
頂點(diǎn)著色器查詢:目標(biāo)為
VERTEX_SHADER_INVOCATIONS
,返回頂點(diǎn)著色器被調(diào)用的次數(shù)。 -
曲面細(xì)分著色器查詢:目標(biāo)為
TESS_CONTROL_SHADER_PATCHES
和TESS_EVALUATION_SHADER_INVOCATIONS
,分別返回曲面細(xì)分控制著色器處理的補(bǔ)丁數(shù)量和曲面細(xì)分評(píng)估著色器被調(diào)用的次數(shù)。 -
幾何著色器查詢:目標(biāo)為
GEOMETRY_SHADER_INVOCATIONS
和GEOMETRY_SHADER_PRIMITIVES_EMITTED
,分別返回幾何著色器被調(diào)用的次數(shù)以及它發(fā)射的圖元數(shù)量。 -
圖元裁剪查詢:目標(biāo)為
CLIPPING_INPUT_PRIMITIVES
和CLIPPING_OUTPUT_PRIMITIVES
,分別返回在圖元裁剪階段處理的圖元數(shù)量和由圖元裁剪階段輸出并進(jìn)一步被光柵化階段處理的圖元數(shù)量。 -
片段著色器查詢:目標(biāo)為
FRAGMENT_SHADER_INVOCATIONS
,返回片段著色器被調(diào)用的次數(shù)。 -
計(jì)算著色器查詢:目標(biāo)為
COMPUTE_SHADER_INVOCATIONS
,返回計(jì)算著色器被調(diào)用的次數(shù)。
查詢對(duì)象創(chuàng)建和激活
異步查詢的結(jié)果不會(huì)在集合中的最后一個(gè)命令完成后立即由GL返回;在查詢結(jié)果完全就緒之前,可以處理后續(xù)命令。一旦可用,查詢結(jié)果將存儲(chǔ)在相關(guān)聯(lián)的查詢對(duì)象中。第4.2.3節(jié)描述的命令提供了確定查詢結(jié)果何時(shí)可用并返回查詢的實(shí)際結(jié)果的機(jī)制。查詢對(duì)象的名稱空間是無(wú)符號(hào)整數(shù),其中零被GL保留。
void glGenQueries( sizei n, uint *ids )
命令在ids中返回n個(gè)先前未使用的查詢對(duì)象名稱。這些名稱被標(biāo)記為已使用,僅用于GenQueries,但在它們首次被BeginQuery、BeginQueryIndexed或QueryCounter使用之前,它們不與任何對(duì)象關(guān)聯(lián)。
void glCreateQueries( enum target, sizei n, uint *ids )
glCreateQueries在ids中返回n個(gè)先前未使用的查詢對(duì)象名稱,每個(gè)名稱表示具有指定目標(biāo)的新查詢對(duì)象。目標(biāo)必須是 **查詢類型** 中描述的查詢對(duì)象目標(biāo)之一。生成的查詢對(duì)象的初始狀態(tài)是結(jié)果已標(biāo)記為可用(查詢對(duì)象的QUERY_RESULT_AVAILABLE的值為TRUE),并且結(jié)果值(QUERY_RESULT的值)為零。
void glDeleteQueries( sizei n, const uint *ids )
ids包含要?jiǎng)h除的n個(gè)查詢對(duì)象的名稱。刪除查詢對(duì)象后,其名稱再次變?yōu)槲词褂?。如果刪除了活動(dòng)查詢對(duì)象,則其名稱立即變?yōu)槲词褂?#xff0c;但底層對(duì)象直到不再處于活動(dòng)狀態(tài)(參見(jiàn)第5.1節(jié))才會(huì)被刪除。對(duì)于GenQueries目的而標(biāo)記為已使用的ids中的未使用名稱將再次標(biāo)記為未使用。未使用的ids中的名稱將被靜默忽略,零值也將被靜默忽略。
在OpenGL中,除TIMESTAMP類型的計(jì)時(shí)器查詢外,對(duì)于支持的每種查詢類型,針對(duì)每個(gè)可能激活的查詢,都有一個(gè)對(duì)應(yīng)的活動(dòng)查詢對(duì)象名稱。如果這個(gè)活動(dòng)查詢對(duì)象名稱非零,則表示OpenGL當(dāng)前正在追蹤相關(guān)的信息,并且查詢結(jié)果會(huì)被記錄到該查詢對(duì)象內(nèi)。
反之,如果活動(dòng)查詢對(duì)象名稱為零,則意味著未追蹤此類信息。
創(chuàng)建并激活查詢對(duì)象可以使用以下命令:
void glBeginQueryIndexed( enum target, uint index, uint id )
target
參數(shù)指定了要執(zhí)行的查詢類型,后續(xù)章節(jié)將詳細(xì)介紹其有效值。- 如果
id
是一個(gè)未使用的查詢對(duì)象名稱,則該名稱會(huì)被標(biāo)記為已使用,并與指定目標(biāo)類型的新的查詢對(duì)象關(guān)聯(lián)起來(lái)。否則,id
必須是現(xiàn)有且同類型查詢對(duì)象的名稱。請(qǐng)注意,通過(guò)ANY_SAMPLES_PASSED或ANY_SAMPLES_PASSED_CONSERVATIVE兩種目標(biāo)指定的遮擋查詢對(duì)象,在未來(lái)的查詢中可以重用于這兩種目標(biāo)中的任何一種。而由SAMPLES_PASSED目標(biāo)指定的對(duì)象只能重用于該目標(biāo)。 index
參數(shù)是查詢的索引,其值必須在0和目標(biāo)特定的最大值之間。- 無(wú)論
id
是否為新創(chuàng)建的查詢對(duì)象,其狀態(tài)都將被設(shè)置為結(jié)果不可用(查詢對(duì)象的QUERY_RESULT_AVAILABLE值為FALSE),并且結(jié)果值(QUERY_RESULT)初始化為零。 - 對(duì)于給定的
target
和index
,其對(duì)應(yīng)的活動(dòng)查詢對(duì)象名稱會(huì)被設(shè)置為id
。
void glBeginQuery( enum target, uint id )
- 等價(jià)于 glBeginQueryIndexed(target, 0, id);
void glEndQueryIndexed( enum target, uint index )
-
標(biāo)記了由target和index指定的活動(dòng)查詢要跟蹤的命令序列的結(jié)束。target和index的含義與BeginQueryIndexed中相同。
-
相應(yīng)的活動(dòng)查詢對(duì)象被更新以指示查詢結(jié)果不可用,并且target和index的活動(dòng)查詢對(duì)象名稱被重置為零。當(dāng)在EndQueryIndexed調(diào)用時(shí)發(fā)出的命令完成并且最終查詢結(jié)果可用時(shí),被調(diào)用時(shí)活動(dòng)的查詢對(duì)象被更新以包含查詢結(jié)果,并指示查詢結(jié)果可用。
void glEndQuery( enum target )
- 等價(jià)于 glEndQueryIndexed(target, 0);
查詢對(duì)象包含兩部分狀態(tài)信息:
- 一個(gè)單比特位,用于指示查詢結(jié)果是否可用。
- 一個(gè)整數(shù),用于存儲(chǔ)查詢結(jié)果的值。這個(gè)表示查詢結(jié)果所使用的比特位數(shù)量(n)是實(shí)現(xiàn)依賴的,并且可以按照4.2.3節(jié)中描述的方式確定。
查詢對(duì)象的初始狀態(tài)取決于它是通過(guò)`CreateQueries`還是`BeginQueryIndexed`創(chuàng)建的,如上所述。如果查詢結(jié)果發(fā)生溢出(即超過(guò)2^n - 1的值),其值將變?yōu)槲炊x。盡管不是必需的,但建議實(shí)現(xiàn)能夠通過(guò)在達(dá)到2^n - 1時(shí)飽和并停止增加的方式來(lái)處理這種溢出情況。對(duì)于每個(gè)可能的活動(dòng)查詢目標(biāo)和索引,都需要維護(hù)的狀態(tài)包括:一個(gè)無(wú)符號(hào)整數(shù),用于保存活動(dòng)查詢對(duì)象名稱(如果沒(méi)有活動(dòng)查詢對(duì)象,則為零);以及任何保持正在進(jìn)行的異步查詢當(dāng)前結(jié)果所需的狀態(tài)。同一時(shí)間內(nèi)只允許一種遮擋查詢類型處于活動(dòng)狀態(tài),因此遮擋查詢所需的必要狀態(tài)會(huì)被共享。
boolean glIsQuery( uint id )
用于檢查給定的ID(id)是否為一個(gè)查詢對(duì)象的名稱。
void glGetQueryIndexediv( enum target, uint index, enum pname, int *params )
查詢有關(guān)活動(dòng)查詢對(duì)象的信息
-
target
和index
指定了要查詢的活動(dòng)查詢,其含義與BeginQueryIndexed
中相同。 -
如果
pname
設(shè)置為CURRENT_QUERY
,則當(dāng)前為target
和index
指定的活動(dòng)查詢對(duì)象名稱(如果有活動(dòng)查詢的話),將被放置在params
指向的內(nèi)存中。若目標(biāo)為TIMESTAMP
,則始終返回0。 -
若
pname
設(shè)為QUERY_COUNTER_BITS
,則忽略index
參數(shù),并將在params
中放置目標(biāo)查詢類型的實(shí)現(xiàn)依賴的查詢結(jié)果所使用的比特位數(shù)。查詢計(jì)數(shù)器的比特位數(shù)量可能為0,這意味著計(jì)數(shù)器不包含有用信息。
對(duì)于不同類型的查詢對(duì)象,如果對(duì)應(yīng)的比特位數(shù)非零,則它們至少應(yīng)具備以下最低位數(shù)要求:
- 基本圖元查詢(PRIMITIVES_GENERATED和TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN):至少32位。
- 變換反饋溢出查詢(TRANSFORM_FEEDBACK_OVERFLOW和TRANSFORM_FEEDBACK_STREAM_OVERFLOW):至少1位。
- 遮擋查詢(ANY_SAMPLES_PASSED或ANY_SAMPLES_PASSED_CONSERVATIVE):至少1位。針對(duì)SAMPLES_PASSED目標(biāo)的遮擋查詢,至少需要32位。
- 計(jì)時(shí)器查詢(TIME_ELAPSED和TIMESTAMP):至少30位,確保至少能測(cè)量一秒的時(shí)間。
- 管道統(tǒng)計(jì)查詢(VERTICES_SUBMITTED、PRIMITIVES_SUBMITTED、VERTEX_SHADER_INVOCATIONS、TESS_CONTROL_SHADER_PATCHES、TESS_EVALUATION_SHADER_INVOCATIONS、GEOMETRY_SHADER_INVOCATIONS、FRAGMENT_SHADER_INVOCATIONS、COMPUTE_SHADER_INVOCATIONS、GEOMETRY_SHADER_PRIMITIVES_EMITTED、CLIPPING_INPUT_PRIMITIVES和CLIPPING_OUTPUT_PRIMITIVES):至少32位。
void glGetQueryiv( enum target, enum pname, int *params )
等價(jià)于 glGetQueryIndexediv(target, 0, pname, params);
查詢對(duì)象的狀態(tài)可以通過(guò)以下命令進(jìn)行查詢
void GetQueryObjectiv( uint id, enum pname, int *params );
void GetQueryObjectuiv( uint id, enum pname, uint *params );
void GetQueryObjecti64v( uint id, enum pname, int64 *params );
void GetQueryObjectui64v( uint id, enum pname, uint64 *params );
void GetQueryBufferObjectiv( uint id, uint buffer, enum pname, intptr offset );
void GetQueryBufferObjectuiv( uint id, uint buffer, enum pname, intptr offset );
void GetQueryBufferObjecti64v( uint id, uint buffer, enum pname, intptr offset );
void GetQueryBufferObjectui64v( uint id, uint buffer, enum pname, intptr offset );
其中:
id
是一個(gè)查詢對(duì)象的名稱。- 對(duì)于
GetQueryBufferObject*
函數(shù),buffer
是緩沖區(qū)對(duì)象的名稱,而offset
是緩沖區(qū)內(nèi)寫入查詢值的偏移量。 - 對(duì)于
GetQueryObject*
函數(shù),查詢值可以被返回到客戶端內(nèi)存中,也可以寫入到緩沖區(qū)對(duì)象中。如果當(dāng)前綁定到查詢結(jié)果緩沖區(qū)綁定點(diǎn)(見(jiàn)第6.1節(jié)中的 QUERY_RESULT)的是零,則params
被視為指向客戶端內(nèi)存的一個(gè)指針,在該位置寫入查詢值;否則,params
將被視為查詢結(jié)果緩沖對(duì)象內(nèi)的一個(gè)偏移量。
對(duì)于查詢對(duì)象的結(jié)果值,可能需要一定時(shí)間才能變得可用。如果 pname
設(shè)置為 QUERY_RESULT_AVAILABLE
,則在需要等待時(shí)函數(shù)將返回 FALSE
;否則返回 TRUE
。必須保證,若任何查詢對(duì)象返回的結(jié)果可用性為 TRUE
,那么在此之前所有相同類型的所有查詢也必須返回 TRUE
。對(duì)任一查詢對(duì)象反復(fù)查詢 QUERY_RESULT_AVAILABLE
保證最終會(huì)返回 TRUE
。
- 若
pname
為QUERY_TARGET
,則返回查詢對(duì)象的目標(biāo)類型作為一個(gè)整數(shù)值。 - 若
pname
為QUERY_RESULT
,則返回查詢對(duì)象的結(jié)果值作為單個(gè)整數(shù)。如果結(jié)果值的大小過(guò)大以至于無(wú)法用請(qǐng)求的類型表示,則返回最接近的可表示值。如果目標(biāo)類型的查詢計(jì)數(shù)器位數(shù)為零,則結(jié)果將以整數(shù)值0的形式返回。查詢QUERY_RESULT
會(huì)使給定查詢對(duì)象在有限時(shí)間內(nèi)完成其計(jì)算過(guò)程。 - 若
pname
為QUERY_RESULT_NO_WAIT
,則僅當(dāng)結(jié)果在執(zhí)行狀態(tài)查詢時(shí)已可用時(shí),才以單個(gè)整數(shù)形式返回查詢對(duì)象的結(jié)果值。若結(jié)果不可用,則不寫入查詢返回值。
如果在調(diào)用上述查詢命令之前,使用同一對(duì)象名稱發(fā)起了多個(gè)查詢操作,則返回的結(jié)果和可用性信息始終來(lái)自最后發(fā)起的那個(gè)查詢。在開始針對(duì)同一目標(biāo)和ID的新查詢之前,如果不先檢索先前查詢的結(jié)果,這些結(jié)果將會(huì)丟失。
時(shí)間查詢(Time Queries)
查詢對(duì)象還可用于追蹤完成一組OpenGL命令所需的時(shí)間(時(shí)間流逝查詢),或確定當(dāng)前的OpenGL時(shí)間(計(jì)時(shí)器查詢)。
當(dāng)使用目標(biāo) TIME_ELAPSED
調(diào)用 BeginQuery
和 EndQuery
時(shí),OpenGL將準(zhǔn)備啟動(dòng)和停止用于時(shí)間流逝查詢的計(jì)時(shí)器。計(jì)時(shí)器會(huì)在所有先前命令對(duì)OpenGL客戶端、服務(wù)器狀態(tài)以及幀緩沖區(qū)的影響完全實(shí)現(xiàn)后開始或停止。BeginQuery
和 EndQuery
命令可能在計(jì)時(shí)器實(shí)際開始或停止之前返回。
當(dāng)時(shí)間流逝查詢的計(jì)時(shí)器最終停止時(shí),流逝的時(shí)間(以納秒為單位)會(huì)被寫入到相應(yīng)的查詢對(duì)象作為查詢結(jié)果值,并標(biāo)記該對(duì)象的查詢結(jié)果為可用。
可以通過(guò)以下命令創(chuàng)建計(jì)時(shí)器查詢對(duì)象:
void QueryCounter( uint id, enum target );
其中 target
必須是 TIMESTAMP
。如果 id
是未使用的查詢對(duì)象名稱,則該名稱會(huì)被標(biāo)記為已使用并與新的類型為 TIMESTAMP
的查詢對(duì)象關(guān)聯(lián)。否則,id
必須是現(xiàn)有同類型查詢對(duì)象的名稱。
另外,也可以通過(guò)調(diào)用 CreateQueries
并將 target
設(shè)置為 TIMESTAMP
來(lái)創(chuàng)建 TIMESTAMP
類型的查詢對(duì)象。
當(dāng)調(diào)用 QueryCounter
時(shí),OpenGL會(huì)記錄下當(dāng)前時(shí)間并將其存入對(duì)應(yīng)的查詢對(duì)象中。這個(gè)時(shí)間是在所有先前命令對(duì)OpenGL客戶端、服務(wù)器狀態(tài)及幀緩沖區(qū)的影響完全實(shí)現(xiàn)之后記錄的。一旦時(shí)間被記錄,該對(duì)象的查詢結(jié)果就會(huì)被標(biāo)記為可用。計(jì)時(shí)器查詢可以在目標(biāo)為 TIME_ELAPSED
的 BeginQuery
/ EndQuery
塊內(nèi)部使用,且不會(huì)影響該查詢對(duì)象的結(jié)果。
通過(guò)調(diào)用 GetIntegerv
或 GetInteger64v
并傳入符號(hào)常量 TIMESTAMP
,可以查詢當(dāng)前的OpenGL時(shí)間。這將返回所有先前命令到達(dá)OpenGL服務(wù)器但不一定執(zhí)行完畢后的GL時(shí)間。通過(guò)結(jié)合這種同步獲取命令和異步時(shí)間戳查詢對(duì)象目標(biāo),應(yīng)用程序可以測(cè)量命令從到達(dá)OpenGL服務(wù)器到在幀緩沖區(qū)實(shí)現(xiàn)之間的延遲。