Spec-Zone.ru › Qt 5.15

Класс QOpenGLDebugLogger

Класс QOpenGLDebugLogger позволяет регистрировать сообщения отладки OpenGL. Подробнее...

Заголовок: #include <QOpenGLDebugLogger>
qmake: QT += gui
С момента: Qt 5.1
Наследует: QObject

Этот класс был представлен в Qt 5.1.

  • Список всех членов, включая унаследованные

Типы

перечисление LoggingMode { AsynchronousLogging, SynchronousLogging }

Свойства

  • loggingMode : const LoggingMode

Открытые функции

QOpenGLDebugLogger(QObject *parent = nullptr)
виртуальный ~QOpenGLDebugLogger()
void disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
void disableMessages(const QVector<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 QVector<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 может привести к остановке всей части приложения, без отображения чего-либо на экране.

Единственный способ быть уверенным, что из реализации OpenGL не возвращаются ошибки, — проверка с glGetError после каждого и каждого вызова API. Более того, ошибки 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 необходимо установить параметр QSurfaceFormat::DebugContext формата QSurfaceFormat, используемого для создания объекта QOpenGLContext:

    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 3.2 — это только для целей примера; этот класс не привязан к какой-либо конкретной версии OpenGL или OpenGL ES, так как он полагается на доступность GL_KHR_debug расширения (см. ниже).

Создание и инициализация QOpenGLDebugLogger

QOpenGLDebugLogger — это простой класс, производный от QObject. Как и все подклассы QObject, вы создаете экземпляр (и необязательно указываете родительский объект), и, как и другие функции OpenGL в Qt, вы обязательно должны инициализировать его перед использованием, вызвав initialize() при наличии текущего контекста OpenGL:

    QOpenGLContext *ctx = QOpenGLContext::currentContext();
    QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);

    logger->initialize(); // initializes in the current context, i.e. ctx

Обратите внимание, что GL_KHR_debug расширение должно быть доступно в контексте, чтобы получить доступ к сообщениям, зарегистрированным OpenGL. Вы можете проверить наличие этого расширения, вызвав:

    ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"))

где ctx — это действительный QOpenGLContext. Если расширение недоступно, initialize() вернет false.

Чтение внутреннего журнала отладки OpenGL

Реализации OpenGL хранят внутренний журнал сообщений отладки. Сообщения, сохраненные в этом журнале, можно получить, используя функцию loggedMessages():

    const QList<QOpenGLDebugMessage> messages = logger->loggedMessages();
    for (const QOpenGLDebugMessage &message : messages)
        qDebug() << message;

Внутренний журнал имеет ограниченный размер; когда он заполняется, более старые сообщения удаляются, чтобы освободить место для новых входящих сообщений. Когда вы вызываете loggedMessages(), внутренний журнал также будет очищен.

Если вы хотите быть уверенным, что не потеряете ни одного сообщения отладки, вы должны использовать протоколирование в реальном времени вместо вызова этой функции. Однако сообщения отладки все еще могут генерироваться в промежутке времени между созданием контекста и активацией протоколирования в реальном времени (или, вообще, когда протоколирование в реальном времени отключено).

Протоколирование сообщений в реальном времени

Также можно получить поток сообщений отладки с сервера OpenGL по мере их генерации реализацией. Для этого вам нужно подключить соответствующий слот к сигналу messageLogged() и начать протоколирование, вызвав startLogging():

    connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);
    logger->startLogging();

Аналогичным образом, протоколирование можно отключить в любое время, вызвав функцию stopLogging().

Протоколирование в реальном времени может быть асинхронным или синхронным, в зависимости от параметра, переданного в startLogging(). При протоколировании в асинхронном режиме (по умолчанию, так как он имеет очень низкую нагрузку) реализация OpenGL может генерировать сообщения в любое время и/или в порядке, отличном от порядка команд OpenGL, которые вызвали эти сообщения. Сообщения также могут генерироваться из потока, который отличается от потока, к которому в данный момент привязан контекст. Это связано с тем, что реализации OpenGL обычно сильно многопоточны и асинхронны, и поэтому никаких гарантий относительно относительного порядка и времени сообщений отладки не дается.

