glDrawElements вылетает в драйвере | подсказки отладки

Укороченная версия: Как может произойти сбой (недопустимый доступ к памяти исключение / исключение nullptr) внутри glDrawElements/glDrawElementsInstanced отлаживаться?

Длинная версия:
У вас есть путь к коду рендеринга OpenGL, который использует VAOsи совершает рендеринг через вызов glDrawElements или же glDrawElementsInstanced, Этот кодовый путь работает правильно большую часть времени. Мы говорим о «коде редактора», что означает: данные могут быть любой геометрии и с большой вероятностью будут часто меняться.

Но иногда после внесения воспроизводимых изменений данных просто происходит сбой в glDrawElements* код водителя (т.е. glDrawElements вызывается, параметры функции в порядке, сбой происходит внутри glDrawElements).

Как вы можете продолжить отладку этой проблемы?

P.S .:

  • вопрос с автоответчиком: все исследовательские усилия пошли на ответ!
  • это нацелено на код редактора. Для простых демонстраций такие сбои в основном вызваны тем, что кодировщик неправильно понимает требования glDrawElements, и, как таковой, путь кода будет либо работать, либо нет — в этих случаях см .:

-3

Решение

Сначала должно быть ясно, что может вызвать сбои в драйвере. В большинстве случаев это плохой доступ к памяти.

Что может вызвать доступ к плохой памяти внутри драйвера?

  • GL_ELEMENT_ARRAY_BUFFERпривязка изменилась как-то (таким образом glDrawElements может вызвать доступ за пределы памяти этого объекта)
  • GL_ELEMENT_ARRAY_BUFFERсодержимое изменилось, возможно, ссылаясь на неинициализированные / несуществующие данные вершин (доступ VBO за пределы)
  • любой из связанных GL_ARRAY_BUFFER данные объектов были изменены, поэтому больше не содержали ссылочные данные вершин (доступ VBO за пределы)
  • или даже больше таких изменений. Нарушения доступа внутри glDrawElements* в основном означает, что к любому объекту, связанному в состоянии VAO, был получен доступ за пределами.

Без дополнительного кода отладки эти нарушения доступа очень трудно уловить. Я предлагаю вставить отладочный вывод прямо перед вызовом glDrawElements*, Выходные данные Debug должны запрашивать все доступные привязки и информацию, чтобы вы могли сравнить параметры «когда он работает» с «когда он падает» и выяснить, что искать, затем.

Моя функция отладки выглядит так:

void debugVAOState(std::string baseMessage)
{
baseMessage.append( " ... querying VAO state:\n" );
int vab, eabb, eabbs, mva, isOn( 1 ), vaabb;
glGetIntegerv( GL_VERTEX_ARRAY_BINDING, &vab );
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eabb );
glGetBufferParameteriv( GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &eabbs );

baseMessage.append( "  VAO: " + std::to_string( vab ) + "\n" );
baseMessage.append( "  IBO: " + std::to_string( eabb ) + ", size=" + std::to_string( eabbs )  + "\n" );

glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &mva );
for ( unsigned i = 0; i < mva; ++i )
{
glGetVertexAttribiv( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &isOn );
if ( isOn )
{
glGetVertexAttribiv( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vaabb );
baseMessage.append( "  attrib #" + std::to_string( i ) + ": VBO=" + std::to_string( vaabb ) + "\n" );
}
}
OutputDebugString( baseMessage.c_str() );
}

Это все еще просто и выводит только наиболее ценную информацию, чтобы увидеть, изменились ли вышеупомянутые привязки как-то. Но это помогло мне найти многочисленные сбои, которые произошли от агрессивной оптимизации OpenGL.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]