Android GLSURFACHEVIEW,GL20-~15毫秒在Renderer.onDrawFrame中丢失
我在安卓Gl20上发现了一些有趣的东西,我可以在“Hello Gl20”安卓工作室的示例中重现这些东西,我很想听听大家对这件事的看法 简言之,在S5(和其他设备)上,首次使用gl*函数会浪费约15毫秒(我会说gl上下文,但我只想展示事实,而不是我的解释) 我让这个ms troll显示它的脸的方式是:在GLSufaceView Renderer.onDraw(在GLThread上)中,我调用本机func GL2JNILib.step(绘制一个简单的三角形)两次,每次调用都有一个不同的id(int)。第一次调用的id为0,第二次调用的id为1。 在本机函数中,我基于时钟单调性设置了一个简单的时间测量。 第一次通话(id为0的通话)需要16毫秒,第二次通话(id为1的通话)需要0毫秒。这个东西会重复下一帧,不知怎么的,是一样的,以此类推 此外,在本机函数GL2JNILib.step中,我将指令分组在块中,并单独测量这些块(不改变执行顺序),结果表明,被浪费的~15毫秒被浪费在清除块中 以下是一些修改的片段: GL2JNIView.javaAndroid GLSURFACHEVIEW,GL20-~15毫秒在Renderer.onDrawFrame中丢失,android,multithreading,opengl-es-2.0,sleep,glsurfaceview,Android,Multithreading,Opengl Es 2.0,Sleep,Glsurfaceview,我在安卓Gl20上发现了一些有趣的东西,我可以在“Hello Gl20”安卓工作室的示例中重现这些东西,我很想听听大家对这件事的看法 简言之,在S5(和其他设备)上,首次使用gl*函数会浪费约15毫秒(我会说gl上下文,但我只想展示事实,而不是我的解释) 我让这个ms troll显示它的脸的方式是:在GLSufaceView Renderer.onDraw(在GLThread上)中,我调用本机func GL2JNILib.step(绘制一个简单的三角形)两次,每次调用都有一个不同的id(int)
....
private static class Renderer implements GLSurfaceView.Renderer {
public void onDrawFrame(GL10 gl) {
GL2JNILib.step(0);
GL2JNILib.step(1);
}
...
h(一个简单的计时器头)
ATime.cpp(一个简单的计时器实现)
值得一提的是,clear-0的持续时间非常时髦,比如:13、16、15..15、18等等:)
在我看来,gl上下文被锁定在另一个线程中,GLThred必须等待gl上下文被释放。这个所谓的“理论”似乎是通过基于时钟线程CPUTIME ID的计时来证实的,并且没有ms troll在GLThread中显示它的脸(如果在没有空闲或睡眠时间的情况下进行测量,则与现实世界不同)。我的意思是所有的测量值都是预期的0毫秒。
我不知道如何摆脱这个特罗尔女士,因为剩下的不多了
有趣的是,屏幕上没有其他东西,活动是全屏的,而16毫秒似乎是一段很长的时间
有没有人知道如何摆脱那些浪费的微软,把微软巨魔踢出局,或者能给这个问题带来任何类型和/或形式的启示
怀着极大的期待和感激
Jean-Arthur Deda.别管伙计们
经过更多的实验后,我想我得到了。VSync上相对于SwapBuffers的GLThread窗口正在根据上一帧中GLThread+RenderThread的工作负载进行更改
所以大巨魔是个好消息
#ifndef TIME_H__
#define TIME_H__
#include "ATypes.h"
namespace ATime {
void init ();
u64 ms ();
f64 s();
void waste (u64 const wasteMs);
};
#include "ATime.h"
#include <time.h>
#define CLOCK CLOCK_MONOTONIC
namespace ATime {
long mStartSec = 0;
void init() {
struct timespec res;
clock_gettime(CLOCK, &res);
mStartSec = res.tv_sec;
}
u64 ms() {
struct timespec res;
clock_gettime(CLOCK, &res);
u64 ms = static_cast<u64>(res.tv_sec - mStartSec) * 1000 + res.tv_nsec / 1000000;
return ms;
}
f64 s() {
struct timespec res;
clock_gettime(CLOCK, &res);
f64 ms = 1000.0 * (res.tv_sec - mStartSec) + (f64) res.tv_nsec / 1000000.0;
return ms / 1000.0;
}
void waste(u64 const wasteMs) {
f64 t = s();
f64 e = t + static_cast<f64>(wasteMs) / 1000.0f;
while (t < e){
t = s ();
}
}
}
...
class MeasureBlock {
public:
MeasureBlock (i32 id, char const *const tag) : mId(id), mName (tag){
mStart = ATime::ms();
}
~MeasureBlock(){
auto duration = ATime::ms() - mStart;
LOGI ("%s - %d duration %d", mName, mId, static_cast<u32>(duration));
}
protected:
u64 mStart;
char const * const mName;
i32 mId;
};
void renderFrame(i32 id) {
MeasureBlock total (id, "total");
static float grey;
grey += 0.01f;
if (grey > 1.0f) {
grey = 0.0f;
}
{
MeasureBlock clear (id, "clear");
glClearColor(grey, grey, grey, 1.0f);
checkGlError("glClearColor");
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
checkGlError("glClear");
}
{
MeasureBlock actualDraw(id, "actualDraw");
glUseProgram(gProgram);
checkGlError("glUseProgram");
glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");
glDrawArrays(GL_TRIANGLES, 0, 3);
checkGlError("glDrawArrays");
}
}
...
...
clear - 0 duration 15
actualDraw - 0 duration 0
total - 0 duration 15
clear - 1 duration 0
actualDraw - 1 duration 0
total - 1 duration 0
...