Imagination PowerVR SDK Blog

glTexImage2D is too slow


#1

when draw YUV frame use opengl 2.0 and shader on nexus one,but the


function glTexImage2D is too slow ,cost 40-60 ms


who can fix it ? the key codes:






int CreateSimpleTexture2D()

       {

               int err, i;







               for (i=0; i<3;i++)

               {

                      glGenTextures(1, &userData.textureId);

                      if (err = glGetError()) {

                      //      NSLog(@"Error: Could not generate texture: %d", err);

                      __android_log_print(ANDROID_LOG_ERROR,"CreateSimpleTexture2D","Error:

Could not generate texture: %d", err);

                               return 0;

                      }



                      glBindTexture(GL_TEXTURE_2D, userData.textureId);

                      if (err = glGetError()) {

                      //      NSLog(@"Error: Could not bind texture: %d", err);

                                       __android_log_print(ANDROID_LOG_ERROR,"CreateSimpleTexture2D","Error:

Could not bind texture: %d", err);

                               return 0;

                      }

               }



               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

               if (err = glGetError()) {

                      //NSLog(@"Error: Could not set texture minimization filter: %d", err);

                      __android_log_print(ANDROID_LOG_ERROR,"CreateSimpleTexture2D","Error:

Could not set texture minimization filter: %d", err);

                      return 0;

               }



               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

               if (err = glGetError()) {

               //      NSLog(@"Error: Could not set texture magnification filter: %d", err);

               __android_log_print(ANDROID_LOG_ERROR,"CreateSimpleTexture2D","Error:

Could not set texture magnification filter: %d", err);

                      return 0;

               }



               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

               glGenerateMipmap(GL_TEXTURE_2D);

               return 1;

       }






render frame



               glViewport ( 0, 0, g_WindowsWidth, g_WindowsHeight );

               checkGlError("glViewport");

               //glDrawBuffer(GL_COLOR_ATTACHMENT0);

               // Clear the color buffer

               glClear ( GL_COLOR_BUFFER_BIT );

               checkGlError("glClear");

               // Use the program object

               glUseProgram ( userData.programObject );

               checkGlError("glUseProgram");

               // Load the vertex position

               glVertexAttribPointer ( userData.positionLoc, 3, GL_FLOAT,

                                                         GL_FALSE, 5 * sizeof(GLfloat), vVertices );

               // Load the texture coordinate

               glVertexAttribPointer ( userData.texCoordLoc, 2, GL_FLOAT,

                                                         GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );



               glEnableVertexAttribArray ( userData.positionLoc );

               glEnableVertexAttribArray ( userData.texCoordLoc );



               long long ttttttt=av_gettime();

               // Bind the texture

               glActiveTexture ( GL_TEXTURE1 );

               glBindTexture ( GL_TEXTURE_2D, userData.textureId[1] );

               glUniform1i ( userData.samplerLocU, 1);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_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);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

               //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);



               //glPixelStorei(GL_UNPACK_ALIGNMENT,1);



               glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width/2, height/2, 0,

GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[1]);

               checkGlError("glTexImage2D....pict->data[1]");

               //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width*0.5,

height*0.5, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[1]);





               // Bind the texture

               glActiveTexture ( GL_TEXTURE2 );

               glBindTexture ( GL_TEXTURE_2D, userData.textureId[2] );

               glUniform1i ( userData.samplerLocV, 2);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_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);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

               //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

               //glPixelStorei(GL_UNPACK_ALIGNMENT,1);





               glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,width/2, height/2, 0,

GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[2]);



               checkGlError("glTexImage2D....pict->data[2]");

               // Set the sampler texture unit to 0

               glActiveTexture ( GL_TEXTURE0 );

               glBindTexture ( GL_TEXTURE_2D, userData.textureId[0] );

               glUniform1i ( userData.samplerLocY, 0);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

               glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_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);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

               //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

               //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

               //glPixelStorei(GL_UNPACK_ALIGNMENT,1);





               glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,

GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[0]);

               __android_log_print(ANDROID_LOG_ERROR,"GPU","%lld",(av_gettime()-ttttttt)/1000);

               checkGlError("glTexImage2D....pict->data[0]");

               glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );

#2

As far as I know the Nexus One doesn’t have a PowerVR GPU, thus, the PowerVR engineers might not be the best qualified people to answer your question. :wink:
Also note that you cannot time OpenGL applications as easily as pure CPU applications. You should rather measure which frame rate you can sustain.
Apart from this, you could try to use glTexSubImage2D and/or upload one combined texture instead of three.


#3

Martin is correct.


The Nexus One has a Qualcomm chip with an Adreno 200 graphics core. You should follow up with Qualcomm to solve this issue.





Btw, its worth noting that a glTexImage2D() call is a fairly slow operation on any hardware and should be avoided from being called on a frame by frame basis, if possible. Some POWERVR platforms expose our GL_IMG_texture_stream extension which allows the GPU to access texture data that is created per frame (e.g. a camera or video source) in a variety of formats (including YUV) with a minimal number of required copy operations, which is much more efficient than calling glTexImage2D regularly.


#4

Something I did with earlier iOS drivers to speed up texture upload was to construct an FBO with the texture I wanted to write to as the backing.





I then used arrays of integer coordinates and bytes for colour data to upload the individual pixels.


This was actually faster on the MBX than glTexSubImage2D, and is still slightly faster than glTexSubImage2D on SGX (but only marginally). I never tried it in comparison with glTexImage2D upload speeds.





This may or may not be of some help on the other hardware you are playing with.


scratt2011-01-16 08:49:56