Класс QOpenGLDebugLogger
Класс QOpenGLDebugLogger позволяет регистрировать сообщения отладки OpenGL. Подробнее...
| Заголовок: | #include <QOpenGLDebugLogger> |
| qmake: | QT += gui |
| С момента: | Qt 5.1 |
| Наследует: | QObject |
Типы публичного доступа
| Перечисление | LoggingMode { АсинхронныйЛог, СинхронныйЛог } |
Свойства
- loggingMode : const LoggingMode
- 1 свойство унаследовано от QObject
Функции публичного доступа
| QOpenGLDebugLogger(QObject *parent = Q_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 |
| LoggingMode | loggingMode() const |
| qint64 | maximumMessageLength() const |
| void | popGroup() |
| void | pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource) |
- 32 функции публичного доступа унаследованы от QObject
Свойства с публичным доступом
| void | logMessage(const QOpenGLDebugMessage &debugMessage) |
| void | startLogging(LoggingMode loggingMode = AsynchronousLogging) |
| void | stopLogging() |
- 1 свойство с публичным доступом унаследовано от QObject
Сигналы
| void | messageLogged(const QOpenGLDebugMessage &debugMessage) |
- 2 сигнала унаследованы от QObject
Дополнительные унаследованные члены
- 11 статических публичных членов унаследованы от QObject
- 9 защищенных функций унаследованы от QObject
Подробное описание
Класс QOpenGLDebugLogger позволяет регистрировать сообщения отладки OpenGL.
Введение
Программирование 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); Также нас интересует много другой информации (как разработчиков приложений), например, проблемы с производительностью или предупреждения об использовании устаревших 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 обычно являются высокопоточными и асинхронными, и поэтому никакие гарантии не даются относительно относительного порядка и времени генерации сообщений отладки.
END_OF_DOCUMENT_MARKERС другой стороны, вход в синхронном режиме имеет большой overhead, но реализация OpenGL гарантирует, что все сообщения, вызванные определенной командой, будут получены в порядке, до возврата команды, и из того же потока, к которому привязан контекст OpenGL.
Это означает, что при входе в синхронном режиме вы сможете запустить свою 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(). По умолчанию все сообщения регистрируются.
Можно включить или отключить сообщения, выбрав их по:
- источнику, типу и степени серьезности (и включив все идентификаторы в выборку);
- идентификатору, источнику и типу (и включив все степени серьезности в выборку).
Обратите внимание, что состояние «включено» для данного сообщения является свойством кортежа (идентификатор, источник, тип, степень серьезности); атрибуты сообщения не образуют иерархии любого рода. Вы должны быть внимательны к порядку вызовов 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().
Обратите внимание, что ведение журнала должно быть начато, иначе значение этого свойства будет бессмысленным.
Функции доступа:
| LoggingMode | loggingMode() const |
См. также startLogging() и isLogging().
Документация по функциям членов
QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = Q_NULLPTR)
Создает новый объект логгера с заданным parent.
Примечание: Объект должен быть инициализирован перед началом ведения журнала.
См. также initialize().
QOpenGLDebugLogger::~QOpenGLDebugLogger()
Удаляет объект логгера.
void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
Отключает ведение журнала сообщений с указанными источниками, типами и степенями серьезности и любым идентификатором сообщения.
Ведение журнала будет отключено в текущей группе управления.
См. также enableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)
Отключает ведение журнала сообщений с заданными идентификаторами, источниками и типами и любой степенью серьезности.
Ведение журнала будет отключено в текущей группе управления.
См. также enableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
Включает ведение журнала сообщений из указанных источников, типов и с заданными степенями серьезности и любым идентификатором сообщения.
Ведение журнала будет включено в текущей группе управления.
См. также disableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::enableMessages(const QVector<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().
LoggingMode QOpenGLDebugLogger::loggingMode() const
Возвращает режим протоколирования объекта.
Примечание: Метод-геттер для свойства loggingMode.
См. также startLogging().
qint64 QOpenGLDebugLogger::maximumMessageLength() const
Возвращает максимальную поддерживаемую длину, в байтах, текста сообщений, передаваемых методу logMessage(). Это также максимальная длина имени группы отладки, поскольку добавление или удаление групп автоматически записывает сообщение с именем группы отладки в качестве текста сообщения.
Если текст сообщения слишком длинный, он автоматически обрезается классом QOpenGLDebugLogger.
Примечание: Тексты сообщений кодируются в UTF-8 при передаче в OpenGL, поэтому их размер в байтах обычно не соответствует количеству единиц кодировки UTF-16, как возвращает, например, QString::length(). (Исключение составляет случай, если сообщение содержит только данные 7-битной ASCII, что характерно для сообщений отладки.)
[signal] void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)
Этот сигнал испускается при протоколировании сообщения отладки (заключенного в аргументе debugMessage) с сервера OpenGL.
В зависимости от реализации OpenGL, этот сигнал может испускаться из других потоков, помимо тех, в которых живет(ют) получатель(и), и даже из потока, отличного от того, в котором живет QOpenGLContext, в котором был инициализирован этот объект. Кроме того, сигнал может испускаться из нескольких потоков одновременно. Обычно это не проблема, так как Qt будет использовать очереди для межпотокового испускания сигналов, но если вы принудительно установите тип соединения на прямой, то вам необходимо учитывать потенциальные проблемы гонок в слотах, подключенных к этому сигналу.
Если протоколирование запущено в режиме SynchronousLogging, OpenGL гарантирует, что этот сигнал будет испускаться из того же потока, к которому привязан QOpenGLContext, и одновременные вызовы никогда не будут происходить.
Примечание: Протоколирование должно быть запущено, иначе этот сигнал не будет испускаться.
См. также startLogging().
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().
[slot] void QOpenGLDebugLogger::startLogging(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().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.9/qopengldebuglogger.html