GLSL,信号量?

Mat*_*Mat 11 opengl concurrency glsl

我之前已经遇到过这样的问题:我希望通过执行以下操作来混合图像单元中的颜色值:

vec4 texelCol = imageLoad(myImage, myTexel);
imageStore(myImage, myTexel, texelCol+newCol);
Run Code Online (Sandbox Code Playgroud)

在多个片段可以具有"myTexel"相同值的情况下,这显然是不可能的,因为无法在imageLoad和imageStore命令之间创建原子性,而其他shaderinvocations可能会更改其间的纹素颜色.

现在有人告诉我,人们通过使用uint纹理上的原子命令创建信号量来解决这个问题,这样着色器会在访问texel之前以某种方式在while循环中等待,并且只要它是空闲的,就会原子地将它写成整数用于阻止其他片段着色器调用的纹理,处理颜色纹理元素,并在完成时以原子方式再次释放整数纹素.

但我无法理解这是如何真正起作用的,以及这些代码会是什么样子?

真的可以这样做吗?可以将GLSL片段着色器设置为在while循环中等待吗?如果有可能,有人可以举个例子吗?

Nic*_*las 9

是的,你可以这样做,但只要与事物混合的顺序无关紧要.否则你需要使用通常的技术.

基本上你只是实现了一个自旋锁.只有一个锁变量而不是一个锁变量.

首先需要一个与用于原子操作的其他图像大小相同的图像.它需要是一个整数纹理__CODE__,并且要匹配的__CODE__格式__CODE__.它应该用0来初始化.原子图像和"混合"图像都必须声明为"连贯".

  1. __CODE__在原子整数图像上的位置执行操作.您将它与0进行比较,并且您将其设置为1的值.

  2. 如果#1返回1,则表示其他人拥有锁.回到第1步.

  3. 如果#1返回0,那么您现在可以独占访问texel(因为texel现在有1个,这要归功于比较/交换操作).继续.

  4. 执行混合操作.__CODE__在混合操作后发出一个.

  5. 执行一个__CODE__值为0.这将解锁螺旋锁.

这是有效的原因是由于原子.GLSL确保原子是原子的.__CODE__执行读/条件修改/写操作作为原子序列.并且因为它是原子的,所以其他着色器调用不可能抢占或中断操作.这意味着着色器运行的线程数无关紧要:如果其中100个调用__CODE__,其中只有一个将获得1作为返回值,其余将获得0(当然,对于相同的纹素) .

所以只有一个线程会获得锁定; 其余的必须等待.

使用该__CODE__函数将确保等待的其他线程在读取时将获取修改后的数据.同样,您需要使用__CODE__限定符来处理您正在执行此操作的图像.

  • @Mat:图像的纹素是否比屏幕的像素多?提前了解这些事情会有所帮助. (2认同)
  • 这是一个古老的话题,但是你不担心这种做法会导致死锁吗?* (2认同)