StaticMesh が対応する DDC ファイルをロードするプロセスを観察します。

役に立たない序文

昔、DDC のコードを観察して表面的な知識を学びました。
最近、DDC関連の問題に遭遇したので、以前書いたものを見直してみました。同時に、この問題に関する私の最近の研究の重要な部分も備忘録として記録しておきます。

目標

StaticMesh が対応する DDC ファイルをロードするプロセスを観察し、重要なポイントのいくつかを記録します。

(注: ここでのエンジンのバージョンは 4.26 であり、UE5 の DDC 関連のコードは大幅に調整されています)

0. コードの開始位置

DDC インターフェイスのGetSynchronoussum関数GetAsynchronousは、DDC データを取得するための統合インターフェイスであり、ここでブレークポイントをトリガーする必要があります。

ただし、今は特定の StaticMesh の DDC だけを観察したいので、最初から内側GetSynchronousと内側のブレークポイントにヒットすると、他の多くのリソースが壊れてしまいます。したがって、最初に StaticMesh が DDC インターフェイスを呼び出す場所にブレークポイントを設定し、次に次のように観察したい StaticMesh リソースをダブルクリックしてロードすることを選択します。 その後、ブレークポイントがトリガーされます: ( Ownerの値を通じて StaticMesh リソースをトリガーしました。これは観察したいものです) StaticMesh が DDC データを取得する準備ができた瞬間です。GetAsynchronous

ここに画像の説明を挿入

ここに画像の説明を挿入

次に、GetSynchronous関数内にブレークポイントを設定してトリガーします: (このリソースはCacheKey値で確認できます)
ここに画像の説明を挿入

ここで呼び出される関数は Get Synchronousで、これは同期方法であるため、このタスクは (別のスレッドで実行されるのではなく) すぐに実行されます。

GetSynchronous 関数の中心は、FAsyncTask<FBuildAsyncWorker>タスクを実行するための を作成することです。

1.FBuildAsyncWorker

FAsyncTask非同期(または同期)実行できるタスクが整理されており、基本的な使い方は前回の記事 にあります。
タスクの具体的な内容はFBuildAsyncWorker定義で定義されており、いくつかのメンバー変数があり、それらの説明は次のコメントで参照できます。

/** true in the case of a cache hit, otherwise the result of the deriver build call **/
bool							bSuccess;
/** true if we should record the timing **/
bool							bSynchronousForStats;
/** true if we had to build the data */
bool							bDataWasBuilt;
/** Data dervier we are operating on **/
FDerivedDataPluginInterface*	DataDeriver;
/** Cache key associated with this build **/
FString							CacheKey;
/** Data to return to caller, later **/
TArray<uint8>					Data;

実行ロジックはDoWork()関数内にあり、その中で最も重要なのはFDerivedDataBackendDDC データを取得することです。

  • 成功すると、ローカル変数がbGetResulttrue として記録され、FBuildAsyncWorkerその変数自体のメンバーもbSuccesstrue になり、メンバーにDataも値が含まれます。
  • 失敗した場合はbSuccessfalse、Dataまたは空になります。

ここに画像の説明を挿入
このようにして、タスクが終了すると、DDC が正常に取得できたかどうか、および DDC データが何であるかを、FBuildAsyncWorker自身のメンバー変数の値bSuccessと値を通じて知ることができます。Data

次に見る必要があるのは、FDerivedDataBackend::Get().GetRoot().GetCachedData

2. DerivedDataBackend がたくさんありますか?

「DerivedDataBackendInterface のサブクラス間の関係の観察」でわかるように、DerivedDataBackend は複数のサブクラスで構成されており、それらは並列ではなく入れ子になっています。

したがって、ここでのルートとしての DerivedDataBackend は DerivedDataLimitKeyLengthWrapper:
ここに画像の説明を挿入
ですが、その後、他の DerivedDataBackend を呼び出して DDC データを取得しようとします。

UE がこのような多数の Backend の構造で設計されているのには理由があるはずですが、それは明確に理解していないため、説明しません。

ただし、1 つ確かなことは、DDC データが最終的にファイルを通じて取得された場合は、それを渡す必要があるということですFFileSystemDerivedDataBackend

3. FFileSystemDerivedDataBackend::GetCachedData の下のブレークポイントで、対応するファイルのパスを取得します

次に、ブレークポイントFFileSystemDerivedDataBackend::GetCachedDataの下で、Filename値を通じて対応する DDC ファイル パスを知ることができます。
ここに画像の説明を挿入
このファイルはディスク上で直接見つけることができます。
ここに画像の説明を挿入

4*. キャッシュ欠落の再構築

後でこのファイルを手動で削除して、DDC ファイルが見つからない状況をシミュレートすることもできます。
この時点で見えるFBuildAsyncWorkerものはDoWork()ここに行き、終わった後はbSuccess偽りで空虚なものになります。yes を返すため、 false を返します。Data
ここに画像の説明を挿入
GetSynchronousPendingTask.GetTask().bSuccess

その後、StaticMesh は呼び出し後に別のブランチに移動します。
ここに画像の説明を挿入

その後、DDC データが再構築されます。

最後に、GetDerivedDataCacheRef().Put電話した後:
ここに画像の説明を挿入

DDC ファイルは再度保存されます (この呼び出しは非同期である必要があるため、この関数が戻った直後にはファイルは生成されません)。

要約する

  1. StaticMesh は DDC の共通インターフェイスを呼び出してGetSynchronousDDC データを取得します
  2. GetSynchronousFAsyncTask<FBuildAsyncWorker>タスクを実行するために内部的に を作成します。
  3. FBuildAsyncWorkerDoWork()そのコアであり、DerivedDataBackend を通じて DDC データを取得していることがわかります。
  4. 多数の DerivedDataBackend が相互に接続され、DDC データを検索するロジックを定義します。
  5. FFileSystemDerivedDataBackend::GetCachedData次のブレークポイントでリソースをロードする DDC ファイルのパスを知ることができます。

最近の質問に注意してください

スタックで発生した最新の問題は、StaticMesh によってロードされた DDC データ内の配列の要素サイズが現在の定義と一致しないことです。一般に、DDC の問題に対して最初に試みることは、DDC をクリアして再生成することです。しかし、クリアした(と思った)後も、同じエラーが発生しました。

最後に、StaticMesh に対応する DDC ファイルの特定のパスを見つけることでわかりました。データを取得するためのファイルはクリアされず、ローカルではなく共有の場所にありましたそして、この場所はかなり前に非推奨になっています。この場所が見つかった理由は、環境変数が以前に構成されていたためです。

おすすめ

転載: blog.csdn.net/u013412391/article/details/131741188