为什么使用Rust的windows-rs crate时,D3 D12 GetLogInterface会失败,并显示“no such interface supported”?

mv1qrgav  于 4个月前  发布在  Windows
关注(0)|答案(1)|浏览(45)

我在Rust中使用windows-rs crate获取D3D12DebugInterface时得到以下错误:

failed to get d3d12 debug interface: No such interface supported (0x80004002)

字符串
下面是我认为应该工作的代码:

#[derive(Default)]
struct DebugLayer {
    d3d12_debug: Option<ID3D12Debug6>,
    dxgi_debug: Option<IDXGIDebug1>,
}

impl DebugLayer {
    fn init() -> Self {
        unsafe {
            let mut debug_layer = Self::default();

            match D3D12GetDebugInterface(&mut debug_layer.d3d12_debug) {
                Ok(()) => {
                    if let Some(ref d3d12_debug) = debug_layer.d3d12_debug {
                        d3d12_debug.EnableDebugLayer();
                        println!("d3d12: debug layer enabled");

                        match DXGIGetDebugInterface1::<IDXGIDebug1>(0) {
                            Ok(dxgi_debug) => {
                                dxgi_debug.EnableLeakTrackingForThread();
                                println!("d3d12: leak tracking enabled");

                                debug_layer.dxgi_debug = Some(dxgi_debug);
                            }

                            Err(err) => println!("failed to get dxgi debug interface: {}", err),
                        }
                    }
                }

                Err(err) => println!("failed to get d3d12 debug interface: {}", err),
            }

            debug_layer
        }
    }
}


我在Cargo.toml中启用的功能:

[target.'cfg(target_os = "windows")'.dependencies.windows]
version = "0.52.0"
features = [
    "Win32_Foundation",
    "Win32_Graphics_Gdi",
    "Win32_Graphics_Direct3D_Fxc",
    "Win32_Graphics_Direct3D12",
    "Win32_Graphics_Dxgi_Common",
    "Win32_Security",
    "Win32_System_LibraryLoader",
    "Win32_System_Threading",
    "Win32_System_WindowsProgramming",
    "Win32_UI_Input_KeyboardAndMouse",
    "Win32_UI_WindowsAndMessaging",
]


我使用的是Windows 10,已检查设置并安装了图形工具。我缺少/做错了什么?

pu82cl6c

pu82cl6c1#

错误诊断是正确的:ID3D12Debug6在你的系统(或我的1)上不可用。这就是错误代码0x80004002i.e.E_NOINTERFACE)所传达的信息。
这里有一个最小的例子来说明这个问题。

  • 货物.toml*
[package]
name = "d3d12_debug_layer"
version = "0.0.0"
edition = "2021"

[dependencies.windows]
version = "0.52.0"
features = ["Win32_Graphics_Direct3D12"]

字符串

  • 来源/main.rs *
use windows::{
    core::Result,
    Win32::Graphics::Direct3D12::{D3D12GetDebugInterface, ID3D12Debug6},
};

fn main() -> Result<()> {
    let mut dbg_itf: Option<ID3D12Debug6> = None;
    unsafe { D3D12GetDebugInterface(&mut dbg_itf) }?;

    Ok(())
}


发出cargo run会产生以下输出1:

Error: Error { code: HRESULT(0x80004002), message: "No such interface supported" }


这不是你可以通过修改代码来“修复”的问题。请求的接口(ID3D12Debug6)没有在你的操作系统发行版附带的二进制文件中实现。
调试接口的可用性取决于代码执行的系统。这超出了您的控制范围,您必须编写适应可用功能的代码。
为了说明这一点,下面的代码首先请求ID3D12Debug接口,然后检查后面的接口是否被实现。它通过调用ComInterface trait的cast()泛型来实现这一点。这是windows-rsQueryInterface()的实现。为了方便起见,尾部的ok()Result<T, E>转换为Option<T>

  • 来源/main.rs *
use windows::{
    core::{ComInterface, Result},
    Win32::Graphics::Direct3D12::{
        D3D12GetDebugInterface, ID3D12Debug, ID3D12Debug1, ID3D12Debug2, ID3D12Debug3,
        ID3D12Debug4, ID3D12Debug5, ID3D12Debug6,
    },
};

fn main() -> Result<()> {
    let dbg_itf = {
        let mut dbg_itf: Option<ID3D12Debug> = None;
        unsafe { D3D12GetDebugInterface(&mut dbg_itf) }?;
        dbg_itf.expect("D3D12GetDebugInterface failed its contract")
    };

    let dbg1_itf = dbg_itf.cast::<ID3D12Debug1>().ok();
    println!("{dbg1_itf:?}");

    let dbg2_itf = dbg_itf.cast::<ID3D12Debug2>().ok();
    println!("{dbg2_itf:?}");

    let dbg3_itf = dbg_itf.cast::<ID3D12Debug3>().ok();
    println!("{dbg3_itf:?}");

    let dbg4_itf = dbg_itf.cast::<ID3D12Debug4>().ok();
    println!("{dbg4_itf:?}");

    let dbg5_itf = dbg_itf.cast::<ID3D12Debug5>().ok();
    println!("{dbg5_itf:?}");

    let dbg6_itf = dbg_itf.cast::<ID3D12Debug6>().ok();
    println!("{dbg6_itf:?}");

    Ok(())
}


运行此命令会产生以下输出1:

Some(ID3D12Debug1(IUnknown(0x1d2f23d50b0)))
Some(ID3D12Debug2(IUnknown(0x1d2f23d50b8)))
Some(ID3D12Debug3(IUnknown(0x1d2f23d50a0)))
None
None
None


代码相当冗长,但你通常只会要求你感兴趣的接口使用。增加复杂性的好处是,它可以利用功能,因为它们变得可用,而不必重新编译和重新部署。
功能通过以下两种方式之一变得可用:

  • 在较新的操作系统版本上运行二进制文件的用户
  • 操作系统更新,将功能向后移植到早期操作系统版本

后者似乎在过去发生过。ID3D12Debug3的文档列出了最低系统要求:
| | |
| --|--|
| 最低支持客户端|Windows 10 Build 20348|
| 最低支持服务器|Windows 10 Build 20348|
如文档所示,ID3D12Debug3接口在我的系统上不应该可用,但上面的输出显然不同意。因此,强烈建议编写“版本自适应代码”来检查功能可用性,而不是操作系统版本。
1Windows 10版本22 H2(OS Build 19045.3693)。

相关问题