Godot 4.0 CPU、GPU优化,大大缩短渲染时间

Hey everyone, I've got some exciting news to share about Godot 4 .0! This version has really stepped up its game when it comes to rendering, especially with some major optimizations for both the CPU and GPU. These improvements have led to a significant reduction in rendering times, giving the engine a serious boost in overall performance.
CPU Optimizations
Godot 4 .0 has been working hard on optimizing the CPU side of things. Here's what they've been up to:
1 . Improved Culling Algorithm: They've switched to a brute-force culling algorithm and added support for multi-threading. This change helps in doing scene culling more efficiently, cutting down on unnecessary rendering overhead.
2 . Efficient Cache Structures: By using more efficient cache structures to store and access rendering data, they've managed to reduce the number of cache misses, thereby boosting rendering efficiency.
3 . Paged Arrays for Rendering Objects: They've introduced paged arrays to pass rendering objects, which helps in reducing memory fragmentation and unnecessary memory access, further enhancing rendering performance.
4 . Multi-threaded Rendering: Implementing multi-threaded rendering allows the CPU to make better use of multi-core processors, enabling it to handle rendering tasks in parallel.
5 . Instancing Methods and Caching Render States: When rendering similar objects, they've adopted instancing methods and caching render states. This approach avoids redundant calculations and state switches, significantly improving rendering efficiency.
It's worth noting that while the initial tests of dynamic culling didn't yield the best results, the development team is planning to tackle this in the coming weeks with further optimizations.
GPU Optimizations
On the GPU front, Godot 4 .0 has also introduced several key improvements:
1 . Automatic LOD: They've implemented automatic Level of Detail (LOD) adjustments to cater to different rendering distances and performance needs. This ensures that visuals are top-notch while keeping the GPU load in check.
2 . Rewritten Shaders and Light Clusters: By rewriting and optimizing shaders and light clusters, they've managed to enhance both rendering quality and performance.
3 . Optimized Texture Formats: Switching to more efficient texture formats has helped in reducing GPU memory usage and bandwidth requirements.
4 . Enhanced Support for Low-End Devices: Through optimizations and compatibility improvements, Godot 4 .0 can now run smoothly on more budget-friendly devices.
5 . Increased Parallelism: By boosting the parallelism of GPU tasks, they've been able to make the most of modern GPUs' powerful computing capabilities, further reducing frame times. For instance, on a Vega6 4 GPU, frame times dropped from 1 0ms to 4 .5 ms, and on an NVIDIA 1 6 5 0, they went from 1 5 ms to 1 0ms. These substantial performance gains are a testament to the effectiveness of these GPU optimizations.
Showcasing the Optimizations
Here’s a snapshot that really brings the optimized rendering of Godot 4 .0 to life. It’s a full frame captured at 1 08 0p with 8 xMSAA, running with all effects enabled, including global illumination (GI). The image clearly demonstrates how Godot 4 .0 delivers stunningly detailed and smooth visuals post-optimization.
Looking Ahead
Even though Godot 4 .0 has already made impressive strides in CPU and GPU optimizations, the team is far from done. They’re still working on refining areas like portal and occlusion culling. As these optimizations continue to roll out, Godot 4 .0 is poised to become a high-performance, open-source game engine, offering developers more efficient and powerful tools.
In summary, Godot 4 .0 has made remarkable progress in CPU and GPU optimizations, drastically cutting down rendering times and boosting overall engine performance. With more optimizations on the horizon, Godot 4 .0 is set to become a standout in the world of game development.

《图解UE4渲染体系》Part 1 多线程渲染

好嘞,咱们接着聊聊UE4 渲染那点事儿。
上回咱们大概明白了UE4 是怎么管游戏场景里那些数据的,但这只是个开始。
今天咱就来深扒一下UE4 渲染体系里底层的、挺宏观的一个部分——多线程渲染。
具体说说都有啥:
首先,得搞明白为啥要用多线程。
咱们得知道,“渲染”到底是咋回事。
最基础的理解就是,CPU调用图形API(比如Direct3 D、Vulkan啥的)给的DrawCall命令。
这命令里头有所有需要渲染的数据和属性信息。
然后CPU就等着GPU把渲染结果给反馈回来。
你要是渲染频率不高,比如搞个静态展示啥的,这单线程方式问题不大。
但游戏里不一样啊,得实时渲染,频率贼高。
这时候,单线程就显得力不从心了。

