rhi: Expose device name, type, and IDs

...to the extent it is sensible. We have to make compromises still,
meaning some fields will only be applicable with certain APIs.

Most of this is already shown upon QRhi::create() as info debug
prints, when enabled. Now expose it all through the QRhi API as
well.

This is useful for printing in qtdiag, and, while it should be
avoided as much as possible, to make decisions about disabling
3D rendering features depending on the driver and GPU in use.

Change-Id: Iebe1e192965c928b82a094d1c7c50ddf4b38b9a2
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
bb10
Laszlo Agocs 2021-01-12 13:02:13 +01:00
parent 04f11f9935
commit 042cd97884
14 changed files with 225 additions and 2 deletions

View File

@ -4735,6 +4735,100 @@ QRhi::Implementation QRhi::backend() const
return d->implType;
}
/*!
\return the backend type as string for this QRhi.
*/
const char *QRhi::backendName() const
{
switch (d->implType) {
case QRhi::Null:
return "Null";
case QRhi::Vulkan:
return "Vulkan";
case QRhi::OpenGLES2:
return "OpenGL";
case QRhi::D3D11:
return "D3D11";
case QRhi::Metal:
return "Metal";
default:
return "Unknown";
}
}
/*!
\enum QRhiDriverInfo::DeviceType
Specifies the graphics device's type, when the information is available. In
practice this is only applicable with Vulkan and Metal. With others the
value will always be UnknownDevice.
\value UnknownDevice
\value IntegratedDevice
\value DiscreteDevice
\value ExternalDevice
\value VirtualDevice
\value CpuDevice
*/
/*!
\struct QRhiDriverInfo
\internal
\inmodule QtGui
\since 6.1
\brief Describes the physical device, adapter, or graphics API
implementation that is used by an initialized QRhi.
Graphics APIs offer different levels and kinds of information. The only
value that is available across all APIs is the deviceName, which is a
freetext description of the physical device, adapter, or is a combination
of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
\c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
Direct 3D.
*/
#ifndef QT_NO_DEBUG_STREAM
static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
{
switch (type) {
case QRhiDriverInfo::UnknownDevice:
return "Unknown";
case QRhiDriverInfo::IntegratedDevice:
return "Integrated";
case QRhiDriverInfo::DiscreteDevice:
return "Discrete";
case QRhiDriverInfo::ExternalDevice:
return "External";
case QRhiDriverInfo::VirtualDevice:
return "Virtual";
case QRhiDriverInfo::CpuDevice:
return "Cpu";
default:
return "";
}
}
QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
<< " deviceId=0x" << Qt::hex << info.deviceId
<< " vendorId=0x" << info.vendorId
<< " deviceType=" << deviceTypeStr(info.deviceType)
<< ')';
return dbg;
}
#endif
/*!
\return metadata for the graphics device used by this successfully
initialized QRhi instance.
*/
QRhiDriverInfo QRhi::driverInfo() const
{
return d->driverInfo();
}
/*!
\return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
*/

View File

@ -1443,6 +1443,29 @@ private:
friend class QRhi;
};
struct Q_GUI_EXPORT QRhiDriverInfo
{
enum DeviceType {
UnknownDevice,
IntegratedDevice,
DiscreteDevice,
ExternalDevice,
VirtualDevice,
CpuDevice
};
QByteArray deviceName;
quint64 deviceId = 0;
quint64 vendorId = 0;
DeviceType deviceType = UnknownDevice;
};
Q_DECLARE_TYPEINFO(QRhiDriverInfo, Q_RELOCATABLE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDriverInfo &);
#endif
struct Q_GUI_EXPORT QRhiInitParams
{
};
@ -1530,6 +1553,8 @@ public:
QRhiNativeHandles *importDevice = nullptr);
Implementation backend() const;
const char *backendName() const;
QRhiDriverInfo driverInfo() const;
QThread *thread() const;
using CleanupCallback = std::function<void(QRhi *)>;

View File

@ -162,6 +162,7 @@ public:
virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
virtual const QRhiNativeHandles *nativeHandles() = 0;
virtual QRhiDriverInfo driverInfo() const = 0;
virtual void sendVMemStatsToProfiler() = 0;
virtual bool makeThreadLocalNativeContextCurrent() = 0;
virtual void releaseCachedResources() = 0;

View File

