郑州网站建设最低价,设计理论网站,thinkphp 做门户网站,wordpress feed地址查询对象和异步查询(Query Objects and Asynchronous Queries)
Query Objects#xff08;查询对象#xff09;是OpenGL中的一种机制#xff0c;用于获取有关一系列GL命令处理过程的信息。这些信息可以包括#xff1a;
绘图命令处理的图元数量。写入变换反馈缓冲区的图元数…查询对象和异步查询(Query Objects and Asynchronous Queries)
Query Objects查询对象是OpenGL中的一种机制用于获取有关一系列GL命令处理过程的信息。这些信息可以包括
绘图命令处理的图元数量。写入变换反馈缓冲区的图元数量。在片段处理期间通过深度测试的样本数量。处理命令所需的时间量。
通过使用查询对象OpenGL应用程序可以动态地获取有关图形渲染过程的各种性能指标和统计信息。这些信息对于性能优化、调试和分析应用程序的渲染流程非常有用。
使用查询对象的一般步骤如下
创建查询对象通过调用OpenGL的API函数可以创建一个查询对象并指定要查询的信息类型。开始查询在需要获取信息的地方通过调用OpenGL的API函数开始一个查询操作。执行一系列GL命令在开始查询和结束查询之间执行一系列的GL命令这些命令可以是绘图命令、变换反馈命令、深度测试命令等。结束查询在执行完一系列GL命令后通过调用OpenGL的API函数结束查询操作。获取查询结果通过调用OpenGL的API函数可以获取查询对象的结果这些结果包含了在查询期间收集的有关图形处理过程的信息比如处理的图元数量、通过的样本数量等。
使用查询对象可以帮助开发人员更好地了解和优化他们的OpenGL应用程序的性能特征从而提高图形渲染的效率和质量。
查询类型
OpenGL 支持的查询类型包括 图元生成查询目标为 PRIMITIVES_GENERATED用于返回通过 OpenGL 处理的图元数量。同时激活的此类查询最多可达 MAX_VERTEX_STREAMS 个。 变换反馈写入的图元查询目标为 TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN用于统计被写入一个或多个缓冲对象中的图元数量。同时激活的此类查询同样不得超过 MAX_VERTEX_STREAMS 个。 变换反馈溢出查询目标为 TRANSFORM_FEEDBACK_OVERFLOW 或 TRANSFORM_FEEDBACK_STREAM_OVERFLOW用于报告一个或多个流是否存在变换反馈溢出情况。 遮挡查询目标为 SAMPLES_PASSED、ANY_SAMPLES_PASSED 或 ANY_SAMPLES_PASSED_CONSERVATIVE用于计数通过深度测试的片段或样本数量或者设置布尔值以表示是否至少有一个片段或样本通过了深度测试。同时只能激活一个此类查询。 时间流逝查询目标为 TIME_ELAPSED记录完成一系列命令所需的完整时间。同时只能激活一个此类查询。 时间戳查询目标为 TIMESTAMP记录当前 OpenGL 的时间。同时只能激活一个此类查询。 提交查询目标为 VERTICES_SUBMITTED 和 PRIMITIVES_SUBMITTED 分别返回传输到 OpenGL 的顶点数量和图元数量信息。 顶点着色器查询目标为 VERTEX_SHADER_INVOCATIONS返回顶点着色器被调用的次数。 曲面细分着色器查询目标为 TESS_CONTROL_SHADER_PATCHES 和 TESS_EVALUATION_SHADER_INVOCATIONS分别返回曲面细分控制着色器处理的补丁数量和曲面细分评估着色器被调用的次数。 几何着色器查询目标为 GEOMETRY_SHADER_INVOCATIONS 和 GEOMETRY_SHADER_PRIMITIVES_EMITTED分别返回几何着色器被调用的次数以及它发射的图元数量。 图元裁剪查询目标为 CLIPPING_INPUT_PRIMITIVES 和 CLIPPING_OUTPUT_PRIMITIVES分别返回在图元裁剪阶段处理的图元数量和由图元裁剪阶段输出并进一步被光栅化阶段处理的图元数量。 片段着色器查询目标为 FRAGMENT_SHADER_INVOCATIONS返回片段着色器被调用的次数。 计算着色器查询目标为 COMPUTE_SHADER_INVOCATIONS返回计算着色器被调用的次数。
查询对象创建和激活
异步查询的结果不会在集合中的最后一个命令完成后立即由GL返回在查询结果完全就绪之前可以处理后续命令。一旦可用查询结果将存储在相关联的查询对象中。第4.2.3节描述的命令提供了确定查询结果何时可用并返回查询的实际结果的机制。查询对象的名称空间是无符号整数其中零被GL保留。
void glGenQueries( sizei n, uint *ids )
命令在ids中返回n个先前未使用的查询对象名称。这些名称被标记为已使用仅用于GenQueries但在它们首次被BeginQuery、BeginQueryIndexed或QueryCounter使用之前它们不与任何对象关联。void glCreateQueries( enum target, sizei n, uint *ids )
glCreateQueries在ids中返回n个先前未使用的查询对象名称每个名称表示具有指定目标的新查询对象。目标必须是 **查询类型** 中描述的查询对象目标之一。生成的查询对象的初始状态是结果已标记为可用查询对象的QUERY_RESULT_AVAILABLE的值为TRUE并且结果值QUERY_RESULT的值为零。void glDeleteQueries( sizei n, const uint *ids )
ids包含要删除的n个查询对象的名称。删除查询对象后其名称再次变为未使用。如果删除了活动查询对象则其名称立即变为未使用但底层对象直到不再处于活动状态参见第5.1节才会被删除。对于GenQueries目的而标记为已使用的ids中的未使用名称将再次标记为未使用。未使用的ids中的名称将被静默忽略零值也将被静默忽略。在OpenGL中除TIMESTAMP类型的计时器查询外对于支持的每种查询类型针对每个可能激活的查询都有一个对应的活动查询对象名称。如果这个活动查询对象名称非零则表示OpenGL当前正在追踪相关的信息并且查询结果会被记录到该查询对象内。
反之如果活动查询对象名称为零则意味着未追踪此类信息。
创建并激活查询对象可以使用以下命令
void glBeginQueryIndexed( enum target, uint index, uint id )
target 参数指定了要执行的查询类型后续章节将详细介绍其有效值。如果id是一个未使用的查询对象名称则该名称会被标记为已使用并与指定目标类型的新的查询对象关联起来。否则id必须是现有且同类型查询对象的名称。请注意通过ANY_SAMPLES_PASSED或ANY_SAMPLES_PASSED_CONSERVATIVE两种目标指定的遮挡查询对象在未来的查询中可以重用于这两种目标中的任何一种。而由SAMPLES_PASSED目标指定的对象只能重用于该目标。index 参数是查询的索引其值必须在0和目标特定的最大值之间。无论id是否为新创建的查询对象其状态都将被设置为结果不可用查询对象的QUERY_RESULT_AVAILABLE值为FALSE并且结果值QUERY_RESULT初始化为零。对于给定的target和index其对应的活动查询对象名称会被设置为id。
void glBeginQuery( enum target, uint id )
等价于 glBeginQueryIndexed(target, 0, id);
void glEndQueryIndexed( enum target, uint index ) 标记了由target和index指定的活动查询要跟踪的命令序列的结束。target和index的含义与BeginQueryIndexed中相同。 相应的活动查询对象被更新以指示查询结果不可用并且target和index的活动查询对象名称被重置为零。当在EndQueryIndexed调用时发出的命令完成并且最终查询结果可用时被调用时活动的查询对象被更新以包含查询结果并指示查询结果可用。
void glEndQuery( enum target )
等价于 glEndQueryIndexed(target, 0); 查询对象包含两部分状态信息
一个单比特位用于指示查询结果是否可用。一个整数用于存储查询结果的值。这个表示查询结果所使用的比特位数量n是实现依赖的并且可以按照4.2.3节中描述的方式确定。
查询对象的初始状态取决于它是通过CreateQueries还是BeginQueryIndexed创建的如上所述。如果查询结果发生溢出即超过2^n - 1的值其值将变为未定义。尽管不是必需的但建议实现能够通过在达到2^n - 1时饱和并停止增加的方式来处理这种溢出情况。对于每个可能的活动查询目标和索引都需要维护的状态包括一个无符号整数用于保存活动查询对象名称如果没有活动查询对象则为零以及任何保持正在进行的异步查询当前结果所需的状态。同一时间内只允许一种遮挡查询类型处于活动状态因此遮挡查询所需的必要状态会被共享。boolean glIsQuery( uint id )
用于检查给定的IDid是否为一个查询对象的名称。
void glGetQueryIndexediv( enum target, uint index, enum pname, int *params )
查询有关活动查询对象的信息 target 和 index 指定了要查询的活动查询其含义与 BeginQueryIndexed 中相同。 如果 pname 设置为 CURRENT_QUERY则当前为 target 和 index 指定的活动查询对象名称如果有活动查询的话将被放置在 params 指向的内存中。若目标为 TIMESTAMP则始终返回0。 若 pname 设为 QUERY_COUNTER_BITS则忽略 index 参数并将在 params 中放置目标查询类型的实现依赖的查询结果所使用的比特位数。查询计数器的比特位数量可能为0这意味着计数器不包含有用信息。
对于不同类型的查询对象如果对应的比特位数非零则它们至少应具备以下最低位数要求
基本图元查询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位确保至少能测量一秒的时间。管道统计查询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); 查询对象的状态可以通过以下命令进行查询
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* 函数buffer 是缓冲区对象的名称而 offset 是缓冲区内写入查询值的偏移量。对于 GetQueryObject* 函数查询值可以被返回到客户端内存中也可以写入到缓冲区对象中。如果当前绑定到查询结果缓冲区绑定点见第6.1节中的 QUERY_RESULT的是零则 params 被视为指向客户端内存的一个指针在该位置写入查询值否则params 将被视为查询结果缓冲对象内的一个偏移量。
对于查询对象的结果值可能需要一定时间才能变得可用。如果 pname 设置为 QUERY_RESULT_AVAILABLE则在需要等待时函数将返回 FALSE否则返回 TRUE。必须保证若任何查询对象返回的结果可用性为 TRUE那么在此之前所有相同类型的所有查询也必须返回 TRUE。对任一查询对象反复查询 QUERY_RESULT_AVAILABLE 保证最终会返回 TRUE。
若 pname 为 QUERY_TARGET则返回查询对象的目标类型作为一个整数值。若 pname 为 QUERY_RESULT则返回查询对象的结果值作为单个整数。如果结果值的大小过大以至于无法用请求的类型表示则返回最接近的可表示值。如果目标类型的查询计数器位数为零则结果将以整数值0的形式返回。查询 QUERY_RESULT 会使给定查询对象在有限时间内完成其计算过程。若 pname 为 QUERY_RESULT_NO_WAIT则仅当结果在执行状态查询时已可用时才以单个整数形式返回查询对象的结果值。若结果不可用则不写入查询返回值。
如果在调用上述查询命令之前使用同一对象名称发起了多个查询操作则返回的结果和可用性信息始终来自最后发起的那个查询。在开始针对同一目标和ID的新查询之前如果不先检索先前查询的结果这些结果将会丢失。
时间查询(Time Queries)
查询对象还可用于追踪完成一组OpenGL命令所需的时间时间流逝查询或确定当前的OpenGL时间计时器查询。
当使用目标 TIME_ELAPSED 调用 BeginQuery 和 EndQuery 时OpenGL将准备启动和停止用于时间流逝查询的计时器。计时器会在所有先前命令对OpenGL客户端、服务器状态以及帧缓冲区的影响完全实现后开始或停止。BeginQuery 和 EndQuery 命令可能在计时器实际开始或停止之前返回。
当时间流逝查询的计时器最终停止时流逝的时间以纳秒为单位会被写入到相应的查询对象作为查询结果值并标记该对象的查询结果为可用。
可以通过以下命令创建计时器查询对象
void QueryCounter( uint id, enum target );其中 target 必须是 TIMESTAMP。如果 id 是未使用的查询对象名称则该名称会被标记为已使用并与新的类型为 TIMESTAMP 的查询对象关联。否则id 必须是现有同类型查询对象的名称。
另外也可以通过调用 CreateQueries 并将 target 设置为 TIMESTAMP 来创建 TIMESTAMP 类型的查询对象。
当调用 QueryCounter 时OpenGL会记录下当前时间并将其存入对应的查询对象中。这个时间是在所有先前命令对OpenGL客户端、服务器状态及帧缓冲区的影响完全实现之后记录的。一旦时间被记录该对象的查询结果就会被标记为可用。计时器查询可以在目标为 TIME_ELAPSED 的 BeginQuery / EndQuery 块内部使用且不会影响该查询对象的结果。
通过调用 GetIntegerv 或 GetInteger64v 并传入符号常量 TIMESTAMP可以查询当前的OpenGL时间。这将返回所有先前命令到达OpenGL服务器但不一定执行完毕后的GL时间。通过结合这种同步获取命令和异步时间戳查询对象目标应用程序可以测量命令从到达OpenGL服务器到在帧缓冲区实现之间的延迟。