找回密码
 立即注册
查看: 301|回复: 0

[杂谈]渲染性能优化

[复制链接]
发表于 2023-4-20 07:11 | 显示全部楼层 |阅读模式
一、负载均衡优化

对于GPU密集型的应用程序,瓶颈常常会发生在GPU侧,而发生的原因是GPU各部件的工作负载不均衡,导致了性能瓶颈。
通过合理分摊GPU各部件的工作负载,可以有效消除瓶颈,充分发挥GPU的功效,提升渲染性能。以下是可区分工作负载的GPU资源:
1、ALU(逻辑运算单元)
在GPU中,ALU(Arithmetic Logic Unit,算术逻辑单元)是一种专门处理数字运算和逻辑运算的硬件单元。GPU中的ALU数量通常比CPU中的要多,因为GPU需要同时处理大量的图形和计算任务。
GPU中的ALU通常由多个计算单元组成,可以执行多个算术和逻辑运算,如加法、减法、乘法、除法、比较、位移等。这些运算单元被组织成一组流处理器(Streaming Processor,SP),可以同时处理多个数据元素,如像素、顶点等。
在GPU中,ALU通常与寄存器文件(Register File)和高速缓存(Cache)等硬件单元一起工作,用于执行着色器程序。着色器程序是GPU中实现图形渲染和计算任务的核心代码,包括顶点着色器、像素着色器、几何着色器、计算着色器等。这些着色器程序通常由GPU的驱动程序生成,并通过API(如OpenGL、DirectX)调用,向GPU发送绘制指令和计算任务。
在GPU中,ALU通常被设计为高度并行化和高效的硬件单元,可以执行大量的计算任务,并通过多线程、向量化、流水线等技术来提高计算性能。对于大规模的图形渲染和计算任务,GPU的ALU能够提供非常高的计算性能和吞吐量。
2、Texturing Load(纹理加载)
在GPU中,Texturing Load(纹理加载)是一种从纹理存储器(Texture Memory)中加载数据的操作。纹理存储器通常是GPU中一种专门用于存储纹理数据的高速缓存,可以存储2D或3D纹理数据,并提供快速的读取和过滤操作。
Texturing Load通常由着色器程序调用,用于从纹理存储器中加载纹理数据,以便在渲染过程中进行纹理映射。纹理映射是一种将纹理数据映射到三维物体表面上的过程,以增加渲染的真实感和细节。
在进行Texturing Load操作时,GPU会根据着色器程序中的纹理坐标,从纹理存储器中读取相应的纹理数据,并进行过滤操作,以确保渲染结果的平滑和真实。GPU中的纹理过滤通常包括点采样、双线性插值、三线性插值等技术,可以根据纹理坐标和相邻纹理像素的颜色进行加权平均,以获得更平滑和真实的纹理映射效果。
总之,Texturing Load是GPU中一种重要的操作,用于从纹理存储器中加载纹理数据,并进行过滤操作,以进行纹理映射,提高渲染效果和细节。
3、ISP Load(图像综合处理器加载)
在GPU中,ISP Load(Image Signal Processor Load,图像综合处理器加载)是一种用于从相机传感器中加载图像数据的操作。相机传感器通常是一种专门用于捕获光学信号并将其转换为数字图像的硬件设备,可以捕获2D或3D图像,并输出数字信号。
ISP Load通常由GPU的图像处理单元(Image Processing Unit,IPU)调用,用于从相机传感器中读取图像数据,并进行预处理、解码、色彩转换等操作,以便在渲染过程中进行图像显示或分析。
在进行ISP Load操作时,GPU会根据传感器的输出信号,将其转换为数字图像,并进行一系列的预处理和解码操作,以获得更高质量和更逼真的图像效果。这些操作通常包括去噪、锐化、降噪、去马赛克等技术,可以提高图像的清晰度和细节,并减少图像噪声和失真。
总之,ISP Load是GPU中一种重要的操作,用于从相机传感器中加载图像数据,并进行预处理和解码操作,以便在渲染过程中进行图像显示或分析。通过ISP Load操作,GPU可以获得更高质量和更逼真的图像效果,提高渲染的真实感和细节
4、Renderer Active(渲染器活动)
在GPU中,Renderer Active(渲染器活动)是指GPU中正在进行渲染操作的状态。当GPU处于Renderer Active状态时,它会执行渲染管线中的各个阶段,包括顶点处理、图元组装、光栅化、像素处理等,以生成最终的渲染结果。
Renderer Active状态通常由应用程序触发,即应用程序向GPU提交渲染命令后,GPU开始执行渲染操作,并进入Renderer Active状态。在这种状态下,GPU会不断地从应用程序中获取渲染命令,并执行相应的渲染操作,直到所有的渲染命令都被执行完毕,或者应用程序中断了渲染操作。
在Renderer Active状态下,GPU会占用大量的计算和存储资源,并执行大量的并行计算操作,以加速渲染过程。因此,在进行大规模的渲染操作时,需要优化渲染流程和算法,以确保GPU能够高效地执行渲染操作,并生成高质量的渲染结果。
总之,Renderer Active是GPU中一种重要的状态,用于指示GPU正在进行渲染操作。在这种状态下,GPU会执行渲染管线中的各个阶段,并生成最终的渲染结果。通过优化渲染流程和算法,可以提高GPU的渲染效率和渲染质量,从而实现更高效、更真实的渲染效果。
5、Tiler Active(分块器活动)
在GPU中,Tiler Active(分块器活动)是指GPU中正在进行分块操作的状态。分块器是GPU中一个重要的硬件单元,用于将大型渲染任务分成多个小块,以便在GPU内存中进行高效的渲染操作。
在Tiler Active状态下,GPU会将渲染任务划分成多个小块,并将这些小块分配到GPU内存中的不同区域,以便进行并行渲染操作。分块器通常会根据渲染任务的大小和复杂度,调整分块的大小和数量,以确保GPU可以高效地处理渲染任务,并在最短时间内生成高质量的渲染结果。
Tiler Active状态通常由应用程序触发,即应用程序向GPU提交渲染命令后,GPU开始执行分块操作,并进入Tiler Active状态。在这种状态下,GPU会不断地从应用程序中获取渲染命令,并将渲染任务分块,以便进行高效的并行渲染操作。
总之,Tiler Active是GPU中一种重要的状态,用于指示GPU正在进行分块操作。通过使用分块器,GPU可以将大型渲染任务分成多个小块,以便在GPU内存中进行高效的并行渲染操作。通过优化分块大小和数量,可以提高GPU的渲染效率和渲染质量,从而实现更高效、更真实的渲染效果。
通过GPU厂商提供的Profiler(如Snapdragon Profiler、PVRMonitor),可以有效监控它们的动态。下面是均衡工作负载的优化描述:
1、使用预计算并将结果存储在查找表(LUT),可以将ALU的工作转移到Texturing Load。
2、使用程序纹理函数代替纹理获取,可以将Texturing Load的工作转移到ALU。
3、使用深度和模板测试减少着色器调用,从而减少纹理负载或ALU的工作量。
4、基于ALU的Alpha test可以用来交换深度prepass和深度测试,会增加draw call和几何开销,但可以显著降低ALU工作量和寄存器压力。
5、Alpha test和噪声函数结合使用来实现LOD过渡效果,会极大提升ALU工作量。在这种情况下,可以执行模板prepass来转移ALU工作量到ISP。
6、高保真画质可以提供更复杂的着色器、更高的分辨率纹理、增加多边形数量来提高。当渲染达到瓶颈时,更好的做法是增加多边形数量,而不是增加片元着色器的复杂度。
二、渲染优化概述

