代码改变世界

slate总结

2022-06-11 21:41  kk20161206  阅读(118)  评论(0编辑  收藏  举报

 

FSlateDrawBUffer里实现一个drawBuffer for slate,存放所有的FSlateWindowElementList,SlateDrawBuffer.h文件中:
 TArray< TSharedRef<FSlateWindowElementList> > WindowElementLists;

// List of window element lists that we store from the previous frame 
// that we restore if they're requested again.
TArray< TSharedRef<FSlateWindowElementList> > WindowElementListsPool;

通过AddWindow得到了windowElementList,如下函数:

FSlateWindowElementList& AddWindowElementList(TSharedRef<SWindow> ForWindow); //如果pool里有这个wiNdow对应的,则将该list挪到list数组,将pool里那个删掉。如果没有,则new一个放到list数组。
void RemoveUnusedWindowElements(const TArray<SWindow*>& AllWindows);//遍历所有list对应的paintWindow,如果该window无效,则从list删除。

调用的地方:

void FSlateApplication::DrawWindowAndChildren( const TSharedRef<SWindow>& WindowToDraw, FDrawWindowArgs& DrawWindowArgs )

  父:

void FSlateApplication::PrivateDrawWindows( TSharedPtr<SWindow> DrawOnlyThisWindow )

 SLateRHIRender类,slateD3DRenderer.h类,SlateOpenGLRenderer类,都包含DrawBuffer类型数据。其中,FSlateRHIRenderer里包含了数组、指针:

/** Keep a pointer around for when we have deferred drawing happening */
    FSlateDrawBuffer* EnqueuedWindowDrawBuffer;

    /** Double buffered draw buffers so that the rendering thread can be rendering windows while the game thread is setting up for next frame */
    FSlateDrawBuffer DrawBuffers[NumDrawBuffers];

 

FSlateWindowElementList类,代表一个顶层的window和他的所有draw elements。

获取其绘制的窗口:

SWindow* GetPaintWindow() const

batchData:

FSlateBatchData BatchData;

drawElement数组:

FSlateDrawElementArray UncachedDrawElements;
FSlateDrawElementArray 即TArray<FSlateDrawElement>;

要渲染到的窗口,可能和绘制的窗口不一样:

SWindow* RenderTargetWindow;

裁剪管理类:

FSlateClippingManager ClippingManager;
TArray<FWidgetDrawElementState, TInlineAllocator<50>> WidgetDrawStack;
TArray<FSlateCachedElementData*, TInlineAllocator<4>> CachedElementDataList;

TArray<int32, TInlineAllocator<4>> CachedElementDataListStack; //liist和stack是对应的,push进去一个data就会放到stack里面一个index。

几个缓存相关函数:

/**
     * Pushes the current widget that is painting onto the widget stack so we know what elements belong to each widget
     * This information is used for caching later.
     *
     */
    SLATECORE_API void PushPaintingWidget(const SWidget& CurrentWidget, int32 StartingLayerId, FSlateCachedElementsHandle& CurrentCacheHandle);

    /**
     * Pops the current painted widget off the stack
     * @return true if an element was added while the widget was pushed
     */
    SLATECORE_API FSlateCachedElementsHandle PopPaintingWidget(const SWidget& CurrentWidget);
//上两个函数会把cacheHandle和对应的widget放到wdigetDrawElementState的数组里和弹出来。
/** Pushes cached element data onto the stack. Any draw elements cached after will use this cached element data until popped */ void PushCachedElementData(FSlateCachedElementData& CachedElementData); void PopCachedElementData();

 

其中的FSlateCachedElementData类型包含了

TSparseArray<FSlateRenderBatch> CachedBatches;

    TArray<TSharedPtr<FSlateCachedElementList>> CachedElementLists;

    TArray<FSlateCachedElementList*, TInlineAllocator<50>> ListsWithNewData;

    TArray<FSlateCachedClipState> CachedClipStates;


FSlateCachedElementsHandle FSlateCachedElementData::AddCache(const SWidget* Widget);//该函数传入一个widget,返回一个包含cachedElementList的handle。

//如果当前裁剪状态不为空,则list里加入当前cached裁剪状态。新添加元素的cachedClippingState设为该状态。

FSlateRenderBatch& FSlateCachedElementData::AddCachedRenderBatch(FSlateRenderBatch&& NewBatch, int32& OutIndex); //cachedBatches里面新加这个newBatch。

void FSlateCachedElementData::RemoveCachedRenderBatches(const TArray<int32>& CachedRenderBatchIndices); //从CachedBatches里面删除数组的index位置的元素。

FSlateDrawElement& FSlateCachedElementData::AddCachedElement(FSlateCachedElementsHandle& CacheHandle, const FSlateClippingManager& ParentClipManager, const SWidget* CurrentWidget); //cachedhandle的nlist的drawelements里面新建一个drawelement,isCached为true。listWithNewData里面加入这个list。如果当前裁剪状态为存在,则list加入缓存裁剪状态。newelement的裁剪状态设为该状态,返回这个新建的drawelement.

void RemoveList(FSlateCachedElementsHandle& CacheHandle);

FSLateCachedElementList中包含了它的父类elementData,和用来创建batch的源drawElement数据,创建batches之后,batch数据存在此类的fastPathRenderingData中,返回的renderbatch放到parentData的batch数组中,list里只放indices数组。这些drawElement所属的widget,快速渲染的缓存数据。后者包含clip列表,vertex数组,index数组等。

/** List of source draw elements to create batches from */
    FSlateDrawElementArray DrawElements;

    TArray<int32> CachedRenderBatchIndices;

    /** The widget whose draw elements are in this list */
    const SWidget* OwningWidget;

    FSlateCachedElementData* ParentData;

    FSlateCachedFastPathRenderingData* CachedRenderingData;

FSlateRenderBatch& AddRenderBatch(int32 InLayer, const FShaderParams& InShaderParams, const FSlateShaderResource* InResource, ESlateDrawPrimitive InPrimitiveType, ESlateShader InShaderType, ESlateDrawEffect InDrawEffects, ESlateBatchDrawFlag InDrawFlags, int8 SceneIndex);

SLATECORE_API void DestroyCachedData();

struct FSlateCachedElementsHandle这个结构通过上面的FSLateCachedElementList构造的:

struct FSlateCachedElementsHandle
{
    friend struct FSlateCachedElementData;

    static FSlateCachedElementsHandle Invalid;
    void ClearCachedElements();
    void RemoveFromCache();

    bool IsOwnedByWidget(const SWidget* Widget) const;

    bool IsValid() const { return Ptr.IsValid(); }

    bool operator!=(FSlateCachedElementsHandle& Other) const { return Ptr != Other.Ptr; }

    FSlateCachedElementsHandle() {}
private:
    FSlateCachedElementsHandle(TSharedRef<FSlateCachedElementList>& DataPtr)
        : Ptr(DataPtr)
    {
    }

private:
    TWeakPtr<FSlateCachedElementList> Ptr;
};

 

其中的FSLateCachedFastPathRenderingData类包含了这些东西:

TArray<FSlateCachedClipState, TInlineAllocator<1>> CachedClipStates;
FSlateVertexArray Vertices;
FSlateIndexArray Indices;
FSlateRenderBatch& FSlateCachedElementList::AddRenderBatch(int32 InLayer, const FShaderParams& InShaderParams, const FSlateShaderResource* InResource, ESlateDrawPrimitive InPrimitiveType, ESlateShader InShaderType, ESlateDrawEffect InDrawEffects, ESlateBatchDrawFlag InDrawFlags, int8 SceneIndex)
{
    FSlateRenderBatch NewRenderBatch(InLayer, InShaderParams, InResource, InPrimitiveType, InShaderType, InDrawEffects, InDrawFlags, SceneIndex, &CachedRenderingData->Vertices, &CachedRenderingData->Indices, CachedRenderingData->Vertices.Num(), CachedRenderingData->Indices.Num());
    int32 RenderBatchIndex = INDEX_NONE;
    FSlateRenderBatch& AddedBatchRef = ParentData->AddCachedRenderBatch(MoveTemp(NewRenderBatch), RenderBatchIndex);
    
    check(RenderBatchIndex != INDEX_NONE);

    CachedRenderBatchIndices.Add(RenderBatchIndex);

    return AddedBatchRef;
    
    //return CachedBatches.Emplace_GetRef(InLayer, InShaderParams, InResource, InPrimitiveType, InShaderType, InDrawEffects, InDrawFlags, SceneIndex, &CachedRenderingData->Vertices, &CachedRenderingData->Indices, CachedRenderingData->Vertices.Num(), CachedRenderingData->Indices.Num());
}

 看看这个函数调用的地方,哪些东西存有cache数据。

 

slate调用堆栈

 

 privateDrawWindows函数里创建FDrawWindowArgs类型参数,然后作为引用类型传入DrawWindowAndChildren函数,该函数参数为SWindow引用类型参数和前面创建的FDrawWIndowArgs类型参数,后者里面包含DrawBuffer,其类内部有windowList成员,通过这个DrawWindowAndCHildren函数,将window对应的slateWindowElementList放到了DrawBuffer里面了就。这个DrawWindowANdChildren函数 还会递归调用这个window的所有children。执行完这个函数之后,DrawWIndowArgs.OutDrawBuffer里面就存放了数据。privateDrawWindows函数里面最后一句执行了Renderer->DrawWindows(DrawWindowArgs.OutDrawBuffer);

FSlateRHIRenderer::DrawWindows(FSlateDrawBuffer& WindowDrawBuffer)

{

  DrawWindows_Private(WindowDrawBuffer);

}

在这个DrawWindows_Private函数里面,对WIndowDrawBuffer里的每个windowElementList,执行ElementBatcher->AddElements(ElementList);(FSLateELmentBatcher类型的ElementBatcher) 在ElementBatcher.cpp文件中,该函数对于windowElementList的uncachedDrawElements直接AddElementsInternal参数是drawElements数组和viewportSIze,对于cachedElementDataList,执行AddCachedElements,该函数遍历cachedElementData的所有listsWIthNewData,调用AddElementsInternal,将这些list里的DrawElements传入函数中去。

privateDrawWindows里面有个DrawPrepass设置dpiScale*ApplicationScale.

AddElement函数会创建一个FSlateRenderBatch类,里面放入vertex和index,createRenderBatch函数用来创建这个FSlateRenderBatch对象,判断currentCachedElementList是否为空,如果不为空,则currentCachedElementList的AddBatch,,否则BatchData的AddBatch,BatchData属于FSlateBatchData类,是FSlateElementBatch类型。如果是前者,FSlateCachedElementList的AddBatch,新建的RenderBatch会放到FSlateCachedElementData中;如果是后者,FSlateBatchData的renderbatches里会放入新建的renderBatch。

SlateElementBatcher作为一个中间枢纽的存在,他AddWindow的时候,batchData指针执行elementList的batchData,完成后清空,再处理下一个windowList。FSlateElementBatcher能创建FSlateRenderBatch。

SLATECORE_API void AddElements( FSlateWindowElementList& ElementList );
void AddElementsInternal(const FSlateDrawElementArray& DrawElements, const FVector2D& ViewportSize);
void AddCachedElements(FSlateCachedElementData& CachedElementData, const FVector2D& ViewportSize);
FSlateRenderBatch& CreateRenderBatch(
        int32 Layer,
        const FShaderParams& ShaderParams,
        const FSlateShaderResource* InResource,
        ESlateDrawPrimitive PrimitiveType,
        ESlateShader ShaderType,
        ESlateDrawEffect DrawEffects,
        ESlateBatchDrawFlag DrawFlags,
        const FSlateDrawElement& DrawElement);
//具体创建vertices的函数
/** 
     * Creates vertices necessary to draw a string (one quad per character)
     */
    template<ESlateVertexRounding Rounding>
    void AddTextElement( const FSlateDrawElement& DrawElement );
private:
/** Uncached Batch data currently being filled in */
    FSlateBatchData* BatchData;

    /** Cached batches currently being filled in */
    FSlateCachedElementList* CurrentCachedElementList;

FSLateBtachData属于windowLIst。还能合renderBatch。

FSlateElementBatch代表一系列batch到一起的slateDrawElement渲染需要的一些信息,shaderResource、shaderParam、DrawFlag、PrimitiveType、shaderType、DrawEffect、instanceCount、instanceOffset、FBatchKey用来决定是否两个batch能合并,BATCH里element的数量,顶点数组index,index数组索引。引用的地方没找到,哈哈哈。估计弃用了。删掉后确实没问题。

 

FSlateDrawElement类存渲染drawElement需要的数据,makeBoxInternal,makeText等,内部会调用其Init函数,

------------恢复内容结束------------