在OpenGL中使用Compute Shader(一)
发布网友
发布时间:2023-03-26 02:10
我来回答
共1个回答
热心网友
时间:2023-10-20 09:23
先了解一些Compute Shader的基本概念
https://www.cg.tuwien.ac.at/courses/Realtime/repetitorium/VU.WS.2014/rtr_rep_2014_ComputeShader.pdf
最小执行单元为thread,也称为invocation,一个thread执行一遍shader程序
网格化的thread构成了work group,可以是1维、2维或者3维的。shader程序中用layout语句指定的local_size_x,local_size_y,local_size_z决定了work group的大小。
网格化的work group构成了dispatch,同样也可以是1维、2维或者3维的。glDispatchCompute中的三个参数指定了x, y, z三维的大小
ps:
https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf
根据资料,work group的尺寸也可以完全由c程序决定,GLSL中的声明改为
layout( local_size_variable ) in;
对比cuda的概念,compute shader中的work group就是cuda的block,dispatch就是cuda的grid。
OpenGL 4.2中Image介绍
https://blog.csdn.net/u010462297/article/details/50469950
image类型数据与sampler类型数据的区别:sampler取样本的时候,可以是非整数坐标,而且需要对周边像素进行插值才能获取。而image类型只能取整数坐标,直接取出原始数据样本
ps: gl_GlobalInvocationID.x的类型是uint,而imageLoad需要的坐标参数为int。可以用int(表达式)进行强制类型转换
要开始跑计算,首先要解决的是数据的输入和输出问题。ComputeShader中参数的声明非常类似原来的FragmentShader,还是使用uniform作为输入。不过数据类型可以使用image类型了,不再是sampler类型,解决精准取值的问题。另外,作为输入的image,还需要在layout指令中指明格式,例如r32f或者rgba32f(这里只有1、2、4色的格式,没有rgb三色的格式。不过比较奇怪的一点,作为输出的image可以不指明格式,暂时不知道为什么)。而且,image对象需要调用glBindImageTexture跟纹理对象进行绑定。而且还有一点需要非常注意
“A very important restriction for using shader images is that the underlying texture must have been allocated using "immutable" storage, i.e. via glTexStorage*()-like functions, and not glTexImage2D().”
cpu与gpu之间传数据,往gpu传入使用 glTexSubImage,从gpu读出使用glGetTexImage(glReadPixels需要跟FBO一起使用才可以,而glGetTexImage可以直接从texture读取)
至于OpenGL的初始化工作,还是采用freeglut+glew的经典组合就可以完成。
一个最简单的例子,传输一个一维数组,然后给数组里面每个元素加1。
参考
http://wili.cc/blog/opengl-cs.html
https://antongerdelan.net/opengl/compute.html
https://www.cnblogs.com/chen9510/p/12000320.html
https://blog.csdn.net/koibiki/article/details/80590885
https://arm-software.github.io/opengl-es-sdk-for-android/compute_intro.html