OpenGL学习-高级OpenGL-ComputeShader

目录

基本概念:

在程序中的使用:

内置变量:

共享变量:

同步计算:

不同Shader之间通信:

原子操作:

限制大小:

学习资料:


 -----------------------博主:mx

基本概念:

OpenGL的Compute shader几乎可以被认为是独立于其他面向图形的阶段运行的独立管道。Compute shader是一种获得系统中图形处理器所拥有的计算能力的方法,不像Vertex 、Tessellation、Geometry、Fragment Shader,Compute shader可以被认为是一种特殊的、每个Compute shader都运行在单个工作单元上,称为工作项。而这些工作项被收集到一起,形成一个称为工作组。这些工作组的集合可以发送到OpenGL的计算管道中进行处理。Compute shader没有任何固定的输入或输出,除了一些内置的变量来告诉着色器它正在处理哪个项目。计算着色器执行的所有处理都被着色器本身显式地写入内存,而不是被随后的流水线阶段消耗。一个非常基本的Compute shader如下所示:

#version 450 core

//本地工作项大小

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

void main(void)

{

// Do nothing

}

工作项大小图示

OpenGL学习-高级OpenGL-ComputeShader_第1张图片

在程序中的使用:

Compute shader在其他方面就像OpenGL中的任何其他着色器阶段。你创建一个类型为GL_COMPUTE_SHADER的着色器对象,用glShaderSource()把你的glsl源代码连接上,用glCompileShader()编译它,然后用glAttachShader()和glLinkProgram()链接到一个程序中。

链接完之后就能够用glUseProgram()函数把它设置为当前要执行的渲染程序,然后用glDispatchCompute()把工作组发送到计算管线。

OpenGL学习-高级OpenGL-ComputeShader_第2张图片

void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);

num_groups_x, num_groups_y和 num_groups_z分别设置工作组在X,Y和Z维度上的数量。每个参数都必须大于0,小于或等于一个与设备相关的常量数组 GL_MAX_COMPUTE_WORK_GROUP_SIZE的对应元素。Compute shader中执行单元的总数是这个3维数组的大小乘以着色器代码中定义的本地工作组的大小。

OpenGL学习-高级OpenGL-ComputeShader_第3张图片

除了使用glDispatchCompute()之外通过 glDispatchComputeIndirect()可以 使用存储在缓冲区对象上的参数来发送计算任务。缓冲区对象被绑定在 GL_DISPATCH_INDIRECT_BUFFER上,并且缓冲区中存储的参数包含三个打包在一起的无符号整数。这三个无符号整数的作用和glDispatchCompute()中的参数是等价的。

void glDispatchComputeIndirect(GLintptr indirect);

 -----------------------博主:mx

内置变量:

Compute shader虽然不能有用户自定义的输入输出变量,但是又内置的变量:

//该变量包含传递给调度函数的工作组数。

in uvec3 gl_NumWorkGroups;

//这是此着色器调用的当前工作组。 每个XYZ组件将在半开放范围[0,gl_NumWorkGroups.XYZ]上。

in uvec3 gl_WorkGroupID;

//这是工作组中着色器的当前调用。 每个XYZ组件都将在半开放范围[0, gl_WorkGroupSize.XYZ ]上。

in uvec3 gl_LocalInvocationID;

//该值是当前执行单元在全局工作组中的位置的一种有效的3维索引

in uvec3 gl_GlobalInvocationID;

//这是gl_LocalInvocationID的一维版本。

in uint gl_LocalInvocationIndex;

共享变量:

例如:

shared uint fool;

如果一个变量被声明为shared,那么它将被保存到特定的位置,从而 对同一个本地工作组内的所有Compute shader请求可见。通常访问共享shared变量的性能会远远好于访问图像或者着色器存储缓存(shader storage buffer)(例如主内存)的性能。

而这样的资源环境是有限的,所以需要查询和了解某个Compute shader程序的共享变量的最大数量。要获取这个限制值,可以调用glGetIntegerv()并设置pname为 GL_MAX_COMPUTE_SHARED_MEMORY_SIZE。

同步计算:

barrier()函数

当在Compute shader执行这个函数时,他将在这里阻塞,直到同一本地的工作组中所有其他Compute shader都调用到这个点的时候才继续。在时间片轮转的架构中,执行barrier()函数意味着舍弃这个时间片,交由其他Compute shader运行到这个点。

glMemoryBarrier(GLbitfield barriers)

glMemoryBarrier —定义对内存事务进行排序的屏障。参数必须为 GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT, GL_ELEMENT_ARRAY_BARRIER_BIT, GL_UNIFORM_BARRIER_BIT, GL_TEXTURE_FETCH_BARRIER_BIT, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, GL_COMMAND_BARRIER_BIT, GL_PIXEL_BUFFER_BARRIER_BIT, GL_TEXTURE_UPDATE_BARRIER_BIT, GL_BUFFER_UPDATE_BARRIER_BIT, GL_FRAMEBUFFER_BARRIER_BIT, GL_TRANSFORM_FEEDBACK_BARRIER_BIT, GL_ATOMIC_COUNTER_BARRIER_BIT, 或 GL_SHADER_STORAGE_BARRIER_BIT的按位组合. 如果指定了特殊值GL_ALL_BARRIER_BITS,将插入所有受支持的障碍。

使用这个函数之后后续使用对应缓冲区的数据的时候,取到的数据必然是Barrier之前就已经写入的。实现一个强制同步的效果。

不同Shader之间通信:

我们来讲一下ComputeShader和正常管线shader之间的通信,这个其实和正常管线shader之间通信一样。我们可以选择使用UBO或者SSAO

我们可以先将SSBO绑定到GL_ARRAY_BUFFER,然后再把这个SSBO的句柄,绑定到ComputeShader中的绑定点上,这样两边就联系起来了。

如果要检验缓冲区的数据究竟有没有写入可以试试glMapBuffer将数据映射出来查看。

原子操作:

可以对整数类型的共享变量(还有向量/数组/结构体)执行多个原子操作。

nint atomicAdd(inout nint mem, nint data)

nint atomicMin(inout nint mem, nint data)

nint atomicMax(inout nint mem, nint data)

n int atomicAnd(inout nint mem, nint data)

nint atomicOr(inout nint mem, nint data)

nint atomicXor(inout nint mem, nint data)

nint atomicExchange(inout nint mem, nint data)

nint atomicCompSwap(inout nint mem, nint compare, nint data)

限制大小:

对于ComputeShader中的各种限制大小我们可以采用

glGetIntegeri_v()函数进行查询。GL_MAX_COMPUTE_WORK_GROUP_SIZE 可以调度的最大工作组数。

GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 工作组中的调用总数,XYZ的乘积

GL_MAX_COMPUTE_SHARED_MEMORY_SIZE ComputShader可以允许的总存储大小

等等

 -----------------------博主:mx

实例使用:

这个仓库里面有个用computeShader做的particleSystem小玩具
GitHub - 1393650770/Opengl-Shadow-CSM: Cascaded Shadow Mapping

学习资料:

核心《 OpenGL SuiperBible 》Chapter10. Compute Shders

https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf

1.OpenGL4.3新特性: 计算着色器 Compute Shader_yofer张耀琦的专栏-CSDN博客_opengl计算着色器

2.https://panda1234lee.blog.csdn.net/article/details/70521910

3.https://panda1234lee.blog.csdn.net/article/details/51777980

4.Memory Model - OpenGL Wiki

5.glMapBuffer | glUnmapBuffer_JeckZ博客-CSDN博客 

-----------------------博主:mx

你可能感兴趣的:(图形学学习笔记,图形学,opengl,图形渲染)