当前位置: 首页 > news >正文

【IMR、TBR、TBDR】【RenderTexture、Cbuffer】学习

【IMR、TBR、TBDR】【RenderTexture、Cbuffer】学习

  • 1. 渲染架构比较
    • 1.1 IMR (Immediate Mode Rendering)
    • 1.2 内存带宽消耗问题
    • 1.3 Tiled Memory
    • 1.4 Rasterizing within tiles
    • 1.5 分箱 Binning
    • 1.6 TBR (Tile-Based Rendering)
    • 1.7 TBR中的多采样
    • 1.8 传统延迟着色 Traditional deferred shading
    • 1.9 TBDR
    • 1.10 TBR的优点与缺点
      • 优点
      • 限制
  • 2. Render Texture
    • 2.1 什么是server-side的texture
    • 2.2 FrameBufferObject
    • 2.3 渲染到Render Texture的几种方式
    • 2.4 一些注意的点
  • 3.CBuffer

1. 渲染架构比较

原文 GPU 渲染架构介绍和比较分析

1.1 IMR (Immediate Mode Rendering)

IMR是PC和主机GPU使用的渲染方式,指每一次渲染API的调用,都会直接绘制图形对象。所以每一次物体颜色和深度的渲染都会读写Frame Buffer和Depth Buffer。IMR架构需要大量的带宽,这点可以通过L1和L2缓存优化,但对于移动端GPU的尺寸和功耗需求,不能使用IMR

1.2 内存带宽消耗问题

在IMR中,三角形提交的顺序决定了访问顺序,但这种访问顺序是无序的,所以可能会导致访问效率低下。也可能会遇到较高的缓存未命中率,GPU缓存中的数据经常不是渲染下一个像素所需要的数据,导致频繁的内存访问。

在这里插入图片描述

1.3 Tiled Memory

贴图内存是一种优化内存带宽使用的技术,它将内存划分为多个二维的矩形区域,即“贴图”或“瓦片”。

工作原理:

  • 瓦片化内存:每个缓存行覆盖帧缓冲和深度缓冲中的一个瓦片区域。与传统的线性缓存相比,这种布局使得渲染操作在缓存内部执行的更多,减少了对外部内存的访问
  • 缓存命中率提高:由于相邻的三角形在渲染时往往连续提交,瓦片化的缓存可以更好地利用缓存行,提高缓存的命中率
  • 减少内存带宽使用:由于更多的渲染操作在缓存内完成,因此与内存的传输变得更少

1.4 Rasterizing within tiles

在现实世界中,帧缓冲区相对于缓存瓦片来说可能会大得多,如果三角形特别大,屏幕上的每一行可能覆盖的瓦片数量超过了缓存能容纳的范围。所以我们可以改变三角形内像素的光栅化顺序:可以先绘制三角形覆盖的一个瓦片内的所有像素,然后再移动到下一个瓦片。

  • 减少缓存失效:通过在一个瓦片内完成所有相关像素的渲染,不需要在渲染过程中频繁地加载和卸载瓦片
  • 提高缓存利用率:因为一旦瓦片被加载到缓存中,就可以处理该瓦片内所有三角形的像素,而不是仅仅处理一个三角形

1.5 分箱 Binning

我们需要确定哪些三角形会影响每个瓦片。当几何体被提交渲染时,它不是立即被光栅化,而是被“分箱”到一个内存结构中,这个结构决定了它可能影响的瓦片。注意这个过程涉及到顶点着色(确定三角形在屏幕上的位置),因为这影响着三角形的位置,但不包括片段着色。

1.6 TBR (Tile-Based Rendering)

核心思想是:将帧缓冲分割为一小块一小块,然后逐块进行渲染。在整个帧缓冲区中处理每个瓦片时,只关注该瓦片区域内的内容。在这个过程中,缓存的作用被缩小到当前处理的瓦片大小。在开始处理瓦片之前,帧缓冲区中的所有像素都需要被重置或清除。
在这里插入图片描述

渲染分为两个阶段:分箱(写入内存)和栅格化(读取分箱内容)。中间存储的几何体相对于帧缓冲区来说通常较小,并且以有序的方式访问

  • 分箱阶段
    • 几何体数据被提交给渲染器。
    • 顶点着色器处理每个顶点,确定三角形在屏幕上的位置。
    • 渲染器将每个三角形分配到可能影响的瓦片中,这个过程称为“分箱”。
    • 分箱信息被存储在一个内存结构中,记录了每个瓦片包含哪些三角形。
  • 栅格化阶段
    • 渲染器按瓦片顺序处理场景,只写入本地瓦片内存。
    • 每个瓦片被处理一次,包括清空帧缓冲区中的对应区域。
    • 栅格化阶段会读取瓦片中的几何体信息,并将其转换为像素。
    • 栅格化完成后,瓦片中的像素会被更新并写回到帧缓冲区中。

