当前位置:  开发笔记 > IOS > 正文

为什么在Metal中不允许的片段着色器中写入缓冲区?

如何解决《为什么在Metal中不允许的片段着色器中写入缓冲区?》经验,为你挑选了1个好方法。

如" 金属着色语言指南"中所述:

片段函数不允许写入缓冲区或纹理.

我明白这是事实,但我很好奇为什么.能够从片段着色器中写入缓冲区是非常有用的 ; 我知道在硬件端可能更复杂的是不提前知道特定线程的内存写入的结束位置,这对于原始缓冲区写入并不总是知道,但这是在Metal计算中公开的一种能力着色器,为什么不在片段着色器中呢?

附录

我应该澄清为什么我认为来自片段函数的缓冲区写入是有用的.在光栅化管道的最常见用例中,三角形被栅格化和着色(根据片段着色器)并写入预定义的存储器位置,每个片段着色器调用之前已知,并由来自规范化设备坐标和帧的预定义映射确定缓冲.这适用于大多数使用情况,因为大多数情况下您只想将三角形​​直接渲染到缓冲区或屏幕.

在其他情况下,您可能希望在片段着色器中进行延迟写入,其末端位置基于片段属性而不是片段的确切位置; 有效地,光栅化与副作用.例如,大多数基于GPU的体素化通过从一些期望的角度渲染具有正交投影的场景,然后写入3D纹理,将片段的XY坐标及其相关联的深度值映射到3D纹理中的位置来工作.这在这里描述.

其他用途包括某些形式的与订单无关的透明度(透明度,其中绘制顺序不重要,允许重叠透明对象).一种解决方案是使用多层帧缓冲区,然后在单独的传递中基于它们的深度值对片段进行排序和混合.由于没有硬件支持这样做(在大多数GPU上,我相信英特尔有硬件加速),你必须维护每个像素的原子计数器和手动纹理/缓冲区写入,以协调写入分层帧缓冲区.

另一个例子可能是通过光栅化提取GI的虚拟点光源(即在光栅化时为相关片段写出点光源).在所有这些用例中,都需要来自片段着色器的缓冲区写入,因为ROP仅为每个像素存储一个结果片段.在没有这个特征的情况下获得相同结果的唯一方法是通过某种深度剥离方式,这对于高深度复杂度的场景来说非常慢.

现在我意识到我给出的例子并不是特别关于缓冲区写入,而是更广泛地关于从片段着色器进行动态内存写入的想法,理想情况下是对原子性的支持.缓冲区写入似乎只是一个简单的问题,它们的包含将大大改善这种情况.

由于我在这里没有得到任何答案,我最终在Apple的开发者论坛上发布了这个问题.我在那里得到了更多的反馈,但仍然没有真正的答案.除非我遗漏了某些内容,否则几乎所有官方支持Metal的OS X设备都支持此功能.据我所知,这个功能最初在2009年左右开始出现在GPU中.这是当前DirectX和OpenGL(甚至不考虑DX12或Vulkan)的常见功能,因此Metal将是唯一缺乏它的"尖端"API .

我意识到PowerVR硬件可能不支持此功能,但Apple没有通过功能集区分金属着色语言的问题.例如,iOS上的Metal允许片段着色器内的"自由"帧缓冲器提取,这由高速缓存的PowerVR架构直接支持在硬件中.此功能直接在Metal Shading Language中显示,因为它允许您使用[[color(m)]]iOS着色器的属性限定符声明片段函数输入.可以说,允许使用device存储空间限定符声明缓冲区,或者使用纹理access::write作为片段着色器的输入,对语言的语义更改不会比Apple为优化iOS所做的更多.因此,就我而言,PowerVR缺乏支持并不能解释我在OS X上缺少的功能.



1> codingminion..:

现在支持从片段着色器写入缓冲区,如iOS 10,tvOS 10和macOS 10.12中的新增功能所述

函数缓冲区读写可用于:iOS_GPUFamily3_v2,OSX_GPUFamily1_v2

片段函数现在可以写入缓冲区.必须在设备地址空间中声明可写缓冲区,且不能为const.使用动态索引写入缓冲区.

此外,在Metal Shading Language Specification 2.0中没有指定限制的行(来自原始问题)

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有