第二章:unity性能优化之drawcall优化-1

news2024/11/18 5:35:20

目录

 前言:

一、什么是drawcall

二、如何合批

 1、什么是合批?

  2、静态批处理

1、什么是静态批处理:

2、静态合批的规则

3、动态批处理

4、GPU Instancing

1、GPU instancing的定义       

2、编写支持GPU instancing Shader步骤

5、Scriptable Render Pipeline Batch(SRP Batch)

1、SRP Batch的定义

2、SRP Batch工作原理

3、SRP Batch规则

4、支持SRP Batch的管线 

总结:


 前言:

       

        有时候内存并不是我们的瓶颈,可能渲染drawcall过多是我们的压力,drawcall过多的最直接后果是程序可能卡,耗电量大等表现。

        移动端的程序不比PC端,留给程序员的优化空间比较小,一般对于相应的渲染指标都比较苛刻。那么设定多少个Drawcall是一个比较合理的标准呢,一般情况下,我们应该尽可能将控制在Drawcall在200平均值一下,对于效果特别要求的可以在250左右,不建议超过这个数

          在讲解drawcall之前,我们先讲解下什么是Drawcall

一、什么是drawcall

        drawcall是cpu对图形绘制接口的调用,CPU通过调用图形库(directx/opengl)接口,命令GPU进行渲染操作。

CPU和GPU之间的数据是通过命令冲区commandBuffer进行传输的。命令缓冲区包含了一个队列,由CPU向其中添加命令,GPU去读取命令,添加和读取的命令都是相互独立的。当CPU需要渲染一个对象时,就可以向命令缓冲区中添加命令,而当GPU完成上一个渲染任务后,就会从命令缓冲区中再取出一条命令并执行它。在渲染绘制过程有很多命令,drawcall就是其中一种。

        我们经常认为,Drawcall是通常认为GPU是Drawcall产生的瓶颈,其实不然,真正的元凶是CPU。

        在每次调用DrawCall之前,CPU需要向GPU发送很多内容,包括数据、状态和命令等。在这一阶段,CPU需要完成很多工作,例如检查渲染状态等。而一旦CPU完成了这些准备工作,GPU就可以开始本次渲染。GPU的渲染能力很强,渲染速度往往快于CPU提交命令的速度,相对来说CPU与GPU命令交互的过程是非常耗时,CPU在等待GPU指令返回之前这期间什么都做不了。如果DrawCall的数量太多,CPU就会把大量时间花费在提交DrawCall上,造成CPU的过载。

        比如:我们渲染10个模型,如果每次渲染时都调用一次Drawcall,那么总共需要调用10次Drawcall;如果10个模型能够合并调用,那么只需要调用一次drawcall,减少了CPU与GPU的指令交互的时间,性能不言而喻,自然就提升了许多。

        既然drawcall是主要的性能瓶颈,那么如何减少Drawcall呢?合批(Draw Call Batching)就是最终的解决办法。


二、如何合批

    1、什么是合批?

                将多个渲染对象的CPU渲染指令统一一起来向GUP提交,将多个独立Drawcall合并成给

        一个drawcall的指令方式。

        绘制调用批处理是一种组合mesh的绘制调用优化方法,以便Unity可以在较少的绘制调用中render mesh 。Unity提供以下内置的绘制调用批处理方法:

                静态批处理(Static batching

                动态批处理(Dynamic batching

                SRP Batcher (只在UPR或SRP项目中有效)
        对于合批是有些限定的,基本规则如下: 

                1)带有如MeshRender、TrailRender、LineRender、ParticleSystem、SpriteRender组

                     件的mesh支持合批。

                2)带有SkinMeshRender和 布料模拟的mesh是不能合批。

                GPU Instancing

  2、静态批处理

            1、什么是静态批处理:

                     静态批处理是一种绘制调用批处理方法,它结合了不移动的mesh以减少绘制调用。

                     它将组合的mesh转换为世界空间,并为它们构建一个共享的顶点和索引缓冲区。然

                     后,对于可见模型,Unity执行一系列简单的绘制调用,每个调用之间几乎没有状态变

                     化。

                     静态批处理不会减少绘制调用的数量,而是减少它们之间的渲染状态更改的数量

                     态批处理比动态批处理更有效,因为静态批处理不会转换CPU上的顶点。

        对于静态mesh,Unity将其组合并一起渲染。将场景的物件勾选static就是告诉编辑器,该Game Object对象不能被移动并且需要合批。

