DirectX 12.0 でプログラミングしているときに、かなり変わった問題に遭遇しました。これまでのところ、洞察に満ちた研究はありません。
C (C++ ではありません) を使用してプログラミングしています。公式の DirectX 12 ヘッダーは C と C++ の両方のバインディングをサポートしているように見えますが、C と同等のコードを記述して上記のタスクを実行するとクラッシュが発生しますが、C++ はそうではありません。エラーが私のものだとは思いません。
詳細は次のとおりです。D3D12 デバイスの初期化手順には、次のコード ブロックがあります。
/* Get a handle to the memory location in the render target
view heap to identify where the render target views will be
located for the two back buffers */
hRTV = pThis->pRTVHeap->lpVtbl->GetCPUDescriptorHandleForHeapStart(pThis->pRTVHeap);
ここで、hRTVは「レンダリング ターゲット ビューへのハンドル」(D3D12_CPU_DESCRIPTOR_HANDLE) を表し、 pRTVHeapは「レンダリング ターゲット ビュー ヒープへのポインター」(ID3D12DescriptorHeap) を表します。
これはC++の同等物です - これはうまくいきます:
/* Get a handle to the memory location in the render target
view heap to identify where the render target views will be
located for the two back buffers */
hRTV = this->pRTVHeap->GetCPUDescriptorHandleForHeapStart();
コンパイル時のエラーはありませんが、実行時に C でこのメソッド (GetCPUDescriptorHandleForHeapStart) を呼び出すと、スタックの破損がトリガーされます (%ESP は 4 バイト分置き換えられます)。
メソッドの逆アセンブリを調べ、RET (リターン) 命令を書き留めました。
mov edi,edi
push ebp
mov ebp,esp
mov ecx,dword ptr [ebp+8]
mov eax,dword ptr [ecx+2Ch]
cmp dword ptr [eax],2
jne 5029004A
mov eax,dword ptr [ebp+0Ch]
mov ecx,dword ptr [ecx+28h]
mov dword ptr [eax],ecx
jmp 50290055
push dword ptr [ebp+0Ch]
call 5029005E
mov eax,dword ptr [ebp+0Ch]
pop ebp
ret 8
__stdcall
アセンブリと (願わくば) COM (コンポーネント オブジェクト モデル) オブジェクトの呼び出し規則に精通している人にとってthis
は、スタック上で渡される (または同等の) ポインターが最初のパラメーターです (この場合、唯一のパラメーターである必要があります)。これは、COM オブジェクトが独自のデータにアクセスできるようにする方法です。
次のコード スニペット (これも上に表示) は、私の混乱を招くものであり、当然のことながら、ランタイムが「スタック ポインターの位置合わせが正しくない/スタックの破損」(%ESP) エラーをスローする場合に、混乱を招きます。
ret 8
この場合、1 つのパラメーターのみを渡す必要があります (this
ポインター)。ポインターのサイズ (32 ビット システム - 私のターゲット アーキテクチャは x86) は 4 バイト (32 ビット) ですが、呼び出し先がスタック上の 8 バイトをクリーンアップするのはなぜですか?
これをバグと呼ぶのは正しいですか?この問題について Microsoft に通知する必要がありますか? 私が間違っている?
お時間をいただきありがとうございます。私よりも多くの知識をお持ちの方に教えていただければ幸いです。CよりもC++を好むという古くからの議論を提案しないでください.