CVOpenGLESTextureCache vs glTexSubImage2D no iOS

Meu aplicativo OpenGL usa o OpenGL para renderizar uma textura em tela cheia e atualiza parte dela em intervalos regulares. Até agora, eu tenho usado o glTexImage2D para empurrar minha textura inicial e então atualizo as regiões sujas com glTexSubImage2D. Para fazer isso, estou usando o buffer único. Isso funciona bem.

Eu vi que pode haver outra maneira de conseguir a mesma coisa usando CVOpenGLESTextureCache. As texturas contidas no cache de textura fazem referência a um CVPixelBuffer. Eu gostaria de saber se posso mudar essas texturas em cache. Eu tentei recriar um CVOpenGLESTexture para cada atualização, mas isso diminui minha taxa de quadros drasticamente (não é surpreendente, afinal, desde que eu não estou especificando a região suja em qualquer lugar). Talvez eu tenha entendido mal o caso de uso desse cache de textura.

Alguém pode fornecer alguma orientação?

UPDATE: aqui está o código que estou usando. A primeira atualização funciona bem. As atualizações subseqüentes não (nada acontece). Entre cada atualização modifico o bitmap bruto.

if (firstUpdate) {

    CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, ctx, NULL, &texCache);

    CVPixelBufferRef pixelBuffer;
    CVPixelBufferCreateWithBytes(NULL, width_, height_, kCVPixelFormatType_32BGRA, bitmap, width_*4, NULL, 0, NULL, &pixelBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);

    CVOpenGLESTextureRef texture = NULL;
    CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, texCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);

    texture_[0] = CVOpenGLESTextureGetName(texture);

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}


CVOpenGLESTextureCacheFlush(texCache, 0);

if (firstUpdate) {
    glBindTexture(GL_TEXTURE_2D, texture_[0]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

if (firstUpdate) {
    static const float textureVertices[] = {
        -1.0, -1.0,
        1.0, -1.0,
        -1.0, 1.0,
        1.0, 1.0
    };

    static const float textureCoords[] = {
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    glVertexPointer(2, GL_FLOAT, 0, &textureVertices[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
}

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

firstUpdate = false;

questionAnswers(1)

yourAnswerToTheQuestion