#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 являются дополнительными функциями.