OpenGL缓冲对象:glMapBufferRange、glMapNamedBufferRange、glMapBuffer、glMapNamedBuffer简介

  1. OpenGL缓冲对象概念
  2. 缓冲区对象 Buffer Objects API列表

  1. 缓冲区对象 Buffer Objects
  2. 创建和绑定缓冲区对象 Creating and Binding Buffer Objects
  3. 创建缓冲对象数据存储 Creating Buffer Object Data Stores
  4. 修改缓冲对象数据存储 Modifying Buffer Object Data Stores
  5. Clear缓冲对象数据存储 Clear Buffer Object Data Stores
  6. 映射映射缓冲数据 Mapping Buffer Data
  7. 刷新映射缓冲数据 Flush Buffer Data
  8. 取消映射缓冲数据 Unmapping Buffer Data
  9. 使缓冲区数据无效 Invalidating Buffer Data
  10. 缓冲区间复制 Copying Between Buffers
  11. 缓冲对象查询 Buffer Object Queries

  1. glMapBufferRange

    • 函数原型:

      void* glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
      
    • 功能:成功调用 MapBufferRange 后,函数会返回指向映射数据范围起始位置的指针。应用程序可以通过这个指针直接操作内存中的数据。当完成数据操作后,应当调用 UnmapBuffer 函数来解除映射,以便让OpenGL继续处理缓冲区数据。

    • 参数说明:

      • target: 指定要映射的缓冲对象目标,例如 GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFER 等。
      • offset: 表示从缓冲区起始位置开始映射的偏移量,单位为基本机器单位。
      • length: 映射的数据范围大小,同样以基本机器单位为单位。
      • access: 一个标志位字段,用来描述请求的映射类型和访问权限。可以包含以下标志:
        • GL_MAP_READ_BIT: 允许通过返回的指针读取缓冲区数据。
        • GL_MAP_WRITE_BIT: 允许通过返回的指针修改缓冲区数据。
        • GL_MAP_PERSISTENT_BIT: 标识在映射期间GPU可以同时读写该缓冲区内容,并要求缓冲的 BUFFER_STORAGE_FLAGS 包含 MAP_PERSISTENT_BIT 标志(使用 glBufferStorage 设置了持久性标志)。
        • GL_MAP_COHERENT_BIT: 标志内存映射应保持一致性,即CPU对缓冲区的修改能够立即反映到GPU(要求缓冲的 BUFFER_STORAGE_FLAGS 包含 MAP_COHERENT_BIT 标志)。
        • GL_MAP_INVALIDATE_RANGE_BIT: 表示可以丢弃指定范围内的原有数据。
        • GL_MAP_INVALIDATE_BUFFER_BIT: 表示可以丢弃整个缓冲区的原有数据。
        • GL_MAP_FLUSH_EXPLICIT_BIT: 表示需要显式调用 FlushMappedBufferRange 来刷新修改后的数据。
        • GL_MAP_UNSYNCHRONIZED_BIT: 表示 GL 在从 Map*BufferRange 返回之前不应尝试同步缓冲区上的挂起操作。
  2. glMapNamedBufferRange

    • 函数原型:

      void* glMapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
      
    • 功能:与 glMapBufferRange 类似,但通过缓冲对象的名字而不是当前绑定的目标来指定需要映射的缓冲。这对于管理多个缓冲时更为方便。

  3. glMapBuffer

    • 函数原型:

      void* glMapBuffer(GLenum target, GLenum access);
      
      // 等价于
      // glMapBufferRange(target, 0, BUFFER_SIZE, flags);
      
    • 功能:这是一个较早版本的API,它将整个缓冲对象映射到客户端内存。target 指定要映射的缓冲类型,而 access 参数只接受三个值:GL_READ_ONLYGL_WRITE_ONLYGL_READ_WRITE,表示对缓冲区内容是只读、只写还是读写。

  4. glMapNamedBuffer

    • 函数原型:

      void* glMapNamedBuffer(GLuint buffer, GLenum access);
      
      // 等价于
      // glMapNamedBufferRange(buffer, 0, BUFFER_SIZE, flags);
      
    • 功能:类似于 glMapBuffer,但针对的是命名缓冲。它根据给定的缓冲对象名字和访问模式,将整个缓冲对象映射到客户端内存。

总的来说,glMapBufferRangeglMapNamedBufferRange 提供了更灵活的缓冲映射选项,允许按需映射特定范围并控制访问权限;而 glMapBufferglMapNamedBuffer 则是对整个缓冲进行映射,且访问模式相对简单。使用这些函数前,通常需要先创建并绑定好缓冲对象。

映射期间,对缓冲区的修改可能不会立即反映到映射的内存中,需要通过 glFlushMappedBufferRange 等手段来刷新数据。

映射结束后,无论哪种方式,都需要调用对应的 glUnmapBufferglUnmapNamedBuffer 来解除映射,以确保GPU能够正确处理已修改的数据。

当一个缓冲对象使用 MAP_FLUSH_EXPLICIT_BIT 标志进行映射时,如果对映射范围内的数据进行了修改,可以通过以下命令来指示这些修改:
  • void glFlushMappedBufferRange( GLenum target, GLintptr offset, GLsizeiptr length );
  • void glFlushMappedNamedBufferRange( GLuint buffer, GLintptr offset, GLsizeiptr length );

对于 glFlushMappedBufferRange 函数,需要指定目标(target),该目标必须是OpenGL规范表6.1中列出的一种类型,并且是当前绑定到该目标的缓冲对象。而对于 glFlushMappedNamedBufferRange 函数,直接通过缓冲对象的名字(buffer)来指定。

offsetlength 参数用于指定映射范围内被修改的子区域,单位为基本机器单元。这个要刷新的子区域是相对于当前已映射缓冲对象范围起始位置的偏移量。可以多次调用 glFlushMapped*BufferRange 来指示不同需要刷新的子区域。

如果一个缓冲区范围同时设置了 MAP_PERSISTENT_BITMAP_FLUSH_EXPLICIT_BIT 标志,则可以调用 FlushMapped*BufferRange 确保客户端写入的数据在服务器端变得可见。对于一致存储(coherent store)中的数据,在未指定的一段时间后,它们总会变为服务器端可见。通过显式刷新,可以更精确地控制何时将更改同步至GPU。

映射缓冲区对其他GL命令的影响

在缓冲区对象的部分或全部被映射时,任何尝试读取、写入或更改缓冲区对象状态的 OpenGL 命令都可能生成 INVALID_OPERATION 错误。但是,只有那些明确描述了这个错误的命令才被要求这样做。如果没有生成错误,这样的命令将产生未定义的结果,可能导致 GL 中断或终止。

要注意的一点是,如果缓冲区对象是通过调用 *BufferStorage 并在 flags 中包含 MAP_PERSISTENT_BIT 来分配的,那么即使部分或全部缓冲区对象被映射,也不会生成 INVALID_OPERATION 错误。这提供了对于某些情况下可以映射的更灵活的缓冲区对象的支持。

总体而言,映射缓冲区时需要谨慎,避免对映射区域进行读写或修改状态的操作,以防止潜在的错误和未定义的结果。

你可能感兴趣的:(OpenGL,图形渲染)