【发布时间】:2021-01-05 10:41:07
【问题描述】:
在 C++/CX D3D12 的 VS2019 项目模板中,订阅了 DisplayInformation::DisplayContentsInvalidated 事件(记录在 here),当此事件触发时,项目模板中的代码会尝试验证 D3D12 设备。用于验证的标准是 default 适配器是否已更改:
// This method is called in the event handler for the DisplayContentsInvalidated event.
void DX::DeviceResources::ValidateDevice()
{
// The D3D Device is no longer valid if the default adapter changed since the device
// was created or if the device has been removed.
// First, get the LUID for the default adapter from when the device was created.
DXGI_ADAPTER_DESC previousDesc;
{
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc));
}
// Next, get the information for the current default adapter.
DXGI_ADAPTER_DESC currentDesc;
{
ComPtr<IDXGIFactory4> currentDxgiFactory;
DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tDxgiFactory)));
ComPtr<IDXGIAdapter1> currentDefaultAdapter;
DX::ThrowIfFailed(currentDxgiFactory->EnumAdapters1(0, ¤tDefaultAdapter));
DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc));
}
// If the adapter LUIDs don't match, or if the device reports that it has been removed,
// a new D3D device must be created.
if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||
previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||
FAILED(m_d3dDevice->GetDeviceRemovedReason()))
{
m_deviceRemoved = true;
}
}
但是,在我看来 default 适配器可能不是 elected 适配器,正如您在这段代码中看到的那样,因为它确保适配器可以创建一个D3D12 设备在选择之前,并且上面的验证代码中不存在相同的检查:
// This method acquires the first available hardware adapter that supports Direct3D 12.
// If no such adapter can be found, *ppAdapter will be set to nullptr.
void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)
{
ComPtr<IDXGIAdapter1> adapter;
*ppAdapter = nullptr;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter); adapterIndex++)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
{
// Don't select the Basic Render Driver adapter.
continue;
}
// Check to see if the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
break;
}
}
*ppAdapter = adapter.Detach();
}
这是否无意中依赖默认适配器作为选择的适配器,或者我们可以根据默认适配器的更改做出更广泛的假设?
DisplayInformation::DisplayContentsInvalidated的真正含义是什么?这是在告诉我什么?为什么这表明该设备可能无效?在哪些情况下会触发此事件并且设备会无效或不会无效?
由于我们也在此处检查DeviceRemovedReason,是否存在默认适配器未更改但设备因DisplayInformation::DisplayContentsInvalidated 而被删除的情况?
我们真的需要处理这个吗?如果我完全忽略此事件并继续尝试渲染会发生什么?我不会最终处理此事件触发在记录的“设备丢失场景”中根据this document 指示的任何问题吗?
【问题讨论】:
-
“和上面的验证码中不存在同样的检查”是什么意思?是不是表示previousDefaultAdapter 和currentDxgiFactory 不匹配?能否提供一个简单的样本供我们测试?
-
我的意思是验证代码不会调用
D3D12CreateDevice来查看是否可以像GetHardwareAdapter函数那样使用默认适配器创建D3D12 设备。我不清楚为什么默认设备在这里是相关的。目前尚不清楚这种验证的基础是什么。 -
这个简单的例子可以通过
DirectX 12 App (Universal Windows C++/CX)项目模板在VS2019中新建项目轻松获取。
标签: visual-studio uwp direct3d