openGLES3.0之glMapBufferRange()函数详解

前言

 glBufferData或glBufferSubData。 应用程序也可以将缓冲区对象的数据存储映射和取消映射到应用程序的地址空间。 有几个原因可以解释为什么应用程序更喜欢映射  

而不是使用glBufferData或glBufferSubData加载它的数据:  

••映射缓冲区可以减少应用程序的内存使用因为可能只需要存储数据的单个副本。  

••在具有共享内存的架构上,映射缓冲区将返回一个直接指向地址空间的指针,在那里的缓冲区将被存储GPU。 通过映射缓冲区,应用程序可以避免复制步骤,从而实现更好的更新性能。

glMapBufferRange命令返回一个指向全部或部分的指针(范围)缓冲区对象的数据存储。 可以使用这个指针由应用程序读取或更新缓冲区对象的内容。  

glUnmapBuffer命令用于表示已经更新完成并释放映射指针。  

官网解释

翻译

Name

glMapBufferRange — map a section of a buffer object's data store

功能:将缓冲区对象数据存储映射到应用程序的地址空间, 他可以代替glBufferData或者                         glBufferSubData函数,以减少程序内存占用
     

C Specification

void *glMapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);

GLboolean glUnmapBuffer(GLenum target);

Parameters for glMapBufferRange

target

Specifies the target to which the buffer object is bound for glMapBufferRange, which must be one of the buffer binding targets in the following table:

翻译:为glMapBufferRange指定缓冲区对象绑定的目标,它必须是下表中的一个缓冲区绑定目标:  

Buffer Binding TargetPurpose
GL_ARRAY_BUFFERVertex attributes
GL_ATOMIC_COUNTER_BUFFERAtomic counter storage
GL_COPY_READ_BUFFERBuffer copy source
GL_COPY_WRITE_BUFFERBuffer copy destination
GL_DISPATCH_INDIRECT_BUFFERIndirect compute dispatch commands
GL_DRAW_INDIRECT_BUFFERIndirect command arguments
GL_ELEMENT_ARRAY_BUFFERVertex array indices
GL_PIXEL_PACK_BUFFERPixel read target
GL_PIXEL_UNPACK_BUFFERTexture data source
GL_SHADER_STORAGE_BUFFERRead-write storage for shaders
GL_TEXTURE_BUFFERTexture data buffer
GL_TRANSFORM_FEEDBACK_BUFFERTransform feedback buffer
GL_UNIFORM_BUFFERUniform block storage

offset

Specifies the starting offset within the buffer of the range to be mapped.

指定要映射的范围的缓冲区内的起始偏移量。  

length

Specifies the length of the range to be mapped.

指定要映射的范围的长度。  

access

Specifies a combination of access flags indicating the desired access to the range.

指定访问标志的组合,指示对范围的期望访问。  

Parameters for glUnmapBuffer

target

Specifies a binding to which the target buffer is bound.

指定目标缓冲区绑定到的绑定。  

Description

glMapBufferRange maps all or part of the data store of a buffer object into the client's address space. target specifies the target to which the buffer is bound and must be one of GL_ARRAY_BUFFERGL_ATOMIC_COUNTER_BUFFERGL_COPY_READ_BUFFERGL_COPY_WRITE_BUFFERGL_DISPATCH_INDIRECT_BUFFERGL_DRAW_INDIRECT_BUFFERGL_ELEMENT_ARRAY_BUFFERGL_PIXEL_PACK_BUFFERGL_PIXEL_UNPACK_BUFFERGL_SHADER_STORAGE_BUFFERGL_TRANSFORM_FEEDBACK_BUFFER or GL_UNIFORM_BUFFERoffset and length indicate the range of data in the buffer object that is to be mapped, in terms of basic machine units. access is a bitfield containing flags which describe the requested mapping. These flags are described below.

glMapBufferRange将buffer对象的全部或部分数据存储映射到客户端地址空间。 Target指定缓冲区绑定到的目标,必须是一个 配置GL_ARRAY_BUFFER、GL_ATOMIC_COUNTER_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_DISPATCH_INDIRECT_BUFFER、GL_DRAW_INDIRECT_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_SHADER_STORAGE_BUFFER、GL_TRANSFORM_FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。 偏移量和长度表示要映射的缓冲区对象中的数据范围,以基本机器单元为单位。 Access是一个包含描述请求映射的标志的位域。 这些标志描述如下。  

