• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:DirectX 11のConsntanBuffer)

DirectX 11 ConsntanBufferの更新について

このQ&Aのポイント
  • マルチスレッドでConsntanBufferの更新を行うときにエラーが出てしまいます。
  • DirectXをDebugモードで実行すると以下のようなエラーが出てしまいました。
  • エラーの解決方法をご存知の方はいらっしゃいますでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • sygh
  • ベストアンサー率76% (42/55)
回答No.1

デバイス コンテキストID3D11DeviceContextのメソッドはいずれもスレッド セーフではありません。 呼び出しがスレッド セーフになったのはID3D11Deviceだけです。そのため、デバイス コンテキストはスレッドごとに作成する必要があります。 具体的には、メインスレッドではイミディエイト コンテキスト(Immediate Context)、サブスレッドではディファード コンテキスト(Deferred Context)として、それぞれスレッドごとに作成する必要があります。 Direct3D 11のマルチスレッド レンダリングは、サブスレッド側で遅延された描画コマンドのリストを記録(作成)し、メインスレッド側で再生(実行)する、という方式になっています。 DirectX SDKにMultithreadedRendering11サンプルが付いているので、(例のごとくDXUTやら大量のグローバル変数やらで少し読みづらいですが)それが参考になるかと思います。Map/Unmapは各スレッドごとに独立して実行しています。 http://msdn.microsoft.com/ja-jp/library/ee422102.aspx http://wlog.flatlib.jp/archive/1/2008-11-7

emuesuenu
質問者

お礼

話は脱線しましたが、 ID3D11DeviceContextがスレッドセーフでないことは理解しました。 # もっとわかりやすい警告を出してくれれば速く気づけたのですが… 大変助かりました。 どうもありがとうございました。

emuesuenu
質問者

補足

>デバイス コンテキストID3D11DeviceContextのメソッドはいずれもスレッド セーフではありません。 >呼び出しがスレッド セーフになったのはID3D11Deviceだけです。そのため、デバイス コンテキストはスレッドごとに作成する必要があります。 なるほど。Direct3D 9ではMULTITHREADオプションでスレッドセーフに出来ましたが、 おっしゃるとおりスレッド単位でコンテキストを分けた方が クリティカルセクションのロスが減らせそうです。 DeferredContextはDirect 3D 10では使えないようですね。 今作っているプログラムはマルチプラットホーム対応を検討しているため、 できるだけ標準化されたAPIで実装しようとしています。 となればリソースの更新も仮想コマンドを投げて 2のスレッドで行うことにします。 ただ、この方法ですと書き込み先のアドレスが、 書き込み元のスレッドで取得できなくなります。 1のスレッドではテンポラリバッファを用意し、 そこに書き込んだ後、2のスレッドでMapをしmemcpyをします。 メモリが余分に必要なのに加えてmemcpy分の処理が上積みされてしまいます。 残るは毎フレームID3D11Device::CreateBuffer/ID3D11Buffer::Releaseを呼び出す方法です。 D3D11_SUBRESOURCE_DATAに1のスレッドで操作しているバッファをセットするので、 コピー処理は不要です。 # Direct3D 9ではコピーが必須ですし、 # Direct3D 10以降であっても内部的にコピー処理が走るかも知れないので # 気休めではありますが… バッファの生成と破棄が大量に呼び出されることになりますが メモリ容量と処理速度と汎用化のバランスが一番とれている気がします。 初期化時にSINGLETHREADフラグがセットできるので、 実質Direct3D 9と同じ扱いになりそうです。