1

60fpsでCADisplayLinkによって呼び出されるOpenGLESで実行ループを作成しました。AFAIK CADisplayLinkは、バックグラウンドスレッドでターゲットを呼び出します。

実行ループで使用される状態変数は約100個あります。

問題:メインスレッドから、何かを描画するために実行ループで使用される状態変数を変更したいと思います。フレームは、すべての状態変数がターゲット値に設定された後にのみ描画する必要があります。

ある時点で状態変数を変更しても、まだすべてを変更していないのではないかと心配しています(メインスレッドでの同じ実行ループの反復での1つの大きなメソッドで)。たとえば、幾何学的形状の位置には、複数の変数があります。 -スレッド関連のクラッシュまたは、状態変数を更新するメソッドの途中でCADisplayLinkが起動し、ガベージまたはクラッシュが発生する問題。

明らかに、同期プロパティまたはアトミックプロパティを使用するだけでは、トランザクションではないため、役に立ちません。取引が必要だと思います。

私の素朴なアプローチはこれです:

実行ループによって読み取られたインスタンス変数:

BOOL updatingState;

updateStateがYESの場合、runloopメソッドは描画をスキップします。

次に、状態の変更を開始する前に、YESに設定しました。そして、すべてが変更されたら、NOに戻します。

もちろん、問題:これを変更しているときにrunloopメソッドが値を読み取っている場合はどうなりますか?

ゲームエンジンはこの問題にどのように対処しますか?次のフレームが描画される前に状態変数の変更を終了できるように、どのようなロックメカニズムがありますか?

4

3 に答える 3

2

リードコピーアップデート戦略が役立つ場合があります。考えられる実装の1つは、各オブジェクトに実際にレンダリングパラメータの2つのコピーが含まれ、アトミックフラグを使用してレンダリングスレッドにどちらを使用するかを指示することです。レンダラーで読み取りメモリーバリアを使用してパラメーターを読み取る前にフラグが読み取られることを確認し、アップデータースレッドで書き込みメモリバリアを使用して、フラグを反転する前にすべてのパラメーター更新が書き込まれることを確認する必要があります。 。

于 2012-05-17T15:57:16.383 に答える
1

これは並行性の一般的な問題だと思うので、それを行うにはいくつかの方法があります。

  1. 不変の状態クラスを使用して、状態変数を保持します。
  2. 状態変数を保護するために、ロックメカニズムを使用します(不変クラスを使用できない場合)。
  3. 変更できる状態が複数ありますが、「アクティブ」なのは1つだけです。これにより、状態を再利用できるようになり、コピーとメモリ割り当てが削減されます。

さらに、次の状況を考慮してください。

スレッド1.何かを描き始めます。
スレッド1.状態01パラメーターの1/2を読み取ります(最初の状態)。
スレッド2。状態01を状態02(2番目の状態)と交換します。
スレッド1。状態02の残りの1/2を読み取りますが、状態01のパラメーターとは異なります。

したがって、描画中に状態の更新を許可しないのが最善のオプションです。したがって、最新の状態を取得して描画するだけなので、オプション3が最適な方法である可能性があります。2つの状態があるとしましょう:drawingStatenonDrawingStatedrawingState描画関数では、他のスレッドがを変更している間、常にを使用して描画しnonDrawingStateます。描画が完了したら、状態を交換して、最新の状態変更で描画を続行できます。

于 2012-05-17T15:54:51.813 に答える
1

これが行われる通常の方法は、描画が行われる前に、すべての状態の更新が各実行ループの反復で行われることです。つまり、実行ループは概略的に次のようになります。

updateState();
draw();

このモデルでは、一貫した状態に達した後にのみ描画が行われます。

これを機能させるには、キーの押下などのイベントが非同期で発生するのではなく、updateState()ごとにポーリングされるモデルと、最後のフレームから経過した時間を示すための各反復での時間測定が必要です。

私はそれについて何も知らないので、iOSプログラミングの具体的なケースでこれがどのように実現されるかをあなたに助けることはできません。しかし、私はあなたを正しい方向に向けることができればと思います。

于 2012-05-17T15:54:02.347 に答える