IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 计算优化--OpenGL Compute Shader -> 正文阅读

[移动开发]计算优化--OpenGL Compute Shader

前言

compute shader是在OpenGL4.3(Opengl es 3.1)以后引入的一种专门用于并行计算的着色器。在计算着色器中,任务以组为单位进行执行,我们称之为工作组(work group)。拥有邻居的工作组被称为本地工作组(local workgroup), 这些组可以组成更大的组,称为全局工作组(global workgroup),而其通常作为执行命令的一个单位。

compute shader会被每个本地工作组中的每个单元调用一次。工作组的每一个单元称为工作项(work item),每次调用称为一次执行。执行的单元之间可以通过变量和显存进行通信,也可以通过执行同步操作保持一致性。下图显示了一个全局工作组。这个全局工作组包括16个本地工作组,每个本地工作组又包括16个执行单元,排成4X4的网格,每个执行单元拥有一个二维向量表示的索引值。尽管图示中,全局和本地工作组都是2维的,而事实上它们都是3维的,为了适应1维、2维的任务,只需把额外的2维或1维设为0即可。计算着色器的每个执行单元本质是相互独立的,可以并行地在支持OpenGL地GPU上执行。

compute shader性能突出,可以支持复杂的渲染及数据处理等,我们可以用其优化渲染性能,甚至可以做一些复杂数据处理,模型训练等。

实践

本人也是刚上手这个技术,结合着网上的资料,在Android侧率先完成了整个项目的跑通。接下来总结下遇到的问题和最后的实验结果。

首先,机型兼容性问题。由于compute shader 在OpenGL4.3后才引入对应的OpenGL ES是3.1,所以就需要Android5.1以上的平台。

第二在onDrawFrame的时候,viewport需要跟你输出的image的大小(width,height)相同,否则生成的纹理有异样。

第三在onDrawFrame的时候,绑定framebuffer之后需要先进行clear,否则输出的image无数据。

第四在编写shader程序时,输入输出image2D需要显式地指定readonly或writeonly限定其读写权限,不然compile shader程序会失败。

GLES31.glViewport(0,0, width, height);
GLES31.glUseProgram(mProgram);
GLES31.glBindFramebuffer(GLES32.GL_FRAMEBUFFER, mCsFrameBufferID);
GLES31.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES31.glClear(GLES32.GL_COLOR_BUFFER_BIT | GLES32.GL_DEPTH_BUFFER_BIT);

最后在compute shader中,image2D需要使用layout 方式进行绑定,使用binding指定位置序列,不能使用glGetUniformLocation的方式获取位置序号。

layout (rgba8, binding = 1)   uniform readonly image2D colorAndDepthTexture;
layout (rgba8, binding = 2)   uniform writeonly image2D outputImage;

下面贴出部分关键代码:

OpenGL 渲染环境


class ComputeActivity : Activity() {
    private var env: GLSurfaceView? = null
    protected fun onCreate(@Nullable savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_compute)
        env = findViewById(R.id.glsv)
        env.setEGLContextClientVersion(3)
        env.setRenderer(ComputeRender(this))
        env.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY)
    }
}

Shader程序

layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
 
uniform float v[1000];
layout(binding = 0, rgba8) readonly uniform  image2D input_image;
layout(binding = 1, rgba8) writeonly uniform  image2D output_image;
 
shared vec4 scanline[8][8];
 
void main(void)
{
    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
    scanline[pos.x][pos.y] = imageLoad(input_image, pos);
    barrier();
    vec4 data = scanline[pos.x][pos.y];
    data.r = data.r + v[999] ;
    data.g = data.g;
    data.b = data.b;
    data.a = data.a;
    imageStore(output_image, pos.xy, data);
}

执行计算

private fun performCompute(inputTeture: Int, outputTexture: Int) {
        GLES31.glUseProgram(0);
        GLES31.glUseProgram(computeProgram);
        GLES31.glUniform1fv(
            GLES31.glGetUniformLocation(mComputeProg, "v"),
            mValueSize,
            mValueBuffer
        )
        GLES31.glBindImageTexture(
            0,
            inputTeture,
            0,
            false,
            0,
            GLES31.GL_READ_ONLY,
            GLES31.GL_RGBA8
        )
        GLES31.glBindImageTexture(
            1,
            outputTexture,
            0,
            false,
            0,
            GLES31.GL_WRITE_ONLY,
            GLES31.GL_RGBA8
        )
        GLES31.glDispatchCompute(1, 1, 1)
        GLES31.glMemoryBarrier(GLES31.GL_ALL_SHADER_BITS)
    }

?结果

fun onDrawFrame(gl: GL10?) {
        val begin = System.currentTimeMillis()
        performCompute(fTexture.get(0), fTexture.get(1))
        performCompute(fTexture.get(1), fTexture.get(2))
        Log.w(TAG, "total compute spent:" + (System.currentTimeMillis() - begin))
    }

经测试在华为荣耀20 pro手机上,Android 10的版本,运行1000次计算着色器计算,也仅耗时20~30ms。欢迎关注微信号

参考

https://blog.csdn.net/koibiki/article/details/80590885

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:26:57  更:2022-10-22 21:29:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:21:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码