对GLSL着色器进行基准测试以比较替代实现的速度

时间:2016-05-27 11:31:53

标签: opengl glsl microbenchmark

我想使用OpenGL和GLSL着色器绘制二维函数z = f(x,y)。我想使用colormap将函数的值映射到颜色,但是一些颜色图使用HSL或HSV颜色空间(例如色调映射)表示。

您可以在GLSL中找到(此处和其他地方)hsv2rgb()的不同替代实现。

如何基准这些着色器(这些功能)找出哪一个最快?

3 个答案:

答案 0 :(得分:1)

实施您想要尝试的所有替代方案,并应用通常的基准建议:

  • 重复个人基准测试足够的时间是秒(较少会受到太大的噪音影响)
  • 在要运行它的环境中重复基准测试。
  • 尽量使设置尽可能接近现实(相同的后台进程等)。
  • 重复基准测试运行几次并忽略异常值。
  • 在运行之间随机化算法/测试的顺序。
  • 确保您为正在测试的部分禁用缓存(如果适用)。

由于您包含OpenGL解决方案,因此您应该考虑是否要计算数据传输。确保刷新管道(opengl会调用一些调用,但flush会等到它们实际完成)。

如果运行时间太近,您可以说它们大致相同或者增加数据大小/重复次数以使差异更加显着。

答案 1 :(得分:0)

为了实现彩色地图,我建议使用纹理。

类似于256x1纹理(ES中不支持1D纹理,如果这对你很重要),然后从f(x,y)的浮点结果,只需使用它作为纹理坐标。

如果你有很多要点的情节,那么每次使用glsl进行评估的速度要快得多,并且GPU在纹理处理时:)

答案 2 :(得分:0)

您需要首先测量GL渲染的时间。我在 C ++ 中这样做:

//------------------------------------------------------------------------------
class OpenGLtime
    {
public:
    unsigned int id[2];
    OpenGLtime();
    OpenGLtime(OpenGLtime& a);
    ~OpenGLtime();
    OpenGLtime* operator = (const OpenGLtime *a);
    //OpenGLtime* operator = (const OpenGLtime &a);
    void _init();
    void tbeg();            // mark start time for measure
    void tend();            // mark end time for measure
    double time();          // wait for measure and return time [s]
    };
//------------------------------------------------------------------------------
OpenGLtime::OpenGLtime()
    {
    id[0]=0;
    id[1]=0;
    }
//------------------------------------------------------------------------------
OpenGLtime::OpenGLtime(OpenGLtime& a)
    {
    id[0]=0;
    id[1]=0;
    }
//------------------------------------------------------------------------------
OpenGLtime::~OpenGLtime()
    {
    }
//------------------------------------------------------------------------------
OpenGLtime* OpenGLtime::operator = (const OpenGLtime *a)
    {
    *this=*a;
    return this;
    }
//------------------------------------------------------------------------------
void OpenGLtime::_init()
    {
    // generate two queries
    glGenQueries(2,id);
    }
//------------------------------------------------------------------------------
void OpenGLtime::tbeg()
    {
    if (!id[0]) _init();
    // issue the query
    glQueryCounter(id[0],GL_TIMESTAMP);
    }
//------------------------------------------------------------------------------
void OpenGLtime::tend()
    {
    if (!id[0]) _init();
    // issue the query
    glQueryCounter(id[1],GL_TIMESTAMP);
    }
//------------------------------------------------------------------------------
double OpenGLtime::time()
    {
    if (!id[0]) { _init(); return 0.0; }
    double dt;
    GLuint64 t0,t1;
    int _stop;

    // wait until the results are available
    for (_stop=0;!_stop;Sleep(1)) glGetQueryObjectiv(id[0],GL_QUERY_RESULT_AVAILABLE,&_stop);
    for (_stop=0;!_stop;Sleep(1)) glGetQueryObjectiv(id[1],GL_QUERY_RESULT_AVAILABLE,&_stop);
    // get query results
    glGetQueryObjectui64v(id[0],GL_QUERY_RESULT,&t0);
    glGetQueryObjectui64v(id[1],GL_QUERY_RESULT,&t1);
    dt=double(t1)-double(t0); dt*=0.000000001;

    return dt;
    }
//------------------------------------------------------------------------------

现在你就这样使用它:

// few variables
OpenGLtime    tim;
double draw_time;

// measurement
tim.tbeg();
// here render your stuff using binded shader
tim.tend();
draw_time=tim.time(); // time the render took in [s] just output it somewhere so you can see it

现在你应该创建你的渲染内容。并且可以直接比较运行时。

你可以看到你将测量整个渲染通道/调用的时间而不是GLSL代码的一部分。所以你必须考虑到这一点。我不知道如何直接测量部分GLSL代码。相反,你可以在没有问题的部分和它的情况下测量时间......并减去时间,但编译器优化可能会搞砸它。