Ошибка glDrawArrays () при рисовании слишком большого количества элементов - PullRequest
1 голос
/ 13 июня 2011

У меня есть простой код OpenGL ES на C ++, который я запускаю на телефоне под управлением Android, на телефоне под управлением webOS и на моем Mac с использованием SDL / OpenGL.Рассматриваемый код просто рисует GL_LINE_STRIP, который хранится в массиве GLfloat s.Вот как я пытаюсь это сделать ( версия 1 ):

GLfloat array* = new GLfloat[2048];
//later... (array gets filled)
int howMany = 1024;
glVertexPointer(2, GL_FLOAT, 0, array); checkError();
glDrawArrays(GL_LINE_STRIP, 0, howMany); checkError();

Кажется, это должно быть довольно просто.Тем не менее, вышеприведенные ошибки кода в драйверах OpenGL как на Android, так и на моем Mac (кажется, нормально работают на webOS по любой причине.) Вот что я должен сделать, чтобы избежать этого ( версия 2 ):

GLfloat array* = new GLfloat[2048];
//later... (array gets filled)
int howMany = 1024;
for (unsigned i = 0; i < howMany; i += 789) {
    glVertexPointer(2, GL_FLOAT, 0, array+i*2); checkError();
    //this is not a bug: we draw one more than we increment by, or there is a hole in the graph
    glDrawArrays(GL_LINE_STRIP, 0, std::min(790U, howMany-i)); checkError();
}

Ограничение количества линий, проводимых за раз, последовательно исключает сегфоут.Число 790 было определено экспериментально;в 791 он падает на OSX (Android может пойти выше, хотя раньше он был ограничен 113 версиями ... так что число, по-видимому, одинаково для каждой версии приложения, но не для разных версий или платформ.)

В моем приложении происходит много других вещей, связанных с GL, но это большое приложение, и публикация всего этого кода будет нецелесообразной.Итак, что может быть причиной этого?Какие возможности мне следует изучить?

Вот вывод valgrind моей программы, работающей и терпящей крах на OSX, когда я пытаюсь использовать версию 1:

==85414== Conditional jump or move depends on uninitialised value(s)
==85414==    at 0x1D022993: glVertexPointer_Exec (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x6AA59A9: glVertexPointer (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib)
==85414==    by 0x2B001: draw_elements (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x2B44C: glDrawArrays (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0xB639: GLImage::glDraw(int, int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0xC292: GLLabel::glDraw(int, int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1AC67: RTAPlot::drawAxes(int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1B30A: RTAPlot::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x225F5: RTAPlotView::updateForeground() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x19FC4: RTAComponent::update() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x805D: AudiaApplication_private::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x267DF: AudiaApplication::run() (in ./rta.app/Contents/MacOS/rta)
==85414==  Uninitialised value was created by a stack allocation
==85414==    at 0x1D02268F: glVertexPointer_Exec (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414== 
==85414== Conditional jump or move depends on uninitialised value(s)
==85414==    at 0x1D022E0C: glTexCoordPointer_Exec (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x6AA5216: glTexCoordPointer (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib)
==85414==    by 0x2B279: draw_elements (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x2B44C: glDrawArrays (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0xB639: GLImage::glDraw(int, int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0xC292: GLLabel::glDraw(int, int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1AC67: RTAPlot::drawAxes(int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1B30A: RTAPlot::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x225F5: RTAPlotView::updateForeground() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x19FC4: RTAComponent::update() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x805D: AudiaApplication_private::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x267DF: AudiaApplication::run() (in ./rta.app/Contents/MacOS/rta)
==85414==  Uninitialised value was created by a stack allocation
==85414==    at 0x1D022A6B: glTexCoordPointer_Exec (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414== 
==85414== Invalid read of size 8
==85414==    at 0x1D0B9166: gleRunVertexSubmitImmediate (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x1D0B84FB: gleLLVMArrayFunc (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x1D0A14F2: gleDrawArraysOrElements_ExecCore (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x1D0A2A04: glDrawElements_IMM_Exec (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine)
==85414==    by 0x6AA304F: glDrawElements (in /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib)
==85414==    by 0x2B2DB: draw_elements (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x2B44C: glDrawArrays (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1FEF6: RTAPlotCanvas::drawLineStrip(float*, unsigned int) (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1E91A: RTAPlotCanvas::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x1B318: RTAPlot::updateGL() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x225F5: RTAPlotView::updateForeground() (in ./rta.app/Contents/MacOS/rta)
==85414==    by 0x19FC4: RTAComponent::update() (in ./rta.app/Contents/MacOS/rta)
==85414==  Address 0xc0000000 is not stack'd, malloc'd or (recently) free'd
==85414== 
==85414== 
==85414== Process terminating with default action of signal 11 (SIGSEGV)
==85414==  General Protection Fault
==85414==    at 0x10AED0: misaligned_stack_error_ (in /usr/lib/libSystem.B.dylib)
==85414==    by 0x1E45E87: -[NSCustomReleaseData dealloc] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0x1E45E37: -[NSBitmapImageRep _freeData] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0x1E45DCA: -[NSBitmapImageRep _freeImage] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0x1E45D74: -[NSBitmapImageRep dealloc] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0x171DF37: CFRelease (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==85414==    by 0x1748691: __CFArrayReleaseValues (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==85414==    by 0x171E100: _CFRelease (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==85414==    by 0x1D89F7A: -[NSImage dealloc] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0x20857D4: -[NSCursor dealloc] (in /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit)
==85414==    by 0xDFE33: QZ_FreeWMCursor (in /opt/PalmPDK/host/lib/libSDL-1.2.0.11.2.dylib)
==85414==    by 0xCA11F: SDL_FreeCursor (in /opt/PalmPDK/host/lib/libSDL-1.2.0.11.2.dylib)
--85414:0:schedule VG_(sema_down): read returned -4

Обратите внимание, что первые две ошибки условного переходапроисходит каждый раз, и не может быть проблемой с моим приложением.Недопустимая ошибка чтения возникает только при попытке использовать версию 1 в OSX.

1 Ответ

7 голосов
/ 13 июня 2011

Возможно, он вообще не связан с вашим массивом вершин.Например, могут быть еще указатели на другие установленные атрибуты вершин, и, конечно, если они имеют меньшие буферы, чем новый массив вершин, вы получите segfault.

Если вы внимательно посмотрите на свой вывод valgrind, выВы увидите, что указатель координат текстуры все еще установлен.

Итак, я предлагаю отключить все массивы атрибутов вершин, которые вам не нужны:

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
/* ... */

в вашем случае

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
...