【UE4源代码观察】观察TargetPlatform模块

2024-09-06 23:48

本文主要是介绍【UE4源代码观察】观察TargetPlatform模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前情提要与本次目标

在之前的博客《【UE4源代码观察】观察 RHI、D3D11RHI、RenderCore 这三个模块的依赖关系》中,我将RHID3D11RHIRenderCore这三个模块加入了我的空白工程中并确保可以成功编译。然而当时RenderCore模块有一个比较大的缺失:没有让shader相关的功能正常编译,因为它需要TargetPlatform模块中的内容。

因此,这次我想观察一下这个模块,并希望能完成下面目标:

  1. 了解这个模块的大体结构是什么,大概要做些什么事情
  2. 将这个模块加入到我的空白工程中,至少保证RenderCore模块中的shader相关功能可以正常编译,其他暂时用不到的部分如果比较麻烦可以先放弃。

观察:模块类

TargetPlatformManagerModule.cpp中指定了这个模块由FTargetPlatformManagerModule类来实现:

IMPLEMENT_MODULE(FTargetPlatformManagerModule, TargetPlatform);

FTargetPlatformManagerModule继承了ITargetPlatformManagerModule

/*** Module for the target platform manager*/
class FTargetPlatformManagerModule: public ITargetPlatformManagerModule

由于FTargetPlatformManagerModule是定义在cpp文件中的,所以不会在其他地方发现有他的继承者了。

这个模块有一个和其他大多数模块醒目的区别:除了上面的FTargetPlatformManagerModule这一模块类,这个模块里还有其他IModuleInterface类,而他们每一个都对应了一个格式的领域,定义了这个领域中格式的模块的通用接口。下面逐个看下这些领域:

IAudioFormatModule

它有如下子类(分别被定义到了各自独立的模块中):
FAudioPlatformADPCMModule
FAudioPlatformOggModule
FAudioPlatformOpusModule

IAudioFormatModule只定义了一个函数:

/**
* Gets the audio format.** @return The audio format interface.*/
virtual IAudioFormat* GetAudioFormat() = 0;

IAudioFormat同样定义在TargetPlatform模块中:

/*** Interface for audio formats.*/
class IAudioFormat

它的子类如下:
FAudioFormatADPCM
FAudioFormatOgg
FAudioFormatOpus
和模块一一对应。

IShaderFormatModule

它有如下子类(分别被定义到了各自独立的模块中):
FMetalShaderFormatModule
FShaderFormatOpenGLModule
FShaderFormatVectorVMModule
FVulkanShaderFormatModule
FShaderFormatD3DModule

IShaderFormatModule只定义了一个函数:

/**
* Gets the shader format.** @return The shader format interface.*/
virtual IShaderFormat* GetShaderFormat() = 0;

IShaderFormat同样定义在TargetPlatform模块中:

/*** IShaderFormat, shader pre-compilation abstraction*/
class IShaderFormat

它的子类如下:
FMetalShaderFormat
FShaderFormatGLSL
FShaderFormatVectorVM
FShaderFormatVulkan
FShaderFormatD3D
和模块一一对应。

ITextureFormatModule

它有如下子类(分别被定义到了各自独立的模块中):
FTextureFormatAndroidModule
FTextureFormatASTCModule
FTextureFormatDXTModule
FTextureFormatIntelISPCTexCompModule
FTextureFormatPVRModule
FTextureFormatUncompressed

ITextureFormatModule只定义了一个函数:

/*** Gets the texture format.** @return The texture format interface.*/
virtual ITextureFormat* GetTextureFormat() = 0;

ITextureFormat同样定义在TargetPlatform模块中:

/*** Interface for texture compression modules.*/
class ITextureFormat

它的子类如下:
FTextureFormatAndroid
FTextureFormatASTC
FTextureFormatDXT
FTextureFormatIntelISPCTexComp
FTextureFormatPVR
FTextureFormatUncompressed
和模块一一对应。

ITargetPlatformModule

