QOpenGLDebugLogger Class
QOpenGLDebugLogger を使用すると、OpenGL のデバッグメッセージをログに記録できます。詳細...
| ヘッダー: | #include <QOpenGLDebugLogger> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS OpenGL) target_link_libraries(mytarget PRIVATE Qt6::OpenGL) |
| qmake: | QT += opengl |
| 継承元: | QObject |
- 継承されたメンバーを含むすべてのメンバーの一覧
- QOpenGLDebugLogger は、3D レンダリングの一部です。
パブリック型
| enum | LoggingMode { AsynchronousLogging, SynchronousLogging } |
プロパティ
- loggingMode : LoggingMode
パブリック関数
| QOpenGLDebugLogger(QObject *parent = nullptr) | |
| virtual | ~QOpenGLDebugLogger() |
| void | disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity) |
| void | disableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType) |
| void | enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity) |
| void | enableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType) |
| bool | initialize() |
| bool | isLogging() const |
| QList<QOpenGLDebugMessage> | loggedMessages() const |
| QOpenGLDebugLogger::LoggingMode | loggingMode() const |
| qint64 | maximumMessageLength() const |
| void | popGroup() |
| void | pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource) |
パブリックスロット
| void | logMessage(const QOpenGLDebugMessage &debugMessage) |
| void | startLogging(QOpenGLDebugLogger::LoggingMode loggingMode = AsynchronousLogging) |
| void | stopLogging() |
シグナル
| void | messageLogged(const QOpenGLDebugMessage &debugMessage) |
詳細な説明
はじめに
OpenGLプログラミングは、非常にエラーが発生しやすいものです。多くの場合、OpenGLへの1回の呼び出しが失敗するだけで、アプリケーションの特定の部分全体が動作しなくなり、画面に何も表示されなくなってしまいます。
OpenGLの実装からエラーが返されていないことを確実に確認する唯一の方法は、API呼び出しのたびにglGetError でチェックすることです。さらに、OpenGLのエラーは積み重なるため、glGetErrorは常に次のようなループ内で使用する必要があります:
GLenum error = GL_NO_ERROR;
do {
error = glGetError();
if (error != GL_NO_ERROR) {
// handle the error
}
} while (error != GL_NO_ERROR);エラースタックをクリアしようとする場合は、GL_NO_ERRORが返されるまで処理を続行するだけでなく、GL_CONTEXT_LOSTが返された場合は処理を中断するようにしてください。このエラー値は繰り返し発生するからです。
(アプリケーション開発者として)関心のある情報は他にも多くあります。例えば、パフォーマンスの問題や、非推奨APIの使用に関する警告などです。こうした種類のメッセージは、通常のOpenGLエラー報告メカニズムでは報告されません。
QOpenGLDebugLoggerは、OpenGLデバッグログへのアクセスを提供することで、これらの問題に対処することを目的としています。お使いのOpenGL実装がこれをサポートしている場合(GL_KHR_debug 拡張機能を公開している場合)、OpenGLサーバーからのメッセージは、内部のOpenGLログに記録されるか、OpenGLから生成される「リアルタイム」でリスナーに渡されます。
QOpenGLDebugLogger は、これら両方の動作モードをサポートしています。両者の違いについては、以下のセクションを参照してください。
OpenGL デバッグコンテキストの作成
効率上の理由から、OpenGLコンテキストがデバッグコンテキストでない限り、OpenGLの実装ではデバッグ出力を一切生成しないことが許容されています。Qtからデバッグコンテキストを作成するには、QOpenGLContext オブジェクトの作成に使用するQSurfaceFormat に対して、QSurfaceFormat::DebugContext フォーマットオプションを設定する必要があります:
QSurfaceFormat format;
// asks for a OpenGL 3.2 debug context using the Core profile
format.setMajorVersion(3);
format.setMinorVersion(2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setOption(QSurfaceFormat::DebugContext);
QOpenGLContext *context = new QOpenGLContext;
context->setFormat(format);
context->create();なお、OpenGL Core Profile 3.2 を指定しているのはあくまでこの例の目的のためであり、このクラスはGL_KHR_debug 拡張機能の利用可能性に依存しているため(後述)、特定のOpenGLやOpenGL ESのバージョンに縛られることはありません。
QOpenGLDebugLoggerの作成と初期化
QOpenGLDebugLoggerは、QObject を継承した単純なクラスです。他のすべてのQObject サブクラスと同様に、インスタンスを作成し(必要に応じて親オブジェクトを指定します)、Qt OpenGLの他の関数と同様に、現在のOpenGLコンテキストが存在する間にinitialize()を呼び出して、使用前に初期化する必要があります。
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
logger->initialize(); // initializes in the current context, i.e. ctxOpenGLによってログに記録されたメッセージにアクセスするには、コンテキストでGL_KHR_debug 拡張機能が利用可能である必要があることに注意してください。この拡張機能の有無は、以下を呼び出すことで確認できます:
ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"));ここで、ctx は有効なQOpenGLContext です。拡張機能が利用できない場合、initialize() は false を返します。
OpenGL内部デバッグログの読み取り
OpenGLの実装では、デバッグメッセージの内部ログが保持されています。このログに記録されたメッセージは、loggedMessages() 関数を使用して取得できます:
constQList<QOpenGLDebugMessage>messages= logger->loggedMessages();
for(constQOpenGLDebugMessage&message: messages)
qDebug() << message;内部ログの容量には制限があります。容量がいっぱいになると、新しいメッセージを受け入れるスペースを確保するために、古いメッセージが破棄されます。loggedMessages() を呼び出すと、内部ログも空になります。
デバッグメッセージを確実に失わないようにするには、この関数を呼び出す代わりに、リアルタイムロギングを使用する必要があります。ただし、コンテキストの作成からリアルタイムロギングの有効化までの間(あるいは、一般的にリアルタイムロギングが無効になっている間)には、デバッグメッセージが生成される可能性があります。
メッセージのリアルタイムロギング
また、実装によって生成されるデバッグメッセージのストリームを OpenGL サーバーから受信することも可能です。これを行うには、適切なスロットをmessageLogged() シグナルに接続し、startLogging() を呼び出してロギングを開始する必要があります:
connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);
logger->startLogging();同様に、stopLogging() 関数を呼び出すことで、いつでもロギングを無効にすることができます。
リアルタイムロギングは、startLogging() に渡されるパラメータに応じて、非同期または同期のいずれかになります。 非同期モード(オーバーヘッドが非常に小さいためデフォルト)でロギングを行う場合、OpenGL 実装はいつでもメッセージを生成することができ、また、それらのメッセージのロギングを引き起こした OpenGL コマンドの順序とは異なる順序で生成されることもあります。 また、メッセージは、コンテキストが現在バインドされているスレッドとは異なるスレッドから生成される場合もあります。これは、OpenGL 実装は通常、高度にスレッド化され、非同期であるためであり、したがって、デバッグメッセージの相対的な順序やタイミングについては保証されません。
一方、同期モードでのログ出力はオーバーヘッドが大きくなりますが、OpenGL 実装は、特定のコマンドによって生成されたすべてのメッセージが、そのコマンドが戻る前に、かつ OpenGL コンテキストがバインドされているのと同じスレッドから、順番通りに受信されることを保証します。
つまり、同期モードでロギングを行う場合、OpenGLアプリケーションをデバッガで実行し、messageLogged()シグナルに接続されたスロットにブレークポイントを設定することで、バックトレースからロギングされたメッセージを発生させた正確な呼び出しを確認することができます。これは、OpenGLの問題をデバッグする際に非常に有用です。 なお、OpenGLのレンダリングが別のスレッドで行われている場合は、実際のバックトレースを確認できるようにするために、シグナル/スロットの接続タイプをQt::DirectConnection に強制設定する必要があります。
ロギングモードの詳細については、LoggingMode 列挙型のドキュメントを参照してください。
注: リアルタイムログ記録が有効になっている場合 、デバッグメッセージは内部の OpenGL デバッグログに挿入されなくなります。ただし、内部ログにすでに存在するメッセージは削除されず、messageLogged() シグナルを通じて出力されることもありません。 リアルタイムロギングが開始される前に一部のメッセージが生成され(その結果、内部の OpenGL ログに残される)、startLogging() を呼び出した後は、そのログにメッセージが含まれていないかを常に確認することが重要です。
デバッグログへのメッセージの挿入
アプリケーションやライブラリは、デバッグログにカスタムメッセージを挿入することができます。例えば、関連する OpenGL コマンドのグループにマークを付け、それらから送信される可能性のあるメッセージを後で特定できるようにするためです。
これを行うには、createApplicationMessage() またはcreateThirdPartyMessage() を呼び出してQOpenGLDebugMessage オブジェクトを作成し、logMessage() を呼び出してログに挿入します:
QOpenGLDebugMessage message =
QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("Custom message"));
logger->logMessage(message);なお、OpenGLの実装によっては、デバッグログに挿入できるメッセージの長さにベンダー固有の制限が設けられている場合があります。この長さは、maximumMessageLength() メソッドを呼び出すことで取得できます。制限を超える長さのメッセージは自動的に切り捨てられます。
デバッグ出力の制御
QOpenGLDebugMessage また、デバッグメッセージにフィルタを適用して、ログに記録されるメッセージの量を制限することも可能です。enableMessages() を呼び出すとメッセージのログ記録を有効にし、disableMessages() を呼び出すと無効にできます。デフォルトでは、すべてのメッセージがログに記録されます。
以下の条件でメッセージを選択し、その表示を有効または無効にすることができます:
- ソース、タイプ、および重大度(選択対象にすべての ID を含める場合);
- ID、ソース、およびタイプ(選択対象にすべての重大度を含む場合);
なお、特定のメッセージに対する「有効」ステータスは (id, source, type, severity) タプルのプロパティであり、メッセージ属性はどのような階層構造も形成しません。enableMessages() およびdisableMessages() の呼び出し順序には注意が必要です。呼び出し順序によって、有効/無効になるメッセージが変化するためです。
メッセージ本文自体によるフィルタリングはできません。アプリケーション側で独自に処理する必要があります(messageLogged() シグナルに接続されたスロット内、またはloggedMessages() を通じて内部デバッグログからメッセージを取得した後)。
有効/無効の状態の管理を簡略化するため、QOpenGLDebugMessage はdebug groups の概念もサポートしています。デバッググループには、デバッグメッセージの有効/無効設定のグループが含まれます。 さらに、デバッググループはスタック構造で管理されており、pushGroup() およびpopGroup() を呼び出すことで、それぞれグループのプッシュやポップを行うことができます。(OpenGL コンテキストが作成されると、スタックにはすでにグループが1つ存在しています)。
enableMessages() およびdisableMessages() 関数は、現在のデバッググループ、つまりデバッググループスタックの最上部に位置するグループの設定を変更します。
新しいグループがデバッググループスタックにプッシュされると、そのグループは、スタックの最上部にあったグループの設定を継承します。逆に、デバッググループをポップすると、スタックの最上部になったデバッググループの設定が復元されます。
デバッググループをスタックにプッシュ(またはポップ)すると、QOpenGLDebugMessage::GroupPushType (またはGroupPopType )型のデバッグメッセージが自動的に生成されます。
QOpenGLDebugMessageも参照してください 。
メンバタイプのドキュメント
enum QOpenGLDebugLogger::LoggingMode
LoggingMode 列挙型は、ロガーオブジェクトのロギングモードを定義します。
| 定数 | 値 | 説明 |
|---|---|---|
QOpenGLDebugLogger::AsynchronousLogging | 0 | OpenGL サーバーからのメッセージは非同期でログに記録されます。つまり、メッセージは、それを引き起こした対応する OpenGL アクションのしばらく後にログに記録される場合があり、OpenGL の実装によっては、順不同で受信されることさえあります。 OpenGL 実装は本質的に高度にスレッド化され、非同期であるため、このモードによるパフォーマンスへの影響はごくわずかです。 |
QOpenGLDebugLogger::SynchronousLogging | 1 | OpenGL サーバーからのメッセージは、同期的かつ順次ログに記録されます。OpenGL の実装は本質的に非常に非同期であるため、このモードではパフォーマンスに深刻な影響が出ますが、OpenGL コマンドによって生成されたメッセージは、対応するコマンドの実行が終了する前にログに記録されることが保証されているため、OpenGL の問題をデバッグするには非常に有用です。 したがって、messageLogged() シグナルにブレークポイントを設定し、バックトレースでどの OpenGL コマンドがそれを引き起こしたかを確認することができます。唯一の注意点として、複数のスレッドから OpenGL を使用している場合、messageLogged() シグナルに接続する際に、直接接続を強制する必要がある場合があります。 |
プロパティのドキュメント
[read-only] loggingMode : LoggingMode
このプロパティには、startLogging() に渡されたロギングモードが格納されます。
なお、ロギングが開始されている必要があります。そうでない場合、このプロパティの値は意味をなさなくなります。
アクセス関数:
| QOpenGLDebugLogger::LoggingMode | loggingMode() const |
startLogging() およびisLogging()も参照してください 。
メンバ関数のドキュメント
[explicit] QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = nullptr)
指定されたparent を使用して、新しいロガーオブジェクトを作成します。
注: ロギングを行うには、事前にオブジェクトを 初期化する必要があります。
initialize()も参照してください 。
[virtual noexcept] QOpenGLDebugLogger::~QOpenGLDebugLogger()
ロガーオブジェクトを破棄します。
void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
指定されたsources 、types 、およびseverities を持つメッセージ、ならびに任意のメッセージIDを持つメッセージのログ記録を無効にします。
現在のコントロールグループにおいて、ログ記録が無効化されます。
enableMessages()、pushGroup()、およびpopGroup()も参照してください 。
void QOpenGLDebugLogger::disableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)
指定されたids を持つメッセージについて、指定されたsources および指定されたtypes からのログ記録を、深刻度を問わず無効にします。
現在のコントロールグループ内で、ログ記録が無効化されます。
enableMessages()、pushGroup()、およびpopGroup()も参照してください 。
void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
指定されたsources 、types 、およびseverities を持つメッセージ、ならびに任意のメッセージIDを持つメッセージのログ記録を有効にします。
ログ記録は、現在のコントロールグループで有効になります。
disableMessages()、pushGroup()、およびpopGroup()も参照してください 。
void QOpenGLDebugLogger::enableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)
指定されたids を持つメッセージについて、指定されたsources からのもの、および指定されたtypes を持つもの、ならびにすべての重大度レベルのメッセージのログ記録を有効にします。
ログ記録は、現在の制御グループで有効になります。
disableMessages()、pushGroup()、およびpopGroup()も参照してください 。
bool QOpenGLDebugLogger::initialize()
現在の OpenGL コンテキストでオブジェクトを初期化します。初期化を成功させるには、コンテキストがGL_KHR_debug 拡張機能をサポートしている必要があります。ログ出力を行うには、事前にオブジェクトを初期化する必要があります。
同じコンテキストからこの関数を複数回呼び出しても問題ありません。
この関数は、以前に初期化されたオブジェクトのコンテキストを変更するためにも使用できます。ただし、この場合、この関数を呼び出す時点でオブジェクトがログ記録を行っていない必要があります。
ロガーが正常に初期化された場合はtrue を返し、そうでない場合はfalseを返します。
QOpenGLContextも参照してください 。
bool QOpenGLDebugLogger::isLogging() const
このオブジェクトが現在ログを記録している場合は `true ` を返し、そうでない場合は `false` を返します。
startLogging()も参照してください 。
[slot] void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage)
OpenGL デバッグログに「debugMessage 」というメッセージを挿入します。これにより、アプリケーションやライブラリは、OpenGL アプリケーションのデバッグを容易にするカスタムメッセージを挿入できるようになります。
注: debugMessage のソースには `QOpenGLDebugMessage::ApplicationSource ` または `QOpenGLDebugMessage::ThirdPartySource ` が指定されており、有効な型および重大度を持つ必要があります。そうでない場合、ログには挿入されません。
注: ログ出力を行うには、オブジェクトを 事前に初期化する必要があります。
initialize()も参照してください 。
QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const
OpenGLの内部デバッグログにある利用可能なメッセージをすべて読み取り、それらを返します。さらに、この関数は内部デバッグログをクリアするため、その後の呼び出しでは、すでに返されたメッセージが再度返されることはありません。
startLogging()も参照してください 。
QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const
オブジェクトのロギングモードを返します。
注: プロパティ `loggingMode`のゲッター 関数です。
関連項目: startLogging()。
qint64 QOpenGLDebugLogger::maximumMessageLength() const
logMessage() に渡されたメッセージのテキストについて、サポートされる最大長(バイト単位)を返します。これはデバッググループ名の最大長でもあります。これは、グループのプッシュやポップを行うと、デバッググループ名をメッセージテキストとしてメッセージが自動的にログに記録されるためです。
メッセージ本文が長すぎる場合、QOpenGLDebugLogger によって自動的に切り捨てられます。
注:メッセージ本文は OpenGL に渡される際に UTF-8 でエンコードされるため、そのバイト数は通常、QString::length() などが返す UTF-16 コード単位の数とは一致しません。(ただし、メッセージが 7 ビット ASCII のみのデータを含む場合は一致します。これはデバッグメッセージでは一般的なケースです。)
[signal] void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)
このシグナルは、OpenGL サーバーから(debugMessage 引数でラップされた)デバッグメッセージが記録されたときに発せられます。
OpenGLの実装によっては、このシグナルは、受信者が存在するスレッドとは異なるスレッドから、さらにはこのオブジェクトが初期化されたQOpenGLContext が存在するスレッドとは異なるスレッドからさえも発火される可能性があります。 さらに、このシグナルは複数のスレッドから同時に発火される可能性があります。通常、Qt はスレッド間のシグナル発火にキュー接続を利用するため、これは問題にはなりませんが、接続タイプを Direct に強制設定する場合は、このシグナルに接続されたスロットで競合が発生する可能性があることに注意する必要があります。
SynchronousLogging モードでロギングが開始されている場合、OpenGLは、このシグナルがQOpenGLContext がバインドされたのと同じスレッドから発火することを保証し、並行した呼び出しは決して発生しません。
注:ロギングが 開始されている必要があります。そうでない場合、このシグナルは発行されません。
startLogging()も参照してください 。
void QOpenGLDebugLogger::popGroup()
デバッググループスタックから最上位のデバッググループを取り出します。グループの取り出しに成功した場合、OpenGL は、取り出されたグループのメッセージ、ID、ソースと一致する、タイプ「QOpenGLDebugMessage::GroupPopType 」、重大度「QOpenGLDebugMessage::NotificationSeverity 」のメッセージを自動的にログに記録します。
デバッググループをポップすると、デバッググループスタックの先頭となるグループのメッセージフィルタリング設定が復元されます。
注: デバッググループを管理するには、オブジェクトを 事前に初期化する必要があります。
pushGroup()も参照してください 。
void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource)
名前が「name 」、IDが「id 」、ソースが「source 」のデバッググループを、デバッググループスタックにプッシュします。グループのプッシュに成功すると、OpenGLは自動的に、メッセージ「name 」、ID「id 」、ソース「source 」、タイプ「QOpenGLDebugMessage::GroupPushType 」、重大度「QOpenGLDebugMessage::NotificationSeverity 」のメッセージをログに記録します。
新しくプッシュされたグループは、スタックの最上部にあったグループと同じフィルタリング設定を継承します。つまり、新しいグループをプッシュしてもフィルタリングは変更されません。
注: source は 、QOpenGLDebugMessage::ApplicationSource またはQOpenGLDebugMessage::ThirdPartySource のいずれかでなければなりません。そうでない場合、グループはプッシュされません。
注: デバッググループを管理する前に、オブジェクトを 初期化する必要があります。
関連項目: popGroup()、enableMessages()、およびdisableMessages()。
[slot] void QOpenGLDebugLogger::startLogging(QOpenGLDebugLogger::LoggingMode loggingMode = AsynchronousLogging)
OpenGL サーバーからのメッセージのロギングを開始します。新しいメッセージを受信すると、messageLogged() シグナルが発信され、ロギングされたメッセージが引数として渡されます。
loggingMode ログ記録を非同期(デフォルト)にするか、同期にするかを指定します。
QOpenGLDebugLogger ログ記録の開始時にGL_DEBUG_OUTPUT およびGL_DEBUG_OUTPUT_SYNCHRONOUS の値を記録し、ログ記録の停止時にそれらを元に戻します。さらに、この関数が呼び出された際に設定されていたユーザー定義の OpenGL デバッグコールバックは、ログ記録が停止された際に復元されます。QOpenGLDebugLogger を使用することで、ログ記録中も既存のコールバックが引き続き呼び出されるようになります。
注: ロギングを一旦停止して再開始しない限り、ロギングモードを変更することはできません 。これは将来の Qt バージョンで変更される可能性があります。
注: ロギングを行うには、オブジェクトを 事前に初期化する必要があります。
関連項目: stopLogging() およびinitialize()。
[slot] void QOpenGLDebugLogger::stopLogging()
OpenGL サーバーからのメッセージのログ記録を停止します。
startLogging()も参照してください 。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.