Ошибка при вызове glGetTexImage (atioglxx.dll)

#opengl

#opengl

Вопрос:

Я сталкиваюсь со сложной проблемой на некоторых картах ATI (Radeon X1650, X1550 и других).

Сообщение выглядит так: «Нарушение доступа по адресу 6959DD46 в модуле ‘atioglxx.dll ‘. Считывание адреса 00000000»

Это происходит в этой строке:

 glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_FLOAT,P);
  

Примечание:

  • Установлены последние графические драйверы.
  • Он отлично работает на других картах.

Вот что я пробовал до сих пор (с утверждениями в коде):

  • Что указатель P действителен и выделено достаточно памяти для хранения изображения
  • Текстурирование включено: glIsEnabled(GL_TEXTURE_2D)
  • Проверьте, является ли текущая текстура той, которую я ожидаю: glGetIntegerv(GL_TEXTURE_2D_BINDING)
  • Проверьте, что текущая связанная текстура имеет ожидаемые размеры: glGetTexLevelParameteriv( GL_TEXTURE_WIDTH / HEIGHT )
  • Проверьте, не было ли сообщений об ошибках: glGetError

Он проходит все эти тесты, а затем все равно выдает сообщение с ошибкой.

Я чувствую, что перепробовал все, и у меня больше нет идей. Я действительно надеюсь, что какой-нибудь GL-guru здесь сможет помочь!

Редактировать:

После того, как я пришел к выводу, что это, вероятно, ошибка драйвера, я также опубликовал об этом здесь: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflatamp;Number=295137#Post295137

Я также пробовал GL_PACK_ALIGNMENT, но это не помогло.

Проведя еще одно исследование, я обнаружил, что это произошло только с текстурами, которые я ранее заполнил пикселями, используя вызов glCopyTexSubImage2D. Таким образом, я мог бы создать обходной путь, заменив вызов glCopyTexSubImage2D вызовами glReadPixels, а затем glTexImage2D вместо этого.

Вот мой обновленный код:

 {
  glCopyTexSubImage2D cannot be used here because the combination of calling
  glCopyTexSubImage2D and then later glGetTexImage on the same texture causes
  a crash in atioglxx.dll on ATI Radeon X1650 and X1550.
  Instead we copy to the main memory first and then update.
}
//    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, PixelWidth, PixelHeight);  //**
GetMem(P, PixelWidth * PixelHeight * 4);
glReadPixels(0, 0, PixelWidth, PixelHeight, GL_RGBA, GL_UNSIGNED_BYTE, P);
SetMemory(P,GL_RGBA,GL_UNSIGNED_BYTE);
  

Комментарии:

1. Звучит как ошибка драйвера. Драйверы OpenGL от ATI имеют плохую репутацию с точки зрения стабильности. Функции, не используемые многими программами, могут выйти из строя. Извлечение изображения текстуры — это редко используемая функция. Поскольку вы уже исключили все возможные причины сбоя, я предлагаю вам сообщить об этом как об ошибке в AMD / ATI.

2. Хорошо, спасибо, я опубликую на opengl.org тогда форум драйверов. Похоже, там работает пара инженеров AMD.

3. 1 за то, что попробовал все правильные вещи и перечислил их в своем вопросе. Я согласен, что это звучит как ошибка драйвера. Обязательно обновите этот вопрос, если услышите что-нибудь от разработчика ATI 🙂

4. Я нашел обходной путь, смотрите Мой обновленный вопрос.

Ответ №1:

Вы могли бы позаботиться о GL_PACK_ALIGNEMENT. Этот параметр указывает ближайшее количество байтов для упаковки текстуры. Т.е., если у вас изображение размером 645 пикселей:

  • При GL_PACK_ALIGNEMENT равном 4 (значение по умолчанию) у вас будет 648 пикселей.
  • При GL_PACK_ALIGNEMENT равном 1 у вас будет 645 пикселей.

Поэтому убедитесь, что значение пакета в порядке, выполнив:

 glPixelStorei(GL_PACK_ALIGNMENT, 1)
  

Перед вашим glGetTexImage() или выровняйте текстуру вашей памяти по GL_PACK_ALIGNEMENT.

Ответ №2:

Скорее всего, это ошибка драйвера. Я сам написал 3D API, и даже легко понять, как это делается. Вы делаете что-то действительно странное и редко подпадающее под действие теста: преобразуете данные с плавающей запятой в 8 бит во время загрузки. Никто не собирается оптимизировать этот путь. Вам следует пересмотреть то, что вы делаете в первую очередь. Вероятно, там срабатывает универсальная функция преобразования процессора, и кто-то перепутал таблицу, которая управляет выделением временных буферов для этого. Вам действительно следует пересмотреть использование внешнего формата float с внутренним 8-битным форматом. Подобные преобразования в GL api обычно указывают на ошибки программирования. Если ваши данные имеют формат float и вы хотите сохранить их как таковые, вам следует использовать текстуру float, а не RGBA. Если вы хотите 8 бит, почему ваш ввод с плавающей точкой?

Комментарии:

1. Я могу согласиться с вами в целом, но поскольку glGetTexImage принимает параметр типа, его должно быть легко охватить модульными тестами этой функции. Я также протестировал сохранение формата постоянным (GL_FLOAT полностью), но ошибка осталась. Причиной ошибки была специфическая комбинация glCopyTexSubImage2D, за которой следует glGetTexImage.

2. На самом деле я неправильно прочитал исходное сообщение и не увидел Get в glGetTexImage. Эта функция в значительной степени считается только отладочной. Вы правы насчет модульных тестов в принципе, но gl api настолько велик, что на самом деле это невозможно. 20 внутренних форматов, 20 внешних, 20 состояний. Загружать, копировать, скачивать, сопоставлять. Это просто для многих комбинаций. И copy, и get являются дополнительными функциями.