Reputation: 323464
I want to plot two-dimensional function z = f(x,y)
using OpenGL and GLSL shaders. I'd like to map the value of function to color using a colormap, but some colormaps are expressed using HSL or HSV colorspace (for example hue maps).
You can find (here and in other places) different alternative implementtions of hsv2rgb()
in GLSL.
How can I benchmark those shaders (those functions) to find out which one is fastest?
Upvotes: 1
Views: 942
Reputation: 51845
You need to be able to measure time of GL rendering first. I do it in C++ like this:
//------------------------------------------------------------------------------
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;
}
//------------------------------------------------------------------------------
Now you just use it like this:
// 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
Now you should create your rendering stuff. And can compare the runtimes directly.
As yo can see you will measure time of the whole rendering pass/call and not of a part of GLSL code. So you have to take that into account. I do not know any way to measure part of GLSL code directly. Instead you can measure time without the part in the question and with it ... and substract the times but the compiler optimizations could mess it up.
Upvotes: 0
Reputation: 2170
For having implemented color maps, I'd just recommend to use a texture.
Something like a 256x1 texture (1D texture are not supported in ES, if that matters to you) and then from the float result of f(x,y), just use that as the texture coordinate.
If you have a lot of points to plot, that's going to be faster than evaluating it in glsl each time and GPU are good at texturing :)
Upvotes: 0
Reputation: 11968
Implement all alternatives you want to try and apply the usual benchmark suggestions:
Since you include OpenGL solutions you should consider if you want to count data transfers as well. Make sure you flush the pipelines (opengl deffers some calls, but flush will wait until they are actually finished).
If the run-times are too close you can either say they are about the same or increase data size/repetitions to make the difference more prominent.
Upvotes: 1