summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhid3d11.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-06-24 15:59:56 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-06-26 14:42:42 +0200
commitdb61e43c81f4b5ed8c36365f63c2e2fb81e2a1e7 (patch)
tree5da4247a52a91872f53464e95c54611ca6db6349 /src/gui/rhi/qrhid3d11.cpp
parentb60f516aca5196a49e3cc53e7620c2b5da3f507c (diff)
rhi: Enable specifying just an adapter or phys dev
Required by OpenXR. A VkPhysicalDevice or an adapter LUID + feature level pair should be adoptable while leaving the rest (device, queue, etc. setup) to QRhi as normal. Change-Id: Iada0972671b037b4efb03e7831b7c9b8c5f2393d Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhid3d11.cpp')
-rw-r--r--src/gui/rhi/qrhid3d11.cpp82
1 files changed, 65 insertions, 17 deletions
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 38f2993049..6157381acb 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -84,10 +84,15 @@ QT_BEGIN_NAMESPACE
When interoperating with another graphics engine, it may be necessary to
get a QRhi instance that uses the same Direct3D device. This can be
achieved by passing a pointer to a QRhiD3D11NativeHandles to
- QRhi::create(). Both the device and the device context must be set to a
- non-null value then.
+ QRhi::create(). When the device is set to a non-null value, the device
+ context must be specified as well. QRhi does not take ownership of any of
+ the external objects.
- The QRhi does not take ownership of any of the external objects.
+ Sometimes, for example when using QRhi in combination with OpenXR, one will
+ want to specify which adapter to use, and optionally, which feature level
+ to request on the device, while leaving the device creation to QRhi. This
+ is achieved by leaving the device and context pointers set to null, while
+ specifying the adapter LUID and feature level.
\note QRhi works with immediate contexts only. Deferred contexts are not
used in any way.
@@ -117,7 +122,7 @@ QT_BEGIN_NAMESPACE
#define D3D11_1_UAV_SLOT_COUNT 64
#endif
-QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
+QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importParams)
: ofr(this),
deviceCurse(this)
{
@@ -126,22 +131,21 @@ QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *import
deviceCurse.framesToActivate = params->framesUntilKillingDeviceViaTdr;
deviceCurse.permanent = params->repeatDeviceKill;
- importedDevice = importDevice != nullptr;
- if (importedDevice) {
- dev = reinterpret_cast<ID3D11Device *>(importDevice->dev);
- if (dev) {
- ID3D11DeviceContext *ctx = reinterpret_cast<ID3D11DeviceContext *>(importDevice->context);
+ if (importParams) {
+ if (importParams->dev && importParams->context) {
+ dev = reinterpret_cast<ID3D11Device *>(importParams->dev);
+ ID3D11DeviceContext *ctx = reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
// get rid of the ref added by QueryInterface
ctx->Release();
+ importedDeviceAndContext = true;
} else {
qWarning("ID3D11DeviceContext1 not supported by context, cannot import");
- importedDevice = false;
}
- } else {
- qWarning("No ID3D11Device given, cannot import");
- importedDevice = false;
}
+ featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
+ adapterLuid.LowPart = importParams->adapterLuidLow;
+ adapterLuid.HighPart = importParams->adapterLuidHigh;
}
}
@@ -215,13 +219,28 @@ bool QRhiD3D11::create(QRhi::Flags flags)
qCDebug(QRHI_LOG_INFO, "DXGI 1.2 = %s, FLIP_DISCARD swapchain supported = %s",
hasDxgi2 ? "true" : "false", supportsFlipDiscardSwapchain ? "true" : "false");
- if (!importedDevice) {
+ if (!importedDeviceAndContext) {
IDXGIAdapter1 *adapterToUse = nullptr;
IDXGIAdapter1 *adapter;
int requestedAdapterIndex = -1;
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
+ // The importParams may specify an adapter by the luid, take that into account.
+ if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ adapter->Release();
+ if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
+ && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
+ {
+ requestedAdapterIndex = adapterIndex;
+ break;
+ }
+ }
+ }
+
if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
@@ -246,6 +265,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
desc.Flags);
if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
adapterToUse = adapter;
+ adapterLuid = desc.AdapterLuid;
qCDebug(QRHI_LOG_INFO, " using this adapter");
} else {
adapter->Release();
@@ -256,9 +276,20 @@ bool QRhiD3D11::create(QRhi::Flags flags)
return false;
}
+ // Normally we won't specify a requested feature level list,
+ // except when a level was specified in importParams.
+ QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
+ bool requestFeatureLevels = false;
+ if (featureLevel) {
+ requestFeatureLevels = true;
+ requestedFeatureLevels.append(featureLevel);
+ }
+
ID3D11DeviceContext *ctx = nullptr;
HRESULT hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
- nullptr, 0, D3D11_SDK_VERSION,
+ requestFeatureLevels ? requestedFeatureLevels.constData() : nullptr,
+ requestFeatureLevels ? requestedFeatureLevels.count() : 0,
+ D3D11_SDK_VERSION,
&dev, &featureLevel, &ctx);
// We cannot assume that D3D11_CREATE_DEVICE_DEBUG is always available. Retry without it, if needed.
if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
@@ -266,7 +297,9 @@ bool QRhiD3D11::create(QRhi::Flags flags)
"Attempting to create D3D11 device without it.");
devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
- nullptr, 0, D3D11_SDK_VERSION,
+ requestFeatureLevels ? requestedFeatureLevels.constData() : nullptr,
+ requestFeatureLevels ? requestedFeatureLevels.count() : 0,
+ D3D11_SDK_VERSION,
&dev, &featureLevel, &ctx);
}
adapterToUse->Release();
@@ -283,6 +316,18 @@ bool QRhiD3D11::create(QRhi::Flags flags)
} else {
Q_ASSERT(dev && context);
featureLevel = dev->GetFeatureLevel();
+ IDXGIDevice *dxgiDev = nullptr;
+ if (SUCCEEDED(dev->QueryInterface(IID_IDXGIDevice, reinterpret_cast<void **>(&dxgiDev)))) {
+ IDXGIAdapter *adapter = nullptr;
+ if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
+ DXGI_ADAPTER_DESC desc;
+ adapter->GetDesc(&desc);
+ adapterLuid = desc.AdapterLuid;
+ adapter->Release();
+ }
+ dxgiDev->Release();
+ }
+ qCDebug(QRHI_LOG_INFO, "Using imported device %p", dev);
}
if (FAILED(context->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&annotations))))
@@ -292,6 +337,9 @@ bool QRhiD3D11::create(QRhi::Flags flags)
nativeHandlesStruct.dev = dev;
nativeHandlesStruct.context = context;
+ nativeHandlesStruct.featureLevel = featureLevel;
+ nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
+ nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
if (deviceCurse.framesToActivate > 0)
deviceCurse.initResources();
@@ -320,7 +368,7 @@ void QRhiD3D11::destroy()
annotations = nullptr;
}
- if (!importedDevice) {
+ if (!importedDeviceAndContext) {
if (context) {
context->Release();
context = nullptr;