2014-10-11 2 views
0

본인은 Android/NDK 네이티브 레벨에서이 게임을 진행하고 있습니다. 시작하려면 텍스처가 하나 뿐이지 만 텍스처가 5에 도달하면 내 fps는 약 60에서 천천히 약 20 (줄무늬가있는)로 줄어 듭니다.네이티브 Android 멀티 스레드 홀수 발생

현재 모든 작업을 단일 스레드에서 수행하고 있습니다. start_routine에 posix 스레드를 사용하는 다른 스레드 (무한 루프와 구현이 없음)를 사용하여 내 fps는 명백한 이유없이 약 40 비트를 기록한 것으로 보입니다.

또 다른 포인트는 스레드의 도입 후 FPS가 42-43에서 안정적이었습니다. 그러나 스레드가 없으면 흔들리는 애니메이션 (18-28fps)이 발생했습니다. 내 의심 :

  1. 왜 위와 같은 현상이 발생 했습니까 (스레드 관련)?
  2. 또한 하나의 텍스처를 사용했을 때의 유일한 차이점은 이제 내 프래그먼트 쉐이더에서의 계산이 더 많은 것입니다. 이것은 GPU에 과부하가 걸려 glSwapBuffers가 더 많은 시간을 소비한다는 의미입니까?
  3. glSwapBuffers가 시간이 걸린다 고 가정하면 내 게임 논리가 항상 렌더러보다 앞서가는 것을 의미합니까?
  4. 프레임을 렌더링하는 데 필요한 정보를 렌더링 스레드에 정확히 전달하려면 어떻게해야합니까? 마찬가지로 내가 렌더링 스레드가 내 게임 논리 스레드에 의해 먹이 대기열에서 대기하게합니까?

    void * start_render (void * param) 
    { 
    
        while (1) { 
    
        } 
    
        return NULL; 
    } 
    
    void android_main(struct android_app* state) { 
    
    
        // Creation of this thread, increased my FPS to around 40 even though start_render wasnt doing  anything 
    
        pthread_t renderthread; 
        pthread_create(&renderthread,NULL,start_render,NULL); 
    
    
        struct engine engine; 
    
        memset(&engine, 0, sizeof(engine)); 
        state->userData = &engine; 
        state->onAppCmd = engine_handle_cmd; 
        state->onInputEvent = engine_handle_input; 
    
    
        engine.assetManager = state->activity->assetManager; 
    
        engine.app = state; 
        engine.texsize = 4; 
    
    
        if (state->savedState != NULL) { 
         // We are starting with a previous saved state; restore from it. 
         engine.state = *(struct saved_state*)state->savedState; 
        } 
    
        // loop waiting for stuff to do. 
    
        while (1) { 
         // Read all pending events. 
         int ident; 
         int events; 
         struct android_poll_source* source; 
    
         // If not animating, we will block forever waiting for events. 
         // If animating, we loop until all events are read, then continue 
         // to draw the next frame of animation. 
         while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, 
           (void**)&source)) >= 0) { 
    
          // Process this event. 
          if (source != NULL) { 
           source->process(state, source); 
          } 
    
    
          // Check if we are exiting. 
          if (state->destroyRequested != 0) { 
           engine_term_display(&engine); 
           return; 
          } 
         } 
    
         if (engine.animating) { 
    
    
    
           for (int i = 0; i < 4;i++) 
           { 
            float cur = engine.mytextures[i].currentposition; 
    
            if (cur < 1.0) 
             engine.mytextures[i].currentposition = cur + engine.mytextures[i].relativespeed; 
            else 
             engine.mytextures[i].currentposition = cur - 1.0; 
           } 
    
          // How do i enable the render thread (created above) to call the below function? 
          on_draw_frame(&engine); 
    
    
    
    
         } 
        } 
    } 
    
    void on_draw_frame(engine * engine) { 
    
        glUseProgram(program); 
    
        engine->texsize = 4; 
    
        glActiveTexture(GL_TEXTURE0); 
        glBindTexture(GL_TEXTURE_2D, engine->mytextures[0].textureid); 
    
        glActiveTexture(GL_TEXTURE1); 
        glBindTexture(GL_TEXTURE_2D, engine->mytextures[1].textureid); 
    
        glActiveTexture(GL_TEXTURE2); 
        glBindTexture(GL_TEXTURE_2D, engine->mytextures[2].textureid); 
    
        glActiveTexture(GL_TEXTURE3); 
        glBindTexture(GL_TEXTURE_2D, engine->mytextures[3].textureid); 
    
        glUniform1i(u_texture_unit_location1,0); 
        glUniform1i(u_texture_unit_location2,1); 
        glUniform1i(u_texture_unit_location3,2); 
        glUniform1i(u_texture_unit_location4,3); 
    
    
        glUniform1f(timeCoord1,engine->mytextures[0].currentposition); 
        glUniform1f(timeCoord2,engine->mytextures[1].currentposition); 
        glUniform1f(timeCoord3,engine->mytextures[2].currentposition); 
        glUniform1f(timeCoord4,engine->mytextures[3].currentposition); 
    
    
    
        glUniform1i(texSize,engine->texsize); 
    
        glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    
        glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_FALSE, 
         4 * sizeof(GL_FLOAT), BUFFER_OFFSET(0)); 
        glVertexAttribPointer(a_texture_coordinates_location, 2, GL_FLOAT, GL_FALSE, 
         4 * sizeof(GL_FLOAT), BUFFER_OFFSET(2 * sizeof(GL_FLOAT))); 
        glEnableVertexAttribArray(a_position_location); 
        glEnableVertexAttribArray(a_texture_coordinates_location); 
    
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
    
        glBindBuffer(GL_ARRAY_BUFFER, 0); 
    
        eglSwapBuffers(engine->display, engine->surface); 
    
    
        // FPS calculation 
        if (fps == 0) 
         clock_gettime(CLOCK_MONOTONIC, &starttime); 
        else 
         clock_gettime (CLOCK_MONOTONIC,&stoptime); 
    
        if (stoptime.tv_sec - starttime.tv_sec == 1) { 
    
         __android_log_print(ANDROID_LOG_VERBOSE, "GAME", "FPS %d",fps); 
         fps = 0; 
    
        } else 
         fps++; 
    
    } 
    

    당신이 코드에 대한 자세한 정보가 필요하면 알려주세요 :

