漫谈C++内存和OpenGL各种缓冲对象(上)

1、C++内存管理
(1)常用数据类型占用内存大小:char 1字节;int 4字节;short 2字节;long 4字节;bool 1字节;float 4字节;double 8字节;
(2)堆栈的比较
  [1] 堆用于动态分配内存,容量大于栈。堆上内存可以随时申请、随时分配、随时释放。要分配的大小运行时才知道,只支持动态分配内存,容易造成内存泄漏。变量可以在进程内供多个线程访问,由开发者管理内存。
  [2] 栈用于函数和局部变量、返回值,编译器自动管理释放和分配。栈上内存是连续分布的,编译器在编译时就知道要分配的内存大小。调用函数栈上分配内存,调用结束回收给栈,先入后出。栈上分配内存要快于堆。每个线程都有一个栈,栈上对象不能跨线程访问,因此栈空间较小。栈不会产生内存碎片。
  [3] 全局变量和静态变量储存于数据区。
  [4] new申请动态堆内存,delete 标记该内存不可用
(3)结构体内存对齐
  [1] 有效对齐值为最宽成员大小和用户指定对齐值中较小的那个。
  [2] 结构体第一个成员偏移量为0,之后的为成员大小和有效对齐值的较小的那个的整数倍。
(4)结构体
2、OpenGL的Buffer创建、释放、使用
  (1)glGenBuffers(Glsizei n,Gluint* buffers);
命令GPU创建buffer对象标记,输入参数n为创建buffer的个数,默认大于0,buffers为buffer对象标记地址,类型为Gluint整型。glGenBuffers并没有真正分配一块GPU缓冲区,而只是创建了n个GPU未使用的buffer对象标记。
  (2)glBindBuffers(GLenum target,GLuint buffer);
命令GPU绑定缓冲区对象,输入参数target为buffer类型分别对应顶点缓冲VAO类型和顶点序号缓冲EBO类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER),buffer为上一步创建的有效buffer对象标记。如果此buffer对象未绑定任何缓冲区则GPU会申请一块缓存并关联上当前对象标记。注意同一时间、线程、上下文只能有一个VBO和一个EBO对象被使用。
  (3)glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
写入数据到GPU缓冲区,输入参数target为缓冲类型;size为机器大小字节;data为写入数据内存地址,当data为null的时候,仍然会分配一块size大小的GPU缓存到这个buffer对象;usage为缓存使用方式,分别为:赋值一次多次被读取调用、多次赋值多次调用、赋值一次调用几次(GL_STATIC_DRAW,GL_DYNAMIC_DRAW,GL_STREAM_DRAW)。如果此buffer对象已有数据,再次调用函数则会覆盖掉原本的数据。
      glBufferSubData(GLenum target,GLintptr offset, GLsizeiptr size, const GLvoid * data)
写入数据到GPU一部分缓冲区,输入参数offset为到buffer对象所在显存起始地址的偏移量,size为所需显存字节大小。用于修改已经分配的缓冲区数据,不会重新分配显存。
  (4)glDeleteBuffers(GLsizei n,const GLuint* buffers)
删除GPU中buffer对象标记,输入参数n为删除的对象个数,buffers为buffer对象标记地址。删除时若对象正被绑定,GPU会先调用glBindBuffers解绑后删除对象标记及其对应的显存。

3、OpenGL的FrameBuffer创建、释放、使用
  (1)void glGenFramebuffers(GLsizei n, GLuint * framebuffers);
创建FBO,其中输入参数n为生成的fbo名称个数,framebuffers为缓冲对象名称。
  (2)void glBindFramebuffer(GLenum target, GLuint framebuffer);
绑定FBO,其中输入参数target为缓冲类型GL_FRAMEBUFFER,framebuffer为缓冲对象名称。一个FBO有一个color attachment挂载点,一个depth attachment挂载点,一个stencil attachment挂载点。GPU可以存放大量的fbo,但同一时间一个线程上下文只能有一个framebuffer能被使用着。FBO的挂载点可以修改。
  (3)void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
挂载纹理到FBO上。输入参数target为GL_FRAMEBUFFER,attachment为GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT 或者GL_STENCIL_ATTACHMENT,textarget为0或者GL_TEXTURE_2D ,texture为纹理缓冲名称,level为0。
4、OpenGL的Uniform Buffer创建、释放、使用
    Uniform buffer用于整块写入shader中uniform变量,uniform数据被认为是vertex shader和fragment shader的全局变量。使用uniform buffer的优点:可以一次写入大量数据到GPU;多个shader可以共享一块buffer;shader中uniform数量受到限制,使用的uniform buffer的uniform数量更大
  (1)创建Uniform buffer:glGenBuffers(1,&object);
  (2) 使用Uniform buffer:
    绑定缓冲对象 glBindBuffer(GL_UNIFORM_BUFFER,object);
    分配足够内存 glBufferData(GL_UNIFORM_BUFFER,152,NULL,GL_STATIC_DRAW)
    解绑缓冲对象 glBindBuffer(GL_UNIFORM_BUFFER,0);
    获取shader中uniform变量绑定点,然后将变量链接到绑定点unsigned int light_index=glGetUniformBlockIndex(shaderA.ID,"Liaghts");
    glUniformBlockBinding(shaderA.ID,light_index,2);
    绑定Uniform 缓冲到相同的绑定点。
    glBindBufferBase(GL_UNIFORM_BUFFER,2,object)其中输入参数2为绑定点索引,object为缓冲对象。
    glBindBufferRange(GLenum target,GLuint index,GLuint buffer,GLintptr offset,Glisizeptr size)其中输入参数 target为uniform类型GL_UNIFORM_BUFFER,index 为绑定点索引,buffer为缓冲对象名称,offset为到缓冲区起始位置偏移量,size为读取的缓冲区大小。
    更新Uniform buffer数据:
    glBindBuffer(GL_UNIFORM_BUFFER, this->ubo);
    glBufferSubData(GL_UNIFORM_BUFFER,sizeof(glm::mat4),sizeof(glm::mat4),glm::value_ptr(view));
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

posted @   王小于的啦  阅读(486)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示