15bd8deadSopenharmony_ciName 25bd8deadSopenharmony_ci 35bd8deadSopenharmony_ci ARB_timer_query 45bd8deadSopenharmony_ci 55bd8deadSopenharmony_ciName Strings 65bd8deadSopenharmony_ci 75bd8deadSopenharmony_ci GL_ARB_timer_query 85bd8deadSopenharmony_ci 95bd8deadSopenharmony_ciContact 105bd8deadSopenharmony_ci 115bd8deadSopenharmony_ci Piers Daniell, NVIDIA Corporation (pdaniell 'at' nvidia.com) 125bd8deadSopenharmony_ci 135bd8deadSopenharmony_ciContributors 145bd8deadSopenharmony_ci 155bd8deadSopenharmony_ci Axel Mamode, Sony 165bd8deadSopenharmony_ci Brian Paul, Tungsten Graphics 175bd8deadSopenharmony_ci Bruce Merry, ARM 185bd8deadSopenharmony_ci James Jones, NVIDIA Corporation 195bd8deadSopenharmony_ci Pat Brown, NVIDIA 205bd8deadSopenharmony_ci Remi Arnaud, Sony 215bd8deadSopenharmony_ci 225bd8deadSopenharmony_ciNotice 235bd8deadSopenharmony_ci 245bd8deadSopenharmony_ci Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at 255bd8deadSopenharmony_ci http://www.khronos.org/registry/speccopyright.html 265bd8deadSopenharmony_ci 275bd8deadSopenharmony_ciSpecification Update Policy 285bd8deadSopenharmony_ci 295bd8deadSopenharmony_ci Khronos-approved extension specifications are updated in response to 305bd8deadSopenharmony_ci issues and bugs prioritized by the Khronos OpenGL Working Group. For 315bd8deadSopenharmony_ci extensions which have been promoted to a core Specification, fixes will 325bd8deadSopenharmony_ci first appear in the latest version of that core Specification, and will 335bd8deadSopenharmony_ci eventually be backported to the extension document. This policy is 345bd8deadSopenharmony_ci described in more detail at 355bd8deadSopenharmony_ci https://www.khronos.org/registry/OpenGL/docs/update_policy.php 365bd8deadSopenharmony_ci 375bd8deadSopenharmony_ciStatus 385bd8deadSopenharmony_ci 395bd8deadSopenharmony_ci Complete. Approved by the ARB at the 2010/01/22 F2F meeting. 405bd8deadSopenharmony_ci Approved by the Khronos Board of Promoters on March 10, 2010. 415bd8deadSopenharmony_ci 425bd8deadSopenharmony_ciVersion 435bd8deadSopenharmony_ci 445bd8deadSopenharmony_ci Last Modified Date: August 9, 2014 455bd8deadSopenharmony_ci Revision: 13 465bd8deadSopenharmony_ci 475bd8deadSopenharmony_ciNumber 485bd8deadSopenharmony_ci 495bd8deadSopenharmony_ci ARB Extension #85 505bd8deadSopenharmony_ci 515bd8deadSopenharmony_ciDependencies 525bd8deadSopenharmony_ci 535bd8deadSopenharmony_ci This extension is written against the OpenGL 3.2 specification. 545bd8deadSopenharmony_ci 555bd8deadSopenharmony_ciOverview 565bd8deadSopenharmony_ci 575bd8deadSopenharmony_ci Applications can benefit from accurate timing information in a number of 585bd8deadSopenharmony_ci different ways. During application development, timing information can 595bd8deadSopenharmony_ci help identify application or driver bottlenecks. At run time, 605bd8deadSopenharmony_ci applications can use timing information to dynamically adjust the amount 615bd8deadSopenharmony_ci of detail in a scene to achieve constant frame rates. OpenGL 625bd8deadSopenharmony_ci implementations have historically provided little to no useful timing 635bd8deadSopenharmony_ci information. Applications can get some idea of timing by reading timers 645bd8deadSopenharmony_ci on the CPU, but these timers are not synchronized with the graphics 655bd8deadSopenharmony_ci rendering pipeline. Reading a CPU timer does not guarantee the completion 665bd8deadSopenharmony_ci of a potentially large amount of graphics work accumulated before the 675bd8deadSopenharmony_ci timer is read, and will thus produce wildly inaccurate results. 685bd8deadSopenharmony_ci glFinish() can be used to determine when previous rendering commands have 695bd8deadSopenharmony_ci been completed, but will idle the graphics pipeline and adversely affect 705bd8deadSopenharmony_ci application performance. 715bd8deadSopenharmony_ci 725bd8deadSopenharmony_ci This extension provides a query mechanism that can be used to determine 735bd8deadSopenharmony_ci the amount of time it takes to fully complete a set of GL commands, and 745bd8deadSopenharmony_ci without stalling the rendering pipeline. It uses the query object 755bd8deadSopenharmony_ci mechanisms first introduced in the occlusion query extension, which allow 765bd8deadSopenharmony_ci time intervals to be polled asynchronously by the application. 775bd8deadSopenharmony_ci 785bd8deadSopenharmony_ciIP Status 795bd8deadSopenharmony_ci 805bd8deadSopenharmony_ci No known IP claims. 815bd8deadSopenharmony_ci 825bd8deadSopenharmony_ciNew Procedures and Functions 835bd8deadSopenharmony_ci 845bd8deadSopenharmony_ci void QueryCounter(uint id, enum target); 855bd8deadSopenharmony_ci 865bd8deadSopenharmony_ci void GetQueryObjecti64v(uint id, enum pname, int64 *params); 875bd8deadSopenharmony_ci void GetQueryObjectui64v(uint id, enum pname, uint64 *params); 885bd8deadSopenharmony_ci 895bd8deadSopenharmony_ciNew Tokens 905bd8deadSopenharmony_ci 915bd8deadSopenharmony_ci Accepted by the <target> parameter of BeginQuery, EndQuery, and 925bd8deadSopenharmony_ci GetQueryiv: 935bd8deadSopenharmony_ci 945bd8deadSopenharmony_ci TIME_ELAPSED 0x88BF 955bd8deadSopenharmony_ci 965bd8deadSopenharmony_ci Accepted by the <target> parameter of GetQueryiv and QueryCounter. 975bd8deadSopenharmony_ci Accepted by the <value> parameter of GetBooleanv, GetIntegerv, 985bd8deadSopenharmony_ci GetInteger64v, GetFloatv, and GetDoublev: 995bd8deadSopenharmony_ci 1005bd8deadSopenharmony_ci TIMESTAMP 0x8E28 1015bd8deadSopenharmony_ci 1025bd8deadSopenharmony_ciAdditions to Chapter 2 of the OpenGL 3.2 (Core Profile) Specification 1035bd8deadSopenharmony_ci(OpenGL Operation) 1045bd8deadSopenharmony_ci 1055bd8deadSopenharmony_ci (Modify table 2.1, Correspondence of command suffix letters to GL argument 1065bd8deadSopenharmony_ci types, p. 14) Add one new type and suffix: 1075bd8deadSopenharmony_ci 1085bd8deadSopenharmony_ci Letter Corresponding GL Type 1095bd8deadSopenharmony_ci ------ --------------------- 1105bd8deadSopenharmony_ci ui64 uint64 1115bd8deadSopenharmony_ci 1125bd8deadSopenharmony_ci (Modify Section 2.14, Asynchronous Queries, p. 89) 1135bd8deadSopenharmony_ci 1145bd8deadSopenharmony_ci Asynchronous queries provide a mechanism to return information about the 1155bd8deadSopenharmony_ci processing of a sequence of GL commands. There are three query types 1165bd8deadSopenharmony_ci supported by the GL. Transform feedback queries (see section 2.16) return 1175bd8deadSopenharmony_ci information on the number of vertices and primitives processed by the GL 1185bd8deadSopenharmony_ci and written to one or more buffer objects. Occlusion queries (see section 1195bd8deadSopenharmony_ci 4.1.6) count the number of fragments or samples that pass the depth test. 1205bd8deadSopenharmony_ci Timer queries (section 5.4) record the amount of time needed to fully 1215bd8deadSopenharmony_ci process these commands or the current time of the GL. 1225bd8deadSopenharmony_ci 1235bd8deadSopenharmony_ciAdditions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization) 1245bd8deadSopenharmony_ci 1255bd8deadSopenharmony_ci None. 1265bd8deadSopenharmony_ci 1275bd8deadSopenharmony_ciAdditions to Chapter 4 of the OpenGL 3.2 Specification (Per-Fragment 1285bd8deadSopenharmony_ciOperations and the Framebuffer) 1295bd8deadSopenharmony_ci 1305bd8deadSopenharmony_ci None. 1315bd8deadSopenharmony_ci 1325bd8deadSopenharmony_ciAdditions to Chapter 5 of the OpenGL 3.2 Specification (Special Functions) 1335bd8deadSopenharmony_ci 1345bd8deadSopenharmony_ci (Add new Section 5.4, Timer Queries, p. 246) 1355bd8deadSopenharmony_ci 1365bd8deadSopenharmony_ci Timer queries use query objects to track the amount of time needed to 1375bd8deadSopenharmony_ci fully complete a set of GL commands, or to determine the current time 1385bd8deadSopenharmony_ci of the GL. 1395bd8deadSopenharmony_ci 1405bd8deadSopenharmony_ci When BeginQuery and EndQuery are called with a <target> of 1415bd8deadSopenharmony_ci TIME_ELAPSED, the GL prepares to start and stop the timer used for 1425bd8deadSopenharmony_ci timer queries. The timer is started or stopped when the effects from all 1435bd8deadSopenharmony_ci previous commands on the GL client and server state and the framebuffer 1445bd8deadSopenharmony_ci have been fully realized. The BeginQuery and EndQuery commands may return 1455bd8deadSopenharmony_ci before the timer is actually started or stopped. When the timer query 1465bd8deadSopenharmony_ci timer is finally stopped, the elapsed time (in nanoseconds) is written to 1475bd8deadSopenharmony_ci the corresponding query object as the query result value, and the query 1485bd8deadSopenharmony_ci result for that object is marked as available. 1495bd8deadSopenharmony_ci 1505bd8deadSopenharmony_ci If the elapsed time overflows the number of bits, <n>, available to hold 1515bd8deadSopenharmony_ci elapsed time, its value becomes undefined. It is recommended, but not 1525bd8deadSopenharmony_ci required, that implementations handle this overflow case by saturating at 1535bd8deadSopenharmony_ci 2^n - 1. 1545bd8deadSopenharmony_ci 1555bd8deadSopenharmony_ci A timer query object is created with the command 1565bd8deadSopenharmony_ci 1575bd8deadSopenharmony_ci void QueryCounter(uint id, enum target); 1585bd8deadSopenharmony_ci 1595bd8deadSopenharmony_ci <target> must be TIMESTAMP. If <id> is an unused query object name, the 1605bd8deadSopenharmony_ci name is marked as used and associated with a new query object of type 1615bd8deadSopenharmony_ci TIMESTAMP. Otherwise <id> must be the name of an existing query object 1625bd8deadSopenharmony_ci of that type. 1635bd8deadSopenharmony_ci 1645bd8deadSopenharmony_ci When QueryCounter is called, the GL records the current time into 1655bd8deadSopenharmony_ci the corresponding query object. The time is recorded after all previous 1665bd8deadSopenharmony_ci commands on the GL client and server state and the framebuffer have been 1675bd8deadSopenharmony_ci fully realized. When the time is recorded, the query result for that 1685bd8deadSopenharmony_ci object is marked available. QueryCounter timer queries can be used 1695bd8deadSopenharmony_ci within a BeginQuery / EndQuery block where the <target> is TIME_ELAPSED 1705bd8deadSopenharmony_ci and it does not affect the result of that query object. 1715bd8deadSopenharmony_ci 1725bd8deadSopenharmony_ci** core profile only 1735bd8deadSopenharmony_ci QueryCounter fails and an INVALID\_OPERATION error is generated if <id> 1745bd8deadSopenharmony_ci is not a name returned from a previous call to GenQueries, or if such a 1755bd8deadSopenharmony_ci name has since been deleted with DeleteQueries. 1765bd8deadSopenharmony_ci** end core profile only 1775bd8deadSopenharmony_ci 1785bd8deadSopenharmony_ci If <id> is already in use within a BeginQuery / EndQuery block, or if 1795bd8deadSopenharmony_ci <id> is the name of an existing query object whose type does not match 1805bd8deadSopenharmony_ci <target>, an INVALID_OPERATION error is generated. 1815bd8deadSopenharmony_ci 1825bd8deadSopenharmony_ci The current time of the GL may be queried by calling GetIntegerv or 1835bd8deadSopenharmony_ci GetInteger64v with the symbolic constant TIMESTAMP. This will return the 1845bd8deadSopenharmony_ci GL time after all previous commands have reached the GL server but have 1855bd8deadSopenharmony_ci not yet necessarily executed. By using a combination of this synchronous 1865bd8deadSopenharmony_ci get command and the asynchronous timestamp query object target, 1875bd8deadSopenharmony_ci applications can measure the latency between when commands reach the GL 1885bd8deadSopenharmony_ci server and when they are realized in the framebuffer. 1895bd8deadSopenharmony_ci 1905bd8deadSopenharmony_ciAdditions to Chapter 6 of the OpenGL 2.0 Specification (State and State 1915bd8deadSopenharmony_ciRequests) 1925bd8deadSopenharmony_ci 1935bd8deadSopenharmony_ci (Modify Section 6.1.6, Asynchronous Queries, p. 255) 1945bd8deadSopenharmony_ci 1955bd8deadSopenharmony_ci Section 6.1.6, Asynchronous Queries 1965bd8deadSopenharmony_ci 1975bd8deadSopenharmony_ci The command 1985bd8deadSopenharmony_ci 1995bd8deadSopenharmony_ci boolean IsQuery(uint id); 2005bd8deadSopenharmony_ci 2015bd8deadSopenharmony_ci returns TRUE if <id> is the name of a query object. If <id> is zero, or if 2025bd8deadSopenharmony_ci <id> is a non-zero value that is not the name of a query object, IsQuery 2035bd8deadSopenharmony_ci returns FALSE. 2045bd8deadSopenharmony_ci 2055bd8deadSopenharmony_ci Information about a query target can be queried with the command 2065bd8deadSopenharmony_ci 2075bd8deadSopenharmony_ci void GetQueryiv(enum target, enum pname, int *params); 2085bd8deadSopenharmony_ci 2095bd8deadSopenharmony_ci <target> identifies the query target and can be SAMPLES_PASSED for 2105bd8deadSopenharmony_ci occlusion queries, PRIMITIVES_GENERATED and 2115bd8deadSopenharmony_ci TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN for primitive queries, or 2125bd8deadSopenharmony_ci TIME_ELAPSED or TIMESTAMP for timer queries. 2135bd8deadSopenharmony_ci 2145bd8deadSopenharmony_ci If <pname> is CURRENT_QUERY, the name of the currently active query for 2155bd8deadSopenharmony_ci <target>, or zero if no query is active, will be placed in <params>. 2165bd8deadSopenharmony_ci 2175bd8deadSopenharmony_ci If <pname> is QUERY_COUNTER_BITS, the implementation-dependent number of 2185bd8deadSopenharmony_ci bits used to hold the query result for <target> will be placed in 2195bd8deadSopenharmony_ci <params>. The number of query counter bits may be zero, in which case 2205bd8deadSopenharmony_ci the counter contains no useful information. 2215bd8deadSopenharmony_ci 2225bd8deadSopenharmony_ci For primitive queries (PRIMITIVES_GENERATED and 2235bd8deadSopenharmony_ci TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) if the number of bits is non-zero, 2245bd8deadSopenharmony_ci the minimum number of bits allowed is 32. 2255bd8deadSopenharmony_ci 2265bd8deadSopenharmony_ci For occlusion queries (SAMPLES_PASSED), if the number of bits is 2275bd8deadSopenharmony_ci non-zero, the minimum number of bits allowed is a function of the 2285bd8deadSopenharmony_ci implementation's maximum viewport dimensions (MAX_VIEWPORT_DIMS). The 2295bd8deadSopenharmony_ci counter must be able to represent at least two overdraws for every pixel 2305bd8deadSopenharmony_ci in the viewport. The formula to compute the allowable minimum value 2315bd8deadSopenharmony_ci (where <n> is the minimum number of bits) is: 2325bd8deadSopenharmony_ci 2335bd8deadSopenharmony_ci n = min(32, ceil(log_2(maxViewportWidth * maxViewportHeight * 2))). 2345bd8deadSopenharmony_ci 2355bd8deadSopenharmony_ci For timer queries (TIME_ELAPSED and TIMESTAMP), if the number 2365bd8deadSopenharmony_ci of bits is non-zero, the minimum number of bits allowed is 30 which 2375bd8deadSopenharmony_ci will allow at least 1 second of timing. 2385bd8deadSopenharmony_ci 2395bd8deadSopenharmony_ci The state of a query object can be queried with the commands 2405bd8deadSopenharmony_ci 2415bd8deadSopenharmony_ci void GetQueryObjectiv(uint id, enum pname, int *params); 2425bd8deadSopenharmony_ci void GetQueryObjectuiv(uint id, enum pname, uint *params); 2435bd8deadSopenharmony_ci void GetQueryObjecti64v(uint id, enum pname, int64 *params); 2445bd8deadSopenharmony_ci void GetQueryObjectui64v(uint id, enum pname, uint64 *params); 2455bd8deadSopenharmony_ci 2465bd8deadSopenharmony_ci If <id> is not the name of a query object, or if the query object named 2475bd8deadSopenharmony_ci by <id> is currently active, then an INVALID_OPERATION error is 2485bd8deadSopenharmony_ci generated. 2495bd8deadSopenharmony_ci 2505bd8deadSopenharmony_ci If <pname> is QUERY_RESULT, then the query object's result 2515bd8deadSopenharmony_ci value is returned as a single integer in <params>. If the value is so 2525bd8deadSopenharmony_ci large in magnitude that it cannot be represented with the requested type, 2535bd8deadSopenharmony_ci then the nearest value representable using the requested type is 2545bd8deadSopenharmony_ci returned. If the number of query counter bits for target is zero, then 2555bd8deadSopenharmony_ci the result is returned as a single integer with the value zero. 2565bd8deadSopenharmony_ci 2575bd8deadSopenharmony_ci There may be an indeterminate delay before the above query returns. If 2585bd8deadSopenharmony_ci <pname> is QUERY_RESULT_AVAILABLE, FALSE is returned if such a delay 2595bd8deadSopenharmony_ci would be required; otherwise TRUE is returned. It must always be true 2605bd8deadSopenharmony_ci that if any query object returns a result available of TRUE, all queries 2615bd8deadSopenharmony_ci of the same type issued prior to that query must also return TRUE. 2625bd8deadSopenharmony_ci 2635bd8deadSopenharmony_ci Querying the state for any given query object forces that occlusion 2645bd8deadSopenharmony_ci query to complete within a finite amount of time. 2655bd8deadSopenharmony_ci 2665bd8deadSopenharmony_ci If multiple queries are issued using the same object name prior to 2675bd8deadSopenharmony_ci calling GetQueryObject[u]i[64]v, the result and availability information 2685bd8deadSopenharmony_ci returned will always be from the last query issued. The results from any 2695bd8deadSopenharmony_ci queries before the last one will be lost if they are not retrieved before 2705bd8deadSopenharmony_ci starting a new query on the same <target> and <id>. 2715bd8deadSopenharmony_ci 2725bd8deadSopenharmony_ciInteractions with NV_present_video and NV_video_capture 2735bd8deadSopenharmony_ci 2745bd8deadSopenharmony_ci The GL timer recorded by this extension is the same timer as that used 2755bd8deadSopenharmony_ci by the NV_present_video and NV_video_capture extensions. This allows 2765bd8deadSopenharmony_ci the timer to be used with any of these extensions interchangeably. 2775bd8deadSopenharmony_ci 2785bd8deadSopenharmony_ciInteractions with the Compatibility Profile 2795bd8deadSopenharmony_ci 2805bd8deadSopenharmony_ci In the compatibility profile, query objects support application-provided 2815bd8deadSopenharmony_ci names, and the language requiring an error is <id> is not a name 2825bd8deadSopenharmony_ci returned from GenQueries is removed. This is noted in the body text 2835bd8deadSopenharmony_ci above. 2845bd8deadSopenharmony_ci 2855bd8deadSopenharmony_ciErrors 2865bd8deadSopenharmony_ci 2875bd8deadSopenharmony_ci The error INVALID_ENUM is generated if BeginQuery or EndQuery is called 2885bd8deadSopenharmony_ci where <target> is not SAMPLES_PASSED, 2895bd8deadSopenharmony_ci TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN or TIME_ELAPSED. 2905bd8deadSopenharmony_ci 2915bd8deadSopenharmony_ci The error INVALID_ENUM is generated if GetQueryiv is called where 2925bd8deadSopenharmony_ci <target> is not SAMPLES_PASSED, TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 2935bd8deadSopenharmony_ci TIME_ELAPSED or TIMESTAMP. 2945bd8deadSopenharmony_ci 2955bd8deadSopenharmony_ci The error INVALID_ENUM is generated if QueryCounter is called where 2965bd8deadSopenharmony_ci <target> is not TIMESTAMP. 2975bd8deadSopenharmony_ci 2985bd8deadSopenharmony_ci The error INVALID_OPERATION is generated if QueryCounter is called 2995bd8deadSopenharmony_ci on a query object that is already in use inside a BeginQuery/EndQuery. 3005bd8deadSopenharmony_ci 3015bd8deadSopenharmony_ci The error INVALID_OPERATION is generated if QueryCounter is called on 3025bd8deadSopenharmony_ci a query object whose type is not TIMESTAMP. 3035bd8deadSopenharmony_ci 3045bd8deadSopenharmony_ci (in the core profile only) 3055bd8deadSopenharmony_ci The error INVALID_OPERATION is generated if QueryCounter is called 3065bd8deadSopenharmony_ci where <id> is not a name returned from a previous call to GenQueries, 3075bd8deadSopenharmony_ci or if such a name has since been deleted with DeleteQueries. 3085bd8deadSopenharmony_ci 3095bd8deadSopenharmony_ci The error INVALID_OPERATION is generated if GetQueryObjecti64v or 3105bd8deadSopenharmony_ci GetQueryObjectui64v is called where <id> is not the name of a query 3115bd8deadSopenharmony_ci object. 3125bd8deadSopenharmony_ci 3135bd8deadSopenharmony_ci The error INVALID_OPERATION is generated if GetQueryObjecti64v or 3145bd8deadSopenharmony_ci GetQueryObjectui64v is called where <id> is the name of a currently 3155bd8deadSopenharmony_ci active query object. 3165bd8deadSopenharmony_ci 3175bd8deadSopenharmony_ci The error INVALID_ENUM is generated if GetQueryObjecti64v or 3185bd8deadSopenharmony_ci GetQueryObjectui64v is called where <pname> is not QUERY_RESULT or 3195bd8deadSopenharmony_ci QUERY_RESULT_AVAILABLE. 3205bd8deadSopenharmony_ci 3215bd8deadSopenharmony_ciNew State 3225bd8deadSopenharmony_ci 3235bd8deadSopenharmony_ci None. 3245bd8deadSopenharmony_ci 3255bd8deadSopenharmony_ciExamples 3265bd8deadSopenharmony_ci 3275bd8deadSopenharmony_ci (1) Here is some rough sample code that demonstrates the intended usage 3285bd8deadSopenharmony_ci of this extension. 3295bd8deadSopenharmony_ci 3305bd8deadSopenharmony_ci GLuint queries[N]; 3315bd8deadSopenharmony_ci GLint available = 0; 3325bd8deadSopenharmony_ci // timer queries can contain more than 32 bits of data, so always 3335bd8deadSopenharmony_ci // query them using the 64 bit types to avoid overflow 3345bd8deadSopenharmony_ci GLuint64 timeElapsed = 0; 3355bd8deadSopenharmony_ci 3365bd8deadSopenharmony_ci // Create a query object. 3375bd8deadSopenharmony_ci glGenQueries(N, queries); 3385bd8deadSopenharmony_ci 3395bd8deadSopenharmony_ci // Start query 1 3405bd8deadSopenharmony_ci glBeginQuery(GL_TIME_ELAPSED, queries[0]); 3415bd8deadSopenharmony_ci 3425bd8deadSopenharmony_ci // Draw object 1 3435bd8deadSopenharmony_ci .... 3445bd8deadSopenharmony_ci 3455bd8deadSopenharmony_ci // End query 1 3465bd8deadSopenharmony_ci glEndQuery(GL_TIME_ELAPSED); 3475bd8deadSopenharmony_ci 3485bd8deadSopenharmony_ci ... 3495bd8deadSopenharmony_ci 3505bd8deadSopenharmony_ci // Start query N 3515bd8deadSopenharmony_ci glBeginQuery(GL_TIME_ELAPSED, queries[N-1]); 3525bd8deadSopenharmony_ci 3535bd8deadSopenharmony_ci // Draw object N 3545bd8deadSopenharmony_ci .... 3555bd8deadSopenharmony_ci 3565bd8deadSopenharmony_ci // End query N 3575bd8deadSopenharmony_ci glEndQuery(GL_TIME_ELAPSED); 3585bd8deadSopenharmony_ci 3595bd8deadSopenharmony_ci // Wait for all results to become available 3605bd8deadSopenharmony_ci while (!available) { 3615bd8deadSopenharmony_ci glGetQueryObjectiv(queries[N-1], GL_QUERY_RESULT_AVAILABLE, &available); 3625bd8deadSopenharmony_ci } 3635bd8deadSopenharmony_ci 3645bd8deadSopenharmony_ci for (i = 0; i < N; i++) { 3655bd8deadSopenharmony_ci // See how much time the rendering of object i took in nanoseconds. 3665bd8deadSopenharmony_ci glGetQueryObjectui64v(queries[i], GL_QUERY_RESULT, &timeElapsed); 3675bd8deadSopenharmony_ci 3685bd8deadSopenharmony_ci // Do something useful with the time. Note that care should be 3695bd8deadSopenharmony_ci // taken to use all significant bits of the result, not just the 3705bd8deadSopenharmony_ci // least significant 32 bits. 3715bd8deadSopenharmony_ci AdjustObjectLODBasedOnDrawTime(i, timeElapsed); 3725bd8deadSopenharmony_ci } 3735bd8deadSopenharmony_ci 3745bd8deadSopenharmony_ci This example is sub-optimal in that it stalls at the end of every 3755bd8deadSopenharmony_ci frame to wait for query results. Ideally, the collection of results 3765bd8deadSopenharmony_ci would be delayed one frame to minimize the amount of time spent 3775bd8deadSopenharmony_ci waiting for the GPU to finish rendering. 3785bd8deadSopenharmony_ci 3795bd8deadSopenharmony_ci (2) This example is basically the same as the example above but uses 3805bd8deadSopenharmony_ci QueryCounter instead. 3815bd8deadSopenharmony_ci 3825bd8deadSopenharmony_ci GLuint queries[N+1]; 3835bd8deadSopenharmony_ci GLint available = 0; 3845bd8deadSopenharmony_ci // timer queries can contain more than 32 bits of data, so always 3855bd8deadSopenharmony_ci // query them using the 64 bit types to avoid overflow 3865bd8deadSopenharmony_ci GLuint64 timeStart, timeEnd, timeElapsed = 0; 3875bd8deadSopenharmony_ci 3885bd8deadSopenharmony_ci // Create a query object. 3895bd8deadSopenharmony_ci glGenQueries(N+1, queries); 3905bd8deadSopenharmony_ci 3915bd8deadSopenharmony_ci // Query current timestamp 1 3925bd8deadSopenharmony_ci glQueryCounter(queries[0], GL_TIMESTAMP); 3935bd8deadSopenharmony_ci 3945bd8deadSopenharmony_ci // Draw object 1 3955bd8deadSopenharmony_ci .... 3965bd8deadSopenharmony_ci 3975bd8deadSopenharmony_ci // Query current timestamp N 3985bd8deadSopenharmony_ci glQueryCounter(queries[N-1], GL_TIMESTAMP); 3995bd8deadSopenharmony_ci 4005bd8deadSopenharmony_ci // Draw object N 4015bd8deadSopenharmony_ci .... 4025bd8deadSopenharmony_ci 4035bd8deadSopenharmony_ci // Query current timestamp N+1 4045bd8deadSopenharmony_ci glQueryCounter(queries[N], GL_TIMESTAMP); 4055bd8deadSopenharmony_ci 4065bd8deadSopenharmony_ci // Wait for all results to become available 4075bd8deadSopenharmony_ci while (!available) { 4085bd8deadSopenharmony_ci glGetQueryObjectiv(queries[N], GL_QUERY_RESULT_AVAILABLE, &available); 4095bd8deadSopenharmony_ci } 4105bd8deadSopenharmony_ci 4115bd8deadSopenharmony_ci for (i = 0; i < N; i++) { 4125bd8deadSopenharmony_ci // See how much time the rendering of object i took in nanoseconds. 4135bd8deadSopenharmony_ci glGetQueryObjectui64v(queries[i], GL_QUERY_RESULT, &timeStart); 4145bd8deadSopenharmony_ci glGetQueryObjectui64v(queries[i+1], GL_QUERY_RESULT, &timeEnd); 4155bd8deadSopenharmony_ci timeElapsed = timeEnd - timeStart; 4165bd8deadSopenharmony_ci 4175bd8deadSopenharmony_ci // Do something useful with the time. Note that care should be 4185bd8deadSopenharmony_ci // taken to use all significant bits of the result, not just the 4195bd8deadSopenharmony_ci // least significant 32 bits. 4205bd8deadSopenharmony_ci AdjustObjectLODBasedOnDrawTime(i, timeElapsed); 4215bd8deadSopenharmony_ci } 4225bd8deadSopenharmony_ci 4235bd8deadSopenharmony_ci (3) This example demonstrates how to measure the latency between GL 4245bd8deadSopenharmony_ci commands reaching the server and being realized in the framebuffer. 4255bd8deadSopenharmony_ci 4265bd8deadSopenharmony_ci /* Submit a frame of rendering commands */ 4275bd8deadSopenharmony_ci while (!doneRendering) { 4285bd8deadSopenharmony_ci ... 4295bd8deadSopenharmony_ci glDrawElements(...); 4305bd8deadSopenharmony_ci } 4315bd8deadSopenharmony_ci 4325bd8deadSopenharmony_ci /* 4335bd8deadSopenharmony_ci * Measure rendering latency: 4345bd8deadSopenharmony_ci * 4355bd8deadSopenharmony_ci * Some commands may have already been submitted to hardware, 4365bd8deadSopenharmony_ci * and some of those may have already completed. The goal is 4375bd8deadSopenharmony_ci * to measure the time it takes for the remaining commands to 4385bd8deadSopenharmony_ci * complete, thereby measuring how far behind the app the GPU 4395bd8deadSopenharmony_ci * is lagging, but without synchronizing the GPU with the CPU. 4405bd8deadSopenharmony_ci */ 4415bd8deadSopenharmony_ci 4425bd8deadSopenharmony_ci /* Queue a query to find out when the frame finishes on the GL */ 4435bd8deadSopenharmony_ci glQueryCounter(endFrameQuery, GL_TIMESTAMP); 4445bd8deadSopenharmony_ci 4455bd8deadSopenharmony_ci /* Get the current GL time without stalling the GL */ 4465bd8deadSopenharmony_ci glGet(GL_TIMESTAMP, &flushTime); 4475bd8deadSopenharmony_ci 4485bd8deadSopenharmony_ci /* Finish the frame, submitting outstanding commands to the GL */ 4495bd8deadSopenharmony_ci SwapBuffers(); 4505bd8deadSopenharmony_ci 4515bd8deadSopenharmony_ci /* Render another frame */ 4525bd8deadSopenharmony_ci 4535bd8deadSopenharmony_ci /* 4545bd8deadSopenharmony_ci * Later, compare the query result of <endFrameQuery> 4555bd8deadSopenharmony_ci * and <flushTime> to measure the latency of the frame 4565bd8deadSopenharmony_ci */ 4575bd8deadSopenharmony_ci 4585bd8deadSopenharmony_ci 4595bd8deadSopenharmony_ciIssues from EXT_timer_query 4605bd8deadSopenharmony_ci 4615bd8deadSopenharmony_ci (1) What time interval is being measured? 4625bd8deadSopenharmony_ci 4635bd8deadSopenharmony_ci RESOLVED: The timer starts when all commands prior to BeginQuery() have 4645bd8deadSopenharmony_ci been fully executed. At that point, everything that should be drawn by 4655bd8deadSopenharmony_ci those commands has been written to the framebuffer. The timer stops 4665bd8deadSopenharmony_ci when all commands prior to EndQuery() have been fully executed. 4675bd8deadSopenharmony_ci 4685bd8deadSopenharmony_ci (2) What unit of time will time intervals be returned in? 4695bd8deadSopenharmony_ci 4705bd8deadSopenharmony_ci RESOLVED: Nanoseconds (10^-9 seconds). This unit of measurement allows 4715bd8deadSopenharmony_ci for reasonably accurate timing of even small blocks of rendering 4725bd8deadSopenharmony_ci commands. The granularity of the timer is implementation-dependent. A 4735bd8deadSopenharmony_ci 32-bit query counter can express intervals of up to approximately 4 4745bd8deadSopenharmony_ci seconds. 4755bd8deadSopenharmony_ci 4765bd8deadSopenharmony_ci (3) What should be the minimum number of counter bits for timer queries? 4775bd8deadSopenharmony_ci 4785bd8deadSopenharmony_ci RESOLVED: 30 bits, which will allow timing sections that take up to 1 4795bd8deadSopenharmony_ci second to render. 4805bd8deadSopenharmony_ci 4815bd8deadSopenharmony_ci (4) How are counter results of more than 32 bits returned? 4825bd8deadSopenharmony_ci 4835bd8deadSopenharmony_ci RESOLVED: Via two new datatypes, int64EXT and uint64EXT, and their 4845bd8deadSopenharmony_ci corresponding GetQueryObject entry points. These types hold integer 4855bd8deadSopenharmony_ci values and have a minimum bit width of 64. 4865bd8deadSopenharmony_ci 4875bd8deadSopenharmony_ci UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0. 4885bd8deadSopenharmony_ci OpenGL 3.2 now has int64 and uint64 datatypes as part of the core spec. 4895bd8deadSopenharmony_ci 4905bd8deadSopenharmony_ci (5) Should the extension measure total time elapsed between the full 4915bd8deadSopenharmony_ci completion of the BeginQuery and EndQuery commands, or just time 4925bd8deadSopenharmony_ci spent in the graphics library? 4935bd8deadSopenharmony_ci 4945bd8deadSopenharmony_ci RESOLVED: This extension will measure the total time elapsed between 4955bd8deadSopenharmony_ci the full completion of these commands. Future extensions may implement 4965bd8deadSopenharmony_ci a query to determine time elapsed at different stages of the graphics 4975bd8deadSopenharmony_ci pipeline. 4985bd8deadSopenharmony_ci 4995bd8deadSopenharmony_ci (6) This extension introduces a second query type supported by 5005bd8deadSopenharmony_ci BeginQuery/EndQuery. Can multiple query types be active 5015bd8deadSopenharmony_ci simultaneously? 5025bd8deadSopenharmony_ci 5035bd8deadSopenharmony_ci RESOLVED: Yes; an application may perform an occlusion query and a 5045bd8deadSopenharmony_ci timer query simultaneously. An application can not perform multiple 5055bd8deadSopenharmony_ci occlusion queries or multiple timer queries simultaneously. An 5065bd8deadSopenharmony_ci application also can not use the same query object for an occlusion 5075bd8deadSopenharmony_ci query and a timer query simultaneously. 5085bd8deadSopenharmony_ci 5095bd8deadSopenharmony_ci (7) Do query objects have a query type permanently associated with them? 5105bd8deadSopenharmony_ci 5115bd8deadSopenharmony_ci RESOLVED: No. A single query object can be used to perform different 5125bd8deadSopenharmony_ci types of queries, but not at the same time. 5135bd8deadSopenharmony_ci 5145bd8deadSopenharmony_ci Having a fixed type for each query object simplifies some aspects of the 5155bd8deadSopenharmony_ci implementation -- not having to deal with queries with different result 5165bd8deadSopenharmony_ci sizes, for example. It would also mean that BeginQuery() with a query 5175bd8deadSopenharmony_ci object of the "wrong" type would result in an INVALID_OPERATION error. 5185bd8deadSopenharmony_ci 5195bd8deadSopenharmony_ci UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0. 5205bd8deadSopenharmony_ci Since EXT_transform_feedback has since been incorporated into the core, 5215bd8deadSopenharmony_ci the resolution is that BeginQuery will generate error INVALID_OPERATION 5225bd8deadSopenharmony_ci if <id> represents a query object of a different type. 5235bd8deadSopenharmony_ci 5245bd8deadSopenharmony_ci (8) How predictable/repeatable are the results returned by the timer 5255bd8deadSopenharmony_ci query? 5265bd8deadSopenharmony_ci 5275bd8deadSopenharmony_ci RESOLVED: In general, the amount of time needed to render the same 5285bd8deadSopenharmony_ci primitives should be fairly constant. But there may be many other 5295bd8deadSopenharmony_ci system issues (e.g., context switching on the CPU and GPU, virtual 5305bd8deadSopenharmony_ci memory page faults, memory cache behavior on the CPU and GPU) that can 5315bd8deadSopenharmony_ci cause times to vary wildly. 5325bd8deadSopenharmony_ci 5335bd8deadSopenharmony_ci Note that modern GPUs are generally highly pipelined, and may be 5345bd8deadSopenharmony_ci processing different primitives in different pipeline stages 5355bd8deadSopenharmony_ci simultaneously. In this extension, the timers start and stop when the 5365bd8deadSopenharmony_ci BeginQuery/EndQuery commands reach the bottom of the rendering pipeline. 5375bd8deadSopenharmony_ci What that means is that by the time the timer starts, the GL driver on 5385bd8deadSopenharmony_ci the CPU may have started work on GL commands issued after BeginQuery, 5395bd8deadSopenharmony_ci and the higher pipeline stages (e.g., vertex transformation) may have 5405bd8deadSopenharmony_ci started as well. 5415bd8deadSopenharmony_ci 5425bd8deadSopenharmony_ci (9) What should the new 64 bit integer type be called? 5435bd8deadSopenharmony_ci 5445bd8deadSopenharmony_ci RESOLVED: The new types will be called GLint64EXT/GLuint64EXT The new 5455bd8deadSopenharmony_ci command suffixes will be i64 and ui64. These names clearly convey the 5465bd8deadSopenharmony_ci minimum size of the types. These types are similar to the C99 standard 5475bd8deadSopenharmony_ci type int_least64_t, but we use names similar to the C99 optional type 5485bd8deadSopenharmony_ci int64_t for simplicity. 5495bd8deadSopenharmony_ci 5505bd8deadSopenharmony_ci UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0. 5515bd8deadSopenharmony_ci OpenGL 3.2 now has int64 and uint64 datatypes as part of the core spec. 5525bd8deadSopenharmony_ci The i64 suffix already exists in OpenGL 3.2 and the ui64 suffix has been 5535bd8deadSopenharmony_ci added as part of this extension. 5545bd8deadSopenharmony_ci 5555bd8deadSopenharmony_ciIssues 5565bd8deadSopenharmony_ci 5575bd8deadSopenharmony_ci (10) What about tile-based implementations? The effects of a command are 5585bd8deadSopenharmony_ci not complete until the frame is completely rendered. Timing recorded 5595bd8deadSopenharmony_ci before the frame is complete may not be what developers expect. Also 5605bd8deadSopenharmony_ci the amount of time needed to render the same primitives is not 5615bd8deadSopenharmony_ci consistent, which conflicts with issue (8) above. The time depends on 5625bd8deadSopenharmony_ci how early or late in the scene it is placed. 5635bd8deadSopenharmony_ci 5645bd8deadSopenharmony_ci RESOLVED: The current language supports tile-based rendering okay as it 5655bd8deadSopenharmony_ci is written. Developers are warned that using timers on tile-based 5665bd8deadSopenharmony_ci implementation may not produce results they expect since rendering is not 5675bd8deadSopenharmony_ci done in a linear order. Timing results are calculated when the frame is 5685bd8deadSopenharmony_ci completed and may depend on how early or late in the scene it is placed. 5695bd8deadSopenharmony_ci 5705bd8deadSopenharmony_ci (11) Can the GL implementation use different clocks to implement the 5715bd8deadSopenharmony_ci TIME_ELAPSED and TIMESTAMP queries? 5725bd8deadSopenharmony_ci 5735bd8deadSopenharmony_ci RESOLVED: Yes, the implementation can use different internal clocks to 5745bd8deadSopenharmony_ci implement TIME_ELAPSED and TIMESTAMP. If different clocks are 5755bd8deadSopenharmony_ci used it is possible there is a slight discrepancy when comparing queries 5765bd8deadSopenharmony_ci made from TIME_ELAPSED and TIMESTAMP; they may have slight 5775bd8deadSopenharmony_ci differences when both are used to measure the same sequence. However, this 5785bd8deadSopenharmony_ci is unlikely to affect real applications since comparing the two queries is 5795bd8deadSopenharmony_ci not expected to be useful. 5805bd8deadSopenharmony_ci 5815bd8deadSopenharmony_ci (12) Why do BeginQuery and QueryCounter have the same arguments in the 5825bd8deadSopenharmony_ci opposite order? 5835bd8deadSopenharmony_ci 5845bd8deadSopenharmony_ci RESOLVED: Due to an unfortunate oversight, which cannot be fixed at 5855bd8deadSopenharmony_ci this point. 5865bd8deadSopenharmony_ci 5875bd8deadSopenharmony_ci 5885bd8deadSopenharmony_ciRevision History 5895bd8deadSopenharmony_ci 5905bd8deadSopenharmony_ci Rev. Date Author Changes 5915bd8deadSopenharmony_ci ---- ------------ -------- ------------------------------------------- 5925bd8deadSopenharmony_ci 13 Aug 9, 2014 Jon Leech Fix typo in example 3 (bug 12552). 5935bd8deadSopenharmony_ci 5945bd8deadSopenharmony_ci 12 Jul 11, 2013 Jon Leech Change type of queries[] in sample code to 5955bd8deadSopenharmony_ci GLuint (public bug 432). 5965bd8deadSopenharmony_ci 5975bd8deadSopenharmony_ci 11 Apr 13, 2012 Jon Leech Clean up error language, add error for 5985bd8deadSopenharmony_ci query objects which are not of type 5995bd8deadSopenharmony_ci TIMESTAMP, and add issue 12 (Khronos 6005bd8deadSopenharmony_ci internal bug 7662) 6015bd8deadSopenharmony_ci 6025bd8deadSopenharmony_ci 10 June 3, 2011 dkoch Add INVALID_OPERATION error when calling 6035bd8deadSopenharmony_ci QueryCounter with a non-generated <id> in 6045bd8deadSopenharmony_ci the core profile (Khronos internal bug 7662). 6055bd8deadSopenharmony_ci 6065bd8deadSopenharmony_ci 9 Dec 18, 2009 pdaniell Remove ambiguous language about "interuptions 6075bd8deadSopenharmony_ci to the GL". Rename CURRENT_TIME to TIMESTAMP. 6085bd8deadSopenharmony_ci 6095bd8deadSopenharmony_ci 8 Dec 10, 2009 Jon Leech Improve description of QueryCounter command. 6105bd8deadSopenharmony_ci 6115bd8deadSopenharmony_ci 7 Dec 10, 2009 Jon Leech Replace non-ASCII punctuation. 6125bd8deadSopenharmony_ci 6135bd8deadSopenharmony_ci 6 Dec 07, 2009 pdaniell Remove ARB suffix from new tokens for core. 6145bd8deadSopenharmony_ci 6155bd8deadSopenharmony_ci 5 Oct 29, 2009 pdaniell TIMESTAMP_ARB renamed to CURRENT_TIME_ARB. 6165bd8deadSopenharmony_ci Issue (11) raised about using different 6175bd8deadSopenharmony_ci clocks to implement CURRENT_TIME and 6185bd8deadSopenharmony_ci TIME_ELAPSED queries. Add example (3) for 6195bd8deadSopenharmony_ci calculating the GL latency. 6205bd8deadSopenharmony_ci 6215bd8deadSopenharmony_ci 4 Oct 23, 2009 pdaniell Add support for TIMESTAMP_ARB as a <value> 6225bd8deadSopenharmony_ci to Get* to allow synchronous time query. 6235bd8deadSopenharmony_ci 6245bd8deadSopenharmony_ci 3 Oct 15, 2009 pdaniell Resolved Issue (10). Added Interactions 6255bd8deadSopenharmony_ci with NV_present_video and NV_video_capture 6265bd8deadSopenharmony_ci section. 6275bd8deadSopenharmony_ci 6285bd8deadSopenharmony_ci 2 Oct 15, 2009 pdaniell Clarified some of the old EXT_timer_query 6295bd8deadSopenharmony_ci Issues wrt OpenGL 3.2. Added specification 6305bd8deadSopenharmony_ci for the TIMESTAMP_ARB time. Added new Issue 6315bd8deadSopenharmony_ci for tile-based implementations. Issue 3 6325bd8deadSopenharmony_ci resolution added to the spec. 6335bd8deadSopenharmony_ci 6345bd8deadSopenharmony_ci 1 Oct 13, 2009 pdaniell Initial revision based on EXT_timer_query 635