为什么为设备和交换链使用相同的IDXGIFactory ?
Why use the same IDXGIFactory for Device and Swap Chain
IDXGIFactory接口的引用告诉我,为了创建交换链,我可以使用用于创建Direct3D设备的相同工厂:
因为您可以在不创建交换链的情况下创建Direct3D设备,因此您可能需要检索用于创建设备的工厂以创建交换链。
它还给出了以下代码示例:
IDXGIDevice * pDXGIDevice;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter * pDXGIAdapter;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
IDXGIFactory * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
这篇文章非常简短,当我试图完全理解它时,出现了以下两个问题,而第一个问题是主要问题(关于这篇文章的标题):
为什么我必须使用用于创建Direct3D设备的相同工厂来创建交换链?工厂实例是否维护一个重要的内部状态,或者只是为了避免创建另一个消耗资源的工厂实例?
同样,在代码示例中,我与以下代码行作斗争:
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
对我来说,IDXGIAdapter是IDXGIDevice的父节点是不符合逻辑的。否则,我会期望IDXGIAdapter有一个类似CreateDevice的方法,它会使适配器成为设备的父设备。但事实并非如此。为什么适配器是设备的父设备?
问题的根源可以追溯到DXGI 1.0 (Direct3D 10)和DXGI 1.1 (Direct3D 11)。如果你试图在同一过程中使用由CreateDXGIFactory
和CreateDXGIFactory1
创建的IDXGIFactory
,事情会很快变成梨形。
另一个问题是,当你使用Direct3D 10的"默认设备"时,会创建一个隐式工厂。X或11。X设备创建。上面的"魔法代码序列"可以让你隐式地创建工厂。
文档中的第二步应该是dxgiDevice->GetAdapter
而不是dxgiDevice->GetParent
。我要把它归档。
如果使用Microsoft::WRL::ComPtr
:
// First, retrieve the underlying DXGI Device from the D3D Device
ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
// And obtain the factory object that created it.
ComPtr<IDXGIFactory1> dxgiFactory;
DX::ThrowIfFailed(dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory));
Direct3D 12
请注意,这整个区域已被Direct3D 12清理,你不能使用QI从ID3D12Device
获得IDXGIDevice
。
引用
DirectX Graphics Infrastructure (DXGI):最佳实践
Direct3D 11 Create Device的解剖
扩展Chuck Walbourn关于如何从D3D12设备获得DXGI工厂的评论,这里是一个可能的实现:
#include <d3d12.h>
#include <dxgi1_6.h>
#include <wrl/client.h>
#include <concepts>
#include <expected>
using namespace Microsoft::WRL;
template <typename TFactory> requires std::derived_from<TFactory, IDXGIFactory>
std::expected<ComPtr<TFactory>, HRESULT> GetDXGIFactoryFromDevice(ID3D12Device* device)
{
ComPtr<TFactory> foundFactory;
HRESULT hr = E_FAIL;
// Get the adapter LUID (locally unique identifier) associated with the D3D device
const LUID adapterLuid = device->GetAdapterLuid();
// Create DXGI factory for adapter enumeration
ComPtr<IDXGIFactory4> enumFactory;
if (FAILED(hr = CreateDXGIFactory1(IID_PPV_ARGS(&enumFactory)))) return std::unexpected(hr);
// Enumerate DXGI adapters to find adapter with the matching LUID
for (UINT adapterIndex = 0u; ; ++adapterIndex)
{
ComPtr<IDXGIAdapter1> adapter1;
if (FAILED(hr = enumFactory->EnumAdapters1(adapterIndex, &adapter1)))
{
if (hr == DXGI_ERROR_NOT_FOUND) break; // No more adapters to enumerate
return std::unexpected(hr); // Error
}
DXGI_ADAPTER_DESC1 desc;
if (FAILED(hr = adapter1->GetDesc1(&desc))) return std::unexpected(hr);
if (desc.AdapterLuid.LowPart == adapterLuid.LowPart &&
desc.AdapterLuid.HighPart == adapterLuid.HighPart)
{
// Found the matching adapter.
// Get the DXGI interface from the adapter
if (FAILED(hr = adapter1->GetParent(IID_PPV_ARGS(&foundFactory)))) return std::unexpected(hr);
break;
}
}
return foundFactory;
}
允许查询DXGI工厂的不同接口版本,并提供基本的错误处理。
当然也可以改成只从设备中获取DXGI适配器
- C++嵌套if语句,基本货币交换
- shell排序中的交换和比较
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 通过交换元素使数组相同
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- 交换运算符 + 重载会导致无限递归
- 为什么 std::reduce 需要交换性?
- 复制和交换习惯用法与移动操作之间的交互
- C++ - 没有自定义交换功能的移动分配运算符?
- 如何在数组中交换最小和最大的位置?
- 尽管一切看起来都很好,但值不会交换
- C++交换来自同一类成员的参数值,处理多个类
- 插入排序的最小交换
- C++在 2 个向量向量之间交换向量
- 转置矩阵:交换元素不会更改值
- 不正确的比较和交换计数器输出用于快速排序功能
- 交换函数不是在 C++ 中交换 2D 数组的元素
- std::vector move 而不是交换到空 vector 并释放存储
- 否,除了交换和移动具有互斥锁的类
- 为什么为设备和交换链使用相同的IDXGIFactory ?