From bfe42215aac68cc290ceeefa19168d4bd1e20b6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 1 Aug 2019 14:29:03 -0700 Subject: [PATCH] DEV-279: Add rendering API information to the platform JSON object --- interface/src/Application.cpp | 3 + libraries/gl/src/gl/GLHelpers.cpp | 43 ++++++--- libraries/gl/src/gl/GLHelpers.h | 22 ++++- libraries/gl/src/gl/GLWindow.cpp | 14 ++- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 8 +- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 12 ++- libraries/platform/CMakeLists.txt | 4 +- .../platform/src/platform/PlatformKeys.h | 38 ++++++++ .../src/platform/backend/MACOSPlatform.cpp | 5 ++ .../src/platform/backend/MACOSPlatform.h | 1 + .../src/platform/backend/Platform.cpp | 39 ++++++++ .../src/platform/backend/PlatformInstance.cpp | 90 +++++++++++++++++++ .../src/platform/backend/PlatformInstance.h | 2 + .../src/platform/backend/WINPlatform.cpp | 6 ++ .../src/platform/backend/WINPlatform.h | 1 + 15 files changed, 254 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7cd45ae37..fd56795e12 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2996,6 +2996,9 @@ void Application::initializeGL() { qCWarning(interfaceapp, "Unable to make window context current"); } + // Populate the global OpenGL context based on the information for the primary window GL context + gl::ContextInfo::get(true); + #if !defined(DISABLE_QML) QStringList chromiumFlags; // HACK: re-expose mic and camera to prevent crash on domain-change in chromium's media::FakeAudioInputStream::ReadAudioFromSource() diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index c9f17b686d..2555ac61fc 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -148,6 +148,33 @@ static bool setupPixelFormatSimple(HDC hdc) { #endif + +const gl::ContextInfo& gl::ContextInfo::get(bool init) { + static gl::ContextInfo INSTANCE; + if (init) { + static std::once_flag once; + std::call_once(once, [&] { + INSTANCE.init(); + }); + } + return INSTANCE; +} + +gl::ContextInfo& gl::ContextInfo::init() { + if (glGetString) { + version = (const char*)glGetString(GL_VERSION); + shadingLanguageVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + vendor = (const char*)glGetString(GL_VENDOR); + renderer = (const char*)glGetString(GL_RENDERER); + GLint n = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + for (GLint i = 0; i < n; ++i) { + extensions.emplace_back((const char*)glGetStringi(GL_EXTENSIONS, i)); + } + } + return *this; +} + uint16_t gl::getAvailableVersion() { static uint8_t major = 0, minor = 0; static std::once_flag once; @@ -277,20 +304,16 @@ int glVersionToInteger(QString glVersion) { return (majorNumber << 16) | minorNumber; } -QJsonObject getGLContextData() { +const QJsonObject& getGLContextData() { static QJsonObject result; static std::once_flag once; std::call_once(once, [] { - QString glVersion = QString((const char*)glGetString(GL_VERSION)); - QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - QString glVendor = QString((const char*) glGetString(GL_VENDOR)); - QString glRenderer = QString((const char*)glGetString(GL_RENDERER)); - + auto contextInfo = gl::ContextInfo::get(); result = QJsonObject { - { "version", glVersion }, - { "sl_version", glslVersion }, - { "vendor", glVendor }, - { "renderer", glRenderer }, + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, }; }); return result; diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index c09f9d4963..5090153bab 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -29,7 +29,7 @@ class QGLFormat; size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); -QJsonObject getGLContextData(); +const QJsonObject& getGLContextData(); int glVersionToInteger(QString glVersion); bool isRenderThread(); @@ -39,6 +39,26 @@ bool isRenderThread(); #define GL_GET_MAJOR_VERSION(glversion) ((glversion & 0xFF00) >> 8) namespace gl { + struct ContextInfo { + std::string version; + std::string shadingLanguageVersion; + std::string vendor; + std::string renderer; + std::vector extensions; + + ContextInfo& init(); + operator bool() const { return !version.empty(); } + + static const ContextInfo& get(bool init = false); + }; + +#define LOG_GL_CONTEXT_INFO(category, contextInfo) \ + qCDebug(category) << "GL Version: " << contextInfo.version.c_str(); \ + qCDebug(category) << "GL Shader Language Version: " << contextInfo.shadingLanguageVersion.c_str(); \ + qCDebug(category) << "GL Vendor: " << contextInfo.vendor.c_str(); \ + qCDebug(category) << "GL Renderer: " << contextInfo.renderer.c_str(); + + void globalLock(); void globalRelease(bool finish = true); diff --git a/libraries/gl/src/gl/GLWindow.cpp b/libraries/gl/src/gl/GLWindow.cpp index 7930e050de..19f8428d0a 100644 --- a/libraries/gl/src/gl/GLWindow.cpp +++ b/libraries/gl/src/gl/GLWindow.cpp @@ -33,14 +33,12 @@ GLWindow::~GLWindow() { bool GLWindow::makeCurrent() { bool makeCurrentResult = _context->makeCurrent(); Q_ASSERT(makeCurrentResult); - - std::call_once(_reportOnce, []{ - qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); - }); - + + if (makeCurrentResult) { + std::call_once(_reportOnce, []{ + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); + }); + } return makeCurrentResult; } diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 69b41da821..c5b8baa6d4 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -73,13 +73,9 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - if (glGetString) { + if (result) { std::call_once(_reportOnce, [] { - qCDebug(glLogging) << "GL Version: " << QString((const char*)glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " - << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*)glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*)glGetString(GL_RENDERER)); + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); }); } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index fef458f536..3e5043003b 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -117,9 +117,10 @@ void GLBackend::init() { static std::once_flag once; std::call_once(once, [] { - - QString vendor{ (const char*)glGetString(GL_VENDOR) }; - QString renderer{ (const char*)glGetString(GL_RENDERER) }; + ::gl::ContextInfo contextInfo; + contextInfo.init(); + QString vendor { contextInfo.vendor.c_str() }; + QString renderer { contextInfo.renderer.c_str() }; // Textures GL_GET_INTEGER(MAX_TEXTURE_IMAGE_UNITS); @@ -131,10 +132,7 @@ void GLBackend::init() { GL_GET_INTEGER(MAX_UNIFORM_BLOCK_SIZE); GL_GET_INTEGER(UNIFORM_BUFFER_OFFSET_ALIGNMENT); - qCDebug(gpugllogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(gpugllogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(gpugllogging) << "GL Vendor: " << vendor; - qCDebug(gpugllogging) << "GL Renderer: " << renderer; + LOG_GL_CONTEXT_INFO(gpugllogging, contextInfo); GPUIdent* gpu = GPUIdent::getInstance(vendor, renderer); // From here on, GPUIdent::getInstance()->getMumble() should efficiently give the same answers. qCDebug(gpugllogging) << "GPU:"; diff --git a/libraries/platform/CMakeLists.txt b/libraries/platform/CMakeLists.txt index f0dce500f4..0d984f9684 100644 --- a/libraries/platform/CMakeLists.txt +++ b/libraries/platform/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME platform) setup_hifi_library() -link_hifi_libraries(shared) +link_hifi_libraries(shared gl) GroupSources("src") target_json() @@ -15,4 +15,4 @@ if (APPLE) elseif(WIN32) target_link_libraries(${TARGET_NAME} Iphlpapi.lib) -endif () \ No newline at end of file +endif() \ No newline at end of file diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 5008a4f6ce..02c6a6021d 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -34,6 +34,43 @@ namespace platform { namespace keys{ extern const char* displays; extern const char* isMaster; } + namespace renderingApis { + extern const char* apiOpenGL; + extern const char* apiVulkan; + extern const char* apiDirect3D11; + extern const char* apiDirect3D12; + extern const char* apiMetal; + namespace gl { + extern const char* version; + extern const char* shadingLanguageVersion; + extern const char* vendor; + extern const char* renderer; + extern const char* extensions; + } + namespace vk { + extern const char* version; + extern const char* devices; + namespace device { + extern const char* apiVersion; + extern const char* driverVersion; + extern const char* deviceType; + extern const char* vendor; + extern const char* name; + extern const char* formats; + extern const char* extensions; + extern const char* queues; + extern const char* heaps; + namespace heap { + extern const char* flags; + extern const char* size; + } + namespace queue { + extern const char* flags; + extern const char* count; + } + } + } + } namespace nic { extern const char* mac; extern const char* name; @@ -78,6 +115,7 @@ namespace platform { namespace keys{ // Keys for categories used in json returned by getAll() extern const char* CPUS; extern const char* GPUS; + extern const char* RENDERING_APIS; extern const char* DISPLAYS; extern const char* NICS; extern const char* MEMORY; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 66c9cd2c5d..8b37cd36b5 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -322,3 +322,8 @@ void MACOSInstance::enumerateComputer(){ } +void MACOSInstance::enumerateRenderingApis() { + Instance::enumerateRenderingApis(); + + // TODO imeplement Metal query +} diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index f249dad001..464d2ced5e 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -19,6 +19,7 @@ namespace platform { void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; + void enumerateRenderingApis() override; }; } // namespace platform diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 17d9d8019e..d15ce34776 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -35,6 +35,44 @@ namespace platform { namespace keys { const char* displays = "displays"; const char* isMaster = "isMaster"; } + namespace renderingApis { + const char* apiOpenGL = "OpenGL"; + const char* apiVulkan = "Vulkan"; + const char* apiDirect3D11 = "D3D11"; + const char* apiDirect3D12 = "D3D12"; + const char* apiMetal = "Metal"; + + namespace gl { + const char* version = "version"; + const char* shadingLanguageVersion = "shadingLanguageVersion"; + const char* vendor = "vendor"; + const char* renderer = "renderer"; + const char* extensions = "extensions"; + } + namespace vk { + const char* version = "version"; + const char* devices = "devices"; + namespace device { + const char* apiVersion = "apiVersion"; + const char* driverVersion = "driverVersion"; + const char* deviceType = "deviceType"; + const char* vendor = "vendor"; + const char* name = "name"; + const char* formats = "formats"; + const char* extensions = "extensions"; + const char* heaps = "heaps"; + namespace heap { + const char* flags = "flags"; + const char* size = "size"; + } + const char* queues = "queues"; + namespace queue { + const char* flags = "flags"; + const char* count = "count"; + } + } + } + } namespace nic { const char* mac = "mac"; const char* name = "name"; @@ -78,6 +116,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; + const char* RENDERING_APIS = "renderingApis"; const char* DISPLAYS = "displays"; const char* NICS = "nics"; const char* MEMORY = "memory"; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index d4cadba3b7..0ac11f9f0f 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -10,9 +10,18 @@ #include "PlatformInstance.h" #include +#include #include "../PlatformKeys.h" #include "../Profiler.h" +// For testing the vulkan dump +//#define HAVE_VULKAN 1 +//#pragma comment(lib, "C:\\VulkanSDK\\1.1.101.0\\Lib\\vulkan-1.lib") + +#ifdef HAVE_VULKAN +#include +#endif + using namespace platform; bool Instance::enumeratePlatform() { @@ -30,6 +39,7 @@ bool Instance::enumeratePlatform() { enumerateCpus(); enumerateGpusAndDisplays(); enumerateNics(); + enumerateRenderingApis(); // eval the master index for each platform scopes updateMasterIndices(); @@ -105,6 +115,72 @@ void Instance::enumerateNics() { } } +#if defined(HAVE_VULKAN) +static std::string vkVersionToString(uint32_t version) { + return QString("%1.%2.%3").arg(VK_VERSION_MAJOR(version)).arg(VK_VERSION_MINOR(version)).arg(VK_VERSION_PATCH(version)).toStdString(); +} +#endif + + +void Instance::enumerateRenderingApis() { + // OpenGL rendering API is supported on all platforms + { + auto& glContextInfo = gl::ContextInfo::get(); + json gl; + gl[keys::renderingApis::gl::version] = glContextInfo.version; + gl[keys::renderingApis::gl::vendor] = glContextInfo.vendor; + gl[keys::renderingApis::gl::renderer] = glContextInfo.renderer; + gl[keys::renderingApis::gl::shadingLanguageVersion] = glContextInfo.shadingLanguageVersion; + gl[keys::renderingApis::gl::extensions] = glContextInfo.extensions; + _renderingApis[keys::renderingApis::apiOpenGL] = gl; + } + +#if defined(HAVE_VULKAN) + // Vulkan rendering API is supported on all platforms (sort of) + { + try { + vk::ApplicationInfo appInfo{ "Interface", 1, "Luci", 1, VK_API_VERSION_1_1 }; + auto instancePtr = vk::createInstanceUnique({ {}, &appInfo }); + if (instancePtr) { + json vkinfo; + const auto& vkinstance = *instancePtr; + vkinfo[keys::renderingApis::vk::version] = vkVersionToString(VK_API_VERSION_1_1); + for (const auto& physicalDevice : vkinstance.enumeratePhysicalDevices()) { + json vkdevice; + auto properties = physicalDevice.getProperties(); + vkdevice[keys::renderingApis::vk::device::driverVersion] = vkVersionToString(properties.driverVersion); + vkdevice[keys::renderingApis::vk::device::apiVersion] = vkVersionToString(properties.apiVersion); + vkdevice[keys::renderingApis::vk::device::deviceType] = vk::to_string(properties.deviceType); + vkdevice[keys::renderingApis::vk::device::vendor] = properties.vendorID; + vkdevice[keys::renderingApis::vk::device::name] = properties.deviceName; + for (const auto& extensionProperties : physicalDevice.enumerateDeviceExtensionProperties()) { + vkdevice[keys::renderingApis::vk::device::extensions].push_back(extensionProperties.extensionName); + } + + for (const auto& queueFamilyProperties : physicalDevice.getQueueFamilyProperties()) { + json vkqueuefamily; + vkqueuefamily[keys::renderingApis::vk::device::queue::flags] = vk::to_string(queueFamilyProperties.queueFlags); + vkqueuefamily[keys::renderingApis::vk::device::queue::count] = queueFamilyProperties.queueCount; + vkdevice[keys::renderingApis::vk::device::queues].push_back(vkqueuefamily); + } + auto memoryProperties = physicalDevice.getMemoryProperties(); + for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) { + json vkmemoryheap; + const auto& heap = memoryProperties.memoryHeaps[heapIndex]; + vkmemoryheap[keys::renderingApis::vk::device::heap::flags] = vk::to_string(heap.flags); + vkmemoryheap[keys::renderingApis::vk::device::heap::size] = heap.size; + vkdevice[keys::renderingApis::vk::device::heaps].push_back(vkmemoryheap); + } + vkinfo[keys::renderingApis::vk::devices].push_back(vkdevice); + } + _renderingApis[keys::renderingApis::apiVulkan] = vkinfo; + } + } catch (const std::runtime_error&) { + } + } +#endif +} + json Instance::getCPU(int index) { assert(index <(int) _cpus.size()); @@ -167,6 +243,18 @@ json Instance::listAllKeys() { keys::gpu::driver, keys::gpu::displays, + keys::renderingApis::apiOpenGL, + keys::renderingApis::apiVulkan, + keys::renderingApis::apiMetal, + keys::renderingApis::apiDirect3D11, + keys::renderingApis::apiDirect3D12, + + keys::renderingApis::gl::version, + keys::renderingApis::gl::shadingLanguageVersion, + keys::renderingApis::gl::vendor, + keys::renderingApis::gl::renderer, + keys::renderingApis::gl::extensions, + keys::display::boundsLeft, keys::display::boundsRight, keys::display::boundsTop, @@ -188,6 +276,7 @@ json Instance::listAllKeys() { keys::CPUS, keys::GPUS, + keys::RENDERING_APIS, keys::DISPLAYS, keys::MEMORY, keys::COMPUTER, @@ -219,6 +308,7 @@ json Instance::getAll() { all[keys::MEMORY] = _memory; all[keys::CPUS] = _cpus; all[keys::GPUS] = _gpus; + all[keys::RENDERING_APIS] = _renderingApis; all[keys::DISPLAYS] = _displays; all[keys::NICS] = _nics; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 069124853e..7078c31d90 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -44,6 +44,7 @@ public: void virtual enumerateNics(); void virtual enumerateMemory() = 0; void virtual enumerateComputer()=0; + virtual void enumerateRenderingApis(); virtual ~Instance(); @@ -57,6 +58,7 @@ protected: std::vector _gpus; std::vector _displays; std::vector _nics; + json _renderingApis; json _memory; json _computer; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index e528618fe1..e0585aa14b 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -251,3 +251,9 @@ void WINInstance::enumerateNics() { } #endif } + +void WINInstance::enumerateRenderingApis() { + Instance::enumerateRenderingApis(); + + // TODO imeplement D3D 11/12 queries +} diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index cc56ebfbbc..0a92efb948 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -20,6 +20,7 @@ namespace platform { void enumerateMemory() override; void enumerateComputer () override; void enumerateNics() override; + void enumerateRenderingApis() override; }; } // namespace platform