Skip to content

Commit 06d44e0

Browse files
committed
add post about struct serializer
add post about custom rendering component in UE4 update streaming POST
1 parent 320cf24 commit 06d44e0

9 files changed

+465
-0
lines changed

8.misc/cpp_msics.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# C++ Actor模式
2+
3+
* 什么是Actor模型
4+
* 分布式
5+
6+
CAF
7+
8+
9+
10+
# ECS框架
11+
12+
* 游戏框架
13+
14+
# 微软Concurency Runtime并行库
15+
16+
17+
18+
# enkiTS
19+
20+
* 开源的任务调度库
21+
* 建立任务依赖
62.8 KB
Loading
128 KB
Loading
36.8 KB
Loading
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# UE4自定义渲染组件
2+
3+
---
4+
5+
## SceneComponent
6+
7+
UE场景最基础组件
8+
9+
---
10+
11+
## PrimitiveComponent
12+
13+
图元组件包含渲染,也包含物理碰撞,导航网格,资源串流等逻辑,是UE最常见组件
14+
15+
``` cpp
16+
class UXXXComponent : public UPrimitiveComponent
17+
{
18+
public:
19+
// 视锥裁剪相关
20+
FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
21+
22+
// 渲染代理
23+
FPrimitiveSceneProxy* CreateSceneProxy() override;
24+
25+
virtual void GetUsedMaterials(TArray<UMaterialInterface *>& OutMaterials, bool bGetDebugMaterials /* = false */) const;
26+
27+
// Streaming相关接口
28+
/** Build the data to compute accuracte StreaminTexture data. */
29+
virtual bool BuildTextureStreamingData(ETextureStreamingBuildType BuildType, EMaterialQualityLevel::Type QualityLevel, ERHIFeatureLevel::Type FeatureLevel, TSet<FGuid>& DependentResources) override;
30+
/** Get the StreaminTexture data include mesh, 此接口加入待流送的纹理、Mesh、关联的包围盒 & TexelFactor */
31+
virtual void GetStreamingRenderAssetInfo(FStreamingTextureLevelContext& LevelContext, TArray<FStreamingRenderAssetPrimitiveInfo>& OutStreamingRenderAssets) const override;
32+
};
33+
34+
class FXXXSceneProxy : public FPrimitiveSceneProxy
35+
{
36+
public:
37+
// View可见性接口实现,【关键】决定在MainView,Reflection Capture是否可见
38+
FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override;
39+
// 获取动态渲染元素
40+
void GetDynamicMeshElements(
41+
const TArray<const FSceneView*>& Views,
42+
const FSceneViewFamily& ViewFamily,
43+
uint32 VisibilityMap,
44+
FMeshElementCollector& Collector) const override;
45+
// 获取静态渲染元素
46+
void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) override;
47+
48+
// 获取光追元素
49+
void GetDynamicRayTracingInstances(FRayTracingMaterialGatheringContext& Context,
50+
TArray<FRayTracingInstance>& OutRayTracingInstances) override;
51+
};
52+
```
53+
54+
> UE4资源流送调用堆栈
55+
56+
![](images/ue4_streaming_call_stack.png)
57+
58+
> Primitive RenderState(Create_Concurrent)
59+
60+
![](images/streaming_manager_notify_primitive.png)
61+
62+
![](images/streaming_manager_notify_detach.png)
63+
64+
> IStreamingManager,如果Component下的RenderState发生变化,需要显式调用`IStreamingManager::Get().NotifyPrimitiveUpdated(this)`
65+
66+
如何继承**UStreamableRenderAsset**
67+
68+
* Streamable RenderAsset仅支持单一文件单一LOD流送
69+
70+
如何流送单一资源文件,多物件流送?
71+
72+
* BulkData、RangeIO
73+
* 自己继承IStreamingManager(^_^),单独管理
74+
75+
### Bulk data的使用
76+
77+
---
78+
79+
``` cpp
80+
class IAsyncReadRequest;
81+
typedef TFunction<void(bool bWasCancelled, IAsyncReadRequest*)> FAsyncFileCallBack;
82+
83+
class FByteBulkData
84+
{
85+
public:
86+
87+
GetFileName();
88+
89+
FBulkDataIORequest*
90+
CreateStreamingRequest(
91+
EAsyncIOPriorityAndFlags Priority,
92+
FAsyncFileCallBack* CompleteCallback,
93+
uint8* UserSuppliedMemory) const;
94+
95+
FBulkDataIORequest*
96+
CreateStreamingRequest(
97+
int64 OffsetInBulkData, int64 BytesToRead,
98+
EAsyncIOPriorityAndFlags Priority,
99+
FAsyncFileCallBack* CompleteCallback,
100+
uint8* UserSuppliedMemory) const;
101+
};
102+
```
103+
104+
---
105+
106+
## AnyComponent
107+
108+
UE4中单一逻辑组件可用,类似体积云、虚拟纹理等,单独管理,单独渲染(无排序),需修改场景管理、渲染器渲染过程、材质Shader相关逻辑。
109+
110+
---
111+
112+
## MeshBatch & MeshCommand & RayTracingInstance
113+
114+
MeshBatch描述**单一VertexBuffer**不同Section的材质渲染,但实际只支持一个材质,但不同的MeshSection(**MeshBatchElement**)的特定材质参数可能不一样。
115+
116+
MeshPassProcessor会将MeshBatch转换成对应MeshCommand。
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# UE4自定义结构体序列化
2+
3+
> 疑问:像TMap这样的复杂结构是如何序列化的呢
4+
5+
先看看TStructOpsTypeTraitsBase2这个类
6+
7+
----
8+
9+
## TStructOpsTypeTraitsBase2
10+
11+
```cpp
12+
USTRUCT()
13+
struct FXXX
14+
{
15+
16+
bool Serialize(FArchive& Ar);
17+
};
18+
19+
20+
template<>
21+
struct TStructOpsTypeTraits<FXXX> : public TStructOpsTypeTraitsBase2<FXXX>
22+
{
23+
enum
24+
{
25+
WithSerializer = true
26+
};
27+
};
28+
```
29+
30+
再看看更基础的**FVector**,序列化的代码位于***UObject/Property.cpp***
31+
32+
> 使用StructOpsTypeTraits的代码位于***UObject/Class.h***
33+
34+
UScriptStruct (代理类) 记录 T 反射信息 ICppStructOps