If no error occurs, a pointer to the beginning of the mapped range is returned once all pending operations on that buffer have completed, and may be used to modify and/or query the corresponding range of the buffer, according to the following flag bits set in access:

  • GL_MAP_READ_BIT indicates that the returned pointer may be used to read buffer object data. No GL error is generated if the pointer is used to query a mapping which excludes this flag, but the result is undefined and system errors (possibly including program termination) may occur.

  • GL_MAP_WRITE_BIT indicates that the returned pointer may be used to modify buffer object data. No GL error is generated if the pointer is used to modify a mapping which excludes this flag, but the result is undefined and system errors (possibly including program termination) may occur.

如果没有错误发生,一旦该缓冲区上所有未决的操作都完成,就返回一个指向映射范围开头的指针,并可用于根据access中设置的下列标志位修改和/或查询缓冲区的相应范围:  

GL_MAP_READ_BIT表示返回的指针可用于读取缓冲区对象数据。 如果指针用于查询排除此标志的映射,则不会产生GL错误,但结果是未定义的,并且可能发生系统错误(可能包括程序终止)。  

GL_MAP_WRITE_BIT表示返回的指针可用于修改缓冲区对象数据。 如果指针用于修改一个排除此标志的映射,则不会产生GL错误,但结果是未定义的,并且可能发生系统错误(可能包括程序终止)。  

Furthermore, the following optional flag bits in access may be used to modify the mapping:

  • GL_MAP_INVALIDATE_RANGE_BIT indicates that the previous contents of the specified range may be discarded. Data within this range are undefined with the exception of subsequently written data. No GL error is generated if subsequent GL operations access unwritten data, but the result is undefined and system errors (possibly including program termination) may occur. This flag may not be used in combination with GL_MAP_READ_BIT.

  • GL_MAP_INVALIDATE_BUFFER_BIT indicates that the previous contents of the entire buffer may be discarded. Data within the entire buffer are undefined with the exception of subsequently written data. No GL error is generated if subsequent GL operations access unwritten data, but the result is undefined and system errors (possibly including program termination) may occur. This flag may not be used in combination with GL_MAP_READ_BIT.

  • GL_MAP_FLUSH_EXPLICIT_BIT indicates that one or more discrete subranges of the mapping may be modified. When this flag is set, modifications to each subrange must be explicitly flushed by calling glFlushMappedBufferRange. No GL error is set if a subrange of the mapping is modified and not flushed, but data within the corresponding subrange of the buffer are undefined. This flag may only be used in conjunction with GL_MAP_WRITE_BIT. When this option is selected, flushing is strictly limited to regions that are explicitly indicated with calls to glFlushMappedBufferRange prior to unmap; if this option is not selected glUnmapBuffer will automatically flush the entire mapped range when called.

  • GL_MAP_UNSYNCHRONIZED_BIT indicates that the GL should not attempt to synchronize pending operations on the buffer prior to returning from glMapBufferRange. No GL error is generated if pending operations which source or modify the buffer overlap the mapped region, but the result of such previous and any subsequent operations is undefined.

此外,在access中可以使用以下可选标志位来修改映射:  

GL_MAP_INVALIDATE_RANGE_BIT表示前一个指定范围的内容可能被丢弃。 除随后写入的数据外,此范围内的数据是未定义的。 如果后续的GL操作访问未写入的数据,则不会产生GL错误,但结果是未定义的,并且可能发生系统错误(可能包括程序终止)。 这个标志不能与GL_MAP_READ_BIT一起使用。  

GL_MAP_INVALIDATE_BUFFER_BIT表示整个缓冲区之前的内容可能被丢弃。 除了随后写入的数据外,整个缓冲区中的数据都是未定义的。 如果后续的GL操作访问未写入的数据,则不会产生GL错误,但结果是未定义的,并且可能发生系统错误(可能包括程序终止)。 这个标志不能与GL_MAP_READ_BIT一起使用。  

