จะใช้ D3D12GetDebugInterface API จาก c # ได้อย่างไร

Sep 16 2020

ฉันกำลังพยายามใช้ Direct3D จาก c # และฉันได้เริ่มต้นโดยใช้ D3D12GetDebugInterface API ไวยากรณ์ C ++ ของฟังก์ชันมีดังต่อไปนี้ (คัดลอกจากเอกสารของ Microsoft):

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

ฉันมีปัญหาในการนำเข้าฟังก์ชันไปยัง C # ฉันคิดว่า riid น่าจะเป็นตัวชี้ไปยัง Guid struct และฉันแค่ใช้ IntPtr สำหรับ ** ppvDebug เนื่องจาก ** ppvDebug เป็นตัวชี้ไปยังตัวชี้ไปยังอินเทอร์เฟซ ID3D12Debug ฉันจึงลองใช้อินเทอร์เฟซ ID3D12Debug ใหม่ในโค้ด C # และใช้ Marshal.PtrToStructure () เพื่อแก้ไข IntPtr เป็นอินสแตนซ์อินเทอร์เฟซ ID3D12Debug ที่ใช้งานได้ แต่จะไม่ได้ผล ฉันจำได้ว่าอ่านเกี่ยวกับอินเทอร์เฟซ ID3D12Debug เป็นวัตถุ COM แต่คุณไม่ต้องการ ID สำหรับวัตถุ COM เพื่อให้คุณสามารถนำเข้าได้หรือไม่ ฉันไม่พบ COM ID ประเภทใดเลยในเอกสารประกอบ

อย่างไรก็ตามนี่คือความพยายามล่าสุดของฉันในการดึงบางสิ่งออกจากฟังก์ชัน:

[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();
    }
}

ในกรณีที่คุณต้องการดูอินเทอร์เฟซ ID3D12Debug ของฉัน:

interface ID3D12Debug
{
    void EnableDebugLayer();
}

อย่างที่ฉันพูดไปฉันคิดว่า Direct3D ใช้ประโยชน์จาก COM ซึ่งฉันขาดหายไปอย่างสิ้นเชิงที่นี่ดังนั้นอาจเป็นสาเหตุที่ใช้ไม่ได้

คำตอบ

1 SimonMourier Sep 16 2020 at 20:41

โดยปกติมีหลายวิธีในการประกาศรหัสการทำงานร่วมกัน นี่คือสิ่งที่ควรใช้:

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();
}
  • คุณต้องเพิ่มแอตทริบิวต์ของอินเตอร์เฟส Guid และ InterfaceType สำหรับอินเตอร์เฟส COM
  • Guid สามารถส่งผ่านได้อย่างง่ายดายโดยใช้การอ้างอิง UnmanagedType.LPStruct
  • คุณไม่จำเป็นต้องใช้รหัสที่ไม่ปลอดภัยที่นี่
  • คุณควรตรวจสอบข้อผิดพลาด (ยกเลิกในรหัสของฉัน)
  • หากคุณต้องการนิยามอินเตอร์เฟส. NET กับ DirectX คุณสามารถใช้โปรเจ็กต์โอเพนซอร์สนี้ได้ที่นี่: https://github.com/smourier/DirectN, ตัวอย่างเช่น: https://github.com/smourier/DirectN/blob/master/DirectN/DirectN/Generated/ID3D12Debug.cs