@ -220,7 +220,6 @@ bool QRhiD3D11::create(QRhi::Flags flags)
hasDxgi2 ? "true" : "false", supportsFlipDiscardSwapchain ? "true" : "false");
if (!importedDeviceAndContext) {
IDXGIAdapter1 *adapterToUse = nullptr;
IDXGIAdapter1 *adapter;
int requestedAdapterIndex = -1;
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
@ -253,6 +252,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
}
}
IDXGIAdapter1 *adapterToUse = nullptr;
for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
@ -266,6 +266,9 @@ bool QRhiD3D11::create(QRhi::Flags flags)
if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
adapterToUse = adapter;
adapterLuid = desc.AdapterLuid;
driverInfoStruct.deviceName = name.toUtf8();
driverInfoStruct.deviceId = desc.DeviceId;
driverInfoStruct.vendorId = desc.VendorId;
qCDebug(QRHI_LOG_INFO, " using this adapter");
} else {
adapter->Release();
@ -323,6 +326,9 @@ bool QRhiD3D11::create(QRhi::Flags flags)
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
adapterLuid = desc.AdapterLuid;
driverInfoStruct.deviceName = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description)).toUtf8();
driverInfoStruct.deviceId = desc.DeviceId;
driverInfoStruct.vendorId = desc.VendorId;
adapter->Release();
}
dxgiDev->Release();
@ -575,6 +581,11 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles()
return &nativeHandlesStruct;
}
QRhiDriverInfo QRhiD3D11::driverInfo() const
{
return driverInfoStruct;
}
void QRhiD3D11::sendVMemStatsToProfiler()
{
// nothing to do here

View File

@ -671,6 +671,7 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
QRhiDriverInfo driverInfo() const override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
@ -704,6 +705,7 @@ public:
bool supportsFlipDiscardSwapchain = false;
bool deviceLost = false;
QRhiD3D11NativeHandles nativeHandlesStruct;
QRhiDriverInfo driverInfoStruct;
struct {
int vsHighestActiveVertexBufferBinding = -1;

View File

@ -461,6 +461,17 @@ bool QRhiGles2::create(QRhi::Flags flags)
if (vendor && renderer && version)
qCDebug(QRHI_LOG_INFO, "OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
if (vendor) {
driverInfoStruct.deviceName += QByteArray(vendor);
driverInfoStruct.deviceName += ' ';
}
if (renderer) {
driverInfoStruct.deviceName += QByteArray(renderer);
driverInfoStruct.deviceName += ' ';
}
if (version)
driverInfoStruct.deviceName += QByteArray(version);
const QSurfaceFormat actualFormat = ctx->format();
caps.ctxMajor = actualFormat.majorVersion();
@ -990,6 +1001,11 @@ const QRhiNativeHandles *QRhiGles2::nativeHandles()
return &nativeHandlesStruct;
}
QRhiDriverInfo QRhiGles2::driverInfo() const
{
return driverInfoStruct;
}
void QRhiGles2::sendVMemStatsToProfiler()
{
// nothing to do here

View File

@ -807,6 +807,7 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
QRhiDriverInfo driverInfo() const override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
@ -957,6 +958,7 @@ public:
QList<GLint> supportedCompressedFormats;
mutable QList<int> supportedSampleCountList;
QRhiGles2NativeHandles nativeHandlesStruct;
QRhiDriverInfo driverInfoStruct;
mutable bool contextLost = false;
struct DeferredReleaseEntry {

View File

@ -372,7 +372,30 @@ bool QRhiMetal::create(QRhi::Flags flags)
return false;
}
qCDebug(QRHI_LOG_INFO, "Metal device: %s", qPrintable(QString::fromNSString([d->dev name])));
const QString deviceName = QString::fromNSString([d->dev name]);
qCDebug(QRHI_LOG_INFO, "Metal device: %s", qPrintable(deviceName));
driverInfoStruct.deviceName = deviceName.toUtf8();
driverInfoStruct.deviceId = [d->dev registryID];
#ifdef Q_OS_IOS
driverInfoStruct.deviceType = QRhiDriverInfo::IntegratedDevice;
#else
if (@available(macOS 10.15, *)) {
const MTLDeviceLocation deviceLocation = [d->dev location];
switch (deviceLocation) {
case MTLDeviceLocationBuiltIn:
driverInfoStruct.deviceType = QRhiDriverInfo::IntegratedDevice;
break;
case MTLDeviceLocationSlot:
driverInfoStruct.deviceType = QRhiDriverInfo::DiscreteDevice;
break;
case MTLDeviceLocationExternal:
driverInfoStruct.deviceType = QRhiDriverInfo::ExternalDevice;
break;
default:
break;
}
}
#endif
if (importedCmdQueue)
[d->cmdQueue retain];
@ -615,6 +638,11 @@ const QRhiNativeHandles *QRhiMetal::nativeHandles()
return &nativeHandlesStruct;
}
QRhiDriverInfo QRhiMetal::driverInfo() const
{
return driverInfoStruct;
}
void QRhiMetal::sendVMemStatsToProfiler()
{
// nothing to do here

View File

@ -435,6 +435,7 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
QRhiDriverInfo driverInfo() const override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
@ -463,6 +464,7 @@ public:
QMetalSwapChain *currentSwapChain = nullptr;
QSet<QMetalSwapChain *> swapchains;
QRhiMetalNativeHandles nativeHandlesStruct;
QRhiDriverInfo driverInfoStruct;
struct {
int maxTextureSize = 4096;

View File

@ -170,6 +170,13 @@ const QRhiNativeHandles *QRhiNull::nativeHandles()
return &nativeHandlesStruct;
}
QRhiDriverInfo QRhiNull::driverInfo() const
{
QRhiDriverInfo info;
info.deviceName = QByteArrayLiteral("Null");
return info;
}
void QRhiNull::sendVMemStatsToProfiler()
{
// nothing to do here

View File

@ -292,6 +292,7 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
QRhiDriverInfo driverInfo() const override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;

View File

@ -361,6 +361,24 @@ static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTyp
return false;
}
static inline QRhiDriverInfo::DeviceType toRhiDeviceType(VkPhysicalDeviceType type)
{
switch (type) {
case VK_PHYSICAL_DEVICE_TYPE_OTHER:
return QRhiDriverInfo::UnknownDevice;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return QRhiDriverInfo::IntegratedDevice;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return QRhiDriverInfo::DiscreteDevice;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
return QRhiDriverInfo::VirtualDevice;
case VK_PHYSICAL_DEVICE_TYPE_CPU:
return QRhiDriverInfo::CpuDevice;
default:
return QRhiDriverInfo::UnknownDevice;
}
}
bool QRhiVulkan::create(QRhi::Flags flags)
{
Q_UNUSED(flags);
@ -454,6 +472,11 @@ bool QRhiVulkan::create(QRhi::Flags flags)
physDevProperties.deviceType);
}
driverInfoStruct.deviceName = QByteArray(physDevProperties.deviceName);
driverInfoStruct.deviceId = physDevProperties.deviceID;
driverInfoStruct.vendorId = physDevProperties.vendorID;
driverInfoStruct.deviceType = toRhiDeviceType(physDevProperties.deviceType);
f->vkGetPhysicalDeviceFeatures(physDev, &physDevFeatures);
// Choose queue and create device, unless the device was specified in importParams.
@ -4224,6 +4247,11 @@ const QRhiNativeHandles *QRhiVulkan::nativeHandles()
return &nativeHandlesStruct;
}
QRhiDriverInfo QRhiVulkan::driverInfo() const
{
return driverInfoStruct;
}
void QRhiVulkan::sendVMemStatsToProfiler()
{
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();

View File

@ -750,6 +750,7 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
QRhiDriverInfo driverInfo() const override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
@ -889,6 +890,7 @@ public:
QVkSwapChain *currentSwapChain = nullptr;
QSet<QVkSwapChain *> swapchains;
QRhiVulkanNativeHandles nativeHandlesStruct;
QRhiDriverInfo driverInfoStruct;
struct OffscreenFrame {
OffscreenFrame(QRhiImplementation *rhi)

View File

@ -228,7 +228,11 @@ void tst_QRhi::create()
QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
if (rhi) {
qDebug() << rhi->driverInfo();
QCOMPARE(rhi->backend(), impl);
QVERIFY(strcmp(rhi->backendName(), ""));
QVERIFY(!rhi->driverInfo().deviceName.isEmpty());
QCOMPARE(rhi->thread(), QThread::currentThread());
// do a basic smoke test for the apis that do not directly render anything