OpenGL 编程指南(第八版)学习笔记——11 内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlk1229/article/details/81838669

OpenGL 编程指南学习资料以及我整理的代码下载地址https://pan.baidu.com/s/1bqrcspD

文中提到的代码为下载文件中的“OpenGL编程指南 VS2015代码.zip”文件,代码也可以到github上下载:https://github.com/Kylewlk/OpenGL-Programming-Guide-8th-Edition-Code

 

11 内存

纹理存储通用数据

通过采样器texture函数可以获取纹理,获取的时候是通过纹理(u, v)坐标,u,v的范围[0, 1]之间,读取是openGL会自动选择mip,缩放,插值等等。这里纹理存储通用数据是直接操作纹理的内存,直接读取纹理某一mip的数据,使用的坐标也是int类型,范围为纹理对应的长宽。

 

读取存储步骤

  1. 通过函数glBindImageTexture将需要操作的纹理绑定到图像单元。
  2. 在着色器中声明图像单元,可以通过布局限定符绑定图像单元,如下:

layout (binding = 1, rgba32f) uniform image2D,

也可以通过glUniform1i设置纹理单元。

     3. 通过imageStore修改数据,通过imageLoad读取数据,读取和存储时使用的坐标不应超过当前图像单元的长宽。

 

通过imageStore写入数据后,因为纹理的数据已经修改了,通过采样器去读取纹理也可以读取到纹理数据。

  • 代码工程11.1-01ImageTex,程序先在纹理中通过imageStore存储了四个球的图像数据,然后再绘制出来,结果:

 

缓存对象

着色器可以读取和写入缓存对象,因为缓存对象可以自定义数据类型,而且程序也可以很容易的使用glMapBuffer操作,其比纹理内存更加灵活。

 

使用步骤

  1. 在着色器中声明缓存layout (std430, binding = 0) buffer bufferObject{}
  2. 创建缓存对象
  3. 将缓存对象通过函数glBindBufferBase绑定到缓存对象单元
  4. 在着色器中直接通过变量读取和写入缓存数据。

      缓存对象最后一个数组变量可以不设置长度,不设置时,数组长度会自动映射绑定的缓存。

  • 代码11.2-01BufferObject,结果:

 

原子操作和同步

原子操作与C++语言中类似,可以通过原子操作函数一步完成读取和写入的操作,防止多线程同时修改数据时造成数据异常。

 

同步

因为GPU渲染本身是一个高并发过程,不同于CPU中同时只有几条线程(与CPU核数有关)执行,其内部会有几百甚至上千个着色器同时执行,其同步方式也与C++有很大的不同。

 

栅栏Fence,可保证栅栏前的GPU都已经执行完成,使用glClientWaitSync进行等待

内存屏障memoryBarrier,可以保证修改内存后其他执行程序读取到最新的值。glMemoryBarrier可保证该函数前命令前修改的数据可以被函数后命令读取到。

猜你喜欢

转载自blog.csdn.net/wlk1229/article/details/81838669