Adreno OpenGL ES 3.1 介绍(7)

举报
knightaa 发表于 2021/12/10 15:00:51 2021/12/10
【摘要】 4.2.3.3 设置图像到目前为止,已经讨论了该示例如何使用计算着色器。本节将仔细研究图像单元和图像uniform 的配置方式。 回忆一下,着色器调用使用它们来存储其结果值。与之前的示例一样,资源在第一次渲染时通过负责渲染帧的函数_rendering_handler进行初始化。这是设置图像uniform的方法:    glGenTextures(1, &_texture);    glBin...

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是一个难题。 频繁的编程错误。

    1

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

    1

内存屏障可确保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常量值
表 4-1 OpenGL ES 3.1 - GL_MAX 常量值
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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。