Cách sử dụng D3D12GetDebugInterface API từ c #?

Sep 16 2020

Tôi hiện đang cố gắng sử dụng Direct3D từ c # và tôi đã bắt đầu bằng cách sử dụng API D3D12GetDebugInterface. Cú pháp C ++ của hàm như sau (được sao chép từ tài liệu Microsoft):

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

Tôi đang gặp sự cố khi nhập hàm vào C #. Tôi nghĩ rằng có lẽ riid nên là một con trỏ đến cấu trúc Guid và tôi chỉ đang sử dụng IntPtr cho ** ppvDebug. Vì ** ppvDebug là một con trỏ trỏ tới một giao diện ID3D12Debug, tôi đã thử hoàn thành lại giao diện ID3D12Debug trong mã C # và sử dụng Marshal.PtrToStructure () để phân giải IntPtr thành một phiên bản giao diện ID3D12Debug có thể sử dụng được, nhưng điều đó sẽ không hoạt động. Tôi nhớ đã đọc về giao diện ID3D12Debug là một đối tượng COM, nhưng bạn không cần ID cho đối tượng COM để có thể nhập nó? Tôi không tìm thấy bất kỳ loại ID COM nào trong tài liệu.

Dù sao đây là nỗ lực mới nhất của tôi trong việc lấy một thứ gì đó ra khỏi chức năng:

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

Trong trường hợp bạn muốn xem giao diện ID3D12Debug của tôi:

interface ID3D12Debug
{
    void EnableDebugLayer();
}

Như tôi đã nói, tôi nghĩ Direct3D sử dụng COM, thứ mà tôi hoàn toàn thiếu ở đây, vì vậy có lẽ đó là lý do tại sao nó không hoạt động.

Trả lời

1 SimonMourier Sep 16 2020 at 20:41

Thường có nhiều cách để khai báo mã interop. Đây là một trong những hoạt động:

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();
}
  • Bạn phải thêm các thuộc tính Hướng dẫn giao diện và Kiểu giao diện cho các giao diện COM.
  • Hướng dẫn có thể được thông qua dễ dàng bằng cách tham khảo bằng cách sử dụng UnmanagedType.LPStruct
  • Bạn không cần mã không an toàn ở đây.
  • Bạn nên kiểm tra lỗi (hoàn tác trong mã của tôi)
  • Nếu bạn cần định nghĩa giao diện .NET với DirectX, bạn có thể sử dụng dự án mã nguồn mở này tại đây: https://github.com/smourier/DirectN, ví dụ: https://github.com/smourier/DirectN/blob/master/DirectN/DirectN/Generated/ID3D12Debug.cs