코드 (코드 관련).

+0

호기심에서 벗어나 :이 기기에서 측정하는 기기는 무엇입니까? –

+0

넥서스 4를 사용 중입니다. – ichigo1191

답변

0

완전히 확신 할 수는 없지만 기기의 전원 관리에 나쁜 영향을주는 것처럼 보입니다.

설명하는 현상은 CPU 사용에 초점을 둔 전원 관리 전략으로 인해 발생할 수 있습니다. 이와 같은 전략을 사용하면 CPU 사용량이 매우 낮 으면 (대부분 GPU가 제한되어 있기 때문에) 전체 시스템이 저전력 상태로 전환되고 GPU가 완전히 감속 되더라도 GPU가 효과적으로 느려질 수 있습니다 짐을 실은.

이 경우 CPU 시간을 소모하는 다른 스레드를 시작하여 추가 CPU로드를 추가하면 시스템을 높은 전원 상태로 유지하고 GPU를 더 빠르게 실행할 수 있습니다.

이런 종류의 전원 관리는 완전히 깨졌습니다. IMHO. CPU 사용률이 낮기 때문에 GPU가 완전히 바쁠 경우 GPU 속도를 늦추는 것은 나에게 어울리지 않습니다. 그러나 일부 장치의 전원 관리는 매우 원시적이므로 이러한 종류의 동작은 드문 일이 아닙니다.

이것이 실제로 문제가된다면 버그를 제출하는 것보다 애플리케이션 개발자로서 그렇게 할 수있는 것이 많지 않습니다. 물론 인공 CPU로드를 작성하면 문제를 해결할 수 없습니다. 전력 관리를 무력화하기 위해 더 많은 전력을 사용하는 것이 원하는 것만은 아닙니다. 많은 게임들이 게임 로직/물리학을 처리하기 위해 상당량의 CPU로드를 생성하므로 영향을받지 않습니다.