Merge pull request #15884 from samcake/nut

BUGZ-736 / BUGZ-914 : Improve the enumeration of the platform and profiler / apply a specific PPI per Tier
This commit is contained in:
Sam Gateau 2019-07-06 02:18:11 +02:00 committed by GitHub
commit f2cda426d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 638 additions and 138 deletions

View file

@ -10,6 +10,8 @@
//
#include "PerformanceManager.h"
#include <platform/Platform.h>
#include <platform/PlatformKeys.h>
#include <platform/Profiler.h>
#include "scripting/RenderScriptingInterface.h"
@ -65,6 +67,19 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
// Ugly case that prevent us to run deferred everywhere...
bool isDeferredCapable = platform::Profiler::isRenderMethodDeferredCapable();
auto masterDisplay = platform::getDisplay(platform::getMasterDisplay());
// eval recommanded PPI and Scale
float recommandedPpiScale = 1.0f;
const float RECOMMANDED_PPI[] = { 200.0f, 120.f, 160.f, 250.f};
if (!masterDisplay.empty() && masterDisplay.count(platform::keys::display::ppi)) {
float ppi = masterDisplay[platform::keys::display::ppi];
// only scale if the actual ppi is higher than the recommended ppi
if (ppi > RECOMMANDED_PPI[preset]) {
// make sure the scale is no less than a quarter
recommandedPpiScale = std::max(0.25f, RECOMMANDED_PPI[preset] / (float) ppi);
}
}
switch (preset) {
case PerformancePreset::HIGH:
@ -72,17 +87,21 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::RenderMethod::DEFERRED :
RenderScriptingInterface::RenderMethod::FORWARD ) );
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
RenderScriptingInterface::getInstance()->setShadowsEnabled(true);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.5f);
break;
case PerformancePreset::MID:
RenderScriptingInterface::getInstance()->setRenderMethod((isDeferredCapable ?
RenderScriptingInterface::RenderMethod::DEFERRED :
RenderScriptingInterface::RenderMethod::FORWARD));
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
RenderScriptingInterface::getInstance()->setShadowsEnabled(false);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::INTERACTIVE);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.5f);
@ -93,6 +112,8 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setShadowsEnabled(false);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::ECO);
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
break;

View file