为啥呢?因为游戏引擎不光要搞渲染,还得处理一大堆游戏逻辑。
比如用户输入、执行游戏脚本、更新物理效果和动画、还有可见性判断这些。
你要是把这些活儿全塞给GameThread(游戏线程)干,等它忙完了所有活儿,把渲染数据交给渲染线程(RenderThread)之后,GameThread就只能干等着GPU出结果。
这期间它可啥也干不了,下一帧的任务就耽误了。

现在咱们是多核CPU、支持多线程的操作系统,对吧?那为啥不把渲染这块儿从GameThread里拆出来,让GameThread专心搞游戏逻辑,让RenderThread专门负责渲染呢?这显然是个挺合理的选择。
这么一来,GameThread干完活儿,把数据扔给RenderThread。
然后RenderThread就开始忙活,处理数据(比如做可见性剔除这些),把DrawCall提交给GPU,等GPU搞定,渲染就完成了。
GameThread就能立刻开始处理下一帧的事儿了,效率高多了。

那RhIThread又是个啥呢?UE4 里搞个RHI(渲染硬件接口)线程,估计是有好几方面的原因。
首先,咱们得考虑跨平台。
Windows用Direct3 D,MacOS用Metal,还有OpenGL和Vulkan这种跨平台的(尤其移动端常用)。
在RHIThread出来之前,RenderThread得自己判断现在用哪个图形API,然后去选对应的DrawCall。
这无疑增加了维护的复杂度和工作量。
引入RHIThread之后,RenderThread只需要把数据打包成RHIDrawCommand格式,然后交给RHIThread。
RHIThread就根据当前跑在哪个平台,找到对应的图形API接口,把命令提交给GPU。
这样一来,RenderThread就解放了,可以专心干自己的事,而RHIThread就负责处理不同平台的图形API那些事儿,包括版本更新啥的。

当然,从工程优化的角度看,搞RHIThread也是为了能更好地并行提交DrawCall。
在一些比较老的图形API里,提交DrawCall是“阻塞”的,就是说,一个线程在提交的时候,别的线程就干不了这个事儿了。
有了RHI,UE4 就不需要开一堆RenderThread了,只需要把那些能并行干的活儿单独拎出来,搞个RHIThread去干,效率也更高。

总而言之,UE4 渲染体系里多线程这块儿的设计,也不是一成不变的,它会随着技术的发展和需求的变化而演进。
比如到了UE5 ,设计上可能又会有新的变化。

今天咱们就先聊到这儿。
这一回也没深入讲每个线程具体干啥细节,也没细说线程之间怎么传数据啥的,毕竟那得写一大堆,太长了。
后面咱们会慢慢梳理这些内容。
网上也有很多相关资料,大家有兴趣可以自己去找找看。

【0】DirectX12介绍和开发预备知识

大家好啊,今天想跟大家聊聊 DirectX1 2 它是微软搞出来的一种图形接口,主要就是奔着高性能游戏和图形软件去的。
跟以前的 DirectX 版本比起来,DX1 2 提供了更底层的硬件访问能力,也给了开发者更多的控制权。
具体来说,它有几个特别厉害的地方:
首先,是更底层的硬件访问。
有了 DX1 2 ,开发者就能更直接地操控 GPU,这样就能更好地优化性能,减少 CPU 的负担,把现代 GPU 的性能发挥到极致。

其次,DX1 2 还支持多线程渲染。
这意味着开发者可以更灵活地管理渲染线程,让多核 CPU 得到更好的利用,避免 CPU 成为瓶颈。

第三,DX1 2 的图形 API 效率更高。
它通过减少 API 调用的次数、优化命令流水线,以及提供更灵活的资源管理,降低了图形 API 的开销,从而提升了应用程序的性能。

