OpenGL 编程指南 (11)

1、计算着色器,一种能够灵活运用GPU高速运算处理非图形任务的着色器,它能够使用大部分着色器的功能当然要出去非常专一性的如EmitVertex这样的方法。

 

2、计算着色器的调用有全局工作组的概念,全局工作组又包含局部工作组(本地工作组),局部工作组包含执行单元

3、局部工作组的大小在shader中由输入布局限定符声明,下面是一个4X4大小的局部工作组声明

  #version 430 core

  layout (local_size_x = 4, local_size_y = 4) in;

  void main()

  {

    ......

  }

  它的创建、编译、链接与其它shader相同,在使用的时候除了调用glUseProgram外还需要调用下面这个方法

  void glDispatchCompute(GLuint num_group_x, GLuint num_group_y, GLuint num_group_z)//分别设置xyz维度上的工作组数量,值需要介于0与GL_MAX_COMPUTE_WORK_GROUP_SIZE之间,因此计算着色器中执行单元的总数是这个3维数组的大小乘以shader中定义的工作组大小

  void glDsipatchComputeIndirect(GLintptr indirect)//三个参数将会绑定到GL_DISPATCH_INDIRECT_BUFFER上

  glGenBuffers(1, dispatchbuffer);

  glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, dispatchbuffer);

  static const struct

  {

    GLuint num_group_x;

    GLuint num_group_y;

    GLuint num_group_z;

  } dispatchob = {4, 4, 1};

  glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(dispatchob), &dispatchob, GL_STATIC_DRAW);

  glDispatchComputeIndirect(0);

 

4、计算着色器的一大优势是它们能够互相通信,因此需要一些内建变量来支持这一特性

 1)gl_WorkGroupSize 局部工作组大小向量,这样工作组大小可以被随意访问而不依赖于预处理,也能够以多维形式表示工作组大小

 2)gl_NumWorkGroups 一个存储了glDispatchCompute参数的向量,能够提供全局工作组的大小

 3)gl_LocalInvocationID 执行单元在局部工作组中的位置,它的范围uvec3(0)~gl_WorkGroupSize-uvec3(1)

 4)gl_WorkGroupID 当前局部工作组在全局工作组中的位置,范围uvec3(0)~gl_NumWorkGroups-uvec3(1)

 5)gl_GlobalInvocationID 当前执行单元在全局工作组中的位置,gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID

 6)gl_LocalInvocationIndex 是gl_GlobalInvocationID的一种扁平化形式,是一维数据,gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gl_LocalInvocationID.y * gl_WorkGroupSize.x * gl_WorkGroupSize.x

 

5、被关键字shared修饰的变量能够在局部工作组之间共享,它们被存储于共享空间中当做局部变量存储内存处理,访问性能较为优异。共享空间大小受限,通过GL_MAX_COMPUTE_SHARED_MEMORY_SIZE获取。

 

6、同步

 1)barrier() 停止当前执行等待其它实例也执行到当前步骤后继续执行,所有实例在同一位置都需要执行barrier

 2)memoryBarrier() 上一节说过

 3)groupMemoryBarrier() 与memoryBarrier等价只是只能应用于局部工作组的请求

 

posted @ 2020-03-14 22:22  no-being  阅读(825)  评论(0编辑  收藏  举报