Я разрабатываю небольшую игру с pyglet. Одна из центральных частей, конечно же, рисование цветных прямоугольников. Первоначально я делал это, создавая изображения в памяти и blit()
используя их, что работало нормально. Заметив, насколько уродливым, обходным и неэффективным (да, я профилировал - ColorRect.draw()
заняло значительное время и стал в 10 раз более эффективен благодаря этому изменению), я начал создавать списки вершин вместо этого с помощью pyglet.graphics.Batch
(я скопировал большую часть дословно код из одного из примеров). С тех пор я столкнулся со странным исключением в каком-то низкоуровневом коде OpenGL, для которого мне не удалось найти причину или надежно воспроизвести.
Нет явного отношения к игровым событиям - как, впрочем, ничего особенного не происходит прямо перед этим, или я постоянно скучаю по нему. Поскольку ошибка происходит где-то глубоко в цикле событий, я не могу легко отследить, какое обновление позиции вызывает ее. Честно говоря, я в тупике. Таким образом, я расскажу о том, что узнал, и надеюсь на какого-нибудь экстрасенса.
Я опробовал его на 32-битной Windows 7 (я скоро смогу попробовать его на Ubuntu 11.10) с Python 3.2.2, с редакцией pyglet 043180b64260 (взятой из кода Goggle и созданной из исходного кода, 1.1 .4 релиз сложнее установить, так как он не запускает 2to3 автоматически, хотя кажется, что он одинаково готов к py3k). Я, вероятно, обновлю до последней версии Mercurial, но это всего лишь несколько коммитов, и изменения кажутся совершенно не связанными.
Полный возвратный путь (некоторые пути были подвергнуты цензуре из принципа, но обратите внимание, что он в своем собственном virtualenv):
Traceback (most recent call last):
File "<my main file>", line 152, in <module>
main()
File "<my main file>", line 148, in main
run()
File "<my main file>", line 125, in run
pyglet.app.run()
File "<virtualenv>\Lib\site-packages\pyglet\app\__init__.py", line 123, in run
event_loop.run()
File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 135, in run
self._run_estimated()
File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 164, in _run_estimated
timeout = self.idle()
File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 278, in idle
window.switch_to()
File "<virtualenv>\Lib\site-packages\pyglet\window\win32\__init__.py", line 305, in switch_to
self.context.set_current()
File "<virtualenv>\Lib\site-packages\pyglet\gl\win32.py", line 213, in set_current
super(Win32Context, self).set_current()
File "<virtualenv>\Lib\site-packages\pyglet\gl\base.py", line 320, in set_current
buffers = (gl.GLuint * len(buffers))(*buffers)
IndexError: invalid index
Работа с посмертным кодом (активный пошаговый просмотр кода до тех пор, пока он не оказался невозможным, поскольку FPS снизился с 60 до 7) pdb
показывает:
buffers
- список целых чисел; Я понятия не имею, что они представляют или откуда они берутся, но они взяты из списка с именем self.object_space._doomed_textures
(где self
- объект окна). Связанный комментарий говорит, что этот блок кода выпускает текстуру, запланированную для удаления. Я не думаю, что я явно использую текстуры где-либо, но кто знает, что делает pyglet под капотом. Я предполагаю, что эти целые числа - это идентификаторы или что-то из текстур, подлежащих уничтожению.
gl.GLuint
- псевдоним для ctypes.c_ulong
; Таким образом, (gl.GLuint * len(buffers))(*buffers)
создает массив ulong
такой же длины и содержания
- Я могу оценить то же самое выражение в приглашении
pdb
без ошибок или повреждения данных.
Независимые эксперименты (за пределами virtualenv и без импорта pyglet) с ctypes показывают, что IndexError
вызывается, если конструктору массива передано слишком много аргументов. Это не имеет смысла, и эксперименты, и логика предполагают, что длина и количество аргументов всегда должны совпадать.
- Есть ли другие случаи, когда это исключение может произойти? Может ли это быть ошибкой pyglet, или я неправильно использовал библиотеку и пропустил соответствующее предупреждение?
- Может ли код, который создает и поддерживает списки вершин, быть полезным для отладки этого? Там, наверное, что-то с этим не так. Я уже смотрел на это, но так как у меня мало опыта с
pyglet.graphics
, это было ограниченное использование. Просто оставьте комментарий, если хотите увидеть код ColorRect
.
- Есть еще идеи, что может вызвать это?