Wie verwende ich die D3D12GetDebugInterface API von c #?

Sep 16 2020

Ich versuche derzeit, Direct3D von c # aus zu verwenden, und habe zunächst die D3D12GetDebugInterface-API verwendet. Die C ++ - Syntax der Funktion lautet wie folgt (aus der Microsoft-Dokumentation kopiert):

HRESULT D3D12GetDebugInterface(
    REFIID riid,
    void   **ppvDebug
);

Ich habe Probleme beim Importieren der Funktion in C #. Ich dachte, dass riid vielleicht ein Zeiger auf eine Guid-Struktur sein sollte, und ich verwende nur ein IntPtr für ** ppvDebug. Da ** ppvDebug ein Zeiger auf einen Zeiger auf eine ID3D12Debug-Schnittstelle ist, habe ich versucht, die ID3D12Debug-Schnittstelle in C # -Code erneut zu implementieren und Marshal.PtrToStructure () zu verwenden, um IntPtr in eine verwendbare ID3D12Debug-Schnittstelleninstanz aufzulösen, aber das funktioniert nicht. Ich erinnere mich, dass ich gelesen habe, dass die ID3D12Debug-Schnittstelle ein COM-Objekt ist, aber benötigen Sie keine ID für ein COM-Objekt, damit Sie es importieren können? Ich habe nirgendwo in der Dokumentation eine COM-ID gefunden.

Hier ist mein letzter Versuch, etwas aus der Funktion herauszuholen:

[DllImport("D3D12.dll")]
static extern int D3D12GetDebugInterface(IntPtr riid, IntPtr ppvDebug);

void func() {
    unsafe
    {
        IntPtr DebugControllerPtr = IntPtr.Zero;

        Type InterfaceType = typeof(ID3D12Debug);
        Guid ID = InterfaceType.GUID;
        IntPtr ptr = Marshal.AllocHGlobal(sizeof(Guid));
        Marshal.StructureToPtr(ID, ptr, false);

        D3D12GetDebugInterface(ptr, DebugControllerPtr);
        Marshal.FreeHGlobal(ptr);
        ID3D12Debug DebugController = null;
        Marshal.PtrToStructure(DebugControllerPtr, DebugController);
        DebugController.EnableDebugLayer();
    }
}

Falls Sie meine ID3D12Debug-Oberfläche sehen möchten:

interface ID3D12Debug
{
    void EnableDebugLayer();
}

Wie gesagt, ich denke, Direct3D nutzt COM, was mir hier völlig fehlt. Vielleicht funktioniert es deshalb nicht.

Antworten

1 SimonMourier Sep 16 2020 at 20:41

Es gibt normalerweise viele Möglichkeiten, Interop-Code zu deklarieren. Hier ist eine, die funktionieren sollte:

public static void Main()
{
    D3D12GetDebugInterface(typeof(ID3D12Debug).GUID, out var obj);
    var debug = (ID3D12Debug)obj;
    debug.EnableDebugLayer(); // for example
}

[DllImport("D3D12")]
public static extern int D3D12GetDebugInterface([MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvDebug);

[Guid("344488b7-6846-474b-b989-f027448245e0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ID3D12Debug
{
    [PreserveSig]
    void EnableDebugLayer();
}
  • Sie müssen die Schnittstellen Guid- und InterfaceType-Attribute für COM-Schnittstellen hinzufügen.
  • Guid kann einfach als Referenz mit übergeben werden UnmanagedType.LPStruct
  • Sie benötigen hier keinen unsicheren Code.
  • Sie sollten nach Fehlern suchen (in meinem Code rückgängig gemacht)
  • Wenn Sie .NET-Schnittstellendefinitionen mit DirectX benötigen, können Sie dieses Open Source-Projekt hier verwenden: https://github.com/smourier/DirectN, beispielsweise: https://github.com/smourier/DirectN/blob/master/DirectN/DirectN/Generated/ID3D12Debug.cs