GLSL memoryBarrierShared()有用吗? [英] GLSL memoryBarrierShared() usefulness?

查看:249
本文介绍了GLSL memoryBarrierShared()有用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道memoryBarrierShared的用处.

I am wondering about the usefulness of memoryBarrierShared.

确实,当我在寻找障碍功能的文档时:我读过:

Indeed, when I am looking the documentation for barrier function : I read :

对于计算着色器中任何给定的静态屏障实例,单个工作组内的所有调用都必须先进入该屏障,然后再允许其继续进行.这样可以确保其他调用在调用同一静态屏障实例之后,可以安全地读取在给定的静态屏障实例之前由一个调用编写的值.由于调用可能会在这些障碍调用之间以不确定的顺序执行,因此在许多情况下,每个顶点或每个补丁输出变量或任何共享变量的值都是不确定的.

For any given static instance of barrier in a compute shader, all invocations within a single work group must enter it before any are allowed to continue beyond it. This ensures that values written by one invocation prior to a given static instance of barrier can be safely read by other invocations after their call to the same static instance of barrier. Because invocations may execute in undefined order between these barrier calls, the values of a per-vertex or per-patch output variable, or any shared variable will be undefined in a number of cases.

因此,如果我们可以在使用屏障后安全地读取值,为什么我们会在某些代码中看到

So, if we can safely read values after using barrier, why do we see in some code

memoryBarrierShared();
barrier();

或类似的错误

barrier();
memoryBarrierShared();

所以,我的问题是:如果使用barrier就足够了,memoryBarrier {Shared,...}的目的是什么?

So, my question is : What is the purpose of memoryBarrier{Shared,...} if using barrier is enough?

对于memoryBarrierBuffer/Image,我可以理解我们是否使用了多个阶段,但是对于共享,我不知道...

For memoryBarrierBuffer/Image I can understand if we use multiple stage, but for shared, I don't have any idea...

推荐答案

更新(2019-12-07):

以下GLSL 4.60的说明现在错误.修订版5之后, GLSL 4.60规范现在显示为:

The GLSL 4.60 clarification below is now wrong. After Revision 5, the GLSL 4.60 spec now reads:

私有GLSL问题#24:阐明barrier()本身足以将控制流和内存访问同步到共享变量和细分控制输出变量.对于其他内存访问,仍然需要附加的内存屏障.

Private GLSL issue #24: Clarify that barrier() by itself is enough to synchronize both control flow and memory accesses to shared variables and tessellation control output variables. For other memory accesses an additional memory barrier is still required.

GLSL ES 3.20也反映了这一点文档:

为了实现对共享变量的读取和写入的排序,必须使用barrier()函数(请参见着色器调用控制功能")使用控制流屏障.

In order to achieve ordering with respect to reads and writes to shared variables, control flow barriers must be employed using the barrier() function (see "Shader Invocation Control Functions").

他们还进一步解释了

A barrier()影响控制流,但仅同步对共享变量和细分控制输出变量的内存访问. 对于其他内存访问,它不能确保在调用barrier()的相同静态实例之后,其他调用可以安全地读取在给定的barrier()静态实例之前由一个调用编写的值.要实现这一点,需要同时使用barrier()和内存屏障.

A barrier() affects control flow but only synchronizes memory accesses to shared variables and tessellation control output variables. For other memory accesses, it does not ensure that values written by one invocation prior to a given static instance of barrier() can be safely read by other invocations after their call to the same static instance of barrier(). To achieve this requires the use of both barrier() and a memory barrier.

TL; DR :如果仅对共享变量使用障碍,则barrier()就足够了.如果将它们用于其他内存访问",则barrier()是不够的.

TL;DR: If you are only using barriers for shared variables, barrier() is sufficient. If you are using them for "other memory accesses", then barrier() is not sufficient.

GLSL 4.60对此进行了澄清:

GLSL 4.60 clarifies this:

为了实现对共享变量的读取和写入的排序,必须使用barrier()memoryBarrier()函数(参见着色器调用控制函数")结合使用控制流和内存屏障. /p>

In order to achieve ordering with respect to reads and writes to shared variables, a combination of control flow and memory barriers must be employed using the barrier() and memoryBarrier() functions (see "Shader Invocation Control Functions").

最好总是像对待桌面GLSL那样对待桌面GLSL.即使以下是GLSL 4.50中所述的方式.

It's probably best to treat desktop GLSL as though it always said this. Even though the following is how it was stated in GLSL 4.50.

GLSL 4.50非常清楚地表明不需要显式的内存屏障.计算着色器中的barrier包括所有内存屏障.

GLSL 4.50 makes it abundantly clear that explicit memory barriers are unnecessary. That barrier in a compute shader includes all memory barriers.

但是,GLSL ES 3.20同样清楚地表明barrier 包括任何种类的内存障碍:

However, GLSL ES 3.20 makes it equally abundantly clear that barrier does not include memory barriers of any kind:

对于计算着色器,屏障只会影响控制流,而本身不会同步内存访问.特别是,它不能确保在调用barrier()的相同静态实例后,其他调用可以安全地读取在barrier()的给定静态实例之前由一个调用编写的值.要实现这一点,需要同时使用 barrier()和内存屏障.

For compute shaders, a barrier only affects control flow and does not by itself synchronize memory accesses. In particular, it does not ensure that values written by one invocation prior to a given static instance of barrier() can be safely read by other invocations after their call to the same static instance of barrier(). To achieve this requires the use of both barrier() and a memory barrier.

值得注意的是,离线glslang编译器将始终使用GLSL ES措辞.因此,如果您要生成SPIR-V以馈入Vulkan,则必须在此处遵循ES的规则.好吧,直到他们以一种或另一种方式解决该问题.

Notably the offline glslang compiler will always use the GLSL ES wording. So if you're generating SPIR-V to feed into Vulkan, you have to follow ES's rules here. Well, until they get that fixed, one way or another.

话虽这么说,ES的措辞更有意义,因为一切的完整存储障碍非常昂贵.尤其是如果您要做的只是同步访问共享变量.

That being said, ES's wording makes a lot more sense, as a full memory barrier for everything is quite expensive. Especially if all you want to do is synchronize access to shared variables.

我建议在barrier调用旁边使用内存屏障.这样,即使在某些实现中可能稍微慢一些,您的着色器也将是正确的.但是,如果要同时使用内存屏障和barrier调用,则必须首先出现内存屏障 .同步执行后执行内存屏障不正确.

I would suggest using the memory barrier alongside the barrier call. That way, your shader will be correct, even if it may be slightly slower on some implementations. However, if you are going to use memory barriers along with barrier calls, then the memory barrier must come first. Executing the memory barrier after synchronizing execution is not correct.

这篇关于GLSL memoryBarrierShared()有用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