Refactor D3D device creation to make adapter selection explicit

To prepare for future changes which require that angle features
be parsed before device creation, we must rearrange device
creation such that driver version can be retrieved from the
adapter BEFORE the device gets created.

Bug: angleproject:8180
Change-Id: I08855b9df318d0a6234231f1e52d3c17cfaa8a30
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4575653
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
This commit is contained in:
Rafael Cintron 2023-05-30 17:01:10 -07:00 коммит произвёл Angle LUCI CQ
Родитель 31aa3fa5da
Коммит 4500079d34
2 изменённых файлов: 124 добавлений и 84 удалений

Просмотреть файл

@ -440,7 +440,6 @@ Renderer11::Renderer11(egl::Display *display)
mD3d11Module = nullptr;
mD3d12Module = nullptr;
mDxgiModule = nullptr;
mDCompModule = nullptr;
mCreatedWithDeviceEXT = false;
@ -542,6 +541,7 @@ egl::Error Renderer11::initialize()
{
HRESULT result = S_OK;
ANGLE_TRY(initializeDXGIAdapter());
ANGLE_TRY(initializeD3DDevice());
#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
@ -587,22 +587,6 @@ egl::Error Renderer11::initialize()
mDeviceContext.As(&mDeviceContext1);
mDeviceContext.As(&mDeviceContext3);
angle::ComPtr<IDXGIDevice> dxgiDevice;
result = mDevice.As(&dxgiDevice);
if (FAILED(result))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
}
result = dxgiDevice->GetParent(IID_PPV_ARGS(&mDxgiAdapter));
if (FAILED(result))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
<< "Could not retrieve DXGI adapter";
}
angle::ComPtr<IDXGIAdapter2> dxgiAdapter2;
mDxgiAdapter.As(&dxgiAdapter2);
@ -688,23 +672,72 @@ egl::Error Renderer11::initialize()
HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
{
angle::ComPtr<IDXGIAdapter> adapter;
// If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or
// D3D11CreateDevice will return E_INVALIDARG.
return createDevice(
mDxgiAdapter.Get(), mDxgiAdapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr,
debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
&(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
}
const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
// Check EGL_ANGLE_platform_angle_d3d_luid
long high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0));
unsigned long low =
static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0));
// Check EGL_ANGLE_platform_angle_device_id
if (high == 0 && low == 0)
egl::Error Renderer11::initializeDXGIAdapter()
{
if (mCreatedWithDeviceEXT)
{
high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0));
low = static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0));
ASSERT(mRequestedDriverType == D3D_DRIVER_TYPE_UNKNOWN);
DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice());
ASSERT(deviceD3D != nullptr);
// We should use the inputted D3D11 device instead
void *device = nullptr;
ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device));
ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device);
if (FAILED(d3dDevice->GetDeviceRemovedReason()))
{
return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
}
if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
{
return egl::EglNotInitialized()
<< "Inputted D3D11 device must be Feature Level 9_3 or greater.";
}
// The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
mDevice = d3dDevice;
mDevice->GetImmediateContext(&mDeviceContext);
mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
return initializeAdapterFromDevice();
}
if (high != 0 || low != 0)
else
{
angle::ComPtr<IDXGIFactory1> factory;
if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
if (FAILED(hr))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
<< "Could not create DXGI factory";
}
// If the developer requests a specific adapter, honor their request regardless of the value
// of EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE.
const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
// Check EGL_ANGLE_platform_angle_d3d_luid
long high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0));
unsigned long low =
static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0));
// Check EGL_ANGLE_platform_angle_device_id
if (high == 0 && low == 0)
{
high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0));
low = static_cast<unsigned long>(
attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0));
}
if (high != 0 || low != 0)
{
angle::ComPtr<IDXGIAdapter> temp;
for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++)
@ -715,7 +748,7 @@ HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice,
// EGL_ANGLE_platform_angle_d3d_luid
if (desc.AdapterLuid.HighPart == high && desc.AdapterLuid.LowPart == low)
{
adapter = temp;
mDxgiAdapter = std::move(temp);
break;
}
@ -726,49 +759,82 @@ HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice,
if ((high == 0 || desc.VendorId == static_cast<UINT>(high)) &&
(low == 0 || desc.DeviceId == static_cast<UINT>(low)))
{
adapter = temp;
mDxgiAdapter = std::move(temp);
break;
}
}
}
}
// For requested driver types besides Hardware such as Warp, Reference, or Null
// allow D3D11CreateDevice to pick the adapter by passing it the driver type.
if (!mDxgiAdapter && mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE)
{
hr = factory->EnumAdapters(0, &mDxgiAdapter);
if (FAILED(hr))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
<< "Could not retrieve DXGI adapter";
}
}
}
return egl::NoError();
}
egl::Error Renderer11::initializeAdapterFromDevice()
{
ASSERT(mDevice);
ASSERT(!mDxgiAdapter);
angle::ComPtr<IDXGIDevice> dxgiDevice;
HRESULT result = mDevice.As(&dxgiDevice);
if (FAILED(result))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
}
// If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or
// D3D11CreateDevice will return E_INVALIDARG.
return createDevice(
adapter.Get(), adapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr,
debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
&(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
result = dxgiDevice->GetParent(IID_PPV_ARGS(&mDxgiAdapter));
if (FAILED(result))
{
return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not retrieve DXGI adapter";
}
return egl::NoError();
}
HRESULT Renderer11::callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12,
PFN_D3D11ON12_CREATE_DEVICE createDevice11on12,
bool debug)
{
angle::ComPtr<IDXGIFactory4> factory;
HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
if (FAILED(result))
HRESULT result = S_OK;
if (mDxgiAdapter)
{
return result;
// Passing nullptr into pAdapter chooses the default adapter which will be the hardware
// adapter if it exists.
result = createDevice12(mDxgiAdapter.Get(), mAvailableFeatureLevels[0],
IID_PPV_ARGS(&mDevice12));
}
if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
else if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
{
angle::ComPtr<IDXGIAdapter> warpAdapter;
result = factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter));
angle::ComPtr<IDXGIFactory4> factory;
result = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
if (FAILED(result))
{
return result;
}
result = factory->EnumWarpAdapter(IID_PPV_ARGS(&mDxgiAdapter));
if (SUCCEEDED(result))
{
result = createDevice12(warpAdapter.Get(), mAvailableFeatureLevels[0],
result = createDevice12(mDxgiAdapter.Get(), mAvailableFeatureLevels[0],
IID_PPV_ARGS(&mDevice12));
}
}
else
{
// Passing nullptr into pAdapter chooses the default adapter which will be the hardware
// adapter if it exists.
result = createDevice12(nullptr, mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12));
ASSERT(mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE ||
mRequestedDriverType == D3D_DRIVER_TYPE_NULL);
result = E_INVALIDARG;
}
if (SUCCEEDED(result))
@ -804,7 +870,6 @@ egl::Error Renderer11::initializeD3DDevice()
PFN_D3D11ON12_CREATE_DEVICE D3D11On12CreateDevice = nullptr;
{
ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
@ -842,10 +907,10 @@ egl::Error Renderer11::initializeD3DDevice()
}
else
{
if (mD3d11Module == nullptr || mDxgiModule == nullptr)
if (mD3d11Module == nullptr)
{
return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
<< "Could not load D3D11 or DXGI library.";
<< "Could not load D3D11 library.";
}
D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
@ -935,33 +1000,13 @@ egl::Error Renderer11::initializeD3DDevice()
<< "Could not create D3D11 device.";
}
}
}
else
{
DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice());
ASSERT(deviceD3D != nullptr);
// We should use the inputted D3D11 device instead
void *device = nullptr;
ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device));
ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device);
if (FAILED(d3dDevice->GetDeviceRemovedReason()))
if (!mDxgiAdapter)
{
return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
// If the D3D11CreateDevice was asked to create the adapter via mRequestedDriverType,
// fill in the adapter here.
ANGLE_TRY(initializeAdapterFromDevice());
}
if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
{
return egl::EglNotInitialized()
<< "Inputted D3D11 device must be Feature Level 9_3 or greater.";
}
// The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
mDevice = d3dDevice;
mDevice->AddRef();
mDevice->GetImmediateContext(&mDeviceContext);
mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
}
mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
@ -2282,12 +2327,6 @@ void Renderer11::release()
mD3d11Module = nullptr;
}
if (mDxgiModule)
{
FreeLibrary(mDxgiModule);
mDxgiModule = nullptr;
}
if (mDCompModule)
{
FreeLibrary(mDCompModule);

Просмотреть файл

@ -552,8 +552,10 @@ class Renderer11 : public RendererD3D
HRESULT callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12,
PFN_D3D11ON12_CREATE_DEVICE createDevice11on12,
bool debug);
egl::Error initializeDXGIAdapter();
egl::Error initializeD3DDevice();
egl::Error initializeDevice();
egl::Error initializeAdapterFromDevice();
void releaseDeviceResources();
void release();
@ -570,7 +572,6 @@ class Renderer11 : public RendererD3D
HMODULE mD3d11Module;
HMODULE mD3d12Module;
HMODULE mDxgiModule;
HMODULE mDCompModule;
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
D3D_DRIVER_TYPE mRequestedDriverType;