之前三个的情况都类似,而ITargetPlatformModule与他们则差别很大,ITargetPlatformModuleITargetPlatform的关系变得更复杂了。

对于ITargetPlatformModule,它的子类如下:
在这里插入图片描述
ITargetPlatformModule有一个函数来获得一个ITargetPlatform

virtual ITargetPlatform* GetTargetPlatform()
{return nullptr;
};

还有一个函数来获得多个ITargetPlatform

/**
* Gets the module's target platforms. This should be overridden by each platform, but * currently, we are re-using the single internal GetTargetPlatform method the old TPModules will implement** @return The target platform.*/
virtual TArray<ITargetPlatform*> GetTargetPlatforms()
{TArray<ITargetPlatform*> TargetPlatforms;ITargetPlatform* TargetPlatform = GetTargetPlatform();if (TargetPlatform != nullptr){TargetPlatforms.Add(TargetPlatform);}return TargetPlatforms;
}

看来,ITargetPlatformModule可能对应一个或多个,但外界应该总是访问TArray<ITargetPlatform*> GetTargetPlatforms()。如果对应一个,则直接重写ITargetPlatform* GetTargetPlatform函数,此时TArray<ITargetPlatform*> GetTargetPlatforms()仍旧可以正确返回。而如果是对应多个,则直接重写TArray<ITargetPlatform*> GetTargetPlatforms()

对于ITargetPlatform,它有一个唯一的子类:

/*** Base class for target platforms.*/
class TARGETPLATFORM_VTABLE FTargetPlatformBase : public ITargetPlatform

随后,FTargetPlatformBase也有一个唯一的子类:

/*** Template for target platforms.** @param TPlatformProperties Type of platform properties.*/
template<typename TPlatformProperties>
class TTargetPlatformBase : public FTargetPlatformBase

TTargetPlatformBase则由丰富的子类继承关系:
在这里插入图片描述
模块在返回ITargetPlatform是可以指定模板的参数的,例如:
FWindowsTargetPlatformModule对应的是:

virtual ITargetPlatform* GetTargetPlatform( ) override
{if (Singleton == nullptr && TGenericWindowsTargetPlatform<true, false, false>::IsUsable()){Singleton = new TGenericWindowsTargetPlatform<true, false, false>();}return Singleton;
}

FWindowsServerTargetPlatformModule对应的是:

virtual ITargetPlatform* GetTargetPlatform( )
{if (Singleton == nullptr && TGenericWindowsTargetPlatform<false, true, false>::IsUsable()){Singleton = new TGenericWindowsTargetPlatform<false, true, false>();}return Singleton;
}

观察:如何获取格式

对于AudioShaderTextureITargetPlatformManagerModule分别定义了GetAudioFormatsGetShaderFormatsGetTextureFormats函数来获取所有格式,这些函数的实现可以在FTargetPlatformManagerModule中被找到,方法都是相同的:通过模块的名字来找。例如对于Audio

TArray<FName> Modules;FModuleManager::Get().FindModules(TEXT("*AudioFormat*"), Modules);if (!Modules.Num())
{UE_LOG(LogTargetPlatformManager, Error, TEXT("No target audio formats found!"));
}for (int32 Index = 0; Index < Modules.Num(); Index++)
{IAudioFormatModule* Module = FModuleManager::LoadModulePtr<IAudioFormatModule>(Modules[Index]);if (Module){IAudioFormat* Format = Module->GetAudioFormat();if (Format != nullptr){Results.Add(Format);}}
}

尝试寻找名字中带有AudioFormat的模块,随后将这些模块尝试转为IAudioFormatModule类型,如果成功的话就调用GetAudioFormat()函数来获得IAudioFormat
对于Texture,方法是一样的,只不过关键字为TextureFormat。对于Shader则是ShaderFormat

此外值得一提的是,PhysXCooking似乎也被看作一个格式,GetPhysXCooking()函数也是类似的操作,在寻找开头为PhysXCookingIPhysXCookingModule类型的模块,之后想得到IPhysXCooking类。IPhysXCookingModuleIPhysXCooking都不在TargetPlatform模块中定义,而是在PhysicsCore模块中定义:

/*** Interface for PhysX format modules.*/
class PHYSICSCORE_API IPhysXCookingModule : public IModuleInterface
/*** IPhysXCooking, PhysX cooking and serialization abstraction
**/
class PHYSICSCORE_API IPhysXCooking

不过,它最终只获得了一个格式:
在这里插入图片描述
我想,既然在TargetPlatform模块中出现,那我想应该是过去存在或是未来将要存在这种格式的多个实例?


ITargetPlatform的情况则稍微复杂些。首先,FTargetPlatformManagerModule拥有一个ITargetPlatform的列表:

// Holds the list of discovered platforms.
TArray<ITargetPlatform*> Platforms;

GetTargetPlatforms函数实际是返回这个列表,实际获得这个列表的值是通过DiscoverAvailablePlatforms函数完成的。

virtual const TArray<ITargetPlatform*>& GetTargetPlatforms() override
{if (Platforms.Num() == 0 || bForceCacheUpdate){DiscoverAvailablePlatforms();}return Platforms;
}

关于Platforms列表的逻辑我没有深究,简单来看还和FPlatformInfo有关:
在这里插入图片描述
对于每一个FPlatformInfo,都试图得到一个ITargetPlatformModule

// there are two ways targetplatform modules are setup: a single DLL per TargetPlatform, or a DLL for the platform
// that returns multiple TargetPlatforms. we try single first, then full platform
FName FullPlatformModuleName = *(PlatInfo.IniPlatformName + TEXT("TargetPlatform"));
FName SingleTargetPlatformModuleName = *(PlatInfo.TargetPlatformName.ToString() + TEXT("TargetPlatform"));
bool bFullPlatformModuleNameIsValid = !PlatInfo.IniPlatformName.IsEmpty();ITargetPlatformModule* Module = nullptr;if (FModuleManager::Get().ModuleExists(*SingleTargetPlatformModuleName.ToString()))
{Module = FModuleManager::LoadModulePtr<ITargetPlatformModule>(SingleTargetPlatformModuleName);
}
else if (bFullPlatformModuleNameIsValid && FModuleManager::Get().ModuleExists(*FullPlatformModuleName.ToString()))
{Module = FModuleManager::LoadModulePtr<ITargetPlatformModule>(FullPlatformModuleName);
}

最终得到的数目比FPlatformInfo的数目要少:
在这里插入图片描述

观察:依赖模块

TargetPlatform.Build.cs文件进行观察:

1.依赖模块:
PrivateDependencyModuleNames.Add("Core");
PrivateDependencyModuleNames.Add("SlateCore");
PrivateDependencyModuleNames.Add("Slate");
PrivateDependencyModuleNames.Add("EditorStyle");
PrivateDependencyModuleNames.Add("Projects");
PublicDependencyModuleNames.Add("AudioPlatformConfiguration");
PublicDependencyModuleNames.Add("DesktopPlatform");
PublicDependencyModuleNames.Add("LauncherPlatform");
2.需要include的模块:
PrivateIncludePathModuleNames.Add("Engine");
PrivateIncludePathModuleNames.Add("PhysicsCore");
3. 动态加载的模块

动态加载的模块有很多条件。
首先是PhysXCooking模块:

if (Target.bBuildDeveloperTools == true && Target.bBuildRequiresCookedData && Target.bCompileAgainstEngine && Target.bCompilePhysX)
{DynamicallyLoadedModuleNames.Add("PhysXCooking");
}

剩下的所有模块的条件都是:

// no need for all these modules if the program doesn't want developer tools at all (like UnrealFileServer)
if (!Target.bBuildRequiresCookedData && Target.bBuildDeveloperTools)

首先是一些所有平台都需要的模块:

// these are needed by multiple platform specific target platforms, so we make sure they are built with the base editor
DynamicallyLoadedModuleNames.Add("ShaderPreprocessor");
DynamicallyLoadedModuleNames.Add("ShaderFormatOpenGL");
DynamicallyLoadedModuleNames.Add("ImageWrapper");

