#define ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(TypeName,ParamType1,ParamName1,ParamValue1,Code)
等效於下面兩個宏:
#define ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER_DECLARE_OPTTYPENAME(TypeName,ParamType1,ParamName1,ParamValue1,OptTypename,Code) \
class EURCMacro_##TypeName : public FRenderCommand \
{ \
public: \
EURCMacro_##TypeName(OptTypename TCallTraits<ParamType1>::ParamType In##ParamName1): \
ParamName1(In##ParamName1) \
{} \
TASK_FUNCTION(Code) \
TASKNAME_FUNCTION(TypeName) \
private: \
ParamType1 ParamName1; \
};
#define ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER_CREATE(TypeName,ParamType1,ParamValue1) \
{ \
if(GIsThreadedRendering || !IsInGameThread()) \
{ \
CheckNotBlockedOnRenderThread(); \
TGraphTask<EURCMacro_##TypeName>::CreateTask().ConstructAndDispatchWhenReady(ParamValue1); \
} \
else \
{ \
EURCMacro_##TypeName TempCommand(ParamValue1); \
FScopeCycleCounter EURCMacro_Scope(TempCommand.GetStatId()); \
TempCommand.DoTask(ENamedThreads::GameThread, FGraphEventRef() ); \
} \
}
示例代碼:
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
BeginDrawingCommand,
FViewport*,Viewport,this,
{
Viewport->BeginRenderFrame(RHICmdList);
});
以上代碼展開宏之後如下:
class EURCMacroBeginDrawingCommand : public FRenderCommand
{
public:
EURCMacroBeginDrawingCommand(OptTypename TCallTraits<ParamType1>::ParamType InViewport):
Viewport(InViewport)
{}
TASK_FUNCTION(Code)
TASKNAME_FUNCTION(TypeName)
private:
FViewport* Viewport;
};
{
if(GIsThreadedRendering || !IsInGameThread())
{
CheckNotBlockedOnRenderThread();
//創建一個渲染任務,並壓入渲染隊列,之後由渲染線程執行
TGraphTask<EURCMacroBeginDrawingCommand>::CreateTask().ConstructAndDispatchWhenReady(this);
}
else
{
//直接由主線程立刻執行
EURCMacroBeginDrawingCommand TempCommand(this);
FScopeCycleCounter EURCMacro_Scope(TempCommand.GetStatId());
TempCommand.DoTask(ENamedThreads::GameThread, FGraphEventRef() );
}
}
#define TASK_FUNCTION(Code) \
void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) \
{ \
FRHICommandListImmediate& RHICmdList = GetImmediateCommandList_ForRenderCommand(); \
Code; \
}
而任務的DoTask方法是如何被執行的,就要去ConstructAndDispatchWhenReady裏找答案了,展開篇幅太長,有空再研究!