GL_MAP_FLUSH_EXPLICIT_BIT表示可以修改映射的一个或多个离散子范围。 设置此标志后,必须通过调用glflushappedbufferrange显式刷新对每个子范围的修改。 如果映射的子范围被修改且未刷新,但缓冲区对应子范围内的数据未定义,则不设置GL错误。 此标志只能与GL_MAP_WRITE_BIT一起使用。 当选择此选项时,刷新严格限于在取消映射之前通过调用glflushappedbufferrange显式指示的区域; 如果未选择此选项,glUnmapBuffer将在调用时自动刷新整个映射范围。  

GL_MAP_UNSYNCHRONIZED_BIT表示GL在从glMapBufferRange返回之前不应该尝试同步缓冲区上挂起的操作。 如果源或修改缓冲区的未决操作与映射区域重叠,但之前和后续操作的结果是未定义的,则不会产生GL错误。  

If an error occurs, glMapBufferRange returns a NULL pointer.

A mapped data store must be unmapped with glUnmapBuffer before its buffer object is used. Otherwise an error will be generated by any GL command that attempts to dereference the buffer object's data store. When a data store is unmapped, the pointer to its data store becomes invalid. glUnmapBuffer returns GL_TRUE unless the data store contents have become corrupt during the time the data store was mapped. This can occur for system-specific reasons that affect the availability of graphics memory, such as screen mode changes. In such situations, GL_FALSE is returned and the data store contents are undefined. An application must detect this rare condition and reinitialize the data store.

A buffer object's mapped data store is automatically unmapped when the buffer object is deleted or its data store is recreated with glBufferData.

如果发生错误,glMapBufferRange返回一个NULL指针。  

在使用buffer对象之前,映射的数据存储必须取消glUnmapBuffer的映射。 否则,任何试图解引用缓冲区对象的数据存储的GL命令都会生成错误。 未映射数据存储时,指向该数据存储的指针将失效。 glUnmapBuffer返回GL_TRUE,除非数据存储的内容在数据存储被映射时已经损坏。 这可能是由于影响图形内存可用性的系统特定原因,例如屏幕模式更改。 在这种情况下,返回GL_FALSE,数据存储内容是未定义的。 应用程序必须检测这种罕见的情况并重新初始化数据存储。  

当删除缓冲区对象或使用glBufferData重新创建缓冲区对象的数据存储时,缓冲区对象的映射数据存储将自动取消映射。  

Notes

Mappings to the data stores of buffer objects may have nonstandard performance characteristics. For example, such mappings may be marked as uncacheable regions of memory, and in such cases reading from them may be very slow. To ensure optimal performance, the client should use the mapping in a fashion consistent with the values of GL_BUFFER_USAGE and access. Using a mapping in a fashion inconsistent with these values is liable to be multiple orders of magnitude slower than using normal memory.

The GL_ATOMIC_COUNTER_BUFFERGL_DISPATCH_INDIRECT_BUFFERGL_DRAW_INDIRECT_BUFFER and GL_SHADER_STORAGE_BUFFER targets are available only if the GL ES version is 3.1 or greater.

The GL_TEXTURE_BUFFER target is available only if the GL ES version is 3.2 or greater.

注意:

到缓冲区对象的数据存储的映射可能具有非标准的性能特征。 例如,这样的映射可能被标记为内存的非缓存区域,在这种情况下,从它们读取可能会非常慢。 为了确保最佳性能,客户端应该以与GL_BUFFER_USAGE和access值一致的方式使用映射。 以与这些值不一致的方式使用映射容易比使用普通内存慢多个数量级。  

GL_ATOMIC_COUNTER_BUFFER、GL_DISPATCH_INDIRECT_BUFFER、GL_DRAW_INDIRECT_BUFFER和GL_SHADER_STORAGE_BUFFER仅在GL ES版本为3.1或更高版本时可用。  

GL_TEXTURE_BUFFER目标仅在GL ES版本为3.2或更高时可用。  

Errors

GL_INVALID_VALUE is generated if either of offset or length is negative, or if offset + length is greater than the value of GL_BUFFER_SIZE.

GL_INVALID_VALUE is generated if access has any bits set other than those defined above.

GL_INVALID_OPERATION is generated for any of the following conditions:

  • The buffer is already in a mapped state.

  • Neither GL_MAP_READ_BIT or GL_MAP_WRITE_BIT is set.

  • GL_MAP_READ_BIT is set and any of GL_MAP_INVALIDATE_RANGE_BITGL_MAP_INVALIDATE_BUFFER_BIT, or GL_MAP_UNSYNCHRONIZED_BIT is set.

  • GL_MAP_FLUSH_EXPLICIT_BIT is set and GL_MAP_WRITE_BIT is not set.

