Recently, I'm reading code of render system in the unreal engine5.3. I feel very confused about some of reflection code in shader. Here is an shader example in AnisotropyRendering.cpp
.
class FAnisotropyVS : public FMeshMaterialShader
{
public:
DECLARE_SHADER_TYPE(FAnisotropyVS, MeshMaterial);
static bool ShouldCompilePermutation(const FMeshMaterialShaderPermutationParameters& Parameters)
{
// Compile if supported by the hardware.
const bool bIsFeatureSupported = IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
return
bIsFeatureSupported &&
IsAnisotropyPassCompatible(Parameters.Platform, Parameters.MaterialParameters) &&
FMeshMaterialShader::ShouldCompilePermutation(Parameters);
}
FAnisotropyVS() = default;
FAnisotropyVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FMeshMaterialShader(Initializer)
{}
};
After expanding DECLARE_SHADER_TYPE
macro, I found some piece of code
private:
using InternalBaseType = typename TGetBaseTypeHelper<FAnisotropyVS>::Type;
template <typename InternalType>
static void InternalInitializeBases(FTypeLayoutDesc &TypeDesc) {
TInitializeBaseHelper<InternalType, InternalBaseType>::Initialize(TypeDesc);
};
public:
using DerivedType = FAnisotropyVS;
static constexpr ETypeLayoutInterface ::Type InterfaceType =
ETypeLayoutInterface ::NonVirtual;
template <int Counter> struct InternalLinkType {
;
static inline __attribute__((always_inline)) void
Initialize(FTypeLayoutDesc &TypeDesc) {}
};
The confused thing is, compiler tells me InternalBaseType
is actually a type alias of FMeshMaterialShader
, but it seems to me that InternalBaseType
should be a alias of FAnisotropyVS
.
TGetBaseTypeHelper
template defined in MemoryLayout.h
template<typename T>
struct TGetBaseTypeHelper
{
UE_STATIC_ONLY(TGetBaseTypeHelper);
template<typename InternalType> static typename InternalType::DerivedType Test(const typename InternalType::DerivedType*);
template<typename InternalType> static void Test(...);
using Type = decltype(Test<T>(nullptr));
};
Because FAnisotropyVS::DerivedType
is just FAnisotropyVS
. I can't see why InternalBaseType
is a alias of FMeshMaterialShader
(base type)
I will very appreciate it if someone can enlighten me what happens here. Though this is a very small implementation problem and nobody cares...
In class FMeshMaterialShader
class RENDERER_API FMeshMaterialShader : public FMaterialShader
{
DECLARE_TYPE_LAYOUT(FMeshMaterialShader, NonVirtual);
};
This macro will be expanded into some code and a piece of it like this
public:
using DerivedType = FMeshMaterialShader;
now the DerivedType is FMeshMaterialShader.
when class FAnisotropyVS inherits class FMeshMaterialShader.
class FAnisotropyVS looks like this
class FAnisotropyVS : public FMeshMaterialShader
{
// The declaration of FMeshMaterialShader
public:
using DerivedType = FMeshMaterialShader;
//... some code
// The declaration of FAnisotropyVS its own
public:
DECLARE_SHADER_TYPE(FAnisotropyVS, MeshMaterial);
};
Now when DECLARE_SHADER_TYPE(FAnisotropyVS, MeshMaterial);
expand like this
private:
using InternalBaseType = typename TGetBaseTypeHelper<FAnisotropyVS>::Type;
// Some code ...
public:
using DerivedType = FAnisotropyVS;
The DerivedType
is still FMeshMaterialShader
, because using DerivedType = FAnisotropyVS;
is after this piece of code.
So InternalBaseType
in FAnisotropyVS
is alias of FMeshMaterialShader