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