SCE-PhyreEngine 发表于 2016-4-23 21:13

Mobile 3D Game Engine Solution-1


本文只针对目前国内自研发手机游戏引擎做优化建议。虽然Vullkan支持Android,但是即使Vullkan在Android的生态圈完善了,仍然不可轻视某些优化。

Purpose
改善我们的引擎弊端,也是现阶段普遍移动端引擎的弊端:•过度的OO设计,AoS数据结构,导致大量CacheMiss, CPU产生Stall
•CPU并行化的合理利用
Ø场景更新并行化
Ø动画计算并行化
Ø可视裁剪并行化
•Forward渲染架构:由于市面主流硬件的技术规格还在GLES2-GLES3层面,GLES2不支持MRT,采用Forward渲染架构较为容易实现
Ø场景复杂度相关的渲染计算
Ø光照计算开销昂贵O(n*m),不支持大量复杂的动态光源
ØPostProcess的带宽开销巨大
Ø纹理格式限制,只支持ETC1,不能使用RGBA格式的压缩贴图
Ø不支持GeometryInstancing
•TBDR架构的兴起,对于大规模的复杂场景,反而增加带宽开销
•UI系统
Ø不支持3D UI,没有3D UI的编辑方式
Ø不支持与粒子排序
•粒子系统
Ø美术更习惯使用基于关键帧的编辑方式
Ø不支持与UI排序
Ø对于2D粒子的支持



•Design
ØPipelineStall
ØOOD vs DOD
ØSSE、SIMD、NEON
ØParallelScene Graph Management
•Rendering
ØUnderstandingMobile GPU
ØGPUHardware Architecture
ØGPU Hardware Features Extensions
ØBuildDeferredShading On Mobile


Design
一些游戏引擎普遍的程序设计问题:•PipelineStall
ØConditionalBranch
ØCacheMiss
ØLHS
•OOD vs DOD
ØAoS vs SoA
•SSE、SIMD、NEON
•ParallelScene Graph Management


Pipeline Stall
•CPUPipeline(5层流水线)
ØIF(InstructionFetch)读取指令
ØID(InstructionDecode)指令解码
ØEX(Execute)执行指令
ØMEM(MemoryAccess)内存访问
ØWB(WriteBack)写回操作



PipelineStall(4层流水线)
指令延迟,造成CPU停滞,导致原因:Conditional BranchCache MissLHSEtc.










Conditional Branch
•ConditionalBranch(条件分支)
Ø导致不可预知的指令跳转,只有在执行阶段才能知道下一条应该执行的指令,造成CPU延迟
Øif(x> 0) {a=0; b=1; c=2; } else d=3;



Ø现代CPU通过Branch Prediction来改善这种情况(仅仅是改善,取决于Prediction的准确度)移动端问题表现要严重N倍
Ø浮点分支造成的更严重的Stall,因为浮点流水线更长


Conditional Move
•ConditionalMove(条件转移)
Ø不打破程序流程结构,同时计算所有结果,根据条件进行跳转
Øfsel指令在不同硬件平台上分别使用fsel/fcmov/sse
‒fsel inPPC
‒fcmov inx87 FPU
ØConditionalBranch可能导致CacheMiss,造成Stall,使用ConditionalMove替代ConditionalBranch,可以获得更高的性能



•Cache Miss
ØCPU读取数据(Fetch)优先访问Cache(L1Cache、L2Cache…),如果Cache中不存在该数据,即CacheMiss,则从主内存数据fetch数据到Cache,Cache将数据存储在若干个数据块内,称为Cacheline。


Cache Miss



ClassDefinition ToMemory Layout





What’swrong with this code?{:6_268:}




Why is it so slow?
Look at GetWorldBoundingSphere()






如何避免CacheMiss


场景更新,在每一帧应该只计算一次

LHSLHS(Load-hit-stores)Ø将数据写入一个地址,如果太快的尝试再次加载数据,就会出现CPU的停滞现象(Stall)Ø造成这个问题的原因是,CPU计算时,Fetch主内存数据到寄存器(L1 Cache),处理完成时,将寄存器数据写回主内存。此时,如果在还没有写回完成时,访问该地址不能保证正确性,CPU要进行“同步”,产生Stall



Return*a+*b;执行该语句时,a和b地址还没有写回主内存,此时CPU不知道a地址是否等于b地址,是否需要写入到同一个地址,所以需要将a和b重新载入到寄存器,该过程发生“Stall
__restrict将a和b当做不同的地址对待,明确告诉CPU不需要写入到同一个地址,该过程不会发生“Stall”
Pipeline Stall

OOD VS DODOOD(ObjectOriented Design)Ø使用AoS(Arrayof Structure)数据结构Østd::vector<Node*>
由于内容术语比较小众,再加之一次性介绍篇幅较长,下一帖子中将继续声音内容,并且翻译成大众化语言。










SCE-PhyreEngine 发表于 2016-4-24 00:29

后续内容,后天就发。如果大家希望用通俗语言解释,我就用袁腾飞说三国的模式讲出来。

SCE-PhyreEngine 发表于 2016-4-24 00:41

同时诚邀隔壁高手一起讨论

笨啦灯 发表于 2016-4-24 00:54

{:5_566:}大晚上的看到代码头好晕

fastone 发表于 2016-4-24 13:56

你上次去做技术支持写的PPT?

SCE-PhyreEngine 发表于 2016-4-24 14:17

对。虽然他们是搞手机游戏的,但是还是去帮了一把

111alan 发表于 2016-4-24 15:55

不做这方面表示有些函数名称没见过。。。大概就是这两种方法降低延迟?
1.处理“是”的同时也处理“否”
2.强制写到不同的缓存地址

SCE-PhyreEngine 发表于 2016-4-24 16:11

后续还有新内容,后续内容发出后,我将一些地方总结起来解释
页: [1]
查看完整版本: Mobile 3D Game Engine Solution-1