С другой стороны, протоколирование в синхронном режиме имеет высокую нагрузку, но реализация OpenGL гарантирует, что все сообщения, вызванные определенной командой, получены в порядке, перед возвратом команды и из того же потока, к которому привязан контекст OpenGL.

END_OF_DOCUMENT_MARKER

Это означает, что при входе в синхронном режиме вы сможете запустить свое приложение OpenGL в отладчике, установить контрольную точку на слоте, подключенном к сигналу messageLogged(), и увидеть в стеке вызовов точный вызов, который вызвал зарегистрированное сообщение. Это может быть чрезвычайно полезно для отладки проблемы с OpenGL. Обратите внимание, что если отрисовка OpenGL происходит в другом потоке, необходимо принудительно установить тип соединения сигнала/слота на Qt::DirectConnection, чтобы увидеть фактический стек вызовов.

Дополнительную информацию о режимах ведения журнала см. в документации перечисления LoggingMode.

Примечание: При включенном журнале в реальном времени сообщения об отладке не будут вставлены во внутренний журнал отладки OpenGL; сообщения, уже присутствующие во внутреннем журнале, не будут удалены, и не будут переданы через сигнал messageLogged(). Поскольку некоторые сообщения могут быть сгенерированы до начала ведения журнала в реальном времени (и, следовательно, останутся во внутреннем журнале OpenGL), важно всегда проверять, содержит ли он какие-либо сообщения после вызова startLogging().

Вставка сообщений в журнал отладки

Приложения и библиотеки могут вставлять пользовательские сообщения в журнал отладки, например, для маркировки группы связанных команд OpenGL и, следовательно, для возможности идентификации возможных сообщений, исходящих от них.

Для этого можно создать объект QOpenGLDebugMessage, вызвав createApplicationMessage() или createThirdPartyMessage(), а затем вставить его в журнал, вызвав logMessage():

    QOpenGLDebugMessage message =
        QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("Custom message"));

    logger->logMessage(message);

Обратите внимание, что реализации OpenGL имеют зависящую от поставщика ограничение на длину сообщений, которые можно вставить в журнал отладки. Это ограничение можно получить, вызвав метод maximumMessageLength(); сообщения, длиннее ограничения, автоматически обрезаются.

Управление выводом отладки

QOpenGLDebugMessage также может применять фильтры к сообщениям отладки и, следовательно, ограничивать количество регистрируемых сообщений. Вы можете включить или отключить регистрирование сообщений, вызвав enableMessages() и disableMessages() соответственно. По умолчанию все сообщения регистрируются.

Включить или отключить сообщения можно, выбрав их по:

  • источнику, типу и серьезности (включая все идентификаторы в выборе);
  • идентификатору, источнику и типу (включая все серьезности в выборе).

Обратите внимание, что состояние «включено» для данного сообщения является свойством кортежа (id, source, type, severity); атрибуты сообщения не образуют иерархии никакого рода. Следует быть внимательным к порядку вызовов enableMessages() и disableMessages(), так как это изменит, какие сообщения будут включены/выключены.

Фильтрация по самому тексту сообщения невозможна; приложения должны выполнять эту операцию самостоятельно (в слотах, подключенных к сигналу messageLogged() или после извлечения сообщений из внутреннего журнала отладки через loggedMessages()).

Для упрощения управления состояниями «включено/выключено», QOpenGLDebugMessage также поддерживает понятие debug groups. Группа отладки содержит группу конфигураций включения/выключения сообщений отладки. Кроме того, группы отладки организованы в стеке: можно добавить и удалить группы, вызвав pushGroup() и popGroup() соответственно. (При создании контекста OpenGL в стеке уже есть группа).

Функции enableMessages() и disableMessages() изменят конфигурацию в текущей группе отладки, то есть в группе, находящейся вверху стека групп отладки.

При добавлении новой группы в стек групп отладки она унаследует конфигурацию группы, которая ранее находилась вверху стека. И наоборот, удаление группы отладки восстановит конфигурацию группы отладки, которая становится новой верхней.

