ComPtr.As() 是做什么的?

2022-01-14 00:00:00 com c++

我正在从一些示例中学习 DirectX 12,但我无法理解 ComPtr.As() 方法的作用.

I am working on learning DirectX 12 from some examples but I am having trouble understanding what does the ComPtr.As() method does.

ComPtr<ID3D12Device> device;
ComPtr<ID3D12Device> device2; 

// Do Stuff with Device
device.As(&device2); // What does this do?

推荐答案

你在哪里找到这个示例代码?看起来很腥这是对 As 的一种无意义的使用.如果将其扩展为底层的 QueryInterface 也同样愚蠢:

Where did you find this example code? It looks fishy. This is kind of a nonsense use of As. It's equally silly if you expand it to the underlying QueryInterface:

hr = device->QueryInterface( IID_PPV_ARGS(device2) );

事实上,你的代码最好写成:

In fact, your code would be better written as:

device2 = device;

通常您会使用 As 从现有接口获取新接口.例如,使用 Direct3D 11,您将设备创建为 Direct3D 11.0 接口,然后必须QueryInterface 11.1、11.2、11.3 和/或 11.4 版本才能使用它们:

Typically you'd use As to obtain a new interface from an existing interface. For example with Direct3D 11, you create the device as a Direct3D 11.0 interface and then have to QueryInterface the 11.1, 11.2, 11.3, and/or 11.4 versions to use them:

ComPtr<ID3D11Device> device;
DX::ThrowIfFailed(D3D11CreateDevice(..., device.ReleaseAndGetAddressOf());

ComPtr<ID3D11Device2> device2;
hr = device.As(&device2);
if (FAILED(hr))
    // Do whatever handling you do if the system doesn't support 11.2

Direct3D 11 的另一个常见用途是处理可能不存在的调试接口:

Another common use with Direct3D 11 is dealing with the debug interfaces which may not be present:

#ifndef NDEBUG
    ComPtr<ID3D11Debug> d3dDebug;
    if (SUCCEEDED(device.As(&d3dDebug)))
    {
        ComPtr<ID3D11InfoQueue> d3dInfoQueue;
        if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue)))
        {
#ifdef _DEBUG
            d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
            d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
#endif
            D3D11_MESSAGE_ID hide [] =
            {
                D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
                // TODO: Add more message IDs here as needed.
            };
            D3D11_INFO_QUEUE_FILTER filter = {};
            filter.DenyList.NumIDs = _countof(hide);
            filter.DenyList.pIDList = hide;
            d3dInfoQueue->AddStorageFilterEntries(&filter);
        }
    }
#endif

同样重要的是不要忽略从 As 返回的 HRESULT 返回值.您应该使用 SUCCEEDEDFAILED 宏,或像 ThrowIfFailed.

It's also important to not ignore the HRESULT return value that comes back from As. You should use SUCCEEDED or FAILED macro, or a fast-fail like ThrowIfFailed.

请参阅 ComPtr.

相关文章