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は、Rendering in 3D に含まれています。
パブリックタイプ
enum | LoggingMode { AsynchronousLogging, SynchronousLogging } |
プロパティ
- loggingMode : const 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 format オプションを設定する必要があります:
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();
3.2のOpenGL Core Profileを要求するのは、この例のためだけであることに注意してください。このクラスは、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. ctx
OpenGLによって記録されたメッセージにアクセスするためには、GL_KHR_debug
拡張がコンテキストで利用可能でなければならないことに注意してください。OpenGLによって記録されたメッセージにアクセスするためには、 拡張機能がコンテキストで利用可能でなければならないことに注意してください:
ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"));
ここで、ctx
は有効なQOpenGLContext です。拡張機能が利用できない場合、initialize() は false を返します。
内部OpenGLデバッグ・ログの読み込み
OpenGLの実装は、デバッグメッセージの内部ログを保持します。このログに保存されたメッセージは、loggedMessages() 関数を使用して取得できます:
constQList<QOpenGLDebugMessage> messages= logger->loggedMessages();for(constQOpenGLDebugMessageメッセージ) 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 enum documentationを参照してください。
注: リアルタイム・ロギングが有効になると、デバッグ・メッセージは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、ソース、タイプ(そして全ての深刻度を含む)。
与えられたメッセージの "enabled" ステータスは、(id, source, type, severity) タプルのプロパティであることに注意してください。enableMessages() とdisableMessages() を呼び出す順番に注意する必要があります。どのメッセー ジが有効/無効になるかが変わってしまうからです。
messageLogged() シグナルに接続されたスロットで、あるいはloggedMessages() を通して内部デバッグ・ログにあるメッセージをフェッチした後で)アプリケーション側でフィルタリングを行う必要があります。
有効/無効ステータスの管理を簡素化するために、QOpenGLDebugMessage はdebug groups
の概念もサポートしています。 デバッグ・グループには、デバッグ・メッセージの有効/無効設定のグループが含まれます。さらに、デバッグ・グループはスタックで構成されます。pushGroup() とpopGroup() をそれぞれ呼び出すことで、グループをプッシュしたりポップしたりすることができます。(OpenGLコンテキストが作成されると、スタックにすでにグループが存在します)。
enableMessages() とdisableMessages() 関数は、現在のデバッグ・グループ、つまりデバッグ・グループ・スタックの最上位にあるグループの設定を変更します。
新しいグループがデバッグ・グループ・スタックにプッシュされると、それまでスタックの最上位にあったグループの構成が継承されます。その逆で、デバッググループをポップすると、新しい最上位になるデバッググルー プの構成が復元されます。
デバッグ・グループをプッシュ(それぞれポップ)すると、QOpenGLDebugMessage::GroupPushType (それぞれGroupPopType )タイプのデバッグ・メッセージも自動的に生成されます。
QOpenGLDebugMessageも参照のこと 。
メンバ型ドキュメント
enum QOpenGLDebugLogger::LoggingMode
LoggingMode enum は、ロガーオブジェクトのロギングモードを定義します。
定数 | 値 | 説明 |
---|---|---|
QOpenGLDebugLogger::AsynchronousLogging | 0 | OpenGLサーバーからのメッセージは、非同期にログに記録されます。これは、メッセージが、それを引き起こした対応するOpenGLアクションのしばらく後にログに記録され、OpenGL実装によっては、アウトオブオーダーで受信されることさえあることを意味します。このモードは、OpenGLの実装がもともとスレッド化され、非同期であるため、非常に低いパフォーマンス・ペナルティを持っています。 |
QOpenGLDebugLogger::SynchronousLogging | 1 | OpenGLサーバーからのメッセージは、同期的に順次記録されます。OpenGLの実装は本質的に非常に非同期なので、このモードはパフォーマンスに深刻な打撃を与えます。しかし、OpenGLコマンドによって生成されたメッセージが、対応するコマンドの実行が戻る前にログに記録されることをOpenGLが保証しているので、OpenGLの問題をデバッグするのに非常に便利です。したがって、messageLogged ()シグナルにブレークポイントを設置し、バックトレースでどのOpenGLコマンドがそれを引き起こしたかを確認することができます。唯一の注意点は、複数のスレッドからOpenGLを使用している場合、messageLogged ()シグナルに接続するときに直接接続を強制する必要があるかもしれないということです。 |
プロパティのドキュメント
[read-only]
loggingMode : const 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)
メッセージdebugMessage をOpenGLデバッグログに挿入します。これは、アプリケーションやライブラリが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 、idid 、ソースsource を持つデバッググループをデバッググループスタックにプッシュします。グループが正常にプッシュされると、OpenGLは自動的にメッセージname 、idid 、ソース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 は、ロギングが開始されたときに と の値を記録し、ロギングが停止されたときにそれらを戻します。さらに、この関数が呼び出されたときにインストールされたユーザー定義のOpenGLデバッグ・コールバックは、ロギングが停止されたときに元に戻されます。 は、既存のコールバックがロギング時にまだ呼び出されることを保証します。GL_DEBUG_OUTPUT
GL_DEBUG_OUTPUT_SYNCHRONOUS
QOpenGLDebugLogger
注意: ロギングを停止し、再び開始することなく、ロギングモードを変更することはできません。これは Qt の将来のバージョンで変更されるかもしれません。
注意: ロギングを行う前に、オブジェクトを初期化する必要があります。
stopLogging() とinitialize()も参照してください 。
[slot]
void QOpenGLDebugLogger::stopLogging()
OpenGLサーバーからのメッセージのロギングを停止する。
startLogging()も参照してください 。
© 2025 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.