由于我们按瓦片处理图像的所有几何体,这意味着每个瓦片内的所有像素都是新渲染的,而不是基于前一个帧的内容。通过避免不必要的读取,可以减少带宽的使用,从而提高渲染效率。

1.7 TBR中的多采样

工作原理

  • 创建样本点:每个像素周围会创建多个样本点,这些样本点代表了周围的颜色和深度信息
  • 渲染样本点:样本点也会被渲染
  • 解析样本点:渲染瓦片时会解析样本点——计算每个像素的最终颜色和深度值。这个过程通常涉及到样本点的平均值或其他形式的组合,以产生更平滑的颜色和深度值。
  • 写入帧缓冲区:解析后的像素值被写入瓦片内存,然后写入帧缓冲区。由于每个像素周围的样本点数量不同,瓦片内存中的像素值需要被缩放或调整以匹配帧缓冲区中的像素大小
  • 深度缓冲区:深度缓冲区通常只在芯片上处理,不会写入主内存,一旦瓦片处理完成,芯片上的深度值就可以丢弃,因为它们不会影响最终的渲染结果。

1.8 传统延迟着色 Traditional deferred shading

它首先记录每个几何体的基本信息(如表面法线),然后在第二次渲染过程中使用这些信息进行像素级的着色操作。这种方法可以减少所需的昂贵状态更改次数,并增加片段着色器可用的潜在并行性。
但是高带宽成本:在第二次渲染过程中,需要读取和写入整个帧缓冲区中的所有像素值。

1.9 TBDR

渲染器首先记录每个瓦片中的几何体的基本信息,如表面法线,然后对这些信息进行第二次渲染,使用这些信息来计算每个像素的最终颜色。只有着色阶段的最终结果需要写入帧缓冲区。

结合了瓦片化和延迟着色的优势,使得基于瓦片的渲染技术能够高效地实现延迟着色,同时保持较低的内存带宽成本。

1.10 TBR的优点与缺点

优点

  • 减少帧缓冲区内存带宽
  • 提高移动设备的性能
  • 纹理缓存性能提升:纹理可以更一致地按瓦片访问,而不是按原始几何体访问,从而提高纹理缓存性能。
  • 芯片上空间优化

限制

  • 基于瓦片的渲染的延迟应该通过流水线化和性能提升来隐藏,但使得某些操作的相对成本更高。
  • 可能超出当前片段的帧缓冲区读取相对成本更高。
  • 由于需要多次遍历几何体,这可能会增加成本。
  • 如果场景主要由顶点着色器限制,基于瓦片的渲染可能会增加开销。

2. Render Texture

参考
Unity3d中渲染到RenderTexture的原理,几种方式以及一些问题
Unity 官方文档

RenderTexture是一种 Unity 在运行时创建和更新的纹理,unity定义的一种特殊的Texture类型,它连接着一个FrameBufferObject的存在于GPU端的Texture(Server-Side Texture)

2.1 什么是server-side的texture

在渲染过程中,一开始的纹理是存储在CPU的,称为client-side的texture;它最终要被送到gpu的存储里,gpu才能使用它进行渲染,送到gpu里的那一份被称为server-side的texture。CPU和GPU之间纹理的传输需要考虑带宽瓶颈。

2.2 FrameBufferObject

Frame Buffer,存储各种颜色、深度、模板信息,是渲染结果的目的地,有一个默认的FBO它直接连着我们的显示器窗口区域,就是把我们的绘制物体绘制到显示器的窗口区域。

在OpenGL中,可以将FBO渲染到一张GPU上的纹理来使用。一般是将可读的FBO的一部分拷贝到存在于gpu上的一个texture对象中,直接考到server-sider就意味着可以马上被gpu渲染使用。
(OpenGL帧缓冲笔记 OpenGL学习笔记 帧缓冲)
在Unity中,将这个fbo直接关联一个gpu上的texture对象,这样就等于在绘制时就直接绘制到这个texure上,这样也省去了拷贝时间。

2.3 渲染到Render Texture的几种方式

  • Assets > Create > Render Texture,然后将其附给一个摄像机,这样这个摄像机实时渲染的结果就都在这个tex上了。
  • 有的时候,我们可以用自定义的shader去渲染这个RenderTexture。可以调用Camera的RenderWithShader函数,它将使用你指定的shader去渲染场景,这时候场景物体上原有的shader都将被自动替换成这个shader,而参数会按名字传递。
  • 可以在Assets文件夹下创建RenderTexture,使用Graphics.Blit(src, target, mat)这个函数来渲染到render texture上,这里的的target就是你要绘制的render texrture,src是这个Material中需要使用的_MainTex,也可以是另一个RenderTexture。这个函数的本质是,绘制一个四方块,然后用mat这个材质,用src做maintex,然后先clear为black,然后渲染到target上。