如图:

    2、静态合批的规则

          1)必须符合合批的基本规则

          2)必须是static类型的mesh,不能移动的mesh

          3)mesh是一样的并且材质相同,有meshRender组件

          4)在大多数平台上,批处理限制为 64k 个顶点和 64k 个索引(OpenGLES 上为 48k 个索

                引,在 macOS 上为 32k 个索引)如果超过会合批成另外个mesh

          5)合批的mesh如果Scale不同无法合批,合批会被打断

          6)相同顶线信息和UV的才能一起合批:

                如:Unity可以对使用顶点位置、顶点法线和一个UV的mesh进行批处理,但不能与顶点

                坐标、顶点法线、UV0、UV1和顶点切线的mesh一起批处理

           7)mesh顶点数必须大于0

           8)Mesh Renderer component组件不使用具有DisableBatching标记设置为true的着色器的

                任何材质。

          9)不同的贴图信息的无法合批。如:烘焙的光照贴图不相同的mesh无法合批在一起

          10)模型的GameObject必须是active状态

          11)位置不相邻的中间夹杂着不同材质的其他物体,不会批处理。

          12)动态改变Render.material会造成一个新的material拷贝,应该使用render.shareMaterial

                 保证材质共享,否则不能合批。


3、动态批处理

      1、动态合批的定义

             对于足够小的mesh,这将在CPU上变换它们的顶点,将相似的顶点分组在一起,并在一

              次绘制调用中渲染它们。

              Unity build-in的调用批处理比手动合并mesh有几个优点;最值得注意的是,Unity仍然可

              以单独剔除mesh。然而dynamic batch会导致一些CPU开销。

      2、动态合批规则:

                1)Unity 无法将动态批处理应用于包含超过 900 个顶点属性和 300 个顶点的网格。

                这是因为网格的动态批处理具有每个顶点的开销。例如,如果您的着色器使用顶点

                位置、顶点法线和单个 UV,则 Unity 最多可以批处理 300 个顶点。但是,如果您

                的着色器使用顶点位置、顶点法线、UV0、UV1 和顶点切线,则 Unity 只能批处理 180

                个顶点。

                2)Unity 无法将动态批处理应用于在其变换组件中包含镜像的对象。例如,如果一个对

                    象的比例为 1,而另一个游戏对象的缩放比例为 –1,Unity 无法将它们批处理在一

                    起。

       

                 3)如果对象使用不同的material实例,Unity 无法将它们批处理在一起,即使它们本质

                    上是相同的。Shadow cast是个例外,仅管Shadow casters使用不同的材质,但是只

                    要它们的材质中给Shadow Caster Pass使用的参数是相同的,他们也能够进行

                    Dynamic batching。

                4)具有lightmap的GameObject具有其他渲染器参数。这意味着,如果要批量光照贴图

                     游戏对象,它们必须指向相同的光照贴图位置。

                5)Unity 无法将dynamic batch完全应用于使用多passShader的对象。

                6)几乎所有 Unity 着色器都支持Forward render中的多个光源。为了实现这一点,他们

                     为每个光源处理一个额外的render pass。Unity 仅对第一个pass进行批处理。它无法

                dynamic batch附加的每个光源的所产生的pass 进行合批处理。

                7)旧版延迟渲染路径,不支持动态批处理,因为它在两个渲染通道中绘制对象。第一遍

                     是轻量级预传递,第二遍渲染对象。


4、GPU Instancing

1、GPU instancing的定义       

        GPU Instancing是一种drawcall优化方法,它在一次绘图调用中使用相同材质render mesh 的

        多个副本。多个mesh的副本都称为Instance。这对于绘制场景中多次出现的对象非常有用,

        例如树或灌木丛。GPU实例化在同一drawcall中渲染相同的mesh。

        每个实例可以具有不同的属性,例如“Color或“Scale”。要对材质使用GPU实例,请在

        material 中Inspector中属性中选择"Enable GPU instacing”选项。、

是否是所有的都支持GPU Instancing?答案肯定不是。只有在支持GPU Instancing的shader才有可能

2、编写支持GPU instancing Shader步骤

shader编写一定需要经历如下几步:

Shader"MyGPUInstance"{
    Properties{
        ...
    }
    SubShader{
        ...
        Pass{
            ...
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #pragma multi_compile_instancing //第一步
            ...
            struct a2v{
                ...
                UNITY_VERTEX_INPUT_INSTANCE_ID //第二步

            };
            struct v2f{
                ...
                UNITY_VERTEX_INPUT_INSTANCE_ID //第二步
            };
            v2f vert(a2v v){
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v); //这里第三步
                UNITY_TRANSFER_INSTANCE_ID(v,o); //第三步
                ...
                return o;
            }
            fixed4 frag(v2f i):SV_Target{
                UNITY_SETUP_INSTANCE_ID(i); //最后一步
                ...
            }
            ENDCG
        }
    }
    FallBack"Diffuse"
}