其中ShaderPreprocessorImageWrapper是目前还不了解的,之后待研究。

而剩下的都是上面讨论的一些和一个格式对应的模块,他们根据平台有不同的情况,具体如下:

TargetPlatform是Win32/Win64TargetPlatform是MacInPlatformGroup(Linux)
-TextureFormatDXTTextureFormatDXTTextureFormatDXT
TextureFormatPVRTextureFormatPVRTextureFormatPVR
TextureFormatASTCTextureFormatASTCTextureFormatASTC
TextureFormatUncompressedTextureFormatUncompressedTextureFormatUncompressed
TextureFormatIntelISPCTexComp--
ShaderFormatOpenGLShaderFormatOpenGLShaderFormatOpenGL
ShaderFormatD3D--
MetalShaderFormat--
bCompileAgainstEngineAudioFormatADPCMAudioFormatADPCMAudioFormatADPCM
AudioFormatOggAudioFormatOggAudioFormatOgg
AudioFormatOpusAudioFormatOpusAudioFormatOpus
TargetType是Editor或ProgramAndroidTargetPlatformAndroidTargetPlatformAndroidTargetPlatform
IOSTargetPlatformIOSTargetPlatform-
TVOSTargetPlatformTVOSTargetPlatform-
MacTargetPlatform--
MacNoEditorTargetPlatform--
MacServerTargetPlatform--
MacClientTargetPlatform--

这么看来Windows平台上模块是最全的?


另外值得一提的是,我发现:还有的依赖模块是上面分析的.Build.cs文件中所没有的。最后找到在UnrealBuildTool中还有操作:
\Engine\Source\Programs\UnrealBuildTool\Platform路径中,有
在这里插入图片描述
这些文件夹,例如对于Windows,有UEBuildWindows.cs文件,有一个ModifyModuleRulesForActivePlatform函数:

/// <summary>
/// Modify the rules for a newly created module, in a target that's being built for this platform.
/// This is not required - but allows for hiding details of a particular platform.
/// </summary>
/// <param name="ModuleName">The name of the module</param>
/// <param name="Rules">The module rules</param>
/// <param name="Target">The target being build</param>
public override void ModifyModuleRulesForActivePlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target)

这个函数尝试改变一些模块依赖,例如这里指定了为TargetPlatform模块增加了一些模块

// allow standalone tools to use target platform modules, without needing Engine
if (ModuleName == "TargetPlatform")
{if (Target.bForceBuildTargetPlatforms){Rules.DynamicallyLoadedModuleNames.Add("WindowsTargetPlatform");Rules.DynamicallyLoadedModuleNames.Add("WindowsNoEditorTargetPlatform");Rules.DynamicallyLoadedModuleNames.Add("WindowsServerTargetPlatform");Rules.DynamicallyLoadedModuleNames.Add("WindowsClientTargetPlatform");Rules.DynamicallyLoadedModuleNames.Add("AllDesktopTargetPlatform");}if (bBuildShaderFormats){Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatD3D");Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatOpenGL");Rules.DynamicallyLoadedModuleNames.Remove("VulkanRHI");Rules.DynamicallyLoadedModuleNames.Add("VulkanShaderFormat");}
}

如果要改动这些内容,则需用先重新编译UBT,然后再编译代码。

实践1:补充模块

1. ShaderPreprocessor模块以及相关模块

TargetPlatform模块需要ShaderPreprocessor模块,这个模块的依赖关系比较简单:

PrivateDependencyModuleNames.AddRange(new string[] {"Core","RenderCore",});
AddEngineThirdPartyPrivateStaticDependencies(Target, "MCPP");

CoreRenderCore都已经在工程中了,而MCPP这个第三方模块还没有。
ShaderPreprocessor看起来是个编译shader的一个重要模块,不过现阶段我想关注的是大体结构,而不是具体细节,因此我选择直接将这两个模块都拷贝。

2. ShaderCompilerCommon模块以及相关模块