GL_OUT_OF_MEMORY is generated if glMapBufferRange fails because memory for the mapping could not be obtained.

错误  

如果offset或length为负,或者offset + length大于GL_BUFFER_SIZE的值,则生成GL_INVALID_VALUE。  

如果访问设置了除上面定义的位之外的任何位,则生成GL_INVALID_VALUE。  

GL_INVALID_OPERATION是针对以下任何一种情况生成的:  

缓冲区已经处于映射状态。  

GL_MAP_READ_BIT和GL_MAP_WRITE_BIT都没有设置。  

设置GL_MAP_READ_BIT,并设置GL_MAP_INVALIDATE_RANGE_BIT、GL_MAP_INVALIDATE_BUFFER_BIT或GL_MAP_UNSYNCHRONIZED_BIT。  

设置GL_MAP_FLUSH_EXPLICIT_BIT,未设置GL_MAP_WRITE_BIT。  

如果glMapBufferRange失败,因为无法获取映射的内存,则生成GL_OUT_OF_MEMORY。  

API Version Support

OpenGL ES API Version
Function Name2.03.03.13.2
glMapBufferRange-
glUnmapBuffer-

See Also

glBindBuffer glFlushMappedBufferRangeglUnmapBuffer,

Copyright

Copyright © 2010-2015 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

代码

// The MIT License (MIT)
//
// Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//
// Book:      OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
// Authors:   Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
// ISBN-10:   0-321-93388-5
// ISBN-13:   978-0-321-93388-1
// Publisher: Addison-Wesley Professional
// URLs:      http://www.opengles-book.com
//            http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
//
// MapBuffers.c
//
//    This example demonstrates mapping buffer objects
//
#include "esUtil.h"
#include <string.h>

typedef struct
{
   // Handle to a program object
   GLuint programObject;

   // VertexBufferObject Ids
   GLuint vboIds[2];

} UserData;


#define VERTEX_POS_SIZE       3 // x, y and z
#define VERTEX_COLOR_SIZE     4 // r, g, b, and a

#define VERTEX_POS_INDX       0
#define VERTEX_COLOR_INDX     1


int Init ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
   const char vShaderStr[] =
      "#version 300 es                            \n"
      "layout(location = 0) in vec4 a_position;   \n"
      "layout(location = 1) in vec4 a_color;      \n"
      "out vec4 v_color;                          \n"
      "void main()                                \n"
      "{                                          \n"
      "    v_color = a_color;                     \n"
      "    gl_Position = a_position;              \n"
      "}";


   const char fShaderStr[] =
      "#version 300 es            \n"
      "precision mediump float;   \n"
      "in vec4 v_color;           \n"
      "out vec4 o_fragColor;      \n"
      "void main()                \n"
      "{                          \n"
      "    o_fragColor = v_color; \n"
      "}" ;

   GLuint programObject;

   // Create the program object
   programObject = esLoadProgram ( vShaderStr, fShaderStr );

   if ( programObject == 0 )
   {
      return GL_FALSE;
   }

   // Store the program object
   userData->programObject = programObject;
   userData->vboIds[0] = 0;
   userData->vboIds[1] = 0;

   glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f );
   return GL_TRUE;
}