并且在材质面中勾选 Eanble GPU Instancing选项。如图:


5、Scriptable Render Pipeline Batch(SRP Batch)

1、SRP Batch的定义

SRP Batcher是一个渲染循环(loop),可以让相同的shader Variant的材质的GameObject能够进行合批,加速你的CPU渲染。

SRP Batcher 通过批处理(batching)一系列绑定(Bind)和绘制(Draw)GPU 命令,来减少DrawCalls之间的GPU设置(工作量)。也就是之前一堆绑定和绘制的GPU命令能够集合的集合起来,不需要一步步设置而来减少CPU与GPU交互次数,从而减少CPU执行的时间。

2、SRP Batch工作原理

传统的合批方法是减少绘制的对象。相反,SRP Batch是减少渲染的状态和执行过程。

我们看到在内置渲染管线中我们需要设置Meterial和Object CBUFFER,如果材质参数不同,会被打断;但是对于SRP渲染管线,只有变体不同时,才会被打断合批。

3、SRP Batch规则:

  1. GameObject必须包含mesh或者 skinned mesh。它不能是粒子。
  2. Game Object没有使用MaterialPropertyBlocks设置材质信息
  3. Shader必须兼容SRP

         

4、支持SRP Batch的管线 

功能

内置渲染管线

通用渲染管线 (URP)

高清渲染管线 (HDRP)

Custom Scriptable

Render Pipeline (SRP)

SRP Batcher


总结:

        对于合批,我们应该实际情况做出选择,它们的合批效率从高到低依次是static->GPU instancing-->Dynamic->SRP。我们知道合批的基本条件是同一个模型,并且是同一份材质信息(动态合批和SRP可以不同)。我们不仅要了解合批的规则,我们也要了解合批限制与在什么情况下被中断,同时要了解他们的优劣,才能选择合适的合批方式。

        由于篇幅原因,该篇主要讲解内容是drawcall 在什么情况产生的以及 减少drawcal的常用方法。下篇我会以项目的具体内容角度讲解如何对drawcall细致优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/349896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Blazor 托管模型 BlazorWebAssembly和Blazor Server

BlazorWebAssembly 应用 BlazorWebAssembly 应用使用基于 WebAssembly 的 .NET 运行时在浏览器中直接执行。 BlazorWebAssembly 应用的工作方式类似于 Angular 和 React 等前端 JavaScript 框架。 但不是编写 JavaScript,而是编写 C#。 .NET 运行时与应用、应用程序…

day18_常用API之String类丶Object类

String概述 java.lang.String 类代表字符串,String类定义的变量可以用于指向字符串对象,同时String类提供了很多操作字符串的功能,我们可以直接使用。Java 程序中的所有字符串文字(例如“abc”)都为此类的对象 特点:St…

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑 前文: blog.csdn.net/weixin_53403301/article/details/128216064 【STM32笔记】HAL库低功耗模式配置(ADC唤醒无法使用、低功耗模式无法烧录解决方案) blog.csdn.net/weixin_534033…

最强找茬小程序

文章目录准备工作环境要求安装步骤效果展示源码下载最强找茬小程序,支持好友对战 准备工作 准备一个Linux系统的云服务器 centos7或ubuntu 安装宝塔面板(不是必需的,建议安装这个) 买一个域名,并配置ssl证书&#x…

NX二次开发编译时dll自动数字签名及拷贝

前言 在UG5.0开始,所有基于UG二次开发的DLL都要“签名”后才能被客户端上正版的NX调用。 一、基于C# 开发签名 1、添加资源文件 (1)项目类库上右键–>属性–>资源–>添加资源右边小三角–>添加现有文件–>切换到UG安装目录下…

Java SSM 笔记(一)重置版

Spring核心技术 **前置课程要求:**请各位小伙伴先完成《JavaWeb》篇、《Java 9-17新特性》篇视频教程之后,再来观看此教程。 **建议:**对Java开发还不是很熟悉的同学,最好先花费半个月到一个月时间大量地去编写小项目&#xff0…

Source lnsight工具的简单使用

多文件编程推荐用Source lnsight工具来进行编写 一、Source lnsight工具的简单使用 1、在桌面上新建一个文件夹factory,在文件夹里新建一个cat.c文件和si文件夹 2、打开Source lnsight工具,点击上方Project--->New Project 3、把文件夹factory中si文…

