Add an option to log opengl messages

Mon, 20 Jun 2022 19:49:56 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Mon, 20 Jun 2022 19:49:56 +0300
changeset 237
10a6298f636f
parent 236
1fa0e1de9f0a
child 238
b8ad4c12d937

Add an option to log opengl messages

CMakeLists.txt file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/gl/debug.cpp file | annotate | diff | comparison | revisions
src/gl/debug.h file | annotate | diff | comparison | revisions
src/gl/partrenderer.cpp file | annotate | diff | comparison | revisions
src/gl/partrenderer.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/mainwindow.ui file | annotate | diff | comparison | revisions
src/settings.h file | annotate | diff | comparison | revisions
src/settingseditor/settingseditor.cpp file | annotate | diff | comparison | revisions
src/settingseditor/settingseditor.ui file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Mon Jun 20 18:40:22 2022 +0300
+++ b/CMakeLists.txt	Mon Jun 20 19:49:56 2022 +0300
@@ -40,6 +40,7 @@
 	src/gl/axesprogram.cpp
 	src/gl/basicshaderprogram.cpp
 	src/gl/compiler.cpp
+	src/gl/debug.cpp
 	src/gl/gridprogram.cpp
 	src/gl/partrenderer.cpp
 #	src/gl/vertexprogram.cpp
@@ -83,6 +84,7 @@
 	src/gl/basicshaderprogram.h
 	src/gl/common.h
 	src/gl/compiler.h
+	src/gl/debug.h
 	src/gl/gridprogram.h
 	src/gl/partrenderer.h
 #	src/gl/vertexprogram.h
--- a/src/basics.h	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/basics.h	Mon Jun 20 19:49:56 2022 +0300
@@ -300,10 +300,12 @@
 struct Message
 {
 	QDateTime time;
-	enum { Info, Warning, Error } type;
+	enum Type { Info, Warning, Error } type;
 	QString text;
 };
 