8.misc/ue4_file_ops.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
UE4 IO & Package介绍
2+
===
3+
4+
* UPackage & FLinker & FArchive
5+
* BulkData
6+
* PlatformFile
7+
* NetworkFileSystem
8+
9+
## 基础IO文件操作
10+
---
11+
12+
- FileHelper (最简单的文件操作方式)
13+
14+
``` cpp
15+
#include "Misc/FileHelper.h"
16+
FFileHelper::BufferToString( FString& Result, const uint8* Buffer, int32 Size )
17+
FFileHelper::LoadFileToArray(TArray<uint8>& Result, const TCHAR* Filename, uint32 Flags = 0);
18+
FFileHelper::LoadFileToString( FString& Result, const TCHAR* Filename, EHashOptions VerifyFlags = EHashOptions::None, uint32 ReadFlags = 0 );
19+
```
20+
21+
- PlatformFile
22+
- IFileManager
23+
24+
``` cpp
25+
#include "HAL/FileManager.h"
26+
class IFileManager
27+
{
28+
public:
29+
static IFileManager& Get();
30+
FArchive* CreateFileReader( const TCHAR* Filename, uint32 ReadFlags=0 );
31+
FArchive* CreateFileWriter( const TCHAR* Filename, uint32 WriteFlags=0 );
32+
bool DirectoryExists( const TCHAR* InDirectory );
33+
FDateTime GetAccessTimeStamp( const TCHAR* Filename );
34+
};
35+
```
36+
37+
- FPlatformFileManager 最复杂的文件读取方式
38+
39+
``` cpp
40+
#include "HAL/PlatformFileManager.h"
41+
class FPlatformFileManager {
42+
public:
43+
static FPlatformFileManager& Get();
44+
// 创建
45+
IPlatformFile* GetPlatformFile( const TCHAR* Name );
46+
IPlatformFile& GetPlatformFile();
47+
};
48+
// 平台文件抽象类
49+
class IPlatformFile {
50+
public:
51+
void InitializeNewAsyncIO();
52+
IFileHandle* OpenRead(const TCHAR* Filename, bool bAllowWrite = false);
53+
IFileHandle* OpenReadNoBuffering(const TCHAR* Filename, bool bAllowWrite = false);
54+
IFileHandle* OpenWrite(const TCHAR* Filename, bool bAppend = false, bool bAllowRead = false);
55+
IAsyncReadFileHandle* OpenAsyncRead(const TCHAR* Filename);
56+
// 内存映射文件
57+
IMappedFileHandle* OpenMapped(const TCHAR* Filename);
58+
IMappedFileHandle* AllocateMapped(const TCHAR* Filename, int64 Size);
59+
bool CopyDirectoryTree(const TCHAR* DestinationDirectory, const TCHAR* Source, bool bOverwriteAllExisting);
60+
};
61+
```
62+
63+
- BulkData 读取
64+
``` cpp
65+
// BulkData (Size > 16K)
66+
class IAsyncReadRequest;
67+
typedef TFunction<void(bool bWasCancelled, IAsyncReadRequest*)> FAsyncFileCallBack;
68+
class FByteBulkData
69+
{
70+
public:
71+
72+
GetFileName();
73+
74+
FBulkDataIORequest*
75+
CreateStreamingRequest(
76+
EAsyncIOPriorityAndFlags Priority,
77+
FAsyncFileCallBack* CompleteCallback,
78+
uint8* UserSuppliedMemory) const;
79+
80+
FBulkDataIORequest*
81+
CreateStreamingRequest(
82+
int64 OffsetInBulkData, int64 BytesToRead,
83+
EAsyncIOPriorityAndFlags Priority,
84+
FAsyncFileCallBack* CompleteCallback,
85+
uint8* UserSuppliedMemory) const;
86+
};
87+
88+
// 异步文件读取
89+
IAsyncReadFileHandle* IORequestHandle = FPlatformFileManager::Get().GetPlatformFile().OpenAsyncRead(*Filename);
90+
check(IORequestHandle); // this generally cannot fail because it is async
91+
if (IORequestHandle == nullptr)
92+
{
93+
return nullptr;
94+
}
95+
const int64 OffsetInFile = GetBulkDataOffsetInFile() + OffsetInBulkData;
96+
IAsyncReadRequest* ReadRequest = IORequestHandle->ReadRequest(OffsetInFile, BytesToRead, Priority, CompleteCallback, UserSuppliedMemory);
97+
if (ReadRequest != nullptr)
98+
{
99+
return new FBulkDataIORequest(IORequestHandle, ReadRequest, BytesToRead);
100+
}
101+
else
102+
{
103+
delete IORequestHandle;
104+
return nullptr;
105+
}
106+
107+
bool FBulkDataIORequest::PollCompletion() const
108+
{
109+
return ReadRequest->PollCompletion();
110+
}
111+
bool FBulkDataIORequest::WaitCompletion(float TimeLimitSeconds) const
112+
{
113+
return ReadRequest->WaitCompletion(TimeLimitSeconds);
114+
}
115+
uint8* FBulkDataIORequest::GetReadResults() const
116+
{
117+
return ReadRequest->GetReadResults();
118+
}
119+
```
120+
121+
- MemoryMapping File(内存映射文件)
122+
123+
```cpp
124+
check(!FPlatformProperties::GetMemoryMappingAlignment() || IsAligned(BulkDataOffsetInFile, FPlatformProperties::GetMemoryMappingAlignment()));
125+
bWasMapped = BulkData.MapFile(*Filename, BulkDataOffsetInFile, GetBulkDataSize());
126+
127+
bool FUntypedBulkData::FAllocatedPtr::MapFile(const TCHAR *InFilename, int64 Offset, int64 Size)
128+
{
129+
check(!MappedHandle && !MappedRegion); // It doesn't make sense to do this twice, but if need be, not hard to do
130+
131+
MappedHandle = FPlatformFileManager::Get().GetPlatformFile().OpenMapped(InFilename);
132+
133+
if (!MappedHandle)
134+
{
135+
return false;
136+
}
137+
MappedRegion = MappedHandle->MapRegion(Offset, Size, true); //@todo we really don't want to hit the disk here to bring it into memory
138+
if (!MappedRegion)
139+
{
140+
delete MappedHandle;
141+
MappedHandle = nullptr;
142+
return false;
143+
}
144+
145+
check(Size == MappedRegion->GetMappedSize());
146+
Ptr = (void*)(MappedRegion->GetMappedPtr()); //@todo mapped files should probably be const-correct
147+
check(IsAligned(Ptr, FPlatformProperties::GetMemoryMappingAlignment()));
148+
bAllocated = true;
149+
return true;
150+
}
151+
152+
void FUntypedBulkData::FAllocatedPtr::UnmapFile()
153+
{
154+
if (MappedRegion || MappedHandle)
155+
{
156+
delete MappedRegion;
157+
delete MappedHandle;
158+
MappedRegion = nullptr;
159+
MappedHandle = nullptr;
160+
Ptr = nullptr; // make sure we don't try to free this pointer
161+
}
162+
}
163+
```
164+
165+
- FArchive
166+
167+
```cpp
168+
class FArchive {
169+
public:
170+
FString GetArchiveName() const;
171+
FLinker* GetLinker();
172+
173+
int64 TotalSize();
174+
bool AtEnd();
175+
void Seek(int64 InPos);
176+
int64 Tell();
177+
void Flush();
178+
179+
void Serialize(void* V, int64 Length);
180+
FArchive& ByteOrderSerialize(void* V, int32 Length);
181+
182+
bool SetCompressionMap(TArray<struct FCompressedChunk>* CompressedChunks, ECompressionFlags CompressionFlags);
183+
void SerializeCompressed(void* V, int64 Length, FName CompressionFormat, ECompressionFlags Flags=COMPRESS_NoFlags, bool bTreatBufferAsFileReader=false);
184+
185+
void AttachBulkData(UObject* Owner, FUntypedBulkData* BulkData);
186+
void DetachBulkData(FUntypedBulkData* BulkData, bool bEnsureBulkDataIsLoaded);
187+
188+
//版本管理
189+
int32 UE4Ver() const;
190+
FEngineVersionBase EngineVer() const;
191+
int32 CustomVer(const struct FGuid& Key) const;
192+
void UsingCustomVersion(const struct FGuid& Guid);
193+
194+
private:
195+
// 自定义版本
196+
mutable FCustomVersionContainer* CustomVersionContainer = nullptr;
197+
};
198+
```
199+
200+
---
201+
202+
## UPackage结构
203+
204+
## DirectStorage
205+
206+
- Queue IO Request
207+
208+
``` cpp
209+
QueueReuest(DestMemoryAddress, FileName)
210+
QueueSignal(Fence)
211+
```

0 commit comments

Comments
 (0)