2.4 一些注意的点

  • rendertexture的格式,rt的格式和普通的tex2D的格式并不是一回事,某些机子还支持ARGBFLOAT浮点格式
  • rendertexture的分配和销毁,如果你频繁的要new一个rt出来,那么不要直接new,而是使用RenderTexture提供的GetTemporary和ReleaseTemporary,它将在内部维护一个池,反复重用一些大小格式一样的rt资源,因为让gpu为你分配一个新的tex其实是要耗时间的。更重要的这里还会调用DiscardContents
  • DiscardContents()这个rendertex的接口非常重要,好的习惯是你应该尽量在每次往一个已经有内容的rt上绘制之前总是调用它的这个DiscardContents函数,大致得到的优化是,在一些基于tile的gpu上,rt和一些tile的内存之间要存在着各种同步, 如果你准备往一个已经有内容的rt上绘制,将触发到这种同步,而这个函数告诉gpu这块rt的内容不用管他了,我反正是要重新绘制,这样就避免了这个同步而产生的巨大开销。

3.CBuffer

参考 Command Buffers In Unity

一个Command Buffer 中存储很多绘制命令(Rendering Command),这些 Rendering Command 其实就是OpenGL或者DirectX 中的一些列指令,比如glDrawElement,glClear等。Command Buffer 扩展渲染管线的方法是:预定义一系列的渲染指令,然后在特定的时机去执行这些指令。这些特定的时机是由我们来指定的,下图渲染过程中的绿点说明了这些可以指定的时机:
在这里插入图片描述
可以使用 Graphics.ExecuteCommandBuffer 立即执行 CommandBuffers。
也可以安排它们,以便它们在渲染管线中的给定点发生

  • Camera.AddCommandBuffer 与 CameraEvent枚举使用
  • Light.AddCommandBuffer 与 LightEvent枚举使用

详细CameraEvent 和 LightEvent 事件的执行顺序见Unity官方文档 使用 CommandBuffers 扩展内置渲染管线

Command Buffer的特点是可以在指定的时机执行一些特殊的渲染操作,从而达到节省资源和实现特殊效果的目的。但不要为了Command Buffer 而刻意使用Command Buffer。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 不用高深的数学知识来理解 LLMs 是如何工作的
  • 影响因子30+的SCI教你如何进行单个率Meta分析!
  • 【分布式事务】-分布式事务的实现方式多种多样,每种方式都有其特定的应用场景和优缺点。以下是几种常见的分布式事务实现方式,2PC,TCC,消息表
  • 原来,考证还可以领取补贴Money
  • Matlab绘制像素风字母颜色及透明度随机变化动画
  • Containerd 介绍
  • LINUX原始机安装JDK
  • Ubuntu 如何优雅关机
  • Kafka 单机和集群环境部署教程
  • 解决oracel锁表问题;SQL 错误 [54] [61000]: ORA-00054: 资源正忙
  • qt quick实现的水波纹特效:横向波纹、纵向波纹效果
  • 真题解析 | CCF CSP-J 2019 入门级 C++语言真题及答案
  • 安装开源软件ChatALL(齐叨)来聚合各大人工智能工具
  • Golang | Leetcode Golang题解之第332题重新安排行程
  • 使用 `@JsonTypeInfo` 和 `@JsonSubTypes` 注解实现多态序列化
  • Angular4 模板式表单用法以及验证
  • gf框架之分页模块(五) - 自定义分页
  • github从入门到放弃(1)
  • Java IO学习笔记一
  • java概述
  • leetcode46 Permutation 排列组合
  • LeetCode算法系列_0891_子序列宽度之和
  • MySQL-事务管理(基础)
  • MySQL主从复制读写分离及奇怪的问题
  • Netty 4.1 源代码学习:线程模型
  • OSS Web直传 (文件图片)
  • Redis中的lru算法实现
  • Tornado学习笔记(1)
  • vuex 学习笔记 01
  • 测试开发系类之接口自动化测试
  • 第十八天-企业应用架构模式-基本模式
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • Semaphore
  • 如何用纯 CSS 创作一个货车 loader
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #微信小程序:微信小程序常见的配置传旨
  • (1)(1.13) SiK无线电高级配置(五)
  • (3) cmake编译多个cpp文件
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (二) 初入MySQL 【数据库管理】
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (利用IDEA+Maven)定制属于自己的jar包
  • (图)IntelliTrace Tools 跟踪云端程序
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (一)kafka实战——kafka源码编译启动
  • (转) 深度模型优化性能 调参
  • (转)shell中括号的特殊用法 linux if多条件判断
  • **python多态
  • .net Application的目录
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