void DrawPrimitiveWithVBOsMapBuffers ( ESContext *esContext,
                                       GLint numVertices, GLfloat *vtxBuf,
                                       GLint vtxStride, GLint numIndices,
                                       GLushort *indices )
{
   UserData *userData = esContext->userData;
   GLuint   offset = 0;

   // vboIds[0] - used to store vertex attribute data
   // vboIds[l] - used to store element indices
   if ( userData->vboIds[0] == 0 && userData->vboIds[1] == 0 )
   {
      GLfloat *vtxMappedBuf;
      GLushort *idxMappedBuf;

      // Only allocate on the first draw
      glGenBuffers ( 2, userData->vboIds );

      glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
      glBufferData ( GL_ARRAY_BUFFER, vtxStride * numVertices,
                     NULL, GL_STATIC_DRAW );

      vtxMappedBuf = ( GLfloat * )
                     glMapBufferRange ( GL_ARRAY_BUFFER, 0, vtxStride * numVertices,
                                        GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT );

      if ( vtxMappedBuf == NULL )
      {
         esLogMessage ( "Error mapping vertex buffer object." );
         return;
      }

      // Copy the data into the mapped buffer
      memcpy ( vtxMappedBuf, vtxBuf, vtxStride * numVertices );

      // Unmap the buffer
      if ( glUnmapBuffer ( GL_ARRAY_BUFFER ) == GL_FALSE )
      {
         esLogMessage ( "Error unmapping array buffer object." );
         return;
      }

      // Map the index buffer
      glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[1] );
      glBufferData ( GL_ELEMENT_ARRAY_BUFFER,
                     sizeof ( GLushort ) * numIndices,
                     NULL, GL_STATIC_DRAW );
      idxMappedBuf = ( GLushort * )
                     glMapBufferRange ( GL_ELEMENT_ARRAY_BUFFER, 0, sizeof ( GLushort ) * numIndices,
                                        GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT );

      if ( idxMappedBuf == NULL )
      {
         esLogMessage ( "Error mapping element array buffer object." );
         return;
      }

      // Copy the data into the mapped buffer
      memcpy ( idxMappedBuf, indices, sizeof ( GLushort ) * numIndices );

      // Unmap the buffer
      if ( glUnmapBuffer ( GL_ELEMENT_ARRAY_BUFFER ) == GL_FALSE )
      {
         esLogMessage ( "Error unmapping element array buffer object." );
         return;
      }
   }

   glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
   glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[1] );

   glEnableVertexAttribArray ( VERTEX_POS_INDX );
   glEnableVertexAttribArray ( VERTEX_COLOR_INDX );

   glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE,
                           GL_FLOAT, GL_FALSE, vtxStride,
                           ( const void * ) offset );

   offset += VERTEX_POS_SIZE * sizeof ( GLfloat );
   glVertexAttribPointer ( VERTEX_COLOR_INDX,
                           VERTEX_COLOR_SIZE,
                           GL_FLOAT, GL_FALSE, vtxStride,
                           ( const void * ) offset );

   glDrawElements ( GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT,
                    0 );

   glDisableVertexAttribArray ( VERTEX_POS_INDX );
   glDisableVertexAttribArray ( VERTEX_COLOR_INDX );

   glBindBuffer ( GL_ARRAY_BUFFER, 0 );
   glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void Draw ( ESContext *esContext )
{
   UserData *userData = esContext->userData;

   // 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
   GLfloat vertices[3 * ( VERTEX_POS_SIZE + VERTEX_COLOR_SIZE )] =
   {
      0.0f,  0.5f, 0.0f,        // v0
      1.0f,  0.0f, 0.0f, 1.0f,  // c0
      -0.5f, -0.5f, 0.0f,        // v1
      0.0f,  1.0f, 0.0f, 1.0f,  // c1
      0.5f, -0.5f, 0.0f,        // v2
      0.0f,  0.0f, 1.0f, 1.0f,  // c2
   };
   // Index buffer data
   GLushort indices[3] = { 0, 1, 2 };

   glViewport ( 0, 0, esContext->width, esContext->height );
   glClear ( GL_COLOR_BUFFER_BIT );
   glUseProgram ( userData->programObject );

   DrawPrimitiveWithVBOsMapBuffers ( esContext, 3, vertices,
                                     sizeof ( GLfloat ) * ( VERTEX_POS_SIZE + VERTEX_COLOR_SIZE ),
                                     3, indices );
}

void Shutdown ( ESContext *esContext )
{
   UserData *userData = esContext->userData;

   glDeleteProgram ( userData->programObject );
   glDeleteBuffers ( 2, userData->vboIds );
}

int esMain ( ESContext *esContext )
{
   esContext->userData = malloc ( sizeof ( UserData ) );

   esCreateWindow ( esContext, "MapBuffers", 320, 240, ES_WINDOW_RGB );

   if ( !Init ( esContext ) )
   {
      return GL_FALSE;
   }

   esRegisterShutdownFunc ( esContext, Shutdown );
   esRegisterDrawFunc ( esContext, Draw );

   return GL_TRUE;
}

运行效果

工程源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值