Добавление (соответственно, удаление) групп отладки также автоматически сгенерирует сообщение об отладке типа QOpenGLDebugMessage::GroupPushType (соответственно, GroupPopType).

См. также QOpenGLDebugMessage.

Документация по типам членов

enum QOpenGLDebugLogger::LoggingMode

Перечисление LoggingMode определяет режим ведения журнала объекта логгера.

Постоянная Значение Описание
QOpenGLDebugLogger::AsynchronousLogging 0 Сообщения с сервера OpenGL регистрируются асинхронно. Это означает, что сообщения могут быть зарегистрированы некоторое время после соответствующих действий OpenGL, которые их вызвали, и даже получены в неправильном порядке, в зависимости от реализации OpenGL. Этот режим имеет очень низкую нагрузку на производительность, так как реализации OpenGL по своей природе сильно многопоточны и асинхронны.
QOpenGLDebugLogger::SynchronousLogging 1 Сообщения с сервера OpenGL регистрируются синхронно и последовательно. Это существенно сказывается на производительности, так как реализации OpenGL по своей природе очень асинхронны; но это очень полезно для отладки проблем с OpenGL, так как OpenGL гарантирует, что сообщения, сгенерированные командой OpenGL, будут зарегистрированы до возвращения соответствующего выполнения команды. Таким образом, вы можете установить контрольную точку на сигнале messageLogged() и увидеть в стеке вызовов, какая команда OpenGL его вызвала; единственное замечание состоит в том, что если вы используете OpenGL из нескольких потоков, вам может потребоваться принудительно установить прямое соединение при подключении к сигналу messageLogged().

Документация по свойствам

loggingMode : const LoggingMode

Это свойство содержит режим ведения журнала, переданный в startLogging().

Обратите внимание, что ведение журнала должно быть начато, иначе значение этого свойства будет бессмысленным.

Функции доступа:

QOpenGLDebugLogger::LoggingMode loggingMode() const

См. также startLogging() и isLogging().

Документация по функциям-членам

QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = nullptr)

Создает новый объект логгера с заданным parent.

Примечание: Объект должен быть инициализирован перед началом ведения журнала.

См. также initialize().

[slot] void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage)

Вставляет сообщение debugMessage в журнал отладки OpenGL. Это позволяет приложениям или библиотекам вставлять пользовательские сообщения, которые могут облегчить отладку приложений OpenGL.

Примечание: debugMessage должен иметь QOpenGLDebugMessage::ApplicationSource или QOpenGLDebugMessage::ThirdPartySource в качестве источника, а также допустимый тип и серьезность; в противном случае он не будет вставлен в журнал.

Примечание: Объект должен быть инициализирован перед началом ведения журнала.

См. также initialize().

[signal] void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)

Этот сигнал испускается, когда сообщение об отладке (обернутое аргументом debugMessage) регистрируется с сервера OpenGL.

В зависимости от реализации OpenGL, этот сигнал может испускаться из других потоков, отличных от тех, в которых находятся получатели, и даже отличных от потока QOpenGLContext, в котором был инициализирован этот объект. Кроме того, сигнал может испускаться из нескольких потоков одновременно. Это обычно не проблема, так как Qt будет использовать очереди для испускания сигналов между потоками, но если вы принудительно устанавливаете тип соединения в «Прямое», то вы должны быть осведомлены о потенциальных конфликтах в слотах, подключенных к этому сигналу.

Если ведение журнала было начато в режиме SynchronousLogging, OpenGL гарантирует, что этот сигнал будет испускаться из того же потока, к которому привязан QOpenGLContext, и одновременные вызовы никогда не будут происходить.

Примечание: Ведение журнала должно быть начато, иначе этот сигнал не будет испускаться.

См. также startLogging().

[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().

[virtual] QOpenGLDebugLogger::~QOpenGLDebugLogger()

Уничтожает объект логгера.

void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)

Отключает протоколирование сообщений с указанными sources, types и severities и любым идентификатором сообщения.

