Adreno OpenGL ES 3.1 介绍(7)
4.2.3.3 设置图像
到目前为止,已经讨论了该示例如何使用计算着色器。本节将仔细研究图像单元和图像uniform 的配置方式。 回忆一下,着色器调用使用它们来存储其结果值。
与之前的示例一样,资源在第一次渲染时通过负责渲染帧的函数_rendering_handler进行初始化。这是设置图像uniform的方法:
glGenTextures(1, &_texture);
glBindTexture (GL_TEXTURE_2D, _texture);
glTexStorage2D(GL_TEXTURE_2D,1, /* levels */ GL_RGBA8,
rendertarget_width,
rendertarget_height);
/* Set up image bindings */
glBindImageTexture(0, /* index */
_texture,
0, /* level */
GL_FALSE, /* layered */
0, /* layer */
GL_WRITE_ONLY,
GL_RGBA8);
/* Point the image uniform at the new binding */
glUseProgram(_program);
glUniform1i(_program_image_uniform_location,0); /* unit */
首先设置一个不变的纹理来保存将由计算着色器生成的数据。 仅需要基本的mipmap级别。 这将用作blit操作的读取缓冲区。
然后,调用glBindImageTexture将纹理对象绑定到索引为0的图像单元。图像的工作方式与纹理对象非常相似。 对于纹理,在着色器中对mipmap采样之前,请将纹理对象绑定到纹理单元之一,然后将采样器uniform设置为指向该纹理单元。 对于图像,该过程是类似的,并且glBindImageTexture的作用等同于glBindTexture。 唯一的区别是glBindImageTexture需要提供有关mipmap(或mipmap集)的更多详细信息(对于2D数组纹理等分层纹理目标),并提供有关使用图像的预期方式的提示。 上面的代码片段的最后一部分激活了一个程序对象,并配置了图像uniform以指向纹理图像单元0,该单元与glBindImageTexture调用所使用的纹理单元相同。
注意:此处并非必须调用glUniform1i,因为OpenGL ES着色器语言中所有图像uniform的默认设置为0,但是最好将其包括在内,因为忘记配置纹理采样器或图像uniform是一个难题。 频繁的编程错误。
4.2.3.4 渲染帧画面
一旦所有OpenGL ES对象都已初始化,则渲染帧的内容。 首先,将新的时间值分配给其中一个计算着色器uniform。 然后,调度计算作业:
glUseProgram(_program);
glUniform1f(_program_time_uniform_location,
float(current_time_msec) / 1000.0f);
glDispatchCompute(_global_workgroup_size[0],
_global_workgroup_size[1],
1); /* num_groups_z */
重要的是要记住,OpenGL ES以异步方式工作。 这在图像的上下文中尤其重要,它允许着色器修改外部实体,例如纹理数据存储。 OpenGL ES不会自动将此类着色器更新与可能对同一对象进行的其他访问同步(对于OpenGL ES这样做会引入大量开销,这可能会严重影响性能)。 因此,在访问可能已从着色器内部修改的任何类型的存储时,请使用适当的同步方法。
在示例中,打算在帧缓冲区blit操作中使用计算作业的结果。 blit是启动计算作业之后代码中的下一步。 如果没有适当的同步,则blit操作可能会在从计算着色器完成对缓冲区更新的更新之前尝试从缓冲区读取。为了序列化这些操作,请发出以下调用:
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
内存屏障可确保OpenGL ES将刷新硬件可能已用于图像存储操作的所有缓存,如果这些缓存可能影响后续的帧缓冲区操作。
最后一步是发出帧缓冲区blit,以将纹理内容传输到后缓冲区,如先前的示例中所做的那样:
glBlitFramebuffer(0, /* srcX0 */
0, /* srcY0 */
rendertarget_width,
rendertarget_height,
0, /* dstX0 */
0, /* dstY0 */
rendertarget_width,
rendertarget_height,
GL_COLOR_BUFFER_BIT,
GL_NEAREST); /* filter */
4.3 对OpenGL ES实施
本节详细介绍了OpenGL ES 3.1上下文中Adreno体系结构的功能。
4.3.2 GL常量值
Pname | Adreno 330 | Adreno 420 |
---|---|---|
GL_MAX_3D_TEXTURE_SIZE | 8192 | 16384 |
GL_MAX_ARRAY_TEXTURE_LAYERS | 512 | 2048 |
GL_MAX_COLOR_ATTACHMENTS | 4 | 8 |
GL_MAX_COMBINED_ATOMIC_COUNTERS | 0 | 48 |
GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS | 0 | 230400 |
GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS | 230272 | 230272 |
GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS | 0 | 24 |
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS | 32 | 96 |
GL_MAX_COMBINED_UNIFORM_BLOCKS | 28 | 84 |
GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS | 230400 | 230400 |
GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS | 0 | 8 |
GL_MAX_COMPUTE_ATOMIC_COUNTERS | 0 | 8 |
GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS | 0 | 24 |
GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS | 0 | 16 |
GL_MAX_COMPUTE_UNIFORM_BLOCKS | 0 | 14 |
GL_MAX_COMPUTE_UNIFORM_COMPONENTS | 0 | 1024 |
GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS | 0 | 1024 |
GL_MAX_COMPUTE_WORK_GROUP_COUNT | 0 | 65535 |
GL_MAX_VIEWPORT_DIMS | 8192 | 16384 |
Pname | Adreno 330 | Adreno 420 |
---|---|---|
GL_ALIASED_LINE_WIDTH_RANGE | 1 | 1 |
GL_ALIASED_POINT_SIZE_RANGE | 1 | 1 |
GL_MIN_PROGRAM_TEXEL_OFFSET | -8 | -8 |
GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT | 0 | 4 |
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT | 32 | 32 |