OpenGL的原子内存操作

        上一章提到,OpenGL的着色器存储块除了读写功能外,还有支持关于内存的一些原子操作。OpenGL的原子操作用于解决不同着色器的调用操作同一块内存导致获取到的数据或者流程并不是按照着色器调用本身的意愿去执行的问题。比如一个着色器A的调用想对显卡上的一块内存上的值+1再写回到内存上,但是由于另一个着色器B在着色器A获取数据后也去同一块内存中获取数据,然后+1写回内存,这就有个问题,两次调用执行,同一块内存中的结果却只有一次调用的效果,这可能违背了这个程序原本的意愿。因此OpenGL提供了一些类似于读-修改-写的内存操作。主要有:

        1、atomicAdd(内存索引,要与内存索引指向的内存上的值进行相加的值)

        2、atomicAnd(内存索引,要与内存索引指向的内存上的值进行与操作的值)

        3、atomicOr(内存索引,要与内存索引指向的内存上的值进行或操作的值)

        4、atomicXor(内存索引,要与内存索引指向的内存上的值进行异或操作的值)

        5、atomicMin(内存索引,要与内存索引指向的内存上的值比较大小的值,将较小的值写回内存上)

        6、atomicMax(内存索引,要与内存索引指向的内存上的值比较大小的值,将较大的值写回内存上)

        7、atomicExchange(内存索引,要写入内存的值)

        8、atomicCompSwap(内存索引,要与内存索引指向的内存上的值比较的值,如果比较值和内存上的值相等,要写入内存的值)

        以上的原子操作接口返回值都是事先在内存中读取到的原始值。并且这些原子操作只支持整型数据,而不支持浮点型数据,以及非32位的整型数据、向量矩阵等其他类型的数据。还需要注意的是,多个原子操作的执行顺序也会影响程序的执行结果。

        因此在不同系统下的不同的执行顺序或多线程、或者着色器和应用程序读写操作之间的竞争还会导致以下的三种hazard:

        1、读-后-写hazard:一个读数据的程序(比如C++程序)想要读取如着色器运算后写入内存的结果,但是由于系统架构的不同,有些系统下是读先执行,导致读程序读取到的是数据还是与意愿相违背。

        2、写后写hazard:一个程序连续调用两次写操作,将不同的值写入同一个内存,意愿是想写入到内存的数据是最后一次写入的数据。而还是由于系统架构的问题,尽管写操作都是原子操作,但是有些系统会先调用最后一次写操作,而第一次写操作反而在最后执行,导致执行到最后内存中的值是第一次写入的值。

        3、写后读hazard:比如有两个线程,一个写线程,一个读线程,读线程想在写线程写入数据前将数据读取出来,但是有可能是写线程先执行,导致读线程最后读取到的是写线程写入的值,仍然与程序的意愿相违背。

        OpenGL有处理这三种hazard的主要手段--内存栅栏(barrier)。所谓的内存栅栏就是在着色器中的某行(例如第10行)调用内存栅栏的相关接口,此时就是告诉OpenGL前10行的调用都必须先于第10行后的调用执行。这其实就是一种同步手段。让一部分调用在某个地方等其他部分调用执行完毕先。OpenGL的内存栅栏设置有两种方式:

        1、在应用程序种调用插入栅栏的接口:

void glMemoryBarrier(GLbitfield barriers);

        barrier参数主要是指明要在OpenGL的哪些内存子系统中设置栅栏,OpenGL中有很多种内存子系统,以下只是展示了部分barriers参数的例子:

        1)GL_SHADER_STORAGE_BARRIER_BIT:在内存栅栏接口运行前的着色器访问着色器存储缓存都必须先运行于栅栏接口后的着色器访问着色器存储缓存的操作。

        2)GL_UNIFORM_BARRIER_BIT:这个的意思是告知OpenGL,在栅栏之后可能会有某个内存要被当作uniform缓存来使用,而在栅栏之前对于这个内存的写操作都要在运行到栅栏接口时就要完成写入数据的动作。

        3)GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT:如果要将缓存作为顶点数据的数据源时,栅栏会让执行流等到数据写入该缓存完毕。

        2、在着色器中设置栅栏

        着色器中调用的基本栅栏内置函数是:

void memoryBarrier();

        在着色器的某处,比如还是着色器主函数的第10行调用了这个内置函数,此时第十行前的读写操作会在这个函数执行完毕前执行完毕。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值