一、 drawcall数量优化
       1、几何实例化
       2、简接绘制
       3、glMultiDraw
       4、图元重启
       5、合批
       6、遮挡查询
二、纹理优化
       1、ASTC,EAC,ETC1,ETC2
       2、MipMap纹理
       3、不可变纹理
       4、纹理采样器对象
       5、使用像素解包缓冲区,将纹理上载到GPU中,不影响CPU时钟
三、带宽优化
       1、VAO+VBO(TBDR下避免缓存Miss而使用多个VBO,mali内置处理TRS)
       2、FrameBufferFetch+PixelLocalStage
       3、glBlitFrameBuffer
       4、glColorMask
       5、glInvalidateFramebuffer
       6、glVertexAttribPointer拆解: glVertexAttribFormat指定顶点格式参数,glBindVertexBuffer指定缓冲区绑定
四、shader优化
       1、二进制着色器码
       2、单独的着色器对象+管道对象
       3、计算着色器
       4、顶点纹理、TBO
       5、UBO常量内存
       6、SSBO全局内存
       7、HalfFloat及Float
       8、if的减少
五、缓冲区相关
       1、映射缓冲区
       2、复制缓冲区
       3、变换反馈缓冲区
六、读图相关优化
       1、使用PBO(像素打包缓冲区,将数据从GPU打包到纹理,不影响CPU时钟)
       2、使用HardwareBuffer,共享内存(CPU\GPU)
       3、CPU-GPU同步原语:eglSwapBuffer、glFinsh、glReadPixel、glFlush、glFence
六、架构相关
       1、RenderGraph优化显存及调节内存屏障的时机
       2、OGL中进行渲染状态缓存,减少OGL的状态切换的耗费
       3、多线程渲染优化
       4、SceneNode中的场景剪裁优化
       5、RenderPipeline中一些在预处理阶段的优化
三、shader具体优化

1、着色器二进制码
2、单独的着色器对象+管道对象
3、ifelse中各有大量计算的判断,应该减少;并且避免动态分支判断,用min(), max(), clamp(), mix(), saturate()避免动态分支会减少时间局部性,但增加缓存压力
4、使用uniformbufferobject,解决uniforom变量与shader绑定;注意大小,小于8kb在常量内存,大于8kb则转存全局内存
5、使用计算着色器解决大量计算问题,但要注意平台是否支持SSBO,mali不支持SSBO,则使用图像变量
6、使用HalfFloat精度,避免Float精度,避免带宽的增加
7、使用适当的数据类型
8、减少类型的转换
9、避免一些依赖性纹理的读取,会导致等待
10、减少采样的次数,能预计算就预计算
11、避免在片段着色器使用discard,在powver架构会造成管线暂停去回写数据
12、不要在着色器频繁的切换空间计算;可将一些不需插值的计算放到顶点着色器
13、GLES提供了glReleaseShaderCompiler函数,标记着色器源码已经编译完成,可以释放其相关的资源了,为后续的着色器编译提供资源空间
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-19 05:32 , Processed in 0.097374 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表