如何执行异步离屏查询?

Posted

技术标签:

【中文标题】如何执行异步离屏查询?【英文标题】:How to perform asynchronous off-screen queries? 【发布时间】:2014-01-13 18:12:30 【问题描述】:

我想渲染几个(可能数千个)场景,以便对所绘制的内容执行查询。我遇到的问题是对glGetQueryObjectiv() 的调用很昂贵,所以我想在等待查询结果可用时提前渲染几个场景。

我已经阅读了一些关于帧缓冲区对象和像素缓冲区对象的内容,但主要是在使用glReadPixels() 保存到文件的上下文中,并且我无法找到在异步中使用这些对象中的任何一个的示例查询。执行glGetQueryObjectiv() 的设置是否与this example 中的glReadPixels() 不同(例如,我应该使用FBO 还是PBO)?

注意: 这不适用于图形应用程序。我感兴趣的是 GL_SAMPLES_PASSED 查询的结果(即绘制了多少像素?)。

具体应用是在其他表面投射阴影时估计有多少阳光照射到一个表面上。有兴趣的可以阅读here。

【问题讨论】:

另外,请记住GL_SAMPLES_PASSED 不是per-se 绘制的像素数。它是通过深度测试的样本数量(如果样本未能通过模板/alpha 测试或被片段着色器丢弃,它不会打折)。此外,1 个样本!= 1 个片段。如果您启用了多重采样,则该数字可能与您使用单次采样的情况不同,具体取决于覆盖范围(尽管确切的行为实际上是由实现定义的)。 【参考方案1】:

Framebuffer Objects(Pixel) Buffer Objects 都不是在(异步)查询中使用的合适的对象类别; GL 有一个完全独立的对象类,称为Query Objects。您可以将某些查询的结果输入到缓冲区对象中,但这只是它们之间的关系。

基本上,异步查询的想法是将查询放入图形管道中,并在尝试读回之前等待一段时间。这使 GPU 有时间首先实际完成查询开始和结束之间的所有命令。另一种方法是同步查询,这意味着您的调用线程会停止执行任何有用的操作并等待 GPU 完成完成查询所需的一切。

实现不强制同步的查询的最简单方法是像往常一样开始和完成查询,但不是立即读取结果,而是在应用程序的主循环中定期检查 GL_QUERY_RESULT_AVAILABLE 的状态您的查询对象。当这为您提供GL_TRUE 时,这意味着您可以从查询对象中读取结果,而不会中断渲染管道。如果您在查询对象处于此状态之前尝试从查询对象获取结果,您将强制执行同步查询。

【讨论】:

为了利用异步查询,我需要做一些其他事情来让我的应用程序在等待结果可用时保持忙碌。我的想法是我可以排队几个渲染(可能进入帧缓冲区对象)并执行查询。当查询结果可用时,我可以排队额外的渲染以保持应用程序忙碌。你是说我不需要额外的缓冲区对象来创建这些渲染? @NealKruis:没错。您所需要的只是多个查询对象(一个用于您要在场景中查询的每个帧/场景)。我认为您需要将渲染可视化为有序流水线过程,这确实是为了充分理解为什么您不需要多个 FBO 来完成此操作。查询基本上封装了一系列命令,并在完成后返回有关结果的一些信息。

以上是关于如何执行异步离屏查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何使两个 SQL 查询真正异步

如何通过异步调用 uid 从 Firebase 查询数据

如何从 lambda 函数异步传递红移查询?

关于异步执行

ADO异步查询显示进度条

CompletableFuture以异步执行多个数据库查询