Нарушение прав доступа на glDelete * - PullRequest
2 голосов
/ 03 марта 2011

У меня возникла странная проблема: у меня есть потенциально большая (до 500 МБ) 3d-текстура, которая создается несколько раз в секунду.Размер текстуры может измениться, поэтому повторное использование старой текстуры не всегда приемлемо.Логическим шагом, позволяющим избежать потребления памяти, является удаление текстуры каждый раз, когда она больше не используется (с использованием glDeleteTexture), но программа довольно быстро завершает работу с нарушением прав чтения или записи.То же самое происходит с glDeleteBuffer при вызове буфера, который я использую для обновления текстуры.

На мой взгляд, этого не может быть, так как функции glDelete * довольно отказоустойчивы.Если вы дадите им дескриптор gl, который не является соответствующим объектом, они просто ничего не сделают.

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

Это работает на 32-разрядной Windows XP, NVIDIA Geforce 9500GT с драйверами 266.58, язык программирования c ++ в visual studio 2005.

Обновление

Очевидно, что glDelete не единственная затронутая функция.Я только что получил нарушения в нескольких других методах (чего не было вчера) ... похоже, что-то здесь чертовски сломано.

Обновление 2

не должно ли это произойти, не так ли?

template <> inline
Texture<GL_TEXTURE_3D>::Texture(
    GLint internalFormat,
    glm::ivec3 size,
    GLint border ) : Wrapper<detail::gl_texture>()
{
    glGenTextures(1,&object.t);

    std::vector<GLbyte> tmp(glm::compMul(size)*4);
    glTextureImage3DEXT(
        object,             // texture
        GL_TEXTURE_3D,          // target
        0,                      // level
        internalFormat,         // internal format
        size.x, size.y, size.z, // size
        border,                 // border
        GL_RGBA,                // format
        GL_BYTE,                // type
        &tmp[0]);               // don't load anything
}

не может с:

Exception (first chance) at 0x072c35c0: 0xC0000005:  Access violoation while writing to position 0x00000004.
Unhandled exception at 0x072c35c0 in Project.exe: 0xC0000005: Access violatione while writing to position 0x00000004.

лучшее предположение: что-то портитпамять программы?

Ответы [ 2 ]

4 голосов
/ 03 марта 2011

Я не знаю, почему произошел сбой glDelete, но я вполне уверен, что он вам все равно не нужен и слишком усложняет это.

glGenTextures создает «имя» для вашей текстуры. glTexImage3D предоставляет OpenGL некоторые данные для привязки к этому имени. Если мое понимание верно, нет причин удалять имя, если вы больше не хотите получать данные .

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

Ниже приведен глупый тест на python (необходим pyglet), который выделяет целую кучу текстур (просто для проверки того, что измерение использования памяти графическим процессором в GPU-Z действительно работает), а затем перераспределяет новые данные для одной и той же текстуры в каждом кадре. со случайным новым размером и некоторыми случайными данными, чтобы обойти любые оптимизации, которые могут существовать, если данные остаются постоянными.

Это (очевидно) медленный ад, но он определенно показывает, по крайней мере, на моей системе (Windows Server 2003 x64, NVidia Quadro FX1800, драйверы 259.81), что использование памяти графическим процессором НЕ увеличивается при циклическом перераспределении текстура.

import pyglet
from pyglet.gl import *
import random

def toGLArray(input):
    return (GLfloat*len(input))(*input)

w, h = 800, 600
AR = float(h)/float(w)
window = pyglet.window.Window(width=w, height=h, vsync=False, fullscreen=False)


def init():
    glActiveTexture(GL_TEXTURE1)
    tst_tex = GLuint()
    some_data = [11.0, 6.0, 3.2, 2.8, 2.2, 1.90, 1.80, 1.80, 1.70, 1.70,  1.60, 1.60, 1.50, 1.50, 1.40, 1.40, 1.30, 1.20, 1.10, 1.00]
    some_data = some_data * 1000*500

    # allocate a few useless textures just to see GPU memory load go up in GPU-Z
    for i in range(10):
        dummy_tex = GLuint()
        glGenTextures(1, dummy_tex)
        glBindTexture(GL_TEXTURE_2D, dummy_tex)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 1000, 1000, 0, GL_RGBA, GL_FLOAT, toGLArray(some_data))
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

    # our real test texture
    glGenTextures(1, tst_tex)
    glBindTexture(GL_TEXTURE_2D, tst_tex)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 1000, 1000, 0, GL_RGBA, GL_FLOAT, toGLArray(some_data))
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

def world_update(dt):
    pass
pyglet.clock.schedule_interval(world_update, 0.015)

@window.event
def on_draw():
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    # randomize texture size and data
    size = random.randint(1, 1000)
    data = [random.randint(0, 100) for i in xrange(size)]
    data = data*1000*4

    # just to see our draw calls 'tick'
    print pyglet.clock.get_fps()

    # reallocate texture every frame
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 1000, size, 0, GL_RGBA, GL_FLOAT, toGLArray(data))

def main():
    init()
    pyglet.app.run()

if __name__ == '__main__':
    main()
0 голосов
/ 03 марта 2011

Посыпать glGetError () s по всему коду. Держу пари, что вас поймает тот факт, что glDelete на самом деле не уничтожает объект. Объект может использоваться на несколько кадров дольше. Поэтому я подозреваю, что у вас недостаточно памяти (т.е. glGetError возвращает GL_OUT_OF_MEMORY).

...