【米尔MYD-JX8MMA7开发板-ARM+FPGA架构试用体验】 4.使用ChatGPT来助力测试GPU 大信(QQ:8125036)
感谢
电子发烧友网与米尔科技给予的MYD-JX8MMA7开发板开发板试用机会。MYD-JX8MMA7开发板是一款整合了高性能ARM与较高参数的FPGA芯片的异构硬件平台。
该开发板在高级图形、高级成像、高级机器视觉、高端音频、高端语音、高端视频和高安全的嵌入式应用等跨领域的多种应用场景比较适用。
本次将测试该开发板的GPU图形图像处理能力,并在ChatGPT帮助下使用OpenGL E2.0 开发一个简单的3D模型实时渲染的应用,及使用ChatGPT来开发Shader 2D图像着色器的有趣的例子。
一、OpenGL ES 简介
OpenGL ES (OpenGL forEmbedded Systems) 是 OpenGL三维图形 API 的子集,针对
手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。
OpenGL ES 是从 OpenGL裁剪的定制而来的,去除了glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。经过多年发展,现在主要有两个版本,OpenGL ES 1.x 针对固定管线硬件的,OpenGL ES 2.x 针对可编程管线硬件。OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的,它们分别又支持 common 和 common lite两种profile。lite profile只支持定点实数, 而common profile既支持定点数又支持浮点数。OpenGL ES 2.0 则是参照 OpenGL 2.0 规范定义的,common profile发布于2005-8,引入了对可编程管线的支持。
OpenGLES整体框架如下:
二、GPU性能测试
首先先用开发板上预置的性能测试程序对CPU做测试,应为在使用GPU是,GPU的数据IO和预处理都在CPU上,因此CPU的性能也对整体有明显的影响。
这里使用 nbench 来做测试,Nbench这款软件的测试项目有内存、整形和浮点型三个运算测试项目,软件测试要花10分钟,是一款真正的CPU测试软件。但是作为CPU测试软件,Nbench基于C语言架构设计,是核心运行的基础语言。
系统里已经预置了nbench ,可以直接运行:
cd /usr/bin
./nbench
再使用glmark测试程序来测试GPU的各项性能指标。glmark2是由alexandrosfrantzis和jessebarker基于本·史密斯的原始glmark基准测试,是一个基于 OpenGL 2.0 和 OpenGL ES 2.0 开发的benchmark程序,主要用于对GPU的基准测试,也能够测试对OpenGL各种规格的支撑情况。
执行:glmark2-es2-wayland
在测试时HDMI输出Opengl的各项测试画面:
从中可见分别测试了,缓冲,建筑,照明,纹理,像素填充等图形图像处理中的各种指标性能。
三、开发三维测试程序
测试完GPU之后,进一步使用开发板带的开发工具来测试一下三维图形软件的开发,因为开发板支持QT,QT有对OpenGL的支持,那么就使用QT里的OpenGL的QOpenGLWidget作为OpenGL渲染窗口,来测试一下实测的三维程序开发的OpenGL的性能。
在QT中创建一个窗体工程,即基于widget模板的工程,然后进入窗体设计器中,在控件栏中拖入OpenGLWidget,这样就窗口设计就OK了,非常简单容易:
然后对这个OpenGLWidget写一个派生类,QT系统已经提供了QOPenGLWidget类,因此我们只要添加一个新类,继承此类即可:
然后就可以看到自动生成QOPenGLWidget的派生类的代码:
最后再补全一些必要的三维渲染的函数的实现,以及OPengl必须要的初始化和GPU管线代码,这里主要加入一个正方体3D模型数据以及6面贴图资源。系统自动生成100多行,最后补充代码约10多行,完成的码如下:
然后在X86上编译运行:
然后选择arm-linux编译选项,进行编译
编译完成,点击运行将自动部署到开发板上,并远程在板上启动运行程序,运行效果如图:
四、GLSL 语言简介
在上面的测试代码中可以看到,主要控制GPU显示和运行的是一段脚本文本,它就是shader,也是GPU上执行的语言之一。下面复习一下OpenGL的开发语言GLSL.
1.什么是GLSL
OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。GLSL其使用C语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。
2 GLSL数据类型
GLSL的数据类型可以来指定变量种类。有如下几类:
基础数据类型:int、float、double、uint和bool。
容器类型:向量(Vector)、矩阵(Matrix)。
因为基础数据类型 和C语言类似,因此不多做阐述,主要讲解向量部分和矩阵部分
2.1 向量
@1 向量形式
GLSL中的向量是一个可以包含有1-4个分量的容器,分量的类型可以是前面默认基础类型的任意一个。它们可以是下面的形式(n代表分量的数量):
vecn:包含n个float分量的默认向量
bvecn:包含n个bool分量的向量
ivecn:包含n个int分量的向量
uvecn:包含n个unsigned int分量的向量
dvecn:包含n个double分量的向量
一个向量的分量可以通过vec.x这种方式获取,也可以使用.x、.y、.z和.w来获取它们的其他几个分量。GLSL也允许对颜色使用rgba,或对纹理坐标使用stpq访问相同的分量。
@2 向量重组
向量这一数据类型也允许一些有趣而灵活的分量选择方式,叫做重组(Swizzling)。重组允许这样的语法:
vec2someVec;
vec4differentVec = someVec.xyxx;
vec3anotherVec = differentVec.zyw;
vec4otherVec = someVec.xxxx + anotherVec.yxzy;
可以使用上面4个字母任意组合来创建一个和原来向量一样长的(同类型)新向量,只要原来向量有那些分量即可。
@3 向量传递
我们也可以把一个向量作为一个参数传给不同的向量构造函数,以减少需求参数的数量:
vec2 vect= vec2(0.5f, 0.7f);
vec4 result= vec4(vect, 0.0f, 0.0f);
vec4otherResult = vec4(result.xyz, 1.0f);
总之,向量是一种灵活的数据类型,我们可以把用在各种输入和输出上。
2.2 矩阵
3 输入输出
3.1 输入输出基础
着色器是各自独立的小程序,因此GLSL为每个着色器都定义了in和out关键字专门来实现数据交流和传递。每个着色器使用in和out来设定输入输出,只要一个输出变量与下一个着色器阶段的输入匹配,它的值就会传递下去。但在顶点和片段着色器中会有点不同。
顶点着色器从顶点数据中直接接收输入。
片段着色器需要一个vec4颜色输出变量,因为它需要生成一个最终输出的颜色。
@1 顶点着色器
#version330 core
layout(loca
tion = 0) in vec3 position; // position变量的属性位置值为0
out vec4vertexColor; // 为片段着色器指定一个颜色输出
voidmain()
{
gl_Position = vec4(position, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
vertexColor = vec4(0.0f, 0.0f, 1.0f, 1.0f);// 把输出变量设置为暗红色
}
@2 片段着色器
#version330 core
in vec4vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
out vec4color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
voidmain()
{
color = vertexColor;
}
在顶点着色器中声明了一个vertexColor变量作为vec4输出,并在片段着色器中声明了一个vertexColor变量作为输入。它们名字相同且类型相同,片段着色器中的vertexColor就和顶点着色器中的vertexColor链接了。由于在顶点着色器中将颜色设置为蓝色,最终的片段也是蓝色的。值传递的过程就像是管道连接过程一样。
五、使用 ChatGPT来编写shader代码
为了看看开发板上运行复杂GLSL的GPU代码效果,那么有必要开发一些shader来让GPU运行一下,因为GPU对嵌入式系统来说是一个很大的挑战,能在嵌入式系统上GPU实现到什么程度,看看能出什么样的显示效果,以及渲染的速度,支持GLSL里面哪些函数和方法。下面设计了这样的测试框架:
在上面的例子中,把模型的顶点坐标z轴全改为0,设置观察角度为垂直与xy平面,这样渲染出来就是一张2D的图片,然后通过输入不同shader渲染管线的代码,查看各个代码运行的效果与性能。
要想编写shader代码,这是一个非常专业的领域了,无奈笔者也不是很擅长这块,在思索片刻突然想到,何不把这个问题扔给ChatGPT来试试看呢?
大家都知道最近非常热门的ChatGPT,有非常智能的对话功能,还有非常强大的编程能力!那就让 ChatGPT来编写shader,看看结果吧:
登录openai网站(如何登录不在本文讨论范围内),点击ChatGPT网页,登录账号:
提出让它编写一段shader 例子
它很快就写出了一段完成的代码,把代码复制下来,保存为fragment.glsl 文件,再结合上面的 vertex_shader.glsl文件就可以了,然后直接上板子运行,开始报错误,仔细查看是ChatGPT生成shader代码的入口和我c++代码里的不一致,于是修改一下,运行:
于是得到了这样惊艳的效果:
既然ChatGPT能轻松的写出这样的代码,那就让它多写一些,于是一口气反复让它写了多段的shader,分别上板子运行,得到了这些shader:
分别运行他们,得到这些奇特的效果:
效果都非常不错,大部分的shader画面帧率都能达到30fps以上。
六、GPU测试总结
通过对MYD-JX8MA7开发板的GPU性能与应用测试,主观评估都取得了很好的效果,一般的三维在5000三角面的几何渲染时都达到了60帧以上的速度,在打开纹理与材质的模型上也达到60fps的帧率,打开全局光效和光线反射和半透明材质时也达到了30fps左右的帧率。
支持了OPenGLES 1.0,2.0里的所有特效和规则,所以在运行OpenGLES 的图形时表现非常不错。
开发SDK上对OpenGL的开发也支持完全,有glx的基础开发包,也有QT的opengl开发sdk,也有python的gl包。因此开发起来非常方便。也很容易开发出高性能的图形图像和三维图像的应用。
此次特别使用ChatGPT来编写opengl的渲染管线代码,并且使用这些代码在该嵌入式板上测试运行,大部分ChatGPT的代码都顺利的跑起来,部分代码没有执行成功。总体来说体验非常不错,有了ChatGPT来帮助做专业代码开发,更加能发掘该开发板的潜能。
ChatGPT 生成的 glsl 管线渲染测试程序