最后,DX1 2 还支持 Direct3 D1 1 和 Direct3 D9 的向后兼容性。
也就是说,现有的游戏和应用程序可以在 DX1 2 平台上运行,而不用进行大规模的重写。

既然 DirectX 游戏在市场上占主导地位,那么学习 DX1 2 对于想要深入理解和开发高性能图形应用程序的朋友们来说,就变得非常重要了。

好了,接下来跟大家分享一下 DirectX1 2 开发前需要了解的一些基础知识。

首先是组件对象模型(COM)。
在 DirectX 开发中,COM 是微软提出的一种二进制接口标准,用于实现组件化的软件设计。
在使用 COM 时,获取 COM 接口指针并不是通过 new 一个接口,而是使用特殊的函数或另一个 COM 接口方法。
COM 会自动管理引用计数,当接口使用完后,调用 Release 删除接口对象。
当 COM 引用计数为 0 时,COM 会自动释放内存。
为了更方便地管理 COM 接口,我们可以使用 Microsoft::WRL::ComPtr 类,它提供了一些很有用的方法,比如 Get() 返回指向底层 COM 接口的指针,GetAddressOf() 返回指向底层 COM 接口的地址,Reset() 将对象设置为 nullptr 并释放所有与之相关的引用。

接下来是交换链(SwapChain)。
交换链是一种用于在前台和后台缓冲区之间进行切换的技术,它的目的是提供流畅的图形渲染,避免画面撕裂和卡顿现象。
前台缓冲区就是用户实际看到的内容,由交换链直接显示在屏幕上。
后台缓冲区则是正在绘制的下一帧,当绘制完成后,交换链会交换两种缓冲区的角色,后台缓冲区变成前台缓冲区,并显示在屏幕上。
交换链可以使用双缓冲或多缓冲技术。
双缓冲使用两个缓冲区(前台和后台),而多缓冲则使用三个或更多缓冲区,以更好地平衡渲染和显示的速度。
在 DirectX 中,交换链通过 ID3 DGISwapChain 接口表示,这个接口不仅可以管理前台缓冲区和后台缓冲区,还提供了一些对缓冲区操作的方法。

然后是资源和描述符。
资源是 GPU 中存储图形数据的对象,包括缓冲区、纹理、常量缓冲区等。
为了告诉 GPU 如何读取和操作这些资源,我们需要为它们添加描述符。
描述符用于描述资源或其他 GPU 资源的属性和位置,通常用于在 GPU 上设置各种资源的引用,比如纹理、缓冲区、着色器资源等。
常用的描述符类型包括渲染目标视图描述符(RTV)、深度模板视图描述符(DSV)、着色器资源视图描述符(SRV)、常量缓冲区视图描述符(CBV)、无序访问视图描述符(UAV)和采样器描述符(Sampler)。
在 DirectX 中,描述符主要通过描述符堆(DescriptorHeap)来管理,描述符堆可以看作是描述符数组,用于存储和管理多个描述符。

最后是命令队列和命令列表。
命令队列和命令列表是与 GPU 通信和执行渲染操作的重要媒介。
命令队列本质上是一个环形缓冲区,CPU 可以使用命令列表将命令提交到命令队列中。
提交的命令不会立即执行,而是等待 GPU 处理。
GPU 会先处理命令队列最下层的命令,新的命令会等待到处于命令队列下层后执行。
命令列表用于存储一系列渲染命令,在 DirectX 中,命令队列和命令列表分别被抽象成 ID3 D1 2 CommandQueue 和 ID3 D1 2 CommandList。
我们可以使用继承于 ID3 D1 2 CommandList 接口的 ID3 D1 2 GraphicsCommandList 接口中提供的一系列方法向命令列表中添加命令。
最后,使用 ID3 D1 2 CommandQueue::ExecuteCommandLists 方法将命令列表提交到命令队列中。
在提交命令列表之前,必须使用 ID3 D1 2 CommandList::Close 关闭命令列表。
此外,还可以使用命令分配器(CommandAllocator)来分配和管理命令列表,命令分配器用于为命令列表分配内存和管理其状态。