@ -167,7 +167,9 @@ bool PlatformInfoScriptingInterface::isStandalone() {
int PlatformInfoScriptingInterface::getNumCPUs() {
return platform::getNumCPUs();
}
int PlatformInfoScriptingInterface::getMasterCPU() {
return platform::getMasterCPU();
}
QString PlatformInfoScriptingInterface::getCPU(int index) {
auto desc = platform::getCPU(index);
return QString(desc.dump().c_str());
@ -176,7 +178,9 @@ QString PlatformInfoScriptingInterface::getCPU(int index) {
int PlatformInfoScriptingInterface::getNumGPUs() {
return platform::getNumGPUs();
}
int PlatformInfoScriptingInterface::getMasterGPU() {
return platform::getMasterGPU();
}
QString PlatformInfoScriptingInterface::getGPU(int index) {
auto desc = platform::getGPU(index);
return QString(desc.dump().c_str());
@ -185,7 +189,9 @@ QString PlatformInfoScriptingInterface::getGPU(int index) {
int PlatformInfoScriptingInterface::getNumDisplays() {
return platform::getNumDisplays();
}
int PlatformInfoScriptingInterface::getMasterDisplay() {
return platform::getMasterDisplay();
}
QString PlatformInfoScriptingInterface::getDisplay(int index) {
auto desc = platform::getDisplay(index);
return QString(desc.dump().c_str());

View file

@ -94,8 +94,8 @@ public slots:
* @returns {string} The graphics card type.
* @deprecated This function is deprecated and will be removed.
* use getNumGPUs() to know the number of GPUs in the hardware, at least one is expected
* use getGPU(0)["vendor"] to get the brand of the vendor
* use getGPU(0)["model"] to get the model name of the gpu
* use getGPU(getMasterGPU())["vendor"] to get the brand of the vendor
* use getGPU(getMasterGPU())["model"] to get the model name of the gpu
*/
QString getGraphicsCardType();
@ -135,6 +135,13 @@ public slots:
*/
int getNumCPUs();
/**jsdoc
* Get the index of the master CPU.
* @function PlatformInfo.getMasterCPU
* @returns {number} The index of the master CPU detected on the hardware platform.
*/
int getMasterCPU();
/**jsdoc
* Get the description of the CPU at the index parameter
* expected fields are:
@ -152,6 +159,13 @@ public slots:
*/
int getNumGPUs();
/**jsdoc
* Get the index of the master GPU.
* @function PlatformInfo.getMasterGPU
* @returns {number} The index of the master GPU detected on the hardware platform.
*/
int getMasterGPU();
/**jsdoc
* Get the description of the GPU at the index parameter
* expected fields are:
@ -169,6 +183,13 @@ public slots:
*/
int getNumDisplays();
/**jsdoc
* Get the index of the master Display.
* @function PlatformInfo.getMasterDisplay
* @returns {number} The index of the master Display detected on the hardware platform.
*/
int getMasterDisplay();
/**jsdoc
* Get the description of the Display at the index parameter
* expected fields are:

View file

@ -21,12 +21,15 @@ bool enumeratePlatform();
int getNumCPUs();
json getCPU(int index);
int getMasterCPU();
int getNumGPUs();
json getGPU(int index);
int getMasterGPU();
int getNumDisplays();
json getDisplay(int index);
int getMasterDisplay();
json getMemory();

View file

@ -20,6 +20,7 @@ namespace platform { namespace keys{
extern const char* model;
extern const char* clockSpeed;
extern const char* numCores;
extern const char* isMaster;
}
namespace gpu {
extern const char* vendor;
@ -30,6 +31,8 @@ namespace platform { namespace keys{
extern const char* model;
extern const char* videoMemory;
extern const char* driver;
extern const char* displays;
extern const char* isMaster;
}
namespace nic {
extern const char* mac;
@ -38,10 +41,19 @@ namespace platform { namespace keys{
namespace display {
extern const char* description;
extern const char* name;
extern const char* coordsLeft;
extern const char* coordsRight;
extern const char* coordsTop;
extern const char* coordsBottom;
extern const char* boundsLeft;
extern const char* boundsRight;
extern const char* boundsTop;
extern const char* boundsBottom;
extern const char* gpu;
extern const char* ppi;
extern const char* ppiDesktop;
extern const char* physicalWidth;
extern const char* physicalHeight;
extern const char* modeRefreshrate;
extern const char* modeWidth;
extern const char* modeHeight;
extern const char* isMaster;
}
namespace memory {
extern const char* memTotal;

View file

@ -32,9 +32,9 @@ Profiler::Tier Profiler::profilePlatform() {
return platformTier;
}
// Not filtered yet, let s try to make sense of the cpu and gpu info
auto cpuInfo = platform::getCPU(0);
auto gpuInfo = platform::getGPU(0);
// Not filtered yet, let s try to make sense of the master cpu and master gpu info
auto cpuInfo = platform::getCPU(platform::getMasterCPU());
auto gpuInfo = platform::getGPU(platform::getMasterGPU());
if (filterOnProcessors(computerInfo, cpuInfo, gpuInfo, platformTier)) {
return platformTier;
}
@ -133,10 +133,12 @@ bool filterOnProcessors(const platform::json& computer, const platform::json& cp
// YES on macos EXCEPT for macbookair with gpu intel iris or intel HD 6000
bool Profiler::isRenderMethodDeferredCapable() {
#if defined(Q_OS_MAC)
// Deferred works correctly on every supported macos platform at the moment, let s enable it
/*
auto computer = platform::getComputer();
const auto computerModel = (computer.count(keys::computer::model) ? computer[keys::computer::model].get<std::string>() : "");
auto gpuInfo = platform::getGPU(0);
auto gpuInfo = platform::getGPU(getMasterGPU());
const auto gpuModel = (gpuInfo.count(keys::gpu::model) ? gpuInfo[keys::gpu::model].get<std::string>() : "");
@ -154,7 +156,7 @@ bool Profiler::isRenderMethodDeferredCapable() {
if ((gpuModel.find("Intel ") != std::string::npos)) {
return false;
}
*/
return true;
#elif defined(Q_OS_ANDROID)
return false;

View file

@ -10,6 +10,7 @@
#include "../PlatformKeys.h"
#include <GPUIdent.h>
#include <QSysInfo>
#include <QtCore/QtGlobal>
using namespace platform;
@ -23,7 +24,7 @@ void AndroidInstance::enumerateCpus() {
_cpus.push_back(cpu);
}
void AndroidInstance::enumerateGpus() {
void AndroidInstance::enumerateGpusAndDisplays() {
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();

View file

@ -16,7 +16,7 @@ namespace platform {
public:
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateGpusAndDisplays() override;
void enumerateMemory() override;
void enumerateComputer() override;
};

View file

@ -12,6 +12,9 @@
#include <thread>
#include <string>
#include <CPUIdent.h>
#include <QtCore/QtGlobal>
#include <GPUIdent.h>
#include <QSysInfo>
@ -27,7 +30,7 @@ void LinuxInstance::enumerateCpus() {
_cpus.push_back(cpu);
}
void LinuxInstance::enumerateGpus() {
void LinuxInstance::enumerateGpusAndDisplays() {
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();

View file

@ -16,7 +16,7 @@ namespace platform {
public:
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateGpusAndDisplays() override;
void enumerateMemory() override;
void enumerateComputer() override;
};

View file

@ -12,16 +12,22 @@
#include <thread>
#include <string>
#include <CPUIdent.h>
#include <GPUIdent.h>
#include <QtCore/QtGlobal>
#ifdef Q_OS_MAC
#include <unistd.h>
#include <cpuid.h>
#include <sys/sysctl.h>
#include <sstream>
#include <regex>
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include <QSysInfo>
#include <QString>
#include <OpenGL/OpenGL.h>
#endif
using namespace platform;
@ -36,73 +42,249 @@ void MACOSInstance::enumerateCpus() {
_cpus.push_back(cpu);
}
void MACOSInstance::enumerateGpus() {
void MACOSInstance::enumerateGpusAndDisplays() {
#ifdef Q_OS_MAC
// ennumerate the displays first
std::vector<GLuint> displayMasks;
{
uint32_t numDisplays = 0;
CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays);
if (numDisplays <= 0 || error != kCGErrorSuccess) {
return;
}
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
std::vector<CGDirectDisplayID> onlineDisplayIDs(numDisplays, 0);
error = CGGetOnlineDisplayList(onlineDisplayIDs.size(), onlineDisplayIDs.data(), &numDisplays);
if (error != kCGErrorSuccess) {
return;
}
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
gpu[keys::gpu::videoMemory] = ident->getMemory();
gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
_gpus.push_back(gpu);
for (auto displayID : onlineDisplayIDs) {
auto displaySize = CGDisplayScreenSize(displayID);
const auto MM_TO_IN = 0.0393701f;
auto displaySizeWidthInches = displaySize.width * MM_TO_IN;
auto displaySizeHeightInches = displaySize.height * MM_TO_IN;
auto displayBounds = CGDisplayBounds(displayID);
auto displayMaster =CGDisplayIsMain(displayID);
auto displayUnit =CGDisplayUnitNumber(displayID);
auto displayModel =CGDisplayModelNumber(displayID);
auto displayVendor = CGDisplayVendorNumber(displayID);
auto displaySerial = CGDisplaySerialNumber(displayID);
auto displayMode = CGDisplayCopyDisplayMode(displayID);
auto displayModeWidth = CGDisplayModeGetPixelWidth(displayMode);
auto displayModeHeight = CGDisplayModeGetPixelHeight(displayMode);
auto displayRefreshrate = CGDisplayModeGetRefreshRate(displayMode);
auto ppiH = displayModeWidth / displaySizeWidthInches;
auto ppiV = displayModeHeight / displaySizeHeightInches;
auto ppiHScaled = displayBounds.size.width / displaySizeWidthInches;
auto ppiVScaled = displayBounds.size.height / displaySizeHeightInches;
auto glmask = CGDisplayIDToOpenGLDisplayMask(displayID);
// Metal device ID is the recommended new way but requires objective c
// auto displayDevice = CGDirectDisplayCopyCurrentMetalDevice(displayID);
CGDisplayModeRelease(displayMode);
json display = {};
// Rect region of the desktop in desktop units
display[keys::display::boundsLeft] = displayBounds.origin.x;
display[keys::display::boundsRight] = displayBounds.origin.x + displayBounds.size.width;
display[keys::display::boundsTop] = displayBounds.origin.y;
display[keys::display::boundsBottom] = displayBounds.origin.y + displayBounds.size.height;
// PPI & resolution
display[keys::display::physicalWidth] = displaySizeWidthInches;
display[keys::display::physicalHeight] = displaySizeHeightInches;
display[keys::display::modeWidth] = displayModeWidth;
display[keys::display::modeHeight] = displayModeHeight;
//Average the ppiH and V for the simple ppi
display[keys::display::ppi] = std::round(0.5f * (ppiH + ppiV));
display[keys::display::ppiDesktop] = std::round(0.5f * (ppiHScaled + ppiVScaled));
// refreshrate
display[keys::display::modeRefreshrate] = displayRefreshrate;
// Master display ?
display[keys::display::isMaster] = (displayMaster ? true : false);
// Macos specific
display["macos_unit"] = displayUnit;
display["macos_vendor"] = displayVendor;
display["macos_model"] = displayModel;
display["macos_serial"] = displaySerial;
display["macos_glmask"] = glmask;
displayMasks.push_back(glmask);
_displays.push_back(display);
}
}
#endif
// Collect Renderer info as exposed by the CGL layers
GLuint cglDisplayMask = -1; // Iterate over all of them.
CGLRendererInfoObj rendererInfo;
GLint rendererInfoCount;
CGLError error = CGLQueryRendererInfo(cglDisplayMask, &rendererInfo, &rendererInfoCount);
if (rendererInfoCount <= 0 || 0 != error) {
return;
}
// Iterate over all of the renderers and use the figure for the one with the most VRAM,
// on the assumption that this is the one that will actually be used.
for (GLint i = 0; i < rendererInfoCount; i++) {
struct CGLRendererDesc {
int rendererID{0};
int deviceVRAM{0};
int accelerated{0};
int displayMask{0};
} desc;
CGLDescribeRenderer(rendererInfo, i, kCGLRPRendererID, &desc.rendererID);
CGLDescribeRenderer(rendererInfo, i, kCGLRPVideoMemoryMegabytes, &desc.deviceVRAM);
CGLDescribeRenderer(rendererInfo, i, kCGLRPDisplayMask, &desc.displayMask);
CGLDescribeRenderer(rendererInfo, i, kCGLRPAccelerated, &desc.accelerated);
// If this renderer is not hw accelerated then just skip it in the enumeration
if (!desc.accelerated) {
continue;
}
// From the rendererID identify the vendorID
// https://github.com/apitrace/apitrace/blob/master/retrace/glws_cocoa.mm
GLint vendorID = desc.rendererID & kCGLRendererIDMatchingMask & ~0xfff;
const GLint VENDOR_ID_SOFTWARE { 0x00020000 };
const GLint VENDOR_ID_AMD { 0x00021000 };
const GLint VENDOR_ID_NVIDIA { 0x00022000 };
const GLint VENDOR_ID_INTEL { 0x00024000 };
const char* vendorName;
switch (vendorID) {
case VENDOR_ID_SOFTWARE:
// Software renderer then skip it (should already have been caught by hwaccelerated test abve
continue;
break;
case VENDOR_ID_AMD:
vendorName = keys::gpu::vendor_AMD;
break;
case VENDOR_ID_NVIDIA:
vendorName = keys::gpu::vendor_NVIDIA;
break;
case VENDOR_ID_INTEL:
vendorName = keys::gpu::vendor_Intel;
break;
default:
vendorName = keys::UNKNOWN;
break;
}
//once we reach this point, the renderer is legit
// Start defining the gpu json
json gpu = {};
gpu[keys::gpu::vendor] = vendorName;
gpu[keys::gpu::videoMemory] = desc.deviceVRAM;
gpu["macos_rendererID"] = desc.rendererID;
gpu["macos_displayMask"] = desc.displayMask;
std::vector<int> displayIndices;
for (int d = 0; d < (int) displayMasks.size(); d++) {
if (desc.displayMask & displayMasks[d]) {
displayIndices.push_back(d);
_displays[d][keys::display::gpu] = _gpus.size();
}
}
gpu[keys::gpu::displays] = displayIndices;
_gpus.push_back(gpu);
}
CGLDestroyRendererInfo(rendererInfo);
{ //get gpu information from the system profiler that we don't know how to retreive otherwise
struct ChipsetModelDesc {
std::string model;
std::string vendor;
int deviceID{0};
int videoMemory{0};
};
std::vector<ChipsetModelDesc> chipsetDescs;
FILE* stream = popen("system_profiler SPDisplaysDataType | grep -e Chipset -e VRAM -e Vendor -e \"Device ID\"", "r");
std::ostringstream hostStream;
while (!feof(stream) && !ferror(stream)) {
char buf[128];
int bytesRead = fread(buf, 1, 128, stream);
hostStream.write(buf, bytesRead);
}
std::string gpuArrayDesc = hostStream.str();
// Find the Chipset model first
const std::regex chipsetModelToken("(Chipset Model: )(.*)");
std::smatch found;
while (std::regex_search(gpuArrayDesc, found, chipsetModelToken)) {
ChipsetModelDesc desc;
}
void MACOSInstance::enumerateDisplays() {
#ifdef Q_OS_MAC
auto displayID = CGMainDisplayID();
auto displaySize = CGDisplayScreenSize(displayID);
const auto MM_TO_IN = 0.0393701;
auto displaySizeWidthInches = displaySize.width * MM_TO_IN;
auto displaySizeHeightInches = displaySize.height * MM_TO_IN;
auto displaySizeDiagonalInches = sqrt(displaySizeWidthInches * displaySizeWidthInches + displaySizeHeightInches * displaySizeHeightInches);
desc.model = found.str(2);
// Find the end of the gpu block
gpuArrayDesc = found.suffix();
std::string gpuDesc = gpuArrayDesc;
const std::regex endGpuToken("Chipset Model: ");
if (std::regex_search(gpuArrayDesc, found, endGpuToken)) {
gpuDesc = found.prefix();
}
// Find the vendor
desc.vendor = findGPUVendorInDescription(desc.model);
// Find the memory amount in MB
const std::regex memoryToken("(VRAM .*: )(.*)");
if (std::regex_search(gpuDesc, found, memoryToken)) {
auto memAmountUnit = found.str(2);
std::smatch amount;
const std::regex memAmountGBToken("(\\d*) GB");
const std::regex memAmountMBToken("(\\d*) MB");
const int GB_TO_MB { 1024 };
if (std::regex_search(memAmountUnit, amount, memAmountGBToken)) {
desc.videoMemory = std::stoi(amount.str(1)) * GB_TO_MB;
} else if (std::regex_search(memAmountUnit, amount, memAmountMBToken)) {
desc.videoMemory = std::stoi(amount.str(1));
} else {
desc.videoMemory = std::stoi(memAmountUnit);
}
}
// Find the Device ID
const std::regex deviceIDToken("(Device ID: )(.*)");
if (std::regex_search(gpuDesc, found, deviceIDToken)) {
desc.deviceID = std::stoi(found.str(2), 0, 16);
}
chipsetDescs.push_back(desc);
}
// GO through the detected gpus in order and complete missing information from ChipsetModelDescs
// assuming the order is the same and checking that the vendor and memory amount match as a simple check
auto numDescs = (int) std::min(chipsetDescs.size(),_gpus.size());
for (int i = 0; i < numDescs; ++i) {
const auto& chipset = chipsetDescs[i];
auto& gpu = _gpus[i];
if ( (chipset.vendor.find( gpu[keys::gpu::vendor]) != std::string::npos)
&& (chipset.videoMemory == gpu[keys::gpu::videoMemory]) ) {
gpu[keys::gpu::model] = chipset.model;
gpu["macos_deviceID"] = chipset.deviceID;
}
}
}
auto displayBounds = CGDisplayBounds(displayID);
auto displayMaster =CGDisplayIsMain(displayID);
auto displayUnit =CGDisplayUnitNumber(displayID);
auto displayModel =CGDisplayModelNumber(displayID);
auto displayVendor = CGDisplayVendorNumber(displayID);
auto displaySerial = CGDisplaySerialNumber(displayID);
auto displayMode = CGDisplayCopyDisplayMode(displayID);
auto displayModeWidth = CGDisplayModeGetPixelWidth(displayMode);
auto displayModeHeight = CGDisplayModeGetPixelHeight(displayMode);
auto displayRefreshrate = CGDisplayModeGetRefreshRate(displayMode);
CGDisplayModeRelease(displayMode);
json display = {};
display["physicalWidth"] = displaySizeWidthInches;
display["physicalHeight"] = displaySizeHeightInches;
display["physicalDiagonal"] = displaySizeDiagonalInches;
display["ppi"] = sqrt(displayModeHeight * displayModeHeight + displayModeWidth * displayModeWidth) / displaySizeDiagonalInches;
display["coordLeft"] = displayBounds.origin.x;
display["coordRight"] = displayBounds.origin.x + displayBounds.size.width;
display["coordTop"] = displayBounds.origin.y;
display["coordBottom"] = displayBounds.origin.y + displayBounds.size.height;
display["isMaster"] = displayMaster;
display["unit"] = displayUnit;
display["vendor"] = displayVendor;
display["model"] = displayModel;
display["serial"] = displaySerial;
display["refreshrate"] =displayRefreshrate;
display["modeWidth"] = displayModeWidth;
display["modeHeight"] = displayModeHeight;
_displays.push_back(display);
#endif
}
@ -132,11 +314,11 @@ void MACOSInstance::enumerateComputer(){
_computer[keys::computer::model]=std::string(model);
free(model);
#endif
auto sysInfo = QSysInfo();
_computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString();
#endif
}

View file

@ -16,8 +16,7 @@ namespace platform {
public:
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateDisplays() override;
void enumerateGpusAndDisplays() override;
void enumerateMemory() override;
void enumerateComputer() override;
};

View file

@ -21,7 +21,8 @@ namespace platform { namespace keys {
const char* model = "model";
const char* clockSpeed = "clockSpeed";
const char* numCores = "numCores";
}
const char* isMaster = "isMaster";
}
namespace gpu {
const char* vendor = "vendor";
const char* vendor_NVIDIA = "NVIDIA";
@ -31,6 +32,8 @@ namespace platform { namespace keys {
const char* model = "model";
const char* videoMemory = "videoMemory";
const char* driver = "driver";
const char* displays = "displays";
const char* isMaster = "isMaster";
}
namespace nic {
const char* mac = "mac";
@ -39,10 +42,19 @@ namespace platform { namespace keys {
namespace display {
const char* description = "description";
const char* name = "deviceName";
const char* coordsLeft = "coordinatesleft";
const char* coordsRight = "coordinatesright";
const char* coordsTop = "coordinatestop";
const char* coordsBottom = "coordinatesbottom";
const char* boundsLeft = "boundsLeft";
const char* boundsRight = "boundsRight";
const char* boundsTop = "boundsTop";
const char* boundsBottom = "boundsBottom";
const char* gpu = "gpu";
const char* ppi = "ppi";
const char* ppiDesktop = "ppiDesktop";
const char* physicalWidth = "physicalWidth";
const char* physicalHeight = "physicalHeight";
const char* modeRefreshrate = "modeRefreshrate";
const char* modeWidth = "modeWidth";
const char* modeHeight = "modeHeight";
const char* isMaster = "isMaster";
}
namespace memory {
const char* memTotal = "memTotal";
@ -117,6 +129,10 @@ json platform::getCPU(int index) {
return _instance->getCPU(index);
}
int platform::getMasterCPU() {
return _instance->getMasterCPU();
}
int platform::getNumGPUs() {
return _instance->getNumGPUs();
}
@ -125,6 +141,10 @@ json platform::getGPU(int index) {
return _instance->getGPU(index);
}
int platform::getMasterGPU() {
return _instance->getMasterGPU();
}
int platform::getNumDisplays() {
return _instance->getNumDisplays();
}
@ -133,6 +153,10 @@ json platform::getDisplay(int index) {
return _instance->getDisplay(index);
}
int platform::getMasterDisplay() {
return _instance->getMasterDisplay();
}
json platform::getMemory() {
return _instance->getMemory();
}

View file

@ -16,18 +16,83 @@
using namespace platform;
bool Instance::enumeratePlatform() {
//clear all knowledge
_computer.clear();
_memory.clear();
_cpus.clear();
_gpus.clear();
_displays.clear();
_nics.clear();
// enumerate platform components
enumerateComputer();
enumerateMemory();
enumerateCpus();
enumerateGpus();
enumerateDisplays();
enumerateGpusAndDisplays();
enumerateNics();
// eval the master index for each platform scopes
updateMasterIndices();
// And profile the platform and put the tier in "computer"
_computer[keys::computer::profileTier] = Profiler::TierNames[Profiler::profilePlatform()];
return true;
}
void Instance::updateMasterIndices() {
// We assume a single CPU at the moment:
{
if (!_cpus.empty()) {
_masterCPU = 0;
_cpus[0][keys::cpu::isMaster] = true;
} else {
_masterCPU = NOT_FOUND;
}
}
// Go through the displays list
{
_masterDisplay = NOT_FOUND;
for (int i = 0; i < (int) _displays.size(); ++i) {
const auto& display = _displays[i];
if (display.count(keys::display::isMaster)) {
if (display[keys::display::isMaster].get<bool>()) {
_masterDisplay = i;
break;
}
}
}
// NO master display found, return the first one or NOT_FOUND if no display
if (_masterDisplay == NOT_FOUND) {
if (!_displays.empty()) {
_masterDisplay = 0;
_displays[0][keys::display::isMaster] = true;
}
}
}
// From the master display decide the master gpu
{
_masterGPU = NOT_FOUND;
if (_masterDisplay != NOT_FOUND) {
const auto& display = _displays[_masterDisplay];
// FInd the GPU index of the master display
if (display.count(keys::display::gpu)) {
_masterGPU = display[keys::display::gpu];
_gpus[_masterGPU][keys::gpu::isMaster] = true;
}
}
// NO master GPU found from master display, bummer, return the first one or NOT_FOUND if no display
if (_masterGPU == NOT_FOUND) {
if (!_gpus.empty()) {
_masterGPU = 0;
_gpus[0][keys::gpu::isMaster] = true;
}
}
}
}
void Instance::enumerateNics() {
QNetworkInterface interface;
foreach(interface, interface.allInterfaces()) {
@ -57,6 +122,7 @@ json Instance::getGPU(int index) {
return _gpus.at(index);
}
json Instance::getDisplay(int index) {
assert(index <(int) _displays.size());
@ -98,13 +164,13 @@ json Instance::listAllKeys() {
keys::gpu::model,
keys::gpu::videoMemory,
keys::gpu::driver,
keys::gpu::displays,
keys::display::description,
keys::display::name,
keys::display::coordsLeft,
keys::display::coordsRight,
keys::display::coordsTop,
keys::display::coordsBottom,
keys::display::boundsLeft,
keys::display::boundsRight,
keys::display::boundsTop,
keys::display::boundsBottom,
keys::display::gpu,
keys::memory::memTotal,

View file

@ -17,16 +17,21 @@ namespace platform {
class Instance {
public:
const int NOT_FOUND { -1 };
bool virtual enumeratePlatform();
int getNumCPUs() { return (int)_cpus.size(); }
json getCPU(int index);
int getMasterCPU() const { return _masterCPU; }
int getNumGPUs() { return (int)_gpus.size(); }
json getGPU(int index);
int getMasterGPU() const { return _masterGPU; }
int getNumDisplays() { return (int)_displays.size(); }
json getDisplay(int index);
int getMasterDisplay() const { return _masterDisplay; }
json getMemory() { return _memory; }
@ -35,8 +40,7 @@ public:
json getAll();
void virtual enumerateCpus()=0;
void virtual enumerateGpus()=0;
void virtual enumerateDisplays() {}
void virtual enumerateGpusAndDisplays()=0;
void virtual enumerateNics();
void virtual enumerateMemory() = 0;
void virtual enumerateComputer()=0;
@ -55,6 +59,14 @@ protected:
std::vector<json> _nics;
json _memory;
json _computer;
int _masterCPU{ -1 };
int _masterGPU{ -1 };
int _masterDisplay{ -1 };
// Traverse the cpus, gpus and displays to update the "master" index in each domain
void updateMasterIndices();
};
} // namespace platform

View file

@ -11,21 +11,31 @@
#include <thread>
#include <string>
#include <CPUIdent.h>
#include <GPUIdent.h>
#include <QtCore/QtGlobal>
#ifdef Q_OS_WIN
#include <sstream>
#include <qstring>
#include <qsysinfo>
#include <Windows.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <QSysInfo>
#include <dxgi1_3.h>
#pragma comment(lib, "dxgi.lib")
#include <shellscalingapi.h>
#pragma comment(lib, "Shcore.lib")
#endif
using namespace platform;
void WINInstance::enumerateCpus() {
json cpu = {};
cpu[keys::cpu::vendor] = CPUIdent::Vendor();
cpu[keys::cpu::model] = CPUIdent::Brand();
cpu[keys::cpu::numCores] = std::thread::hardware_concurrency();
@ -33,23 +43,153 @@ void WINInstance::enumerateCpus() {
_cpus.push_back(cpu);
}
void WINInstance::enumerateGpus() {
void WINInstance::enumerateGpusAndDisplays() {
#ifdef Q_OS_WIN
struct ConvertLargeIntegerToString {
std::string convert(const LARGE_INTEGER& version) {
std::ostringstream value;
value << uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF);
value << ".";
value << uint32_t((version.HighPart) & 0x0000FFFF);
value << ".";
value << uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF);
value << ".";
value << uint32_t((version.LowPart) & 0x0000FFFF);
return value.str();
}
} convertDriverVersionToString;
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
gpu[keys::gpu::videoMemory] = ident->getMemory();
gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
// Create the DXGI factory
// Let s get into DXGI land:
HRESULT hr = S_OK;
_gpus.push_back(gpu);
_displays = ident->getOutput();
IDXGIFactory1* pFactory = nullptr;
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory));
if (hr != S_OK || pFactory == nullptr) {
return;
}
std::vector<int> validAdapterList;
using AdapterEntry = std::pair<std::pair<DXGI_ADAPTER_DESC1, LARGE_INTEGER>, std::vector<DXGI_OUTPUT_DESC>>;
std::vector<AdapterEntry> adapterToOutputs;
// Enumerate adapters and outputs
{
UINT adapterNum = 0;
IDXGIAdapter1* pAdapter = nullptr;
while (pFactory->EnumAdapters1(adapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
// Found an adapter, get descriptor
DXGI_ADAPTER_DESC1 adapterDesc;
pAdapter->GetDesc1(&adapterDesc);
// Only describe gpu if it is a hardware adapter
if (!(adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) {
LARGE_INTEGER version;
hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
std::wstring wDescription(adapterDesc.Description);
std::string description(wDescription.begin(), wDescription.end());
json gpu = {};
gpu[keys::gpu::model] = description;
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024;
gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE);
gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version);
std::vector<int> displayIndices;
UINT outputNum = 0;
IDXGIOutput* pOutput;
bool hasOutputConnectedToDesktop = false;
while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) {
// FOund an output attached to the adapter, get descriptor
DXGI_OUTPUT_DESC outputDesc;
pOutput->GetDesc(&outputDesc);
pOutput->Release();
outputNum++;
// Grab the monitor info
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
// Grab the dpi info for the monitor
UINT dpiX{ 0 };
UINT dpiY{ 0 };
GetDpiForMonitor(outputDesc.Monitor, MDT_RAW_DPI, &dpiX, &dpiY);
UINT dpiXScaled{ 0 };
UINT dpiYScaled{ 0 };
GetDpiForMonitor(outputDesc.Monitor, MDT_EFFECTIVE_DPI, &dpiXScaled, &dpiYScaled);
// Current display mode
DEVMODEW devMode;
devMode.dmSize = sizeof(DEVMODEW);
EnumDisplaySettingsW(outputDesc.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
auto physicalWidth = devMode.dmPelsWidth / (float)dpiX;
auto physicalHeight = devMode.dmPelsHeight / (float)dpiY;
json display = {};
// Display name
std::wstring wDeviceName(outputDesc.DeviceName);
std::string deviceName(wDeviceName.begin(), wDeviceName.end());
display[keys::display::name] = deviceName;
display[keys::display::description] = "";
// Rect region of the desktop in desktop units
//display["desktopRect"] = (outputDesc.AttachedToDesktop ? true : false);
display[keys::display::boundsLeft] = outputDesc.DesktopCoordinates.left;
display[keys::display::boundsRight] = outputDesc.DesktopCoordinates.right;
display[keys::display::boundsBottom] = outputDesc.DesktopCoordinates.bottom;
display[keys::display::boundsTop] = outputDesc.DesktopCoordinates.top;
// PPI & resolution
display[keys::display::physicalWidth] = physicalWidth;
display[keys::display::physicalHeight] = physicalHeight;
display[keys::display::modeWidth] = devMode.dmPelsWidth;
display[keys::display::modeHeight] = devMode.dmPelsHeight;
//Average the ppiH and V for the simple ppi
display[keys::display::ppi] = std::round(0.5f * (dpiX + dpiY));
display[keys::display::ppiDesktop] = std::round(0.5f * (dpiXScaled + dpiYScaled));
// refreshrate
display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;;
// Master display ?
display[keys::display::isMaster] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY);
// Add the display index to the list of displays of the gpu
displayIndices.push_back((int) _displays.size());
// And set the gpu index to the display description
display[keys::display::gpu] = (int) _gpus.size();
// WIN specific
// One more display desc
_displays.push_back(display);
}
gpu[keys::gpu::displays] = displayIndices;
_gpus.push_back(gpu);
}
pAdapter->Release();
adapterNum++;
}
}
pFactory->Release();
#endif
}
void WINInstance::enumerateMemory() {
json ram = {};
#ifdef Q_OS_WIN
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
@ -60,16 +200,18 @@ void WINInstance::enumerateMemory() {
_memory = ram;
}
void WINInstance::enumerateComputer(){
void WINInstance::enumerateComputer() {
_computer[keys::computer::OS] = keys::computer::OS_WINDOWS;
_computer[keys::computer::vendor] = "";
_computer[keys::computer::model] = "";
auto sysInfo = QSysInfo();
#ifdef Q_OS_WIN
auto sysInfo = QSysInfo();
_computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString();
#endif
}
void WINInstance::enumerateNics() {
// Start with the default from QT, getting the result into _nics:
Instance::enumerateNics();
@ -78,23 +220,23 @@ void WINInstance::enumerateNics() {
// We can usually do better than the QNetworkInterface::humanReadableName() by
// matching up Iphlpapi.lib IP_ADAPTER_INFO by mac id.
ULONG buflen = sizeof(IP_ADAPTER_INFO);
IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*) malloc(buflen);
IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen);
// Size the buffer:
if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(buflen);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen);
}
// Now get the data...
if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) {
for (json& nic : _nics) { // ... loop through the nics from above...
for (json& nic : _nics) { // ... loop through the nics from above...
// ...convert the json to a string without the colons...
QString qtmac = nic[keys::nic::mac].get<std::string>().c_str();
QString qtraw = qtmac.remove(QChar(':'), Qt::CaseInsensitive).toLower();
// ... and find the matching one in pAdapter:
for (IP_ADAPTER_INFO* pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) {
QByteArray wmac = QByteArray((const char*) (pAdapter->Address), pAdapter->AddressLength);
QByteArray wmac = QByteArray((const char*)(pAdapter->Address), pAdapter->AddressLength);
QString wraw = wmac.toHex();
if (qtraw == wraw) {
nic[keys::nic::name] = pAdapter->Description;
@ -108,4 +250,4 @@ void WINInstance::enumerateNics() {
free(pAdapterInfo);
}
#endif
}
}

View file

@ -16,7 +16,7 @@ namespace platform {
public:
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateGpusAndDisplays() override;
void enumerateMemory() override;
void enumerateComputer () override;
void enumerateNics() override;

View file

@ -86,19 +86,30 @@ PropFolderPanel {
var itemLabel = proItem.property;
var itemDepth = root.indentDepth + 1;
if (Array.isArray(itemRootObject)) {
if (objectItem.length > 1) {
itemLabel = itemLabel + " " + objectItem.length
itemLabel = proItem.property + "[] / " + itemRootObject.length
if (itemRootObject.length == 0) {
var component = Qt.createComponent("PropItem.qml");
component.createObject(propItemsContainer, {
"label": itemLabel
})
} else {
itemLabel = itemLabel + " " + objectItem.length
itemRootObject = itemRootObject[0];
var component = Qt.createComponent("PropGroup.qml");
component.createObject(propItemsContainer, {
"label": itemLabel,
"rootObject":itemRootObject,
"indentDepth": itemDepth,
"isUnfold": true,
})
}
} else {
var component = Qt.createComponent("PropGroup.qml");
component.createObject(propItemsContainer, {
"label": itemLabel,
"rootObject":itemRootObject,
"indentDepth": itemDepth,
"isUnfold": true,
})
}
var component = Qt.createComponent("PropGroup.qml");
component.createObject(propItemsContainer, {
"label": itemLabel,
"rootObject":itemRootObject,
"indentDepth": itemDepth,
})
} break;
case 'printLabel': {
var component = Qt.createComponent("PropItem.qml");
@ -125,12 +136,6 @@ PropFolderPanel {
function populateFromObjectProps(object) {
var propsModel = []
if (Array.isArray(object)) {
if (object.length <= 1) {
object = object[0];
}
}
var props = Object.keys(object);
for (var p in props) {
var o = {};

View file

@ -51,6 +51,7 @@ Rectangle {
}
Prop.PropFolderPanel {
label: "Platform"
isUnfold: true
panelFrameData: Component {
Platform {
}