【问题标题】:Shared variables in Fragment shaders in Metal or OpenGLESMetal 或 OpenGLES 中片段着色器中的共享变量
【发布时间】:2018-02-17 18:54:07
【问题描述】:

这可能不太可能,但是是否存在共享全局变量的概念,可以在 Metal 和 OpenGLES 中的片段着色器的每次传递中更新?我想在处理每个像素后更新一些统计信息。我假设每个片段着色器并行运行时会出现很多并发问题。

【问题讨论】:

    标签: ios opengl-es fragment-shader metal metal-performance-shaders


    【解决方案1】:

    类似于 atomic_uint 的东西?我最近需要做类似的事情,这就是我使用的。在这里查看我的问题的答案:How to implement/use atomic counter in Metal fragment shader?

    【讨论】:

    • 这听起来很有趣,但可能有点矫枉过正。我想要的只是计算图像的直方图。为此,我可以检查片段着色器中的像素值,然后更新像素强度所在的 256 个计数器之一。我唯一担心的是当片段着色器并行计算时累加器如何更新?
    【解决方案2】:

    老实说,片段着色器的原子性能可能很糟糕,因为如果您采用每个输入纹素 1 个片段的幼稚方法,着色器将非常短,因此您将从多个着色器核心获得大量并行读取和写入.

    通常的实现是将直方图编码为帧缓冲区。

    从顶点着色器中的纹理读取,并在与“直方图”坐标匹配的位置放置一个点。

    可以使用混合操作来累积直方图。

    使用 glReadPixels 将直方图读回 CPU。

    【讨论】:

    • 我知道 glBlend 操作来累积直方图累加器。我的问题是这种混合如何在没有原子性的情况下并行发生?你有这么多的片段着色器并行写入,它会将所有写入序列化到帧缓冲区吗?
    • 使用混合方法的另一个问题是,由于所有颜色深度都是 256,您如何增加超过 256?
    • 你可以例如使用 map-reduce 类型算法对帧缓冲区进行条带化并执行多个并行直方图,这些直方图在第二遍中合并。
    • 平铺输入,这样每个平铺最多有 1024 个纹理像素(这样你就可以饱和 10 位直方图),分配一个输出帧缓冲区,这样你就有 256 列和 num_tiles 行。根据图块索引(行)和亮度(列)将点分配给片段位置。第二遍从中间帧缓冲区中读取数据并将 num_tiles 行合并到真正的 UI32 帧缓冲区中。
    • 只有两个。一个有效地创建一个直方图列表,每个 1024 texel tile 一个。将这个直方图列表合并为一个直方图。
    猜你喜欢
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多