总而言之,学习 DirectX1 2 需要掌握组件对象模型(COM)、交换链、资源与描述符、命令队列和命令列表等基础知识。
这些概念和技术对于深入理解 DirectX1 2 的底层机制以及开发高性能图形应用程序来说,都是至关重要的。

激烈模拟器多线程3d渲染是什么意思

好嘞,跟你说说我了解到的关于激烈模拟器里多线程3 D渲染这事儿。
简单来说,渲染效果好不好,其实是个挺复杂的问题,好多因素掺和在一起,可以叫它综合变量。

我之前也查过一些公开的信息,搞明白3 D渲染到底是个啥。
说白了,就是电脑通过算力,把那些在3 D空间里由点线面组成的模型网格,给“画”成我们能在屏幕上看到的那种看起来特别真实的2 D画面。
这个过程可没那么多玄学,它需要计算光线怎么在场景里跑来跑去,包括主要的光线还有辅助的光线(比如阴影啥的),还得知道场景里东西是用什么材料做的,这些材料的光泽、颜色、纹理细节得算进去,还有相机怎么摆放、视角怎么设置等等,这些都是计算过程中非常重要的变量。
所以你看,渲染效果是不是好,真的跟这些设置紧密相关。

Re:从零开始的UE渲染学习-2多线程

在UE的渲染体系中,多线程机制扮演着至关重要的角色,它主要包含以下几个方面:
首先,我们来谈谈多线程的概念。
简单来说,多线程就像是多个工人同时合作完成一项任务,效率自然更高。
在UE渲染中,我们的目标很明确,那就是要输出画面,这其中涉及到物体状态的更新、渲染以及后处理等多个步骤。

那么,多线程的优势又是什么呢?当单线程处理某个任务耗时较长时,在多核CPU的环境下,我们可以将任务分配给不同的线程,让它们并行工作,从而提高整体的效率。

接下来,我们来看看UE中主要的线程分配。
游戏线程负责逻辑更新,渲染线程负责生成渲染命令,而RHI线程则负责将这些命令转换成底层的图形API。
这里的分配原则是以效率为主,尽量让各个线程并行执行任务,减少因为线程间依赖而导致的等待时间。

任务系统是多线程中非常重要的一部分,它的功能是记录各个线程的任务,并确保这些任务能够并行执行,从而提高效率。
可以想象成游戏线程向渲染线程添加任务,就像是一个项目经理在管理任务一样。

在UE中,多线程的实现基础是FRunnableThread和FRunnable的拆分,而FTaskThreadBase则是一个特殊的线程,用于管理任务系统。
任务系统的构建中,FTaskGraphImplementation负责管理任务表,而TGraphTask则负责执行这些任务。
游戏线程会将任务添加到渲染线程,然后由渲染线程去执行任务系统中的任务。

在多线程的通信方面,游戏线程与渲染线程之间通过ENQUEUE_RENDER_COMMAND宏来创建任务,实现高效的任务分配。
而渲染线程与RHI线程之间,UE内部已经预定义了RHI命令,FRHICommandList负责管理命令的执行,而ImmediateFlush则负责将这些命令刷新到RHI线程和GPU。

当然,多线程也带来了一些问题,比如资源竞争。
在多线程间读写内存时,可能会出现竞争问题。
为了解决这个问题,UE通过渲染线程额外拷贝内存,存储要渲染对象资源,避免直接竞争。
游戏线程更新资源,渲染线程更新其代理资源。

最后,我们来看看线程同步的问题。
渲染线程可能会执行较慢,导致游戏与画面不同步。
为了解决这个问题,UE使用了栅栏同步机制。
游戏线程每帧添加一个栅栏,当渲染线程执行到这个栅栏时,就表示当前帧的绘制已经完成。
这样,游戏线程就可以比渲染线程快一帧,从而稳定帧率。

总的来说,UE通过多线程技术将渲染分为游戏线程、渲染线程和RHI线程,高效地执行任务。
各个线程之间通过任务系统进行通信,多线程优化了资源利用与同步,有效解决了渲染过程中出现的挑战。