2023年初级会计职称考试《经济法基础》大纲变动内容

整体变动:2023年度考试大纲主要作了以下调整:1. 第四章中增加了增值税出口退税和地方教育附加相关内容;2. 第五章中增加了企业重组业务企业所得税处理,企业所得税特别纳税调整和纳税电报表相关内容;3. 第六章中增加了印花税相关内容。具体变动:第一章 总论无变化第二…

QML矩形(Rectangle)

Rectangle 用于绘制矩形 常见的属性: 填充颜色:纯色:color 渐变 :Gradient类 渐变的优先级大于纯色Gradient(渐变色): 渐变由多种颜色定义,这些颜色将无缝混合&#xff0c…

【前端基础问题】浏览器调起桌面通知功能 Notification

浏览器调起桌面通知功能 Notification一、Notification二、注意事项三、使用步骤1、向用户发起权限请求2、调用 Notification API 进行推送消息四、完整代码五、效果一、Notification Notifications API 允许网页或应用程序在系统级别发送在页面外部显示的通知;这样即使应用程序…

【Servlet+Jsp+Mybatis+Maven】WEB图书馆管理系统

web图书馆管理系统一、绪论二、流程和其页面展示效果流程页面效果项目结构三、具体实现第一步:备数据库表第二步:编写登录前端代码第三步:利用过滤器处理安全问题第四步:控制层去实现相关调用第五步:实现持久化层与数据…

教你如何搭建人事OA-薪资管理系统,demo可分享

1、简介1.1、案例简介本文将介绍,如何搭建人事OA-薪资管理。1.2、应用场景根据设置薪资基础及考勤和绩效的数据计算得到各个员工工资详情。2、设置方法2.1、表单搭建1)新建表单【工资表】,字段设置如下;名称类型名称类型人员资料分…

一款私有化部署的企业级在线文档和知识库

项目介绍基础说明:无忧企业文档是JVS体系下的一款企业协同在线文档,主要服务客群为企业用户,解决企业内部文档编辑、知识沉淀、知识协同等痛点。项目主要采用Java开发,基础框架采用JVS(spring cloudVue)适用…

基于微信小程序的一款小程序版知乎

从零开始开发的一款小程序,所以没有使用任何框架及UI库,记录一下本次开发中踩过的坑吧~展示效果(界面样式设计与交互来自iOS 4.8.0版本知乎App):项目地址:https://download.csdn.net一、开始前的准备申请账号:根据小程…

钉钉配置事件订阅(Python)

钉钉配置事件订阅 0.需求分析 需要实现钉钉企业通讯录同步至企业微信通讯录,这就需要用到钉钉的事件与回调 1.配置应用 登陆开放平台 https://open-dev.dingtalk.com/去企业内部开发里面,先创建个应用,后面都借用这个应用来调接口 创建完…

自定义分库分表组件(实现分库分表的组件)——java

系列文章目录 文章目录系列文章目录前言一、所需技术二、技术总结1. ThreadLocal2.HashMap三、实现1、定义路由注解自定义注解格式要求元注解: 用于描述注解的注解在程序使用(解析)注解:获取注解中定义的属性值小例子:注解定义一个简单的测试…

AI算法创新赛-人车目标检测竞赛总结03

团队简介AI0000032 团队成员均为从事计算机视觉领域的企业员工,热爱技术,勇于挑战,致力于更通用目标检测算法的研究与落地。团队由三人组成,队长何正海 主要负责整体方案设计与模型的量化工作,余洋主要负责模型训练与调…

YOLOV5输出的txt里面有什么猫腻(用于图像分类竞赛中提升图像信息密度)

背景概括: kaggle最近举办了一场医学乳腺癌检测的比赛(图像分类) 比赛官网地址 给的数据是dcm的专业的医学格式,自己通过DICOM库转为png后,发现该图像胸部不同的患者乳腺大小不一,简言之乳腺的CT有效图在…

MySQL性能调优与设计——MySQL中的索引

MySQL中的索引 InnoDB存储引擎支持以下几种常见索引:B树索引、全文索引、哈希索引,其中比较关键的是B树索引。 B树索引 InnoDB中的索引自然也是按照B树来组织的,B树的叶子节点用来存放数据。 聚集索引/聚簇索引 InnoDB中使用了聚集索引&…

LeetCode 141. 环形链表

原题链接 难度:easy\color{Green}{easy}easy 题目描述 给你一个链表的头节点 headheadhead ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 nextnextnext 指针再次到达,则链表中存在环。 为了表示给定链表中的…