本机Android多线程奇数发生

时间:2014-10-11 23:13:04

标签: android c++ multithreading opengl-es

我一直在原生Android / NDK级别上玩这个游戏。首先,我只有一个纹理但是当我的纹理达到5时,我的fps从60左右慢慢减少到大约20(带有断断续续)。

目前我正在一个线程上执行所有操作。在使用带有start_routine的posix线程引入另一个线程(它无限循环并且没有实现)时,我的fps似乎没有明显的原因达到40左右。

另一点是,在引入该线程后,FPS稳定在42-43。但没有线程,就会出现断断续续的动画(18-28 fps)。 我的疑惑:

  1. 为什么上面提到的(线程相关)?
  2. 另外,我使用1个纹理时的唯一区别是我的片段着色器中的计算现在更多了。这是否意味着GPU正在过载,因此glSwapBuffers需要更多时间?
  3. 假设glSwapBuffers确实需要时间,这是否意味着我的游戏逻辑总是领先于我的渲染器?
  4. 我究竟如何使用渲染帧所需的信息来提供渲染线程?正如我在渲染线程中等待由我的游戏逻辑线程提供的队列? (代码相关)
  5. 代码:

    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++;
    
    }
    

    如果您需要有关代码的更多信息,请与我们联系。

1 个答案:

答案 0 :(得分:0)

我不能完全确定,但这看起来很像电源管理对设备的不良影响。

您描述的症状可能是由专注于CPU使用的电源管理策略引起的。有了这样的策略,如果你的CPU使用率非常低(因为你主要是GPU受限),整个系统就会进入低功耗状态,并且有效地减慢了GPU的速度,即使GPU是完全的加载。

在这种情况下,当您通过启动另一个消耗CPU时间的线程来增加额外的CPU负载时,可以使系统保持更高的功耗状态,并允许GPU更快地运行。

这种电源管理完全坏了,恕我直言。如果因为CPU利用率低而完全忙碌的话,请放慢GPU对我没有任何意义。但是某些设备上的电源管理非常原始,所以这种行为并不少见。

如果这确实是您的问题,除了提交错误之外,作为应用程序开发人员,您无法做很多事情。创建人工CPU负载来解决它当然不能令人满意。使用更多功率来破坏电源管理并不是您想要的。许多游戏可能会产生大量的CPU负载来处理他们的游戏逻辑/物理,因此它们不会受到影响。