2012-05-23 12 views
6

Programuję grę Android 2d używając opengl es 2.0. Po narysowaniu moich duszków do bufora wstecznego rysuję światła do FBO i próbuję ponownie wtopić je w bufor powrotny. Kiedy rysuję FBO do framebuffera, nawet trasparent bez żadnego koloru, ilość klatek na sekundę spada z 60 na 30 na Samsung Galaxy w (ma adreno 205 jako gpu). Szukałem wszędzie i próbowałem wszystkiego, nawet jeśli narysowałem pojedynczy obraz na scenie i wstawiłem przezroczystą teksturę FBO na ekran, w którym liczba klatek na sekundę spada. Próbowałem innych gier z efektami świetlnymi na tym telefonie i działają dobrze, prawie każda gra jest w porządku na tym telefonie, wierzę, że używają również bufora ramki. Na Galaxy SII (mali 400 gpu) działa dobrze, jestem całkiem nowy na opengl, więc wierzę, że gdzieś popełniam błąd, dzielę się moim kodem.Replikacja ramek FBO do tekstury jest bardzo powolna, używając OpenGL ES 2.0 na Androida, dlaczego?

// Create a framebuffer and renderbuffer 
GLES20.glGenFramebuffers(1, fb, offset); 
GLES20.glGenRenderbuffers(1, depthRb, offset); 

// Create a texture to hold the frame buffer 
GLES20.glGenTextures(1, renderTex, offset); 
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]); 

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 
        screenWidth, screenHeight, 0, 
        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, 
        null); 


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

//bind renderbuffer 
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]); 

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, 
          screenWidth, screenHeight); 

// bind the framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]); 

// specify texture as color attachment 
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 
           GLES20.GL_TEXTURE_2D, renderTex[offset], 0); 

// specify depth_renderbufer as depth attachment 
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 
           GLES20.GL_RENDERBUFFER, depthRb[0]); 

// Check FBO status. 
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 

if (status == GLES20.GL_FRAMEBUFFER_COMPLETE) 
{ 
    Log.d("GLGame framebuffer creation", "Framebuffer complete"); 
} 


// set default framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

Robię to raz przy tworzeniu powierzchni. Nie jestem pewien, czy jest poprawny. Zachowuję teksturę i identyfikatory bufora ramki, aby przełączać się do nich, gdy tego potrzebuję. Mój kod rysunek:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 
ShaderProgram program = glgame.getProgram(); 

//put vertices in the floatbuffer 
mTriangleVertices.put(vertices, 0, len); 
mTriangleVertices.flip(); 

GLES20.glVertexAttribPointer(program.POSITION_LOCATION, 2, GLES20.GL_FLOAT, false, 
          TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 

//preparing parameter for texture position 
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
GLES20.glEnableVertexAttribArray(program.POSITION_LOCATION); 

//preparing parameter for texture coords 
GLES20.glVertexAttribPointer(program.TEXTURECOORD_LOCATION, 2, GLES20.GL_FLOAT, 
          false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
          mTriangleVertices); 

//set projection matrix 
GLES20.glEnableVertexAttribArray(program.TEXTURECOORD_LOCATION); 
GLES20.glUniformMatrix4fv(program.MATRIX_LOCATION, 1, false, matrix, 0); 

//draw triangle with indices to form a rectangle 
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numSprites * 6, GLES20.GL_UNSIGNED_SHORT, 
         indicesbuf); 

//clear buffers 
mTriangleVertices.clear(); 
mVertexColors.clear(); 

Wszystko staje się prawidłowo na ekranie, ale wydajność jest zniszczony tylko kiedy narysować FBO tekstury. Dziękuję bardzo za pomoc. Pracowałem nad tym bardzo ciężko i nie znalazłem rozwiązania.

+0

Późna odpowiedź, ale robię coś podobnego na HD2 pod ICS i to prawie tak samo. Mogę renderować wszystko bez problemu przy 60 klatkach na sekundę, ale kiedy używam FBO, liczba klatek spada do 45, a jeśli używam innego FBO to spada do 30. –

+0

Hmm ... Widziałem kilka gier na Samsunga Galaxy bez problemu działało i wydawało się, że używają bufora ramki do oświetlenia 2d, mój kod działa powoli. Zastanawiam się, czy robię błędy. – mao

+0

galaxy używa chipsetu sgx. tak jak powiedziałem przed jego związkiem z małą architekturą gmem i kaflami, za każdym razem, gdy zmieniasz framebuffer stary, musisz zostać skopiowany do zwykłego memu, jeśli usuniesz go jako pierwsze po wywołaniu, nie trzeba go kopiować z powrotem z normalnego mem do gmem, to dlatego framebuffery są powolne, szczególnie na adreno 200 :) możesz sprawdzić aplikację używając framebufferów z profilerem adreno, jeśli masz urządzenie adreno, po prostu podłącz je i pobierz aktualną ramkę, następnie sprawdź fb w teksturach. jeśli znajdziesz taki, będziesz pewny, – ZZZ

Odpowiedz

12

Zgodnie z dokumentacją qualcomm, po każdym buforze glbindfrf musisz mieć większą przejrzystość, jest to problem związany z architekturą kaflową, jeśli przełączasz framebuffery, dane muszą zostać skopiowane z fastmem do zwykłej pamięci, aby zapisać bieżący framebuffer i slowmem do szybkie memowanie, aby uzyskać zawartość nowo oprawionej ramki, na wypadek gdybyś wyczyścił zaraz po glbind żadne dane nie są kopiowane z slowmem do fastmem i oszczędzasz czas, ale musisz przeprojektować często renderowanie, aby uniknąć odczytu danych i naprzód między wolną i szybką pamięcią, więc spróbuj zrobić glasar po każdym wiązaniu, a to powinno pomóc, możesz również użyć profilera adreno, aby uzyskać dodatkowe informacje o problematycznych połączeniach, ale wątpię, czy to pomoże w adreno200 Próbuję uzyskać dwa bufory dla rozmycie i kończę z 10 klatek na sekundę, wywołanie funkcji bindframebuffer może zająć do 20 ms, jeśli nie jest wyczyszczone, jeśli jest to sho kończy się na 2ms.

+0

Spróbuję tego, jak tylko będę mógł ponownie wyciągnąć ręce na adreno 205. Znalazłem dokumentację qualcomm, a ja to zrobię. Bardzo ci dziękuje za pomoc! – mao

+0

[tutaj] (https://www.google.sk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDEQFjAA&url=https%3A%2F%2Fdeveloper.qualcomm.com%2Fdownload%2Fadreno200performularzoptymalizacjaprzystępów itricksmarch10 .pdf & ei = DT6IUcaTMYXV4ASEwYHYAQ & usg = AFQjCNFbU3Vf2mT2sf7LTAJQ3xqijdyUAA & sig2 = JMoeTn8G1MQgor9ZGDdFQg & bvm = bv.45960087, d.bGE) jest dokumentem kwalifikacyjnym. –

+1

Jeśli chcesz zachować zawartość bufora ramki, po prostu wykonaj 'glClear (0);', która również wydaje się naprawić problem. – Thomas

Powiązane problemy