Протоколирование будет отключено в текущей группе управления.

См. также enableMessages(), pushGroup() и popGroup().

void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)

Отключает протоколирование сообщений с указанными ids, sources и types и любой severity.

Протоколирование будет отключено в текущей группе управления.

См. также enableMessages(), pushGroup() и popGroup().

void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)

Включает протоколирование сообщений из указанных sources, types и severities и любого идентификатора сообщения.

Протоколирование будет включено в текущей группе управления.

См. также disableMessages(), pushGroup() и popGroup().

void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)

Включает протоколирование сообщений с указанными ids, sources и types и любой severity.

Протоколирование будет включено в текущей группе управления.

См. также disableMessages(), pushGroup() и popGroup().

bool QOpenGLDebugLogger::initialize()

Инициализирует объект в текущем контексте OpenGL. Контекст должен поддерживать GL_KHR_debug расширение для успешной инициализации. Объект должен быть инициализирован перед любым протоколированием.

Безопасно вызывать эту функцию несколько раз из одного контекста.

Также можно использовать эту функцию для изменения контекста ранее инициализированного объекта; в этом случае объект не должен выполнять протоколирование при вызове этой функции.

Возвращает true , если логгер успешно инициализирован; в противном случае — false.

См. также QOpenGLContext.

bool QOpenGLDebugLogger::isLogging() const

Возвращает true , если этот объект выполняет протоколирование в данный момент; в противном случае — false.

См. также startLogging().

QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const

Считывает все доступные сообщения в внутреннем журнале отладки OpenGL и возвращает их. Кроме того, эта функция очистит внутренний журнал отладки, так что последующие вызовы не вернут сообщения, которые уже были возвращены.

См. также startLogging().

QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const

Возвращает режим протоколирования объекта.

Примечание: Функция-получатель для свойства loggingMode.

См. также startLogging().

qint64 QOpenGLDebugLogger::maximumMessageLength() const

Возвращает максимальную поддерживаемую длину, в байтах, для текста сообщений, передаваемых в logMessage(). Это также максимальная длина имени группы отладки, так как создание или удаление групп автоматически протоколирует сообщение с именем группы отладки в качестве текста сообщения.

Если текст сообщения слишком длинный, он будет автоматически усечён классом QOpenGLDebugLogger.

Примечание: Тексты сообщений кодируются в UTF-8 при передаче в OpenGL, поэтому их размер в байтах обычно не совпадает с количеством единиц UTF-16, возвращаемых, например, QString::length(). (Это так, если сообщение содержит только данные 7-битного ASCII, что типично для сообщений отладки.)

void QOpenGLDebugLogger::popGroup()

Удаляет верхнюю группу отладки из стека групп отладки. Если группа успешно удалена, OpenGL автоматически протоколирует сообщение с идентификатором и источником, соответствующими удаленной группе, типом QOpenGLDebugMessage::GroupPopType и степенью важности QOpenGLDebugMessage::NotificationSeverity.

Удаление группы отладки восстановит настройки фильтрации сообщений для группы, которая становится верхней в стеке групп отладки.

Примечание: Объект должен быть инициализирован перед управлением группами отладки.

См. также pushGroup().

void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource)

Добавляет группу отладки с именем name, идентификатором id и источником source в стек групп отладки. Если группа успешно добавлена, OpenGL автоматически протоколирует сообщение с сообщением name, идентификатором id, источником source, типом QOpenGLDebugMessage::GroupPushType и степенью важности QOpenGLDebugMessage::NotificationSeverity.

Новая добавленная группа унаследует те же настройки фильтрации, что и группа, которая была вверху стека; другими словами, фильтрация не меняется при добавлении новой группы.

Примечание: source должен быть либо QOpenGLDebugMessage::ApplicationSource, либо QOpenGLDebugMessage::ThirdPartySource, иначе группа не будет добавлена.

Примечание: Объект должен быть инициализирован перед управлением группами отладки.

См. также popGroup(), enableMessages() и disableMessages().

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/qopengldebuglogger.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API