Класс QOpenGLDebugLogger
Класс QOpenGLDebugLogger позволяет регистрировать сообщения об отладке OpenGL. Подробнее...
| Заголовок: | #include <QOpenGLDebugLogger> |
| qmake: | QT += gui |
| С тех пор: | Qt 5.1 |
| Наследует: | QObject |
Типы public
| перечисление | LoggingMode { АсинхроннаяРегистрация, СинхроннаяРегистрация } |
Свойства
- loggingMode : const LoggingMode
- 1 свойство унаследовано от QObject
Функции public
| QOpenGLDebugLogger(QObject *parent = nullptr) | |
| virtual | ~QOpenGLDebugLogger() |
| void | disableMessages(QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types, QOpenGLDebugMessage::Severities severities) |
| void | disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types) |
| void | enableMessages(QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types, QOpenGLDebugMessage::Severities severities) |
| void | enableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types) |
| 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) |
- 34 функции public, унаследованные от QObject
Свойства public
| void | logMessage(const QOpenGLDebugMessage &debugMessage) |
| void | startLogging(QOpenGLDebugLogger::LoggingMode loggingMode = AsynchronousLogging) |
| void | stopLogging() |
- 1 свойство public, унаследованное от QObject
Сигналы
| void | messageLogged(const QOpenGLDebugMessage &debugMessage) |
- 2 сигнала, унаследованные от QObject
Дополнительные унаследованные члены
- 1 переменная public, унаследованная от QObject
- 10 статических членов public, унаследованных от QObject
- 9 защищенных функций, унаследованных от QObject
- 2 защищенных переменных, унаследованных от 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 3.2 Core Profile приведен только для примера; этот класс не привязан к какой-либо конкретной версии 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().
Обратите внимание, что ведение журнала должно быть начато, иначе значение этого свойства будет бессмысленным.
Функции доступа:
| QOpenGLDebugLogger::LoggingMode | loggingMode() const |
См. также startLogging() и isLogging().
Документация по функциям членов
QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = nullptr)
Создаёт новый объект логгера с заданным parent.
Примечание: Объект должен быть инициализирован перед тем, как можно будет вести журнал.
См. также initialize().
[virtual] QOpenGLDebugLogger::~QOpenGLDebugLogger()
Удаляет объект логгера.
void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types, QOpenGLDebugMessage::Severities severities)
Отключает регистрацию сообщений с заданными источниками, заданными типами и заданными степенями критичности и любым идентификатором сообщения.
Регистрация будет отключена в текущей группе управления.
См. также enableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types)
Отключает регистрацию сообщений с заданными идентификаторами, из заданных источников и заданных типов и любой степени критичности.
Регистрация будет отключена в текущей группе управления.
См. также enableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types, QOpenGLDebugMessage::Severities severities)
Включает регистрацию сообщений из заданных источников, заданных типов и заданных степеней критичности и любого идентификатора сообщения.
Регистрация будет включена в текущей группе управления.
См. также disableMessages(), pushGroup() и popGroup().
void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources, QOpenGLDebugMessage::Types types)
Включает протоколирование сообщений с заданными 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.
Примечание: Тексты сообщений кодируются в 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(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().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/qopengldebuglogger.html