使用多个渲染目标的成本

 liuningning666223 发布于 2023-01-17 11:47

我使用glsl作为GPGPU的框架进行实时图像处理.我目前正在尝试"刮掉"几毫秒来使我的应用程序实时.这是基本设置:

我拍摄输入图像,计算它的几个变换,然后输出结果图像.例如,让输入图像为I.然后,一个片段着色器计算f(I);第二个计算g(I);,最后一个计算h(f(I),g(I)).

我的问题是关于有效计算f(I),g(I):如果我使用2个单独的片段着色器(因此2个渲染通道),或者如果我使用具有2个输出的单个片段着色器,这是否重要?后者会跑得更快吗?我大多发现了关于"如何做"的讨论; 不是表现.

编辑

感谢到目前为止的回复.下面是几个评论,以下是我的用例示例,其中包含更多详细信息:

我希望I用1-d滤镜过滤图像行; 并且还过滤平方图像的行(每个像素的平方). f(I) = filter rows并且g(I) = square and filter rows:

shader1: (input image) I --> filter rows --> I_rows (output image)

shader2: (input image) I --> square pixels and filter rows--> I^2_rows (output image)

问题是:编写一个着色器,执行两个操作比一个接一个地运行这两个着色器要快吗?@derhass建议答案是肯定的,因为访问相同的纹理位置和享受地点.但如果它不适合纹理局部:我还能享受性能提升吗?或者是一个着色器渲染到两个输出基本上相当于两个渲染过程?

1 个回答
  • 使用多次渲染过程通常比使用MRT输出的一次过程要慢,但这也取决于您的情况.

    据我了解,双方f(I)g(I)采样输入图像I,并且如果每个样本相同(或紧密相邻的)loactions,可以极大地从纹理缓存利润之间的不同的操作-你可以只接一次采样输入质地,而不是使用多通道方法两次.

    采取这种方法更进一步:您是否甚至需要中间结果f(I)g(I)单独进行?也许你可以h(f(I),g(I))直接放在一个着色器上,所以你既不需要多次传递也不需要MRT.如果您希望能够动态地组合您的操作,您仍然可以使用该apporach并以编程方式动态组合不同的着色器代码部分以实现操作(如果可能),并且仅在绝对必要时使用多个传递.

    编辑

    由于问题在此期间已经更新,我想我可以提供一些更具体的答案:

    到目前为止我所说的,特别是关于将h(f(I),g(f(I))放入一个着色器中只是一个好主意,如果h(或f和g)不需要任何相邻像素.如果h是a nxn过滤器内核,你必须访问nxn不同的输入纹理元素,并且由于这些输入不是直接知道的,你必须为它们中的每一个计算f和g.如果f和h都是滤波器内核,则有效的过滤器大小为复合操作会更大,最好先计算中间结果并使用多次通过.

    看看你描述的具体问题,可以归结为这个问题.

    如果以最天真的方式使用两个单独的着色器,则渲染将如下所示.

      使用shader1

      选择一些输出颜色缓冲区

      绘制四边形

      使用shader2

      选择一些不同的颜色缓冲区

      绘制四边形

    每个绘制调用都有其开销.GL将不得不做一些额外的验证.与组合着色器方法相比,切换着色器可能是此处最昂贵的额外步骤,因为它可能会强制GPU管道刷新.Als,对于每个绘制调用,您都有顶点处理,栅格化和每个片段属性的相互关联操作.只有一个着色器,这个开销很多就会消失,到目前为止所描述的每个片段计算可以为两个过滤器"共享".

    但如果它不适合纹理局部:我还能享受性能提升吗?

    由于我到目前为止所说的内容,以及你提供的着色器的具体内容,我倾向于说:是的.但是如果我们忽略这里的纹理凹陷,效果将是非常小的可忽略的,特别是如果我们假设合理的高分辨率图像,使得相对于工作总量的相对开销很小.我至少会说使用单次通过MRT设置不会慢.但是,只有对特定GPU上的特定实现进行基准测试/分析才能给出明确的答案.

    为什么我说"你呈现的着色器".因为在这两种情况下,您都可以在一个着色器中进行图像平方.您可以将其拆分为两个不同的着色器和渲染通道.在这种情况下,您将获得额外的开销(已经提到过)用于编写中间结果,并且必须阅读它.但是,由于您在中间结果上运行过滤器,因此您不必多次对任何输入纹理元素进行平方,但在组合方法中,您可以执行此操作.如果平方操作足够昂贵,并且您的滤波器尺寸足够大,理论上可以节省比多次传递开销所引入的更多的时间.同样,只有基准测试/分析能够告诉你收支平衡的地方.

    虽然我感兴趣的图像处理操作与您的图像处理操作有点不同,但我已经在过去对MRT与多个渲染过程进行了一些基准测试.我发现在这种情况下,纹理访问是关键因素,您可以在纹理访问延迟中隐藏许多其他计算(如平方颜色值).我认为你的"但如果它不是纹理局部性"有点不切实际,因为它是对整体运行时间的主要贡献.而且它不仅仅是局部性,它也是纹理访问的总数:使用多重着色器方法,一个大小的尺寸w*h和大小的一维过滤器n,你将最终得到2*w*h*n整体的纹理访问,而与结合的方法,你将减少到*w*h*n,这将在过去产生巨大的差异.

    对于AMD FirePro V9800,图像尺寸为1920x1080,只是通过渲染纹理quds将像素复制到两个输出缓冲区,我得到了两次传递:~0,320ms(即使没有切换着色器)vs 1次传递MRT:~0,230ms.因此执行时间减少了"仅"30%,但这只是每个着色器调用一次texutre获取.使用过滤器内核,我希望看到这个数字随着内核大小的增加而减少50%(但我没有测量过).

    2023-01-17 11:50 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有