+Q_DECLARE_METATYPE(Message)
+
 inline Message logInfo(const QString text)
 {
 	return Message{.time = QDateTime::currentDateTime(), .type = Message::Info, .text = text};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gl/debug.cpp	Mon Jun 20 19:49:56 2022 +0300
@@ -0,0 +1,100 @@
+#include "debug.h"
+
+QString sourceToString(const QOpenGLDebugMessage::Source source)
+{
+	switch (source) {
+	case QOpenGLDebugMessage::InvalidSource:
+		return QObject::tr("invalid");
+	case QOpenGLDebugMessage::APISource:
+		return QObject::tr("API");
+	case QOpenGLDebugMessage::WindowSystemSource:
+		return QObject::tr("window system");
+	case QOpenGLDebugMessage::ShaderCompilerSource:
+		return QObject::tr("shader compiler");
+	case QOpenGLDebugMessage::ThirdPartySource:
+		return QObject::tr("third party");
+	case QOpenGLDebugMessage::ApplicationSource:
+		return QObject::tr("application");
+	case QOpenGLDebugMessage::OtherSource:
+		return QObject::tr("other");
+	case QOpenGLDebugMessage::AnySource:
+		return QObject::tr("any");
+	}
+	return "";
+}
+
+QString typeToString(const QOpenGLDebugMessage::Type type)
+{
+	switch (type) {
+	case QOpenGLDebugMessage::ErrorType:
+		return QObject::tr("error");
+	case QOpenGLDebugMessage::DeprecatedBehaviorType:
+		return QObject::tr("deprecated behavior");
+	case QOpenGLDebugMessage::UndefinedBehaviorType:
+		return QObject::tr("undefined behavior");
+	case QOpenGLDebugMessage::PortabilityType:
+		return QObject::tr("portability");
+	case QOpenGLDebugMessage::PerformanceType:
+		return QObject::tr("performance");
+	case QOpenGLDebugMessage::MarkerType:
+		return QObject::tr("marker");
+	case QOpenGLDebugMessage::GroupPushType:
+		return QObject::tr("push group");
+	case QOpenGLDebugMessage::GroupPopType:
+		return QObject::tr("pop group");
+	case QOpenGLDebugMessage::OtherType:
+		return QObject::tr("other");
+	case QOpenGLDebugMessage::InvalidType:
+		return QObject::tr("invalid");
+	case QOpenGLDebugMessage::AnyType:
+		return QObject::tr("any");
+	}
+	return "";
+}
+
+QString severityToString(const QOpenGLDebugMessage::Severity severity)
+{
+	switch (severity) {
+	case QOpenGLDebugMessage::HighSeverity:
+		return QObject::tr("high");
+	case QOpenGLDebugMessage::MediumSeverity:
+		return QObject::tr("medium");
+	case QOpenGLDebugMessage::LowSeverity:
+		return QObject::tr("low");
+	case QOpenGLDebugMessage::NotificationSeverity:
+		return QObject::tr("notification");
+	case QOpenGLDebugMessage::InvalidSeverity:
+		return QObject::tr("invalid");
+	case QOpenGLDebugMessage::AnySeverity:
+		return QObject::tr("any");
+	}
+	return "";
+}
+
+constexpr Message::Type severityToMessageType(const QOpenGLDebugMessage::Severity severity)
+{
+	switch (severity) {
+	case QOpenGLDebugMessage::HighSeverity:
+		return Message::Error;
+	case QOpenGLDebugMessage::MediumSeverity:
+		return Message::Warning;
+	default:
+		return Message::Info;
+	}
+}
+
+Message debugMessageToString(const QOpenGLDebugMessage& glmessage)
+{
+	QString text;
+	QTextStream stream{&text};
+	stream << QObject::tr("OpenGL debug message [%1]").arg(glmessage.id()) << "\n";
+	stream << QObject::tr("Source: %1\n").arg(sourceToString(glmessage.source()));
+	stream << QObject::tr("Type: %1\n").arg(typeToString(glmessage.type()));
+	stream << QObject::tr("Severity: %1\n").arg(severityToString(glmessage.severity()));
+	stream << glmessage.message();
+	return Message{
+		.time = QDateTime::currentDateTime(),
+		.type = severityToMessageType(glmessage.severity()),
+		.text = text,
+	};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gl/debug.h	Mon Jun 20 19:49:56 2022 +0300
@@ -0,0 +1,5 @@
+#pragma once
+#include <QOpenGLDebugMessage>
+#include "basics.h"
+
+Message debugMessageToString(const QOpenGLDebugMessage& glmessage);
--- a/src/gl/partrenderer.cpp	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/gl/partrenderer.cpp	Mon Jun 20 19:49:56 2022 +0300
@@ -27,6 +27,8 @@
 #include "partrenderer.h"
 #include "model.h"
 #include "gl/compiler.h"
+#include "gl/debug.h"
+#include "settings.h"
 
 static constexpr double MIN_ZOOM = -3.0;
 static constexpr double MAX_ZOOM = 3.0;
@@ -47,6 +49,9 @@
 	QSurfaceFormat surfaceFormat;
 	surfaceFormat.setSamples(8);
 	this->setFormat(surfaceFormat);
+	connect(&this->logger, &QOpenGLDebugLogger::messageLogged, [&](const QOpenGLDebugMessage& glmessage){
+		Q_EMIT this->message(debugMessageToString(glmessage));
+	});
 	connect(model, &Model::rowsInserted, [&]{
 		this->needBuild = true;
 	});
@@ -92,6 +97,10 @@
 	for (RenderLayer* layer : this->inactiveRenderLayers) {
 		layer->initializeGL();
 	}
+	this->logger.initialize();
+	if (setting<Setting::LogOpenGLDebugMessages>()) {
+		this->logger.startLogging();
+	}
 	connect(this->model, &Model::dataChanged, this, &PartRenderer::build);
 	this->initialized = true;
 	this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0});
@@ -484,6 +493,15 @@
 	{
 		this->build();
 	}
+	if (this->initialized) {
+		this->makeCurrent();
+		if (setting<Setting::LogOpenGLDebugMessages>()) {
+			this->logger.startLogging();
+		}
+		else {
+			this->logger.stopLogging();
+		}
+	}
 	Q_EMIT this->renderPreferencesChanged();
 	this->update();
 }
--- a/src/gl/partrenderer.h	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/gl/partrenderer.h	Mon Jun 20 19:49:56 2022 +0300
@@ -1,5 +1,6 @@
 #pragma once
 #include <QOpenGLWidget>
+#include <QOpenGLDebugLogger>
 #include "basics.h"
 #include "gl/common.h"
 #include "gl/compiler.h"
@@ -29,6 +30,7 @@
 	std::vector<RenderLayer*> activeRenderLayers;
 	std::vector<RenderLayer*> inactiveRenderLayers;
 	bool frozen = false;
+	QOpenGLDebugLogger logger;
 public:
 	PartRenderer(
 		Model* model,
@@ -50,6 +52,7 @@
 	void modelMatrixChanged(const glm::mat4& newMatrix);
 	void viewMatrixChanged(const glm::mat4& newMatrix);
 	void renderPreferencesChanged();
+	void message(const Message& message);
 private:
 	void initializeGL() override;
 	void resizeGL(int width, int height) override;
--- a/src/main.cpp	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/main.cpp	Mon Jun 20 19:49:56 2022 +0300
@@ -2,6 +2,7 @@
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QMdiSubWindow>
+#include <QScrollBar>
 #include <QStackedWidget>
 #include <QCloseEvent>
 #include "mainwindow.h"
@@ -55,6 +56,7 @@
 	QCoreApplication::setApplicationName(::appName);
 	QCoreApplication::setOrganizationName("hecknology.net");
 	QCoreApplication::setOrganizationDomain("hecknology.net");
+	qRegisterMetaType<Message>();
 	qRegisterMetaTypeStreamOperators<Library>("Library");
 	qRegisterMetaTypeStreamOperators<Libraries>("Libraries");
 	qRegisterMetaTypeStreamOperators<gl::RenderStyle>();
@@ -343,7 +345,6 @@
 	return result;
 }
 