ShaderCompilerCommonShaderFormatOpenGLShaderFormatD3D这种提供shader格式的模块所依赖,它的依赖关系也比较简单:

PrivateDependencyModuleNames.AddRange(new string[] {"Core","RenderCore",});// We only need a header containing definitions
PublicSystemIncludePaths.Add("ThirdParty/hlslcc/hlslcc/src/hlslcc_lib");

hlslcc也是个第三方模块,应该和HLSL的shader编译有关

2.ShaderFormatD3D相关

对于D3D,还需要有dll,否则之后会报错:

1>UnrealBuildTool : error : Unhandled exception: Source file 'D:\0_WorkSpace\UEYaksueTest\Engine\Binaries\ThirdParty\Windows\DirectX\x64\dxil.dll' does not exist
1>                        while creating runtime dependencies for module 'ShaderFormatD3D'

因此将\Engine\Binaries\ThirdParty\Windows\DirectX\拷贝。

3. OpenGL模块以及相关模块

ShaderFormatOpenGL模块Build.cs内容如下:

PrivateIncludePathModuleNames.Add("TargetPlatform");PrivateIncludePaths.Add("Runtime/OpenGLDrv/Private");
PrivateIncludePaths.Add("Runtime/OpenGLDrv/Public");PrivateDependencyModuleNames.AddRange(new string[] {"Core","RenderCore","ShaderCompilerCommon","ShaderPreprocessor","RHI" // @todo platplug: this is caused by the DataDrivenShaderPlatformInfo stuff - maybe it should move to somewhere else, like RenderCore?});AddEngineThirdPartyPrivateStaticDependencies(Target, "OpenGL","HLSLCC");if (Target.IsInPlatformGroup(UnrealPlatformGroup.Linux)){AddEngineThirdPartyPrivateStaticDependencies(Target, "SDL2");}
if (Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.Win64)
{AddEngineThirdPartyPrivateStaticDependencies(Target,"ShaderConductor","SPIRVReflect");
}if (Target.Platform == UnrealTargetPlatform.Win64)
{PublicDelayLoadDLLs.Add("dxcompiler_sc.dll");PublicDelayLoadDLLs.Add("ShaderConductor.dll");
}

其中涉及到的ShaderConductorSPIRVReflect都是第三方模块,(其中SPIRV应该是指Vulkan的 SPIR-V shader格式)。将其拷贝。

另外要注意的是,它还需要include OpenGLDrv这个模块的头文件,于是我将其拷贝过来,但是暂时先删除头文件之外其他的文件。

此外,还需要拷贝ShaderConductor.lib文件,不然会有报错:

fatal error LNK1181: 无法打开输入文件“..\Binaries\ThirdParty\ShaderConductor\Win64\ShaderConductor.lib”
4. VulkanShaderFormat模块相关

VulkanShaderFormat依赖了Vulkan这个第三方模块。
VulkanShaderFormat还依赖了 GlsLang模块,我看这里有个EPIC-Changes.txt文件,看来他们对里面的内容做了些改变。

5. 其他

DesktopPlatformLauncherPlatform是所依赖的。但他们自己所依赖的模块较少,直接添加进来就没有问题。

实践2: 去掉一些暂时用不到的内容

1.Slate相关

TargetPlatform需要slate相关的模块是我暂时所不能理解的。我暂时将.Build.cs中对SlateCore模块Slate模块的依赖给去掉。
随后,我将界面相关的文件SDeviceBrowserDefaultPlatformAddWidget.h/cppDeviceBrowserDefaultPlatformWidgetCreator.h/cpp给去掉。
我看到了FTargetPlatformBase::GetCustomWidgetCreator函数用到了上面的内容:

TSharedPtr<IDeviceManagerCustomPlatformWidgetCreator> FTargetPlatformBase::GetCustomWidgetCreator() const
{static TSharedPtr<FDeviceBrowserDefaultPlatformWidgetCreator> DefaultWidgetCreator = MakeShared<FDeviceBrowserDefaultPlatformWidgetCreator>();return DefaultWidgetCreator;
}

于是我暂时将它去掉:

TSharedPtr<IDeviceManagerCustomPlatformWidgetCreator> FTargetPlatformBase::GetCustomWidgetCreator() const
{//static TSharedPtr<FDeviceBrowserDefaultPlatformWidgetCreator> DefaultWidgetCreator = MakeShared<FDeviceBrowserDefaultPlatformWidgetCreator>();//return DefaultWidgetCreator;return nullptr;//yaksuetest
}
2.PHYSX相关

TargetPlatform模块中的WITH_PHYSX宏制定了是否编译PHYSX相关的内容。
在UBT中有对这个宏的逻辑:在\Engine\Source\Programs\UnrealBuildTool\Configuration\ModuleRules.cs中:

// definitions used outside of PhysX/APEX need to be set here, not in PhysX.Build.cs or APEX.Build.cs, 
// since we need to make sure we always set it, even to 0 (because these are Private dependencies, the
// defines inside their Build.cs files won't leak out)
if (Target.bCompilePhysX == true)
{PrivateDependencyModuleNames.Add("PhysX");PublicDefinitions.Add("WITH_PHYSX=1");
}
else
{PublicDefinitions.Add("WITH_PHYSX=0");
}

但是,我在编译时遇到的错误是(这些文件都用到了这个宏):

1>D:/0_WorkSpace/UEYaksueTest/Engine/Source/Developer/TargetPlatform/Private/TargetPlatformManagerModule.cpp(24): error C4668: 没有将“WITH_PHYSX”定义为预处理器宏,用“0”替换“#if/#elif”
1>D:/0_WorkSpace/UEYaksueTest/Engine/Source/Developer/TargetPlatform/Private/TargetPlatformManagerModule.cpp(550): error C4668: 没有将“WITH_PHYSX”定义为预处理器宏,用“0”替换“#if/#elif”
1>D:/0_WorkSpace/UEYaksueTest/Engine/Source/Developer/TargetPlatform/Private/TargetPlatformManagerModule.cpp(584): error C4668: 没有将“WITH_PHYSX”定义为预处理器宏,用“0”替换“#if/#elif”

提示的是没有将“WITH_PHYSX”定义为预处理器宏,用“0”替换“#if/#elif”,这说明这个宏就没有被定义(不管是0还是1),也就是说上面UBT里的逻辑并没有走到。
目前我还不清楚这是为什么,现在我只能在TargetPlatform.Build.cs中加入这个宏(值是0,暂时不想使用它):

PublicDefinitions.Add("WITH_PHYSX=0");//yaksuetest

我知道这不是引擎原本的方法,希望之后能搞明白这个问题。

3.TextureFormat相关

注释掉相关的模块:

//DynamicallyLoadedModuleNames.Add("TextureFormatDXT");
//DynamicallyLoadedModuleNames.Add("TextureFormatPVR");
//DynamicallyLoadedModuleNames.Add("TextureFormatASTC");//DynamicallyLoadedModuleNames.Add("TextureFormatUncompressed");
4.Audio相关

注释掉相关的模块:

//DynamicallyLoadedModuleNames.Add("AudioFormatOgg");
//DynamicallyLoadedModuleNames.Add("AudioFormatOpus");
//DynamicallyLoadedModuleNames.Add("AudioFormatADPCM");

实践3:确保RenderCore模块中Shader部分可编译

1. Core模块中的TargetPlatform部分

首先,在之前《【UE4源代码观察】观察Core模块》时候,为了保证Core模块能编译,我将Build.cs文件中我注释掉了PrivateIncludePathModuleNames中的内容,现在,是时候放出TargetPlatform了:

PrivateIncludePathModuleNames.AddRange(new string[] {"TargetPlatform",/*"DerivedDataCache","InputDevice","Analytics","RHI"*/});

随后,可以将之前在CoreMisc.cpp中对于TargetPlatform的注释去掉:

#include "Interfaces/ITargetPlatformManagerModule.h"

使得下面两个函数可用:

class ITargetPlatformManagerModule* GetTargetPlatformManager()
{static class ITargetPlatformManagerModule* SingletonInterface = NULL;if (!FPlatformProperties::RequiresCookedData()){static bool bInitialized = false;if (!bInitialized){check(IsInGameThread());bInitialized = true;SingletonInterface = FModuleManager::LoadModulePtr<ITargetPlatformManagerModule>("TargetPlatform");}}return SingletonInterface;
}class ITargetPlatformManagerModule& GetTargetPlatformManagerRef()
{class ITargetPlatformManagerModule* SingletonInterface = GetTargetPlatformManager();if (!SingletonInterface){UE_LOG(LogInit, Fatal, TEXT("Target platform manager was requested, but not available."));CA_ASSUME( SingletonInterface != NULL );	// Suppress static analysis warning in unreachable code (fatal error)}return *SingletonInterface;
}

这两个函数被RenderCore中的代码用到了很多次。

2. RenderCore模块中的TargetPlatform部分

首先,将RenderCore.Build.cs中对TargetPlatform的注释去掉。
之后,恢复掉之前TargetPlatform的注释,具体来说是下面的几个文件:
Engine\Source\Runtime\RenderCore\Private\RenderUtils.cpp
Engine\Source\Runtime\RenderCore\Private\Shader.cpp
Engine\Source\Runtime\RenderCore\Private\ShaderCodeLibrary.cpp
Engine\Source\Runtime\RenderCore\Private\ShaderCore.cpp

随后,编译成功。

总结

这一篇我观察了TargetPlatform模块的大体结构,并且将之前代码中注释掉的TargetPlatform部分恢复,使得其Shader相关的部分可以编译。然而,这并不是说Shader相关的部分可以使用了,加断点可以看到:
在这里插入图片描述
这一块是CompileGlobalShaderMap这个函数调用的,而它是Engine模块的内容。这块想必是很重要的,接下来值得研究。

这篇关于【UE4源代码观察】观察TargetPlatform模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143462

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

python内置模块datetime.time类详细介绍

​​​​​​​Python的datetime模块是一个强大的日期和时间处理库,它提供了多个类来处理日期和时间。主要包括几个功能类datetime.date、datetime.time、datetime.datetime、datetime.timedelta,datetime.timezone等。 ----------动动小手,非常感谢各位的点赞收藏和关注。----------- 使用datet

C8T6超绝模块--EXTI

C8T6超绝模块–EXTI 大纲 控制流程结构体分析EXTI实现按键 具体案例 控制流程 这里是流程框图,具体可以去看我STM32专栏的EXTI的具体分析 结构体分析 typedef struct {uint32_t EXTI_Line; // 中断/事件线EXTIMode_TypeDef EXTI_Mode; // EXTI 模式EXTITrigger_TypeDef EXTI_

1、创建多模块的maven springboot项目

现在的java的项目都是多模块的,这次也跟个风。 目标:实现下述结构 项目AcedBoot, 子模块:         aced-api 对外提供接口,         aced-web 给前端提供接口,         aced-service 服务层,         aced-dao 数据底层,包含数据库mapper和实体类entity,         aced-commo

Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

文章目录 一、Home模块拆分1. 三级联动组件TypeNav2. 其余组件 二、发送请求的准备工作1. axios的二次封装2. 统一管理接口API----跨域3. nprogress进度条 三、 vuex模块开发四、TypeNav三级联动组件开发1. 动态展示三级联动数据2. 三级联动 动态背景(1)、方式一:CSS样式(2)、方式二:JS 3. 控制二三级数据隐藏与显示--绑定styl

PrestaShop免费模块/插件/扩展/工具下载

PrestaShop免费模块/插件/扩展/工具下载 PrestaShop免费模块 适用于您的电子商务网站的PrestaShop模块 现有超过3,000个PrestaShop模块可帮助您自定义在线商店,增加流量,提高转化率并建立客户忠诚度。 使您的电子商务网站成功! 下载(超过142+之多的PrestaShop官网认证的免费模块) 标签PrestaShop免费, PrestaShop免费工