2010-11-02 3 views
1

J'ai une application iPad avec interface utilisateur écrite en OpenGL ES 2.0, certains éléments de l'interface utilisateur sont cachés par défaut et quand j'ai besoin de les montrer il y a assez de retard avant qu'ils ne soient réellement affichés (à propos 300-500 ms sur un contrôle qui contient environ 20 autres contrôles à l'intérieur), en utilisant Instruments.app J'ai déterminé que quand je rends chaque objet unique, il faut beaucoup plus de temps pour le rendre la première fois après qu'il ait été rendu au moins une fois en rendant le temps est énorme. Voici le code que j'ai pour le rendu et ce code est illustré par des instruments prenant tout ce retard:premier appel à glDrawArrays est très lent sur iPad

- (void)render:(id <ESRenderer>)renderer 
{ 
    [shader useShader]; 
    glEnableVertexAttribArray(ATTRIB_VERTEX); 
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, _squareVertices); 
    glEnableVertexAttribArray(ATTRIB_TEXTCOORD); 
    glVertexAttribPointer(ATTRIB_TEXTCOORD, 2, GL_SHORT, 0, 0, coords); 
    float x1 = self.position.x; 
    float y1 = self.position.y; 
    glUniform1f(shader.ext_uniforms[UNIFORM_TRANSLATE_X], -x1+_squareVertices[0]); 
    glUniform1f(shader.ext_uniforms[UNIFORM_TRANSLATE_Y], -y1+_squareVertices[1]); 
    glUniform1f(shader.ext_uniforms[UNIFORM_ROTATE], self.rotation); 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
    glDisableVertexAttribArray(ATTRIB_VERTEX); 
    glDisableVertexAttribArray(ATTRIB_TEXTCOORD); 
} 

Quand il est appelé au moins une fois, il fonctionne parfaitement vite. Mon shaders est aussi très simple:

vec4 col = texture2D(texture, coordVarying); 
gl_FragColor = col; 

Merci!

Répondre

1

Je suppose que c'est le transfert réel de données au GPU qui se produit une seule fois. Vous devriez être en mesure de forcer le chargement/compilation à un moment donné avant votre premier rendu pour supprimer ce hit de performance. Soit le transfert de données de sommet s'il est énorme, soit le transfert/compilation de shader.

EDIT: comme noté dans l'autre réponse, il y a aussi les données de texture qui pourraient être transférées.

+0

la quantité de données est seulement 8 flotteurs plus couple shorts comme texcoords, aussi shader est assez petit et je charge, lier les variables et le lier au moment du chargement de l'application. Donc, dans mon [shader useShader] appel suit: - (void) useShader { \t glUseProgram (_program); \t glBindTexture (GL_TEXTURE_2D, _texture); \t glUniform1i (uniformes [UNIFORM_TEXTURE], 0); } –

+0

le problème était dans le chargement des shaders, il y avait quelques petits shaders chargés et liés au début, mais comme vous l'avez dit le transfert a commencé lors de la première utilisation, j'ai utilisé les shaders pendant le chargement , Merci! –

0

Les implémentations OpenGL communément chargées les textures paresseusement, c'est-à-dire que la texture n'est réellement initialisée qu'à la première utilisation (à peu près ce que dit jv42, mais pas les données de géométrie). Il se peut que ce soit ce qui se passe ici. Si vous ne faites pas varier vos textures entre les objets, obtenez-vous les mêmes ralentissements?

Une solution consiste à dessiner des triangles hors écran triviaux avec vos textures liées au moment de l'initialisation pour forcer le chargement de ces textures avant votre boucle de rendu principale.

BTW Je ne mettrais pas beaucoup de temps à mesurer la longueur des appels de tirage individuels sur un rendu différé comme celui de l'iPhone.

+0

J'ai un gestionnaire de texture, donc c'était facile à essayer, j'ai spécifié d'utiliser seulement 1 texture dans toute l'application, mais rien n'a changé, donc ce ne sont pas des textures :( –

+0

Vous avez complètement raison, je n'ai pas mentionné de textures , corrigé dans mon post. – jv42

0

Je l'ai eu aussi. Pour moi, c'était un problème avec la texture. Sur NVIDA, les choses ont vite fonctionné. Mais mon optimisation optique a provoqué la démission d'une carte ATI.

Je travaille avec une texture de taille 4720 x 5600 (environ) et les cartes modernes fonctionnent bien avec.

J'ai essayé d'optimiser les bordures en utilisant Wrapmode = GL_CLAMP_TO_BORDER_ARB. Par conséquent, j'ai besoin de fournir l'argument border à glTeximage2D comme au moins == 1. Puisque la carte douteuse ne supportait pas la bordure dans HW, il s'est avéré que cela prenait 20 secondes pour une image. Revenir à GL_CLAMP_TO_BORDER + border param == 0 l'a fait accélérer à nouveau.