This is the documentation for Enlighten.
7.16. ライトマップ LOD
導入
プレイヤーが屋内と屋外エリアの両方を探索する大きなマップに合わせて調整できるようにするために、Enlighten ライトマップを解決する際の詳細度のメカニズムがあります。これはテレイン LODと似ていますが、テレインではないシステムに適用することを意図したものです。テレイン システムに対しては、テレイン LODメカニズムを使用することをお勧めします。
ライトマップ LOD メカニズムの背景にある全般的な思想は、さまざまな解像度で Enlighten システム ライトマップを生成し、既定のタイミングでどの解像度を解決およびレンダリングするかをコントロールできるようにすることです。たとえば、以下の図の小屋のモデルを考えてください。プレイヤー (カメラが) 近い場合、高い忠実度で間接光を解決しますが、カメラが離れるにつれて細かな詳細は必要なくなります。
詳細度の低いライトマップ ピクセル サイズを増加させると、Enlighten ランタイムによって解決されるピクセルが減少します。LOD 0 を解決するには、Enlighten は小屋全体で 4264 ピクセル解決する必要があり、LOD 1 では 2640、LOD 2 では 1400、LOD 4 では 880 に減ります。遠くのオブジェクトで解決する必要があるピクセル数を減らすとマップ全体でより多くの部分を解決でき、その一方で Enligten の割り当て量は維持できます。これにより、幅広い景色がレンダリングされているシーンのパーツで、より滑らかで素早い間接光の収束が得られます。
概要
2 つのジオメトリ (のインスタンス) を含む 1 つの Enlighten のシステムの単純なケースを考えてみましょう。Geom 1 は、床 (Geom 2) の上にあるブロックです。ユーザーが Geom 1 と Geom 2 のためにそれぞれ 3 つの LOD が生成されるよう要求したとしましょう (その方法の詳細は後で説明します)。Geom 1 と Geom 2 は個別にパッキングされます。それぞれが 3 回パッキングされ、パッキングのたびにピクセル サイズが 2 倍に増加します。以下の図をご覧ください。
次の OutputSystem 作成ステップでは、同じ LOD のパッキングされたジオメトリが出力 (パッキングされた) システムの LOD に組み合わされ (そしてリパッキングされ) ます。
システムのすべての LOD バージョンが同じジオメトリ (頂点、面、法線、アルベド UV など) を共有しており、出力ライトマップ ピクセル サイズとライトマップ UV (チャート) のみが異なることに注意してください。次に、システムにクラスタ (リーフクラスタ、クラスタ ツリー階層) が作成されます。これは、システムのすべての LOD バージョンで共有されます。すべての LOD でクラスタが同じであるという事実は、実行時に使用されるすべてのクラスタごとのバッファ (入力ライティング、バウンス バッファ、アルベド バッファなど) は、解決された LOD が変わっても有効であり続けることを意味します。
クラスタとダスターの位置は、システムのすべての LOD バージョンで共有されます。ダスター ポイントは、各 LOD での位置で個別の UV 座標を持ちます。
Light Transport 作成ステージは、システムのすべての LOD バージョンに対して実行されます。異なる LOD のピクセルから異なるフォーム ファクターが得られます。最終的なデータセットがコンパイルされ、すべての LOD に個別の RadCore が作成されます。これらの RadCore を使用して、実行時にシステムの特定の LOD バージョンを解決できます。クラスタごとのバッファはすべての LOD 間で共有されるため、LOD の変更の際に入力ライティングを再計算する必要はありません。同様に、前の LOD で使用されていたバウンスとアルベド バッファも再使用できます。既定の LOD でライトマップにアクセスするために必要なライトマップ UV は、パック システムのパッキングされたインスタンスとパッキングされたジオメトリにアクセスすることで取得できます。
High Level Build System
ライトマップ LOD の生成を有効にするには、XML シーン記述に追加する必要がある特別なマークアップがいくつかあります。このセクションでは、必要なステップとライトマップ LOD が有効な場合のプリコンピュート パイプラインの出力について説明します。
生成する LOD の数は、<geom> ごとに決定します。<Geom> が異なると、LOD の数も異なることがあります。LOD 数の異なる複数のジオメトリのインスタンスが同じシステムにある場合、そのシステムでは、ジオメトリについて要求される最大限の数の LOD が生成されます。たとえば、2 つのジオメトリがあるシステムがあり、ジオメトリがそれぞれ 2 つの LOD と 4 つの LOD を持つ場合、そのシステムの LOD は 4 つになります。ジオメトリに対して存在しない LOD が要求された場合、保持されている最小限の LOD が使用されます。以下の例をご覧ください。
生成する LOD の数は、numLods XML 属性により要求されます (.geom ファイル内)。
<?xml version="1.0" encoding="utf-8"?> <geom name="Cube_0" version="3" numLods="2" //...他のジオメトリ属性...// > <mesh name="Cube_0_LOD0" //...他のメッシュ属性...// /> </geom>
連続した LOD は、それぞれ前の LOD の 2 倍のピクセルサイズを持ちます。numLods 属性は、1 以上の正の整数である必要があります。1 に設定するのは、LOD 生成をオフにすることと同じです。デフォルト値は 1 です。
例とプリコンピュートの出力
単純なシーンを再度考えてみます。シーンは 2 つのインスタンス (Instance A と Instance B) と 2 つのジオメトリ (それぞれ Geom A と Geom B) からなります。Geom A は 2 つの LOD、Geom B は 4 つの LOD を持ちます。
<?xml version="1.0" encoding="utf-8"?> <geom name="Geom_A" version="3" simpNumIterationsPerSimp="500" simpMaxNumSimps="250" simpUsePixelUnits="true" numLods="2"> <mesh name="Geom_A" guid="c9408aee000000000000000000000000" filename="Geom_A.pim" direct="true" indirect="true" target="true"/> </geom>
<?xml version="1.0" encoding="utf-8"?> <geom name="Geom_B" version="3" simpNumIterationsPerSimp="500" simpMaxNumSimps="250" simpUsePixelUnits="true" numLods="4"> <mesh name="Geom_B" guid="dc670a1c000000000000000000000000" filename="Geom_B.pim" direct="true" indirect="true" target="true"/> </geom>
<?xml version="1.0" encoding="utf-8"?> <scene name="World" version="1" axes="-x+y+z"> <instance name="Instance_B" instanceGuid="00000000000000000000000000000001" systemId="System_0" systemGuid="8494c213000000000000000000000000" paramSet="High" geometry="Geom_B" type="Radiosity" position="0.000000 20.000000 50.000000" rotation="0.000000 0.000000 0.000000 1.000000"/> <instance name="Instance_A" instanceGuid="00000000000000000000000000000002" systemId="System_0" systemGuid="8494c213000000000000000000000000" paramSet="High" geometry="Geom_A" type="Radiosity" position="230.000000 20.000000 290.000000" rotation="0.000000 0.000000 0.000000 1.000000"/> </scene>
このマークアップのあるシーンが High Level Build System への入力として使用されるとき、以下の出力が precomp フォルダーに生成されます。
ファイル名 | 説明 |
---|---|
Geom_A_High.ig | Geom_A を説明する |
Geom_B_High.ig | Geom_B を説明する |
System_0.is | System_0 で使用される Geom_A と Geom_B のインスタンスを説明する |
Geom_A_High.pag | Geom_A のすべての LOD 向けの |
Geom_B_High.pag | Geom_B のすべての LOD 向けの |
System_0.pas | すべての LOD 向けの |
System_0.sdeps | System_0 のシステム依存関係のシリアル化です。システム依存関係は、すべてのシステムの LOD 0 バージョンのみを使用して計算されます。 |
System_0.prc | プレクラスタリング (クラスタ メッシュ、リーフクラスタ) データのシリアル化です。クラスタ メッシュの各頂点には、システムのすべての LOD のライトマップ UV があります。 |
System_0.clu | クラスタ ツリー階層のシリアル化で、LOD データは含まれません。 |
System_0.dust | システム ダスターのシリアル化です (入力ライティングとバウンス リサンプリングに使用します)。各ダスター ポイントには、すべての LOD のライトマップ UV があります。これらは、すべての LOD のバウンス リサンプリングに必要です。 |
System_0.lt | System_0 とそのすべての LOD のライト トランスポート データ (フォーム ファクターなど) を含む、 |
System_0.ltz | RadCore へのエキスポートが可能な形式のライト トランスポート データを含む |
System_0.prc、System_0.clu、System_0.dust、System_0.lt、System_0.ltz は、プリコンピュート パイプラインの内部ステージであり、便利なパブリック インターフェイスはありません。
radiosity フォルダーに、以下の出力が生成されます。
ファイル名 | 説明 |
---|---|
System_0.caw | System_0 のクラスタ アルベド ワークスペース です。LOD に依存します。 |
System_0.clo | System_0 のクラスタ出力です。LOD に依存します。デバッグ/診断に使用します。 |
System_0.iw.ref | リファレンス ソルバーとともに使用する System_0 の入力ワークスペース データです。LOD に依存します。 |
System_0.iw.sse | SSE 最適化ソルバーとともに使用する System_0 の入力ワークスペース データです。LOD に依存します。 |
System_0.lto | すべての LOD の System_0 ライト トランスポート出力です。LOD データへのアクセス方法については、ILightTransportOutput API をご覧ください。デバッグ/診断に使用します。 |
System_0.vis | System_0 のディレクショナル可視性データです。LOD に依存します。 |
System_0.mso | LOD 0 メッシュ簡素化出力での System_0 です。デバッグ/診断に使用します。メッシュ、チャート、ライトマップ UV などのパッキングデータを含みます。 |
System_0_LOD_1.mso | LOD 1 メッシュ簡素化出力での System_0 です。デバッグ/診断に使用します。メッシュ、チャート、ライトマップ UV などのパッキングデータを含みます。 |
System_0_LOD_2.mso | LOD 2 メッシュ簡素化出力での System_0 です。デバッグ/診断に使用します。メッシュ、チャート、ライトマップ UV などのパッキングデータを含みます。 |
System_0_LOD_3.mso | LOD 3 メッシュ簡素化出力での System_0 です。デバッグ/診断に使用します。メッシュ、チャート、ライトマップ UV などのパッキングデータを含みます。 |
System_0.rc.ref | LOD 0 ラジオシティ コア データでの System 0 です。イラディアンスを解決するためにリファレンス ソルバーから要求されるコア データです。 |
System_0.rc_LOD_1.ref | LOD 1 ラジオシティ コア データでの System 0 です。イラディアンスを解決するためにリファレンス ソルバーから要求されるコア データです。 |
System_0.rc_LOD_2.ref | LOD 2 ラジオシティ コア データでの System 0 です。イラディアンスを解決するためにリファレンス ソルバーから要求されるコア データです。 |
System_0.rc_LOD_3.ref | LOD 3 ラジオシティ コア データでの System 0 です。イラディアンスを解決するためにリファレンス ソルバーから要求されるコア データです。 |
System_0.rc.sse | LOD 0 ラジオシティ コア データでの System 0 です。イラディアンスを解決するために SSE 最適化 ソルバーから要求されるコア データです。 |
System_0.rc_LOD_1.sse | LOD 1 ラジオシティ コア データでの System 0 です。イラディアンスを解決するために SSE 最適化 ソルバーから要求されるコア データです。 |
System_0.rc_LOD_2.sse | LOD 2 ラジオシティ コア データでの System 0 です。イラディアンスを解決するために SSE 最適化 ソルバーから要求されるコア データです。 |
System_0.rc_LOD_3.sse | LOD 3 ラジオシティ コア データでの System 0 です。イラディアンスを解決するために SSE 最適化 ソルバーから要求されるコア データです。 |
System_0.rnt | LOD 0 ラジオシティ法線テクスチャでの System_0 です。ソルバーがディレクショナル イラディアンスを解決するために必要です。 |
System_0_LOD_1.rnt | LOD 1 ラジオシティ法線テクスチャでの System_0 です。ソルバーがディレクショナル イラディアンスを解決するために必要です。 |
System_0_LOD_2.rnt | LOD 2 ラジオシティ法線テクスチャでの System_0 です。ソルバーがディレクショナル イラディアンスを解決するために必要です。 |
System_0_LOD_3.rnt | LOD 3 ラジオシティ法線テクスチャでの System_0 です。ソルバーがディレクショナル イラディアンスを解決するために必要です。 |
プリコンピュート LOD データへの低レベル API のアクセス
LOD 生成の要求
LOD 生成は、ジオメトリごとに要求されます。IPrecompInputGeometry クラスは、このジオメトリについて、ジオメトリ パッキング ステージで生成する必要がある LOD の数を設定するメソッドを含みます。
/// この入力ジオメトリにパッキングで生成する必要がある LOD の数を取得します virtual Geo::s32 GetNumLods() const = 0; /// この入力ジオメトリにパッキングで生成する必要がある LOD の数を設定します virtual void SetNumLods(Geo::s32 numLods) = 0;
SetNumLods
と GetNumLods
はライトマップ LOD のみに適用でき、テレイン LOD 生成 (SetIsTerrain(true)
が呼び出されるときなど) には使用できないことに注意してください。ジオメトリのテレイン ジオメトリとしての設定、およびライトマップ LOD の 1 以外の数での設定は不正です。
LOD データへのアクセス
すべての低レベル API で、LOD データへのアクセスは同じパターンに従います。LOD の表現を持つプリコンピュート オブジェクトがある場合、そのオブジェクトに対して 2 つの API 関数が提供されます。1 つはオブジェクトが持つ LOD の数を返し、もう 1 つは指定された LOD 表現への読み取り専用アクセスを提供します。
/// このジオメトリの LOD の数を取得します。 virtual Geo::s32 GetNumLods() const = 0; /// このジオメトリの既定の (lodIndex) LOD を取得します。GetLod(0) は、ジオメトリ自身を返します。 virtual const IPrecompPackedGeometry* GetLod(Geo::s32 lodIndex) const = 0;
/// LOD アクセス /// LOD が生成されていないシステムの場合、GetNumLods は 1 を返します (つまり、メイン システムが 1 つ目の LOD とみなされます) virtual Geo::s32 GetNumLods() const = 0; ///システムの LOD バージョンを表す IPrecompPackedSystem にアクセスします。GetLod(0) は、メイン システム (このシステム) へのポインターを返します virtual const IPrecompPackedSystem* GetLod(Geo::s32 lodIndex) const = 0;
/// LOD が生成されていないシステムの場合、GetNumLods は 1 を返します (つまり、メイン システムが 1 つ目の LOD とみなされます) virtual Geo::s32 GetNumLods() const = 0; /// システムの LOD バージョンを表す IPrecompSystemCompressedLightTransport にアクセスします。GetLod(0) は、メイン システム (このシステム) へのポインターを返します virtual const IPrecompSystemCompressedLightTransport* GetLod(Geo::s32 lodIndex) const = 0;
/// LOD が生成されていないシステムの場合、GetNumLods は 1 を返します (つまり、メイン システムが 1 つ目の LOD とみなされます) virtual Geo::s32 GetNumLods() const = 0; /// システムの LOD バージョンを表す RadSystemCore にアクセスします。GetLod(0) は、メイン システム コア (このシステム) へのポインターを返します virtual const RadSystemCore* GetLodRadCore(Geo::s32 lodIndex) const = 0;
常に GetNumLods()
は 1
以上の値を返し、GetLod(0)
はオブジェクト自身 (LOD 0
を表す) へのポインターを返すため、オブジェクトのすべての LOD で繰り返すことができます。たとえば、IPrecompPackedGeometry (pGeom)
のすべての LOD で繰り返すには、以下を行います。
for (Geo::s32 lodIndex = 0; lodIndex < pGeom->GetNumLods(); ++lodIndex) { // パッキングされたジオメトリの LOD バージョンを取得します IPrecompPackedGeometry const* pGeomLOD = pGeom->GetLod(lodIndex); // この LOD に固有の操作をします pGeomLOD->DoSomethingForThisLOD(); }
上記のコードは LOD 0 を含むパッキングされたジオメトリのすべての LOD で反復します。
プリコンピュート API
すべてのプリコンピュート API は、自動的に詳細度を持つ入力オブジェクトを取り扱います。既定のプリコンピュート API への入力オブジェクトに LOD があった場合、その呼び出しの出力には LOD が生成されます (出力が LOD 依存の場合を除く)。たとえば、Precompute::PackSystem API
に渡される IPrecompPackedGeometry
オブジェクトに LOD がある場合、その結果として IPrecompPackedSystem
にも LOD が存在します。
ライトマップ LOD とテレイン LOD
同じ Enlighten のシステムでライトマップ LOD とテレイン LOD を混在させることはできません。つまり、Enlighten のシステムがテレイン システムとしてマークされている場合、テレインとマークされているジオメトリのインスタンスのみを保持できます。これらのジオメトリではライトマップ LOD を 1
以外に設定できません。
低レベル ランタイム API でのライトマップ LOD の使用
低レベル ランタイムに関しては、LOD に扱うための特別な API は存在しません。プリコンピュートの出力は、各 LOD の RadSystemCore
であり、上記のファイル名構造で識別できます。インテグレーションでは、同じ既存の API 関数を使用してこれらの個別の RadSystemCore
をロードおよび管理できます。
ただし、解決関数への入力と対応するメモリの管理方法は異なります。一部の入力はシステムごとに管理されますが、別の入力は LOD ごとに管理する必要があります。
入力ライティング
DirectInputLighting
および IndirectInputLighting
ステージは、LOD の影響を受けません。これらの関数での入出力は、LOD なしのシステムと同様です。また、UpdateTransparencyWorkspace()
と UpdateProbeBounceBuffer()
も同じです。
システムの解決
以下のソルバー入力は変更されず、引き続きシステムごとに管理する必要があります。
//システムごとのメンバー class RadIrradianceTask { public: //... const InputLightingBuffer** m_InputLighting; const InputLightingBuffer* m_Environment; eOutputFormat m_OutputFormat; eOutputFormatByteOrder m_OutputFormatByteOrder; float m_OutputScale; float m_TemporalCoherenceThreshold; float m_TemporalCoherenceEpsilon; //... };
以下の入力および出力は、LOD ごとに管理する必要があります。
class RadIrradianceTask { public: //... const RadSystemCore* m_CoreSystem; Geo::s32 m_OutputStride; Geo::s32 m_DirectionalOutputStride; void* m_IrradianceOutput; void* m_DirectionalOutput; void* m_DirectionalOutputG; void* m_DirectionalOutputB; void* m_PersistentData; //... };
RadSystemCore を入力とする CalcRequiredPersistentDataSize() などの API 関数には、適切な LOD の RadSystemCore オブジェクトを渡す必要があります。
バウンス リサンプリング LOD
バウンス リサンプリング LOD は、システムの解決ごとに 1 度のみ呼び出し、1 つの LOD からのみリサンプリングする必要があります (理想的は、可能な最高の詳細度の LOD)。たとえば、LOD 2 から LOD 5 を解決する場合、LOD 2 ソリューションからのみバウンスをリサンプリングします。
以下の入力パラメーターは、入力 LOD とは関係なく、変化しません。
class ResampleBounceParameters { //... BounceBuffer* m_BounceBuffer; float m_OutputScale; //... };
以下の入力パラメーターは、バウンスをリサンプリングしたい LOD 向けに設定する必要があります。
class ResampleBounceParameters { //... ResampleTextureParameters* m_ResampleTextureParams; const Enlighten::RadSystemCore* m_RadSystemCore; void* m_PersistentData; //... };
時間的なコヒーレンスの最適化によりソルバーが動作しなかった場合、バウンスをリサンプリングする必要はありません。これは、ソルバーに対し、numSolvePixels
パラメーターで返された値を確認することによりテストできます。この値が 0
の場合、このシステムのバウンス リサンプリングをスキップできます。
テクスチャ アルベド
プリコンピュートされたテクスチャ アルベド サンプリング データが、LOD 0 の RadSystemCore データに対して生成されます。従って、アルベド テクスチャをレンダリングする際に使用される UV とテクスチャ サイズが、LOD 0 の UV および解像度に対応していることが重要です。これは、InitialiseAlbedoBufferFromTexture()
、InitialiseEmissiveBufferFromTexture()
、InitialiseTransparencyBufferFromTexture()
にのみ適用されます。Enlighten::AlbedoBuffer
、Enlighten::EmissiveBuffer
、Enlighten::TransparencyBuffer
は IndirectInputLighting
ステージへの入力であるため、LOD の影響を受けません (つまりバッファはシステムごとに格納されています)。
高レベル ランタイム API でのライトマップ LOD の使用
システムで LOD を使用できるようにするには、各 LOD に対し ISystemSolutionSpace を作成し、追加します。
// Enlighten のシステムを割り当てます HlrtSystem.System = UpdateManager->AllocateSystem(DynamicData.GetInputWorkspace(), DynamicData.GetDirectionalVisibilityData(), 1); check(HlrtSystem.System); // システム ソリューション スペースを割り当てます (RadCore 0..N が LOD を参照します) for (int32 LodIndex = 0; LodIndex < DynamicData.GetRadCoreCount(); ++LodIndex) { // ソリューション スペースごとに使用する出力テクスチャを取得します static_assert(Enlighten::ENLIGHTEN_NUM_OUTPUT_TEXTURE_TYPES == 4, "ENLIGHTEN_NUM_OUTPUT_TEXTURE_TYPES is different than 4."); Enlighten::IGpuTexture* OutputTextures[Enlighten::ENLIGHTEN_NUM_OUTPUT_TEXTURE_TYPES] = { NULL, NULL, NULL, NULL }; OutputTextures[Enlighten::ENLIGHTEN_OUTPUT_IRRADIANCE] = System->CreateUpdater(EEnlightenTextureType::Irradiance, LodIndex); OutputTextures[Enlighten::ENLIGHTEN_OUTPUT_DIRECTIONAL] = System->CreateUpdater(EEnlightenTextureType::Direction, LodIndex); // ソリューション スペースを割り当てます Enlighten::ISystemSolutionSpace* NewSolutionSpace = UpdateManager->AllocateSystemSolutionSpace(DynamicData.GetRadCore(LodIndex), OutputTextures, Enlighten::OUTPUT_FORMAT_LRB); check(NewSolutionSpace); // ソリューション スペースを追跡します HlrtSystem.SolutionSpaces.Add(NewSolutionSpace); }
デフォルトで、システムに割り当てられるすべてのソリューション スペースは解決されます。したがって、レンダリングに必要なソリューション スペースのみを設定し、ソリューション スペース配列のどのインデックスがバウンスのリサンプリングに使用されるかを示すかどうかは、エンジン インテグレーションによって決まります。通常、これは最高品質の LOD です。カメラが動き、別の LOD のセットが必要な場合、エンジンは別の LOD のセットを持つ SetSystemSolutionSpaces()
を呼び出し、解決する必要があります。
// 選択した LOD 範囲のシステム ソリューション スペースを見つけます NumLodsToSolve = FMath::Abs(Range.FarLod - Range.NearLod) + 1; int32 MinLod = FMath::Min(Range.FarLod, Range.NearLod); check(MinLod >= 0); // 解決する LOD の新しい範囲を設定するコマンドをエンキューします Enlighten::EnqueueWorkerFunctorCommand(UpdateManager, [=](Enlighten::IUpdateManagerWorker* worker) { UMSystem->SetSystemSolutionSpaces(System.SolutionSpaces.GetData() + MinLod, NumLodsToSolve, 0); });
レンダリング
ソリューション スペースの Enlighten のシステムでの設定とテクスチャの GPU での更新にはタイム ラグがあるため、ISystemSolutionSpace::IsReadyForRendering()
メソッドが true を返すまではライトマップの使用を開始しないことが重要です。これは、システムが解決され、GPU テクスチャが更新されたことを示します。(つまり BaseWorker::UpdateGpuTextures()
が呼びだされたということです)。このラグを考慮しなかった場合、未解決 (かつ古い) のライトマップがレンダリングに使用され、アーティファクトが出現してしまいます。
レンダリングのブロックを防ぐには、IsReadyForRendering()
が新しい LOD のセットについて個別に true を返すまで、レンダラーが古い Enlighten LOD のセットを使ってレンダリングし続けられる柔軟性が必要です。
リソースの解放
ゲーム プレイ中、使用されていない LOD に使われているメモリを戻せるようにする必要があります。たとえば、遠くのシステムに対しては、メモリに詳細度の高いソリューション スペースを割かずに、低い詳細度のライトマップからレンダリングする場合などです。これは、ソリューション スペースの設置がシステムで解除された後に実施できます。IUpdateManager::EnqueueReleaseSystemSolutionSpaces()
メソッドを呼び出して、 (ソリューション スペースへのすべての参照が切り離された後に) レンダー スレッドのリソースを解放できます。
// ソリューション スペースを解放するコマンドをエンキューします。 UpdateManager->EnqueueReleaseSystemSolutionSpaces(SolutionSpaces.GetData(), SolutionSpaces.Num());
ソリューション スペースは、ソリューション スペースを使用するシステムが高レベル ランタイムから削除された後ですべて安全に解放できます。または、ソリューション スペースを解放する前に BaseSystem::RemoveSystemSolutionSpaces() を呼び出してすべてのソリューション スペースをシステムから明示的に削除します。
注意: システムを削除または解放しても、 ISystemSolutionSpace
オブジェクトにより使用されるメモリは解放されません。IUpdateManager::EnqueueReleaseSystemSolutionSpaces()
を呼び出して、エンジン インテグレーションにより明示的に開放する必要があります。