-#include <QScrollBar>
 int main(int argc, char *argv[])
 {
 	doQtRegistrations();
@@ -478,6 +479,7 @@
 						}
 					}
 				});
+			QObject::connect(data->canvas.get(), &PartRenderer::message, &messageLog, &MessageLog::addMessage);
 			const QFileInfo fileInfo{*documents.modelPath(modelId)};
 			ModelSubWindow* subWindow = new ModelSubWindow{modelId, ui.mdiArea};
 			subWindow->setWidget(data->canvas.get());
@@ -636,6 +638,7 @@
 		ui.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum());
 	});
 	QObject::connect(&messageLog, &MessageLog::rowsInserted, [&]{
+		ui.messageLog->resizeRowsToContents();
 		if (ui.messageLog->property("shouldAutoScroll").toBool()) {
 			ui.messageLog->scrollToBottom();
 		}
--- a/src/mainwindow.ui	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/mainwindow.ui	Mon Jun 20 19:49:56 2022 +0300
@@ -228,12 +228,21 @@
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QTableView" name="messageLog">
+       <property name="verticalScrollBarPolicy">
+        <enum>Qt::ScrollBarAlwaysOn</enum>
+       </property>
+       <property name="horizontalScrollBarPolicy">
+        <enum>Qt::ScrollBarAlwaysOn</enum>
+       </property>
        <property name="alternatingRowColors">
         <bool>true</bool>
        </property>
        <property name="verticalScrollMode">
         <enum>QAbstractItemView::ScrollPerPixel</enum>
        </property>
+       <property name="horizontalScrollMode">
+        <enum>QAbstractItemView::ScrollPerPixel</enum>
+       </property>
        <property name="gridStyle">
         <enum>Qt::DotLine</enum>
        </property>
--- a/src/settings.h	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/settings.h	Mon Jun 20 19:49:56 2022 +0300
@@ -38,6 +38,7 @@
 SETTING(MainSplitterState, QByteArray{})
 SETTING(RecentFiles, QStringList{})
 SETTING(ViewMode, QMdiArea::TabbedView)
+SETTING(LogOpenGLDebugMessages, false)
 
 // File management options
 SETTING(Libraries, QVector<Library>{})
--- a/src/settingseditor/settingseditor.cpp	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/settingseditor/settingseditor.cpp	Mon Jun 20 19:49:56 2022 +0300
@@ -45,6 +45,7 @@
 	setSetting<Setting::SelectedColor>(this->ui.selectedColorButton->selectedColor());
 	setSetting<Setting::LineThickness>(static_cast<GLfloat>(this->ui.lineThickness->value()));
 	setSetting<Setting::LineAntiAliasing>(this->ui.lineAntiAliasing->isChecked());
+	setSetting<Setting::LogOpenGLDebugMessages>(this->ui.logOpenGLDebugMessages->isChecked());
 	const int viewMode = this->ui.viewModeButtonGroup->checkedId();
 	if (viewMode != -1) {
 		setSetting<Setting::ViewMode>(static_cast<QMdiArea::ViewMode>(viewMode));
@@ -82,6 +83,7 @@
 	this->ui.selectedColorButton->setSelectedColor(setting<Setting::SelectedColor>());
 	this->ui.lineThickness->setValue(double_cast(setting<Setting::LineThickness>()));
 	this->ui.lineAntiAliasing->setChecked(setting<Setting::LineAntiAliasing>());
+	this->ui.logOpenGLDebugMessages->setChecked(setting<Setting::LogOpenGLDebugMessages>());
 	auto* const viewModeButton = this->ui.viewModeButtonGroup->button(setting<Setting::ViewMode>());
 	if (viewModeButton != nullptr) {
 		viewModeButton->setChecked(true);
--- a/src/settingseditor/settingseditor.ui	Mon Jun 20 18:40:22 2022 +0300
+++ b/src/settingseditor/settingseditor.ui	Mon Jun 20 19:49:56 2022 +0300
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>574</width>
-    <height>416</height>
+    <width>716</width>
+    <height>472</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -236,6 +236,33 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_2">
+      <attribute name="title">
+       <string>Debug</string>
+      </attribute>
+      <layout class="QFormLayout" name="formLayout_3">
+       <item row="1" column="1">
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="0" column="1">
+        <widget class="QCheckBox" name="logOpenGLDebugMessages">
+         <property name="text">
+          <string>Log OpenGL debug messages</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>

mercurial