OpenGL performance stuff

Discuss programming topics that involve the OpenGL API.
Post Reply
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

OpenGL performance stuff

Post by Baker »

OpenGL 1.x questions

1) glGetIntegerv, glGetFloatv, etc. These don't have to interact with the graphics card, right? So these are near "instant" and close to free? My guess is yes.
2) I do glEnable (GL_ALPHA_TEST). It was already on. Can I expect the driver to ignore this since it is redundant? My guess is yes or doesn't materially matter.

I worry about some of this stuff being left on accidentally (forgot to turn something off in code or restore it) and in the past, I've had to track down a couple of places where something "wasn't right" and then find where something wasn't restored.

If I check the state of every GL capability I care about (probably 20 of them at most) before drawing an entity, is that going to affect performance? My guess is no because even if it did, say, 6000 glGetFloatv/glGetIntegerv per frame the speeds are similar to any other external library simple function call.

Now I probably plan to #ifdef _DEBUG this anyway so it is only in the debug build.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: OpenGL performance stuff

Post by Baker »

Actually, it looks glGetFloatv and glGetIntegerv does get the info from the gpu == slow == avoid.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: OpenGL performance stuff

Post by Spike »

1: glGet* are not expected to be particuarly optimised. You're expected to be tracking any such state yourself, which removes the need for any such calls mid-frame.
2: you're still thunking through at least two different dlls. in cpu cache terms alone, that's quite significant, more so than a simple statically linked lib. If you're changing textures at the same time then its *probably* not otherwise significant.

By all means use glGet to query implementation-defined limits, or in debug builds. Just don't rely upon it because its basically pointless to do so. It will nearly always be faster to directly store the current value somewhere than to go through thunks to query it.

This stuff is all cpu stuff, rather than any intrinsic hardware stuff. CPU optimisation rules apply.
I'm not even sure drivers will actually see any of those gl enums.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: OpenGL performance stuff

Post by Baker »

Spike wrote:1: glGet* are not expected to be particuarly optimised. You're expected to be tracking any such state yourself, which removes the need for any such calls mid-frame.
I wanted to make sure wasn't overkilling for no reason, but yeah I'm setting that up. I just wanted to make sure I wasn't investing time in tracking them in the engine for no reason.

Code: Select all

/*
////////////////////////////////////////////////////////////////////////////////
GL Capabilities and States ...
////////////////////////////////////////////////////////////////////////////////
*/

// Base 3D state ...
glstate_t base_glstate_3d =
{
/*		glEnable (GL_ALPHA_TEST)	*/	GL_FALSE,								//	(bool)	gl_alpha_test;
/*		glAlphaFunc (a, b)			*/	GL_GREATER, 0.666f,						//	(int)	gl_alpha_test_func, (float) gl_alpha_test_ref;
/*		glEnable (GL_BLEND)			*/	GL_FALSE,								//	(bool)	gl_blend;
/*		glBlendFunc (s, d)			*/	GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,	//	(int)	gl_blend_src, (int) gl_blend_dest;
/*		glEnable (GL_DEPTH_TEST)	*/	GL_TRUE,								//	(bool)	gl_depth_test;
/*		glDepthFunc (a)				*/	GL_LEQUAL,								//	(bool)	gl_depthfunc;
/*		glEnable (GL_CULL_FACE)		*/	GL_TRUE,								//	(bool)	gl_cull_face;
/*		glCullFace (x)				*/	GL_FRONT,	/*was back*/							//	(bool)	gl_cull_face_mode;
/*		glEnable (GL_TEXTURE_2D)	*/	GL_TRUE,								//	(bool)	gl_texture_2d;		
/*		glTexEnvf (c, c, p)			*/	GL_REPLACE,								//	(int)	gl_texture_env_mode (gltexenvf)
/*		glColor4 (r,g,b,a)			*/	{ 1.0f, 1.0f, 1.0f, 1.0f},				//	(float)	gl_current_color[4]
};

// Base 2D state ... Nearly identical to above but with blending on, depth test off and culling off.


glstate_t base_glstate_2d =
{
/*		glEnable (GL_ALPHA_TEST)	*/	GL_FALSE,								//	(bool)	gl_alpha_test;
/*		glAlphaFunc (a, b)			*/	GL_GREATER, 0.666f,						//	(int)	gl_alpha_test_func, (float) gl_alpha_test_ref;
/*		glEnable (GL_BLEND)			*/	GL_TRUE,	/* CHANGE */				//	(bool)	gl_blend;
/*		glBlendFunc (s, d)			*/	GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,	//	(int)	gl_blend_src, (int) gl_blend_dest;
/*		glEnable (GL_DEPTH_TEST)	*/	GL_FALSE,  /* CHANGE */					//	(bool)	gl_depth_test;
/*		glDepthFunc (a)				*/	GL_LEQUAL,								//	(bool)	gl_depthfunc;
/*		glEnable (GL_CULL_FACE)		*/	GL_FALSE,	/* CHANGE */				//	(bool)	gl_cull_face;
/*		glCullFace (x)				*/	GL_BACK,								//	(bool)	gl_cull_face_mode;
/*		glEnable (GL_TEXTURE_2D)	*/	GL_TRUE,								//	(bool)	gl_texture_2d;		
/*		glTexEnvf (c, c, p)			*/	GL_REPLACE,								//	(int)	gl_texture_env_mode (gltexenvf)
/*		glColor4 (r,g,b,a)			*/	{ 1.0f, 1.0f, 1.0f, 1.0f},				//	(float)	gl_current_color[4]
};
If debugging ... get the actual stuff to validate if tracking down some issue ...

Code: Select all

void Renderer_GL_SetStates (glstate_t* setState)
{
	#define GL_SetCapability(cap, val) {if (val) glEnable (cap); else glDisable(cap); }

	GL_SetCapability	(GL_ALPHA_TEST, setState->gl_alpha_test);
	GL_SetCapability	(GL_BLEND,		setState->gl_blend);
	GL_SetCapability	(GL_DEPTH_TEST, setState->gl_depth_test);
	GL_SetCapability	(GL_CULL_FACE,	setState->gl_cull_face);
	GL_SetCapability	(GL_TEXTURE_2D,	setState->gl_texture_2d);

	glTexEnvf			(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, setState->gl_texture_env_mode);
	
	glAlphaFunc			(setState->gl_alpha_test_func, setState->gl_alpha_test_ref);
	glBlendFunc			(setState->gl_blend_src, setState->gl_blend_dest);
	glDepthFunc			(setState->gl_depthfunc);
	glCullFace			(setState->gl_cull_face_mode);
	
	glColor4fv			(setState->gl_current_color);
}

void Renderer_GL_GetStates (glstate_t* getState)
{
	glstate_t temp;

	glGetBooleanv	(GL_ALPHA_TEST,			&temp.gl_alpha_test);
	glGetIntegerv	(GL_ALPHA_TEST_FUNC,	&temp.gl_alpha_test_func);
	glGetFloatv		(GL_ALPHA_TEST_REF,		&temp.gl_alpha_test_ref);
	glGetBooleanv	(GL_BLEND,				&temp.gl_blend);
	glGetIntegerv	(GL_BLEND_SRC,			&temp.gl_blend_src);
	glGetIntegerv	(GL_BLEND_DST,			&temp.gl_blend_dest);
	glGetBooleanv	(GL_DEPTH_TEST,			&temp.gl_depth_test);
	glGetIntegerv	(GL_DEPTH_FUNC,			&temp.gl_depthfunc);
	glGetBooleanv	(GL_CULL_FACE,			&temp.gl_cull_face);
	glGetIntegerv	(GL_CULL_FACE_MODE,		&temp.gl_cull_face_mode);
	glGetBooleanv	(GL_TEXTURE_2D,			&temp.gl_texture_2d);
	glGetFloatv		(GL_TEXTURE_ENV_MODE, 	&temp.gl_texture_env_mode);
	glGetFloatv		(GL_CURRENT_COLOR, 		&temp.gl_current_color[0]);

	memcpy (getState, &temp, sizeof(getState));
}

void Renderer_GL_SetStates (glstate_t* setState);
void Renderer_GL_GetStates (glstate_t* getState);
fbool Renderer_GL_CompareStates(const glstate_t* state1, const glstate_t* state2)
{
	fbool matches = memcmp (state1, state2, sizeof(state1) ) == 0;

	return matches;
}
I'm trying to actually strip all the glEnable / glDisable and friends out of the code in favor of specifying "Ok, this is the drawing state for X ... " and then comparing the current engine-tracking idea of what the states are versus the new states and changing what needs to be changed.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: OpenGL performance stuff

Post by Spike »

try reading fte's gl_backend.c's BE_SendPassBlendDepthMask, maybe it'll give you an idea (I believe the basic idea for that function came from qfusion).
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: OpenGL performance stuff

Post by mh »

The driver may or may not cache values for glGet calls locally; if it does then it shouldn't need to round-trip to the GPU, if it doesn't then it will, but it depends on the driver and todays driver behaviour may be completely different tomorrow. So don't depend on it. ;)
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Post Reply