Spec-Zone.ru › Qt 6.0

Класс QOpenGLDebugLogger

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

Заголовок: #include <QOpenGLDebugLogger>
CMake: find_package(Qt6 COMPONENTS OpenGL REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::OpenGL)
qmake: QT += opengl
С момента: Qt 5.1
Наследует: QObject
  • Список всех членов, включая унаследованные

Типы публичного доступа

перечисление LoggingMode { АсинхроннаяРегистрация, СинхроннаяРегистрация }

Свойства

  • 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 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 может привести к остановке целого участка приложения, не отображая ничего на экране.

Единственный способ убедиться, что от 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 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 обычно являются многопоточными и асинхронными, и поэтому не гарантируется относительный порядок и временные характеристики сообщений об отладке.

С другой стороны, синхронная запись имеет высокую нагрузку, но реализация 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, источник, тип, серьезность); атрибуты сообщения не образуют иерархию любого рода. Следует быть внимательным к порядку вызовов enableMessages() и disableMessages(), так как это изменит, какие сообщения будут включены/выключены.

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

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

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

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

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

См. также QOpenGLDebugMessage.

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

перечисление QOpenGLDebugLogger::LoggingMode

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

Константа Значение Описание
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().

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

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 будет использовать очереди для межпоточных событий сигналов, но если вы принудительно установите тип соединения на Direct, то вы должны учитывать потенциальные конфликты в слотах, подключенных к этому сигналу.

Если регистрация была запущена в режиме 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, а также любого 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().

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(). (Он совпадает, если сообщение содержит только данные ASCII с 7 битами, что типично для сообщений отладки.)

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

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

Spec-Zone.ru

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