[ue4] 着色器绑定(Shader Binding)
当我们在ue4中制作了一个美术材质之后,引擎本身会为我们做很多事情,它会把结点翻译为hlsl,生成多个shader变体,并在多个mesh pass中去选择性的调用所需的shader,其中一个重要的过程就是获取shader绑定的数据。
本文将主要讨论ue4是如何处理来自材质的不同的输入,它们将以怎样的形式传递给shader,以怎样的频率更新,并在调用层做了怎样的优化处理。
输入类型
我们在材质中能控制输入的地方有两处,一个是材质直接输入,另一个是材质参数集合:
① 材质直接输入。
我们可以在母材质中开放给shader的参数,如美术纹理和参数。静态的参数我们使用静态材质,动态可运行时修改的参数我们使用动态材质。
这种输入的特点是每个材质独享一份参数输入,因此它在底层设计为每个Material实例独立的Uniform Buffer,在ue4中使用FUniformExpressionCache数据结构来描述。
② 材质参数集合(MPC, Material Parameter Collection)
我们还可以创建MPC资产,可以添加vector或scalar参数。
这种输入的特点是参数可以在多个材质共享,比较适合一些全场景的效果控制,但一个材质支持输入的MPC数量是比较有限的。
它在底层设计为场景中全局的Uniform Buffer集合,同时每个shader引用到的MPC索引由FUniformExpressionCache记录,可方便我们快速查找。
材质会生成多个shader变体,其中可能包括prepass, shadowpass, basepass的vs和ps,根据顶点类型的不同可能还包括了不同的顶点工厂(Vertex Factory),比如staticmesh, instance或skeletal。这些shader是在代码中定义的,每个特定的shader还可以指定一些输入。
③ 顶点工厂的输入
主要包括的是顶点属性(Vertex Attribute)的输入,包括位置、法线、顶点色、实例位置等。我们可以使用Vertex Buffer或Buffer传输这些数据。
④ 顶点或像素着色器的输入
主要包括的是更加底层模块的一些输入,比如光照/阴影/大气等的输入。
这部分的输入格式是由代码指定的,和材质中主要通过Uniform Buffer来绑定不一样,这里输入的格式更加灵活,一些共用的数据可能会放在Uniform Buffer中,而一些常量(Loose Data)可能直接绑定到shader中,我们还可以绑定一些资源类型的数据(SRV),比如Texture2D, Buffer, Structure Buffer等。
⑤ 全局输入
在多个shader中共享的数据或者一些必需的数据会设计在全局的Uniform Buffer中。
比如在basepass和defer pass中都可能会用到的各种LightUniformBuffer,存储灯光方向等信息;几乎在所有pass都会用到的ViewUniformBuffer,存储相机位置等信息。
还设计了一些高频数据作为独立的Unform Buffer,比如逐物件的PrimitivieUniformBuffer等;
输入上传
ue4在开始计算场景可见性(SceneVisibility)前,会先尽早地完成一些数据的上传,让GPU先开始忙碌起来,这样的话可以不阻碍后续的一些渲染工作,包括:
① 上传Primitive Uniform Buffer(静态物件初始化调用,动态物件多帧上传)
② 上传GPU Skin(蒙皮物件动画信息)
③ 上传Material Uniform Buffer(静态材质初始化调用,动态材质多帧上传)
④ 上传Material Parameter Collection(更新时上传)
⑤ 上传一些代码中定义的Uniform Buffer(如View等)
还有一部分数据比如LightmapUniformBuffer一般都是静态的,所以不会频繁更新,我们也较难捕获到这方面的数据。
单个ub数据上传的时间并不算太长,大概是us的量级。但如果场景中使用了大量的动态物件和动态材质,整体的上传时间还是比较可观的。
输入绑定
当我们向shader传入特定输入的时候,意味着shader中应该有对应的变量。材质中的变量是由ue4自动生成的,而代码中则是程序指定的变量。
在整个绘制工作流中,我们会首先完成shader的编译,并且去收集这些shader中存在的绑定信息。当我们在C++中收集绑定输入的实际值时,会先去校验shader中对应的绑定点和slot id。
绑定类型
ue4的Mesh Draw管线中,我们使用Shader Binding来完成这一点,它是一种延迟的设计,因为它会先去收集所有可用的绑定实参,提交前再调用实际的RHI层的绑定。
它支持的类型包括Uniform Buffer,Sampler,SRV(texture, buffer),Loose Data,顶点的输入则由Input Stream负责,不包含在Shader Binding负责的范畴中。所有的绑定信息我们可以认为是一个Input Layout,它可编码为缓冲区。
其中,Uniform Buffer, Sampler, SRV记录的是实际分配的引用,是一种分离式的设计;而Loose Data是我们直接绑定在shader上的参数,存储了实际的数据,可以理解为一个内联的常量数据。
API映射
我们在API中完成一次drawcall,通常会设置首先去各种状态量和绑定量,包括:
● SetPipelineState
● SetVertexBuffer/ SetIndexBuffer
● SetShaderBinding
对于CPU端来说,消耗主要体现在数据的准备和调用上;实际指令执行的过程中,GPU也会产生状态切换的消耗。
在API底层,如在Vulkan中,Shader Binding的调用会被映射为vkCmdBindDescriptorSets;dx12则相对复杂,它可能会映射到SetGraphicsRootConstantBufferView或SetGraphicsRootDescriptorTable等。
Vulkan的设计可能会产生更少的调用,而DX12的设计会更加适合输入排列的复用,但大多数的游戏引擎并不会优化到这么细致。
输入调用
在输入调用上,Shader Binding之所以要设计为延迟调用,是为了尽可能缓存一些绑定命令,减少CPU端渲染指令调用的次数。缓存的可复用性依赖于绘制对象的排序,我们应该尽可能把共享相同状态的对象合并到一起。
在缓存机制上,我们可以去缓存的内容包括PipelineState,它包含的最重要内容就是Shader,如果Shader Code完全一致仅仅是输入不同我们是可以缓存的。其次是一些输入,比如Uniform Buffer, SRV等,这些数据的缓存会对一些图形API产生收益。
Vertex Buffer和Index Buffer是比较特殊的阶段,我们没有办法去缓存这些数据。
实际实现中,Shader Binding会去维护一个缓存的状态,只有在绑定发生变化的时候,才去实际调用RHI层的设置接口,当我们把具有相同状态的对象排列在一起时,尤其是使用相同Shader的物体,缓存优化会得到较好的收益。
相关文章:
[ue4] 着色器绑定(Shader Binding)
当我们在ue4中制作了一个美术材质之后,引擎本身会为我们做很多事情,它会把结点翻译为hlsl,生成多个shader变体,并在多个mesh pass中去选择性的调用所需的shader,其中一个重要的过程就是获取shader绑定的数据。 本文将主…...
Rust语言之迭代器
文章目录Rust迭代器Rust迭代器的实现Iterator特型IntoIterator特型for循环与迭代器迭代器类型再看for循环实现自定义迭代器方式一方式二相关参考Rust迭代器 Rust语言内置了迭代器模式,用于实现对一个项的序列进行特定的处理,通常配合for循环使用。当我们…...
TreeSet 与 TreeMap And HashSet 与 HashMap
目录 Map TreeMap put()方法 : get()方法 : Set> entrySet() (重) : foreach遍历 : Set 哈希表 哈希冲突 : 冲突避免 : 冲突解决 ---- > 比散列(开放地址法) : 开散列 (链地址法 . 开链法) 简介 : 在Java中 , TreeSet 与 TreeMap 利用搜索树实现 Ma…...
Java围棋游戏的设计与实现
技术:Java等摘要:围棋作为一个棋类竞技运动,在民间十分流行,为了熟悉五子棋规则及技巧,以及研究简单的人工智能,决定用Java开发五子棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为S…...
第七十三章 使用 irisstat 实用程序监控 IRIS - 使用选项运行 irisstat
文章目录第七十三章 使用 irisstat 实用程序监控 IRIS - 使用选项运行 irisstat使用选项运行 irisstatirisstat Options第七十三章 使用 irisstat 实用程序监控 IRIS - 使用选项运行 irisstat 使用选项运行 irisstat 不带选项运行 irisstat 会生成基本报告。通常,…...
【博客619】PromQL如何实现Left joins以及不同metrics之间的复杂联合查询
PromQL如何实现Left joins以及不同metrics之间的复杂联合查询 1、场景 我们需要在PromQL中实现类似SQL中的连接查询: SELECT a.value*b.value, * FROM a, b2、不同metrics之间的复杂联合查询 瞬时向量与瞬时向量之间进行数学运算: 例如:根…...
Win11自定义电脑右下角时间显示格式
Win11自定义电脑右下角时间显示格式 一、进入附加设置菜单 1、进入控制面板,选择日期和时间 2、选择修改日期和时间 3、选择修改日历设置 4、选择附加设置 二、自定义时间显示出秒 1、在选项卡中,选时间选项卡 2、在Short time的输入框中输入H:m…...
TrueNas篇-trueNas Scale安装
安装TrueNAS Scale 在尝试trueNas core时发下可以成功安装,但是一直无法成功启动,而且国内对我遇见的错误几乎没有案例,所以舍弃掉了,而且trueNas core是基于Linux的,对Linux的生态好了很多,还可以可以在t…...
element表单搜索框与表格高度自适应
一般在后台管理系统中,表单搜索框和表格的搭配是非常常见的,如下所示: 在该图中,搜索框有五个,分为了两行排列。但根据大多数的UI标准,搜索框默认只显示一行,多余的需要进行隐藏。此时的页面被…...
MySQL使用技巧整理
title: MySQL使用技巧整理 date: 2021-04-11 00:00:00 tags: MySQL categories:数据库 重建索引 索引可能因为删除,或者页分裂等原因,导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面…...
七大设计原则之里氏替换原则应用
目录1 里氏替换原则2 里氏替换原则应用1 里氏替换原则 里氏替换原则(Liskov Substitution Principle,LSP)是指如果对每一个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都替换成 o2 时,程序 P…...
1行Python代码去除图片水印,网友:一干二净
大家好,这里是程序员晚枫。 最近小明在开淘宝店(店名:爱吃火锅的少女),需要给自己的原创图片加水印,于是我上次给她开发了增加水印的功能:图片加水印,保护原创图片,一行…...
Connext DDS属性配置参考大全(2)
DDSSecure安全com.rti.servcom.rti.serv.load_plugin...
一起Talk Android吧(第四百九十二回:精简版动画)
文章目录概念介绍使用方法示例代码经验总结各位看官们大家好,上一回中咱们说的例子是"动画集合:AnimatorSetBuilder",这一回中咱们说的例子是" 精简版动画"。闲话休提,言归正转,让我们一起Talk Android吧&…...
seata源码-全局事务回滚服务端源码
这篇博客来记录在发起全局事务回滚时,服务端接收到netty请求是如何处理的 1. 发起全局事务回滚请求 在前面的博客中,有说到过,事务发起者在发现分支事务执行异常之后,会提交全局事务回滚的请求到netty服务端,这里是发…...
【Vue3源码】第一章 effect和reactive
文章目录【Vue3源码】第一章 effect和reactive前言1、实现effect函数2、封装track函数(依赖收集)3、封装reactive函数4、封装trigger函数(依赖触发)5、单元测试【Vue3源码】第一章 effect和reactive 前言 今天就正式开始Vue3源码…...
C函数指针
函数指针是指向函数的指针变量。通常我们说的指针变量是指向一个整型、数组或字符型等变量,而函数指针是指向函数。函数指针可以像一般函数一样,用于调用函数、传递参数。函数指针变量的声明:typedef int (*fun_ptr)(int,int); // 声明一个指…...
2023同等学力申请硕士计算机综合国考
同等学力国考报名要开始了 2023年2月15日,中国教育考试网和“全国同等学力人员申请硕士学位管理工作信息平台”(https://tdxl.chsi.com.cn,联系服务电话:010-67410388)公布报名工作通知。考生须按照通知要求进行注册或…...
英语基础-并列句概述
什么是并列句?并列句就是用连词把独立的句子连接起来,使得句子之间产生并列的逻辑。 1. 并列句中的逻辑 1. 小明步行上学,小红骑自行车上班。 Ming goes to school on foot,and Hong goes to work by bike. 平行逻辑 2. 小红经常玩手机…...
大数据框架之Hadoop:HDFS(一)HDFS概述
1.1HDFS产出背景及定义 HDFS 产生背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
