放一下類圖。node
簡單介紹一下相關類型:數組
- FrameGraphHandle:只有一個uint16_t的標識,初始化爲一個無效值。
- FrameGraphId:一個模板類,繼承自FrameGraphHandle,沒有自定義的屬性或者方法。
- FrameGraphRenderTarget: 一個命名空間,裏面定義了Attachments和Descriptor兩個結構體。
- Attachments,主要定義了AttachmentInfo這個內部結構,AttachmentInfo有兩個屬性:FrameGraphId<FrameGraphTexture>類型的handle(僅僅是個handle,對應的是ResourceNode,並非真正的紋理資源)和一個mLevel(紋理的mipmap level)。一個Attachments包含了兩個AttachmentInfo,這裏寫死了。
2. Descriptor:包含三個屬性:Attachments, Viewport 和 samples緩存
- FrameGraphTexture: 定義了一個內部結構Descriptor,實現了方法create/destroy,持有真正的gpu資源。其建立和銷燬均經過調用FrameGraph類的ResourceAllocator相應方法實現。
- VirtualResource:資源類的祖先。定義了虛方法create和destroy,有兩個PassNode類型的指針,指向第一個和最後一個ref這個資源的pass,在FrameGraph的方法compile內計算賦值的。
- ResourceEntryBase:繼承自VirtualResource,id,name變量沒啥用,imported標記資源是否FrameGraph外部導入,uint8_t型version變量,還有一個引用計數,fg.compile內更新爲:全部相關ResourceNode的readerCount之和。
- ResourceEntry<T>,一個模板類,繼承自ResourceEntryBase。包含T類型的resource屬性和T::Descriptor類型的descriptor屬性。實現了VirtualResource定義的兩個虛接口,當!imported時會調用resource.相應方法。一個經常使用的實例化爲T=FrameGraphTexture。ResourceEntry有兩個構造,其中一個包含一個T類型的引用,這時會將import置爲true,意思是這個資源是外部引入的。這時候咱們注意到:ResourceEntryBase/ResourceEntry都是不能經過handle來查找訪問的。這時候須要一個類ResourceNode。
- ResourceNode:資源節點類。構造時須要傳入一個ResourceEntryBase指針和一個uint8_t的version,ResourceEntryBase指向其對應的資源(好比一張紋理),version初始化爲ResourceEntryBase的version。PassNode* writer指針指向寫入這個資源的pass,只有一個?引用計數readerCount,還有一個renderTargetIndex,是fg中rt數組的索引,用來獲取rt的信息?
- RenderTargetResource:繼承自VirtualResource,構造時須要傳入FrameGraphRenderTarget::Descriptor的描述,是否imported,backend::TargetBufferFlags,寬高,紋理格式。主要包含一個FrameGraphPassResources::RenderTargetInfo類型的屬性,其只有真正的硬件資源和backend::RenderPassParams params(包含viewport,discardstart,end等信息)。也是資源類,因此須要實現create/destroy兩個接口,具體也是根據Descriptor調用FrameGraph類的ResourceAllocator相應方法實現。
- RenderTarget:構造時須要傳入FrameGraphRenderTarget::Descriptor,fg中數組索引,及name。包含屬性:backend::TargetBufferFlags userClearFlags,backend::RenderPassFlags targetFlags及RenderTargetResource* cache等。其包含一個方法:void resolve(FrameGraph& fg) noexcept,負責初始化RenderTargetResource* cache指針,具體實現爲:首先根據Descriptor去fg的緩存中找(FrameGraph會緩存一個RenderTargetResource的列表),找到直接賦值而後執行一個cache->targetInfo.params.flags.clear |= userClearFlags;操做。不然從新建立一個新的。
- FrameGraphPassResources:雖然也叫Resource但非繼承自VirtualResource。構造時須要傳入一個FrameGraph的引用和一個PassNode的引用,將其緩存下來。提供了幾個get方法來從fg裏面獲取資源或者描述等信息,裏面定義告終構RenderTargetInfo:
- FrameGraphPassExecutor:只定義了一個接口virtual void execute(FrameGraphPassResources const& resources, backend::DriverApi& driver) noexcept = 0;
- FrameGraphPass<typename Data, typename Execute>:一個模板類,繼承自FrameGraphPassExecutor,包含兩個變量:Execute mExecute和Data mData。構造時須要傳入一個Execute&& execute。實現了父類的execute方法,只有一行代碼:mExecute(resources, mData, driver); 全部pass的具體操做都是經過這個Execute傳入執行的。
- PassNode:構造時須要傳入FrameGraph的引用,name,id, 及一個FrameGraphPassExecutor的指針。表明一個pass。
主要屬性:ide
- FrameGraph::UniquePtr<FrameGraphPassExecutor> base; // type eraser for calling execute()。
- 該pass reads/writes的資源handle列表。
- renderTargets列表。
- 該pass須要devirtualize/destroy的VirtualResource*列表。
- refCount // count resources that have a reference to us
- hasSideEffect // whether this pass has side effects
主要方法:ui
- FrameGraphHandle read(FrameGraph& fg, FrameGraphHandle const& handle, bool isRenderTarget = false);將資源handle添加到reads列表中,保證不重複,且會確保相應資源描述爲backend::TextureUsage::SAMPLEABLE
- FrameGraphHandle write(FrameGraph& fg, const FrameGraphHandle& handle);主要操做爲:將資源的version加1,以前/傳入的handle就無效了。若是資源是imported的,則將hasSideEffect置true。建立一個新的handle返回。
- void declareRenderTarget(fg::RenderTarget& renderTarrget);添加一個renderTarrget的id到renderTargets列表中。
- ResourceAllocator: 提供了RT、Texture的建立和銷燬實現。關於Texture的建立和銷燬,維護了兩個列表:在用的Texture和cache的texture。銷燬時能夠不執行真正的紋理銷燬而是將其加入到cache列表(從在用列表中移除)。這樣下次若是須要建立新的紋理時先去cache列表中找,若是找到就不用建立新的紋理了,將其添加到在用列表中。並提供了一個gc實現來釋放cache的紋理資源。
- FrameGraph::Builder:構造時須要傳入FrameGraph和PassNode的引用,提供一些資源的建立和銷燬操做轉發到緩存的FrameGraph/PassNode引用對象上。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------this
以上是FrameGraph相關的基礎類,關於FrameGraph類:3d
- 構造時須要傳入一個ResourceAllocator
- 主要屬性:PassNode列表,ResourceNode列表,RenderTarget列表。ResourceEntryBase列表、RenderTargetResource列表(這兩個列表存放真正的資源)。Alias資源重命名列表。
- 模板方法
template <typename Data, typename Setup, typename Execute>
FrameGraphPass<Data, Execute>& addPass(const char* name, Setup setup, Execute&& execute)指針
添加一個pass到pass列表中,並執行指定的Setup操做對象
- void present(FrameGraphHandle input)方法爲‘input’添加一個引用,防止被cull掉。
- bool isValid(FrameGraphHandle r)。判斷一個handle是否有效。主要判斷其node.version和指向資源的version是否相同。A resource handle becomes invalid after it's used to declare a resource write
- importResource方法:引入一個外部RT。主要操做:建立一個紋理資源handle/node(並未指向真正的硬件資源)。建立一個RenderTargetResource,填充相應信息,添加到cache列表中,等待resolve。
- FrameGraphId<T> import方法:引入一個現有resource。主要操做:建立一個imported標記的ResourceEntryBase指針(緩存到ResourceEntryBase中),而後建立一個ResourceNode。返回handle。
- moveResource(FrameGraphHandle from, FrameGraphHandle to)方法:all handles referring to the resource 'to' are redirected to the resource 'from'。 handle 'from' 失效了,返回一個新的handle。
- compile方法:
- 處理mAliases:將全部指向to.resource的node的資源指向from.resource。若是某個rt包含指向from節點的resource的color attachment,且這個resource是imported,那麼將這個rt的全部非color attachments置無效。處理全部pass的reads:若是是from,那麼改爲to。處理全部pass的writes:erase掉全部from。
- 更新pass和資源的refCount,並更新每一個資源的writer爲相應pass節點:pass的置爲writes和hasSideEffect之和。resource爲read該資源的pass數目。
- cull passes and resources:若是資源的readerCount爲0,入棧。遍歷棧中元素:若是writer不爲空,那麼writer的引用減一,若是writer的引用變0,將其全部的reads計數減1。最後根據node的計數更新resource的計數(由於多個node可能指向相同的resource)。
- resolve全部pass的全部rt。
- 對於全部資源(rt和紋理等),計算第一次及最後一次訪問其的pass節點。
- 遍歷全部資源,若是引用計數不爲0的話,將其添加到第一次及最後一次訪問其的pass節點中的devirtualize/destroy列表中。
- execute方法:依序執行全部的pass:建立資源,執行,釋放資源。