vault backup: 2024-02-06 17:24:44

This commit is contained in:
BlueRose 2024-02-06 17:24:44 +08:00
parent 35c941f86f
commit 67a7f200b8
4 changed files with 469 additions and 1 deletions

View File

@ -193,4 +193,472 @@ private:
// 缓冲区尺寸. // 缓冲区尺寸.
uint32 LayoutConstantBufferSize; uint32 LayoutConstantBufferSize;
}; };
```
// 定义FRHIUniformBuffer的引用类型.
typedef TRefCountPtr<FRHIUniformBuffer> FUniformBufferRHIRef;
// Engine\Source\Runtime\RenderCore\Public\ShaderParameterMacros.h
// 引用了指定类型的FRHIUniformBuffer的实例资源. 注意是继承了FUniformBufferRHIRef.
template<typename TBufferStruct>
class TUniformBufferRef : public FUniformBufferRHIRef
{
public:
TUniformBufferRef();
// 根据给定的值创建Uniform Buffer, 并返回结构体引用. (模板)
static TUniformBufferRef<TBufferStruct> CreateUniformBufferImmediate(const TBufferStruct& Value, EUniformBufferUsage Usage, EUniformBufferValidation Validation = EUniformBufferValidation::ValidateResources);
// 根据给定的值创建[局部]的Uniform Buffer, 并返回结构体引用.
static FLocalUniformBuffer CreateLocalUniformBuffer(FRHICommandList& RHICmdList, const TBufferStruct& Value, EUniformBufferUsage Usage);
// 立即刷新缓冲区数据到RHI.
void UpdateUniformBufferImmediate(const TBufferStruct& Value);
private:
// 私有构造体, 只能给TUniformBuffer和TRDGUniformBuffer创建.
TUniformBufferRef(FRHIUniformBuffer* InRHIRef);
template<typename TBufferStruct2>
friend class TUniformBuffer;
friend class TRDGUniformBuffer<TBufferStruct>;
};
```
最后TUniformBuffer和TRDGUniformBuffer引用了FUniformBufferRHIRef。TUniformBuffer为`TUniformBufferRef<TBufferStruct> UniformBufferRHI`成员变量TRDGUniformBuffer为`TRefCountPtr<FRHIUniformBuffer> UniformBufferRHI`
![[UE_Uniform.png]]
### 定义宏
- SHADER_PARAMETER_STRUCT_REF引用着色器参数结构体(全局的才行)
- SHADER_PARAMETER_STRUCT_INCLUDE包含着色器参数结构体(局部或全局都行)
# Vertex Factory
我们知道在引擎中存在着静态网格、蒙皮骨骼、程序化网格以及地形等等类型的网格类型而材质就是通过顶点工厂FVertexFactory来支持这些网格类型。实际上顶点工厂要涉及各方面的数据和类型包含但不限于
- 顶点着色器。顶点着色器的输入输出需要顶点工厂来表明数据的布局。
- 顶点工厂的参数和RHI资源。这些数据将从C++层传入到顶点着色器中进行处理。
- 顶点缓冲和顶点布局。通过顶点布局我们可以自定义和扩展顶点缓冲的输入从而实现定制化的Shader代码。
- 几何预处理。顶点缓冲、网格资源、材质参数等等都可以在真正渲染前预处理它们。
![[UE_VertexFactory.png]]
**顶点工厂在渲染层级中的关系。由图可知顶点工厂是渲染线程的对象横跨于CPU和GPU两端。**
```c++
// Engine\Source\Runtime\RHI\Public\RHI.h
// 顶点元素.
struct FVertexElement
{
uint8 StreamIndex; // 流索引
uint8 Offset; // 偏移
TEnumAsByte<EVertexElementType> Type; // 类型
uint8 AttributeIndex;// 属性索引
uint16 Stride; // 步长
// 实例索引或顶点索引是否实例化的, 若是0, 则元素会对每个实例进行重复.
uint16 bUseInstanceIndex;
FVertexElement();
FVertexElement(uint8 InStreamIndex, ...);
void operator=(const FVertexElement& Other);
friend FArchive& operator<<(FArchive& Ar,FVertexElement& Element);
FString ToString() const;
void FromString(const FString& Src);
void FromString(const FStringView& Src);
};
// 顶点声明元素列表的类型.
typedef TArray<FVertexElement,TFixedAllocator<MaxVertexElementCount> > FVertexDeclarationElementList;
// Engine\Source\Runtime\RHI\Public\RHIResources.h
// 顶点声明的RHI资源
class FRHIVertexDeclaration : public FRHIResource
{
public:
virtual bool GetInitializer(FVertexDeclarationElementList& Init) { return false; }
};
// 顶点缓冲区
class FRHIVertexBuffer : public FRHIResource
{
public:
FRHIVertexBuffer(uint32 InSize,uint32 InUsage);
uint32 GetSize() const;
uint32 GetUsage() const;
protected:
FRHIVertexBuffer();
void Swap(FRHIVertexBuffer& Other);
void ReleaseUnderlyingResource();
private:
// 尺寸.
uint32 Size;
// 缓冲区标记, 如BUF_UnorderedAccess
uint32 Usage;
};
// Engine\Source\Runtime\RenderCore\Public\VertexFactory.h
// 顶点输入流.
struct FVertexInputStream
{
// 顶点流索引
uint32 StreamIndex : 4;
// 在VertexBuffer的偏移.
uint32 Offset : 28;
// 顶点缓存区
FRHIVertexBuffer* VertexBuffer;
FVertexInputStream();
FVertexInputStream(uint32 InStreamIndex, uint32 InOffset, FRHIVertexBuffer* InVertexBuffer);
inline bool operator==(const FVertexInputStream& rhs) const;
inline bool operator!=(const FVertexInputStream& rhs) const;
};
// 顶点输入流数组.
typedef TArray<FVertexInputStream, TInlineAllocator<4>> FVertexInputStreamArray;
// 顶点流标记
enum class EVertexStreamUsage : uint8
{
Default = 0 << 0, // 默认
Instancing = 1 << 0, // 实例化
Overridden = 1 << 1, // 覆盖
ManualFetch = 1 << 2 // 手动获取
};
// 顶点输入流类型.
enum class EVertexInputStreamType : uint8
{
Default = 0, // 默认
PositionOnly, // 只有位置
PositionAndNormalOnly // 只有位置和法线
};
// 顶点流组件.
struct FVertexStreamComponent
{
// 流数据的顶点缓冲区, 如果为null, 则不会有数据从此顶点流被读取.
const FVertexBuffer* VertexBuffer = nullptr;
// vertex buffer的偏移.
uint32 StreamOffset = 0;
// 数据的偏移, 相对于顶点缓冲区中每个元素的开头.
uint8 Offset = 0;
// 数据的步长.
uint8 Stride = 0;
// 从流读取的数据类型.
TEnumAsByte<EVertexElementType> Type = VET_None;
// 顶点流标记.
EVertexStreamUsage VertexStreamUsage = EVertexStreamUsage::Default;
(......)
};
// 着色器使用的顶点工厂的参数绑定接口.
class FVertexFactoryShaderParameters
{
public:
// 绑定参数到ParameterMap. 具体逻辑由子类完成.
void Bind(const class FShaderParameterMap& ParameterMap) {}
// 获取顶点工厂的着色器绑定和顶点流. 具体逻辑由子类完成.
void GetElementShaderBindings(
const class FSceneInterface* Scene,
const class FSceneView* View,
const class FMeshMaterialShader* Shader,
const EVertexInputStreamType InputStreamType,
ERHIFeatureLevel::Type FeatureLevel,
const class FVertexFactory* VertexFactory,
const struct FMeshBatchElement& BatchElement,
class FMeshDrawSingleShaderBindings& ShaderBindings,
FVertexInputStreamArray& VertexStreams) const {}
(......)
};
// 用来表示顶点工厂类型的类.
class FVertexFactoryType
{
public:
// 类型定义
typedef FVertexFactoryShaderParameters* (*ConstructParametersType)(EShaderFrequency ShaderFrequency, const class FShaderParameterMap& ParameterMap);
typedef const FTypeLayoutDesc* (*GetParameterTypeLayoutType)(EShaderFrequency ShaderFrequency);
(......)
// 获取顶点工厂类型数量.
static int32 GetNumVertexFactoryTypes();
// 获取全局的着色器工厂列表.
static RENDERCORE_API TLinkedList<FVertexFactoryType*>*& GetTypeList();
// 获取已存的材质类型列表.
static RENDERCORE_API const TArray<FVertexFactoryType*>& GetSortedMaterialTypes();
// 通过名字查找FVertexFactoryType
static RENDERCORE_API FVertexFactoryType* GetVFByName(const FHashedName& VFName);
// 初始化FVertexFactoryType静态成员, 必须在VF类型创建之前调用.
static void Initialize(const TMap<FString, TArray<const TCHAR*> >& ShaderFileToUniformBufferVariables);
static void Uninitialize();
// 构造/析构函数.
RENDERCORE_API FVertexFactoryType(...);
virtual ~FVertexFactoryType();
// 数据获取接口.
const TCHAR* GetName() const;
FName GetFName() const;
const FHashedName& GetHashedName() const;
const TCHAR* GetShaderFilename() const;
// 着色器参数接口.
FVertexFactoryShaderParameters* CreateShaderParameters(...) const;
const FTypeLayoutDesc* GetShaderParameterLayout(...) const;
void GetShaderParameterElementShaderBindings(...) const;
// 标记访问.
bool IsUsedWithMaterials() const;
bool SupportsStaticLighting() const;
bool SupportsDynamicLighting() const;
bool SupportsPrecisePrevWorldPos() const;
bool SupportsPositionOnly() const;
bool SupportsCachingMeshDrawCommands() const;
bool SupportsPrimitiveIdStream() const;
// 获取哈希.
friend uint32 GetTypeHash(const FVertexFactoryType* Type);
// 基于顶点工厂类型的源码和包含计算出来的哈希.
const FSHAHash& GetSourceHash(EShaderPlatform ShaderPlatform) const;
// 是否需要缓存材质的着色器类型.
bool ShouldCache(const FVertexFactoryShaderPermutationParameters& Parameters) const;
void ModifyCompilationEnvironment(...);
void ValidateCompiledResult(EShaderPlatform Platform, ...);
bool SupportsTessellationShaders() const;
// 增加引用的Uniform Buffer包含.
void AddReferencedUniformBufferIncludes(...);
void FlushShaderFileCache(...);
const TMap<const TCHAR*, FCachedUniformBufferDeclaration>& GetReferencedUniformBufferStructsCache() const;
private:
static uint32 NumVertexFactories;
static bool bInitializedSerializationHistory;
// 顶点工厂类型的各类数据和标记.
const TCHAR* Name;
const TCHAR* ShaderFilename;
FName TypeName;
FHashedName HashedName;
uint32 bUsedWithMaterials : 1;
uint32 bSupportsStaticLighting : 1;
uint32 bSupportsDynamicLighting : 1;
uint32 bSupportsPrecisePrevWorldPos : 1;
uint32 bSupportsPositionOnly : 1;
uint32 bSupportsCachingMeshDrawCommands : 1;
uint32 bSupportsPrimitiveIdStream : 1;
ConstructParametersType ConstructParameters;
GetParameterTypeLayoutType GetParameterTypeLayout;
GetParameterTypeElementShaderBindingsType GetParameterTypeElementShaderBindings;
ShouldCacheType ShouldCacheRef;
ModifyCompilationEnvironmentType ModifyCompilationEnvironmentRef;
ValidateCompiledResultType ValidateCompiledResultRef;
SupportsTessellationShadersType SupportsTessellationShadersRef;
// 全局顶点工厂类型列表.
TLinkedList<FVertexFactoryType*> GlobalListLink;
// 缓存引用的Uniform Buffer的包含.
TMap<const TCHAR*, FCachedUniformBufferDeclaration> ReferencedUniformBufferStructsCache;
// 跟踪ReferencedUniformBufferStructsCache缓存了哪些平台的声明.
bool bCachedUniformBufferStructDeclarations;
};
// ------顶点工厂的工具宏------
// 实现顶点工厂参数类型
#define IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FactoryClass, ShaderFrequency, ParameterClass)
// 顶点工厂类型的声明
#define DECLARE_VERTEX_FACTORY_TYPE(FactoryClass)
// 顶点工厂类型的实现
#define IMPLEMENT_VERTEX_FACTORY_TYPE(FactoryClass,ShaderFilename,bUsedWithMaterials,bSupportsStaticLighting,bSupportsDynamicLighting,bPrecisePrevWorldPos,bSupportsPositionOnly)
// 顶点工厂的虚函数表实现
#define IMPLEMENT_VERTEX_FACTORY_VTABLE(FactoryClass
// 顶点工厂
class FVertexFactory : public FRenderResource
{
public:
FVertexFactory(ERHIFeatureLevel::Type InFeatureLevel);
virtual FVertexFactoryType* GetType() const;
// 获取顶点数据流.
void GetStreams(ERHIFeatureLevel::Type InFeatureLevel, EVertexInputStreamType VertexStreamType, FVertexInputStreamArray& OutVertexStreams) const
{
// Default顶点流类型
if (VertexStreamType == EVertexInputStreamType::Default)
{
bool bSupportsVertexFetch = SupportsManualVertexFetch(InFeatureLevel);
// 将顶点工厂的数据构造到FVertexInputStream中并添加到输出列表
for (int32 StreamIndex = 0;StreamIndex < Streams.Num();StreamIndex++)
{
const FVertexStream& Stream = Streams[StreamIndex];
if (!(EnumHasAnyFlags(EVertexStreamUsage::ManualFetch, Stream.VertexStreamUsage) && bSupportsVertexFetch))
{
if (!Stream.VertexBuffer)
{
OutVertexStreams.Add(FVertexInputStream(StreamIndex, 0, nullptr));
}
else
{
if (EnumHasAnyFlags(EVertexStreamUsage::Overridden, Stream.VertexStreamUsage) && !Stream.VertexBuffer->IsInitialized())
{
OutVertexStreams.Add(FVertexInputStream(StreamIndex, 0, nullptr));
}
else
{
OutVertexStreams.Add(FVertexInputStream(StreamIndex, Stream.Offset, Stream.VertexBuffer->VertexBufferRHI));
}
}
}
}
}
// 只有位置和的顶点流类型
else if (VertexStreamType == EVertexInputStreamType::PositionOnly)
{
// Set the predefined vertex streams.
for (int32 StreamIndex = 0; StreamIndex < PositionStream.Num(); StreamIndex++)
{
const FVertexStream& Stream = PositionStream[StreamIndex];
OutVertexStreams.Add(FVertexInputStream(StreamIndex, Stream.Offset, Stream.VertexBuffer->VertexBufferRHI));
}
}
// 只有位置和法线的顶点流类型
else if (VertexStreamType == EVertexInputStreamType::PositionAndNormalOnly)
{
// Set the predefined vertex streams.
for (int32 StreamIndex = 0; StreamIndex < PositionAndNormalStream.Num(); StreamIndex++)
{
const FVertexStream& Stream = PositionAndNormalStream[StreamIndex];
OutVertexStreams.Add(FVertexInputStream(StreamIndex, Stream.Offset, Stream.VertexBuffer->VertexBufferRHI));
}
}
else
{
// NOT_IMPLEMENTED
}
}
// 偏移实例的数据流.
void OffsetInstanceStreams(uint32 InstanceOffset, EVertexInputStreamType VertexStreamType, FVertexInputStreamArray& VertexStreams) const;
static void ModifyCompilationEnvironment(...);
static void ValidateCompiledResult(...);
static bool SupportsTessellationShaders();
// FRenderResource接口, 释放RHI资源.
virtual void ReleaseRHI();
// 设置/获取顶点声明的RHI引用.
FVertexDeclarationRHIRef& GetDeclaration();
void SetDeclaration(FVertexDeclarationRHIRef& NewDeclaration);
// 根据类型获取顶点声明的RHI引用.
const FVertexDeclarationRHIRef& GetDeclaration(EVertexInputStreamType InputStreamType) const
{
switch (InputStreamType)
{
case EVertexInputStreamType::Default: return Declaration;
case EVertexInputStreamType::PositionOnly: return PositionDeclaration;
case EVertexInputStreamType::PositionAndNormalOnly: return PositionAndNormalDeclaration;
}
return Declaration;
}
// 各类标记.
virtual bool IsGPUSkinned() const;
virtual bool SupportsPositionOnlyStream() const;
virtual bool SupportsPositionAndNormalOnlyStream() const;
virtual bool SupportsNullPixelShader() const;
// 用面向摄像机精灵的方式渲染图元.
virtual bool RendersPrimitivesAsCameraFacingSprites() const;
// 是否需要顶点声明.
bool NeedsDeclaration() const;
// 是否支持手动的顶点获取.
inline bool SupportsManualVertexFetch(const FStaticFeatureLevel InFeatureLevel) const;
// 根据流类型获取索引.
inline int32 GetPrimitiveIdStreamIndex(EVertexInputStreamType InputStreamType) const;
protected:
inline void SetPrimitiveIdStreamIndex(EVertexInputStreamType InputStreamType, int32 StreamIndex)
{
PrimitiveIdStreamIndex[static_cast<uint8>(InputStreamType)] = StreamIndex;
}
// 为顶点流组件创建顶点元素.
FVertexElement AccessStreamComponent(const FVertexStreamComponent& Component,uint8 AttributeIndex);
FVertexElement AccessStreamComponent(const FVertexStreamComponent& Component, uint8 AttributeIndex, EVertexInputStreamType InputStreamType);
// 初始化顶点声明.
void InitDeclaration(const FVertexDeclarationElementList& Elements, EVertexInputStreamType StreamType = EVertexInputStreamType::Default)
{
if (StreamType == EVertexInputStreamType::PositionOnly)
{
PositionDeclaration = PipelineStateCache::GetOrCreateVertexDeclaration(Elements);
}
else if (StreamType == EVertexInputStreamType::PositionAndNormalOnly)
{
PositionAndNormalDeclaration = PipelineStateCache::GetOrCreateVertexDeclaration(Elements);
}
else // (StreamType == EVertexInputStreamType::Default)
{
// Create the vertex declaration for rendering the factory normally.
Declaration = PipelineStateCache::GetOrCreateVertexDeclaration(Elements);
}
}
// 顶点流, 需要设置到顶点流的信息体.
struct FVertexStream
{
const FVertexBuffer* VertexBuffer = nullptr;
uint32 Offset = 0;
uint16 Stride = 0;
EVertexStreamUsage VertexStreamUsage = EVertexStreamUsage::Default;
uint8 Padding = 0;
friend bool operator==(const FVertexStream& A,const FVertexStream& B);
FVertexStream();
};
// 用于渲染顶点工厂的顶点流.
TArray<FVertexStream,TInlineAllocator<8> > Streams;
// VF(顶点工厂)可以显式地将此设置为false以避免在没有声明的情况下出现错误. 主要用于需要直接从缓冲区获取数据的VF(如Niagara).
bool bNeedsDeclaration = true;
bool bSupportsManualVertexFetch = false;
int8 PrimitiveIdStreamIndex[3] = { -1, -1, -1 };
private:
// 只有位置的顶点流, 用于渲染深度Pass的顶点工厂.
TArray<FVertexStream,TInlineAllocator<2> > PositionStream;
// 只有位置和法线的顶点流.
TArray<FVertexStream, TInlineAllocator<3> > PositionAndNormalStream;
// 用于常规渲染顶点工厂的RHI顶点声明.
FVertexDeclarationRHIRef Declaration;
// PositionStream和PositionAndNormalStream对应的RHI资源.
FVertexDeclarationRHIRef PositionDeclaration;
FVertexDeclarationRHIRef PositionAndNormalDeclaration;
};
```
上面展示了Vertex Factory的很多类型有好几个是核心类比如FVertexFactory、FVertexElement、FRHIVertexDeclaration、FRHIVertexBuffer、FVertexFactoryType、FVertexStreamComponent、FVertexInputStream、FVertexFactoryShaderParameters等。那么它们之间的关系是什么呢
为了更好地说明它们之间的关系以静态模型的FStaticMeshDataType为例
![[UE_VertexFactory_FStaticMeshDataType.jpg]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB