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);