Sign in to follow this  
jsg007

OpenGL OpenGL clear screen much slower than DirectX

Recommended Posts

jsg007    100
Hello! I was trying to make an app which renders both in OpenGL and Direct3D. When I got to the point to clear the screen I noticed that OpenGL is much slower than Direct3D. So I made an iteration to clear the screen 100 times. The DirectX version always performs 2 times faster. The framebuffer format is 32bit color / 24bit depth / 8bit stencil. Is this normal? Or I did something wrong in my code? This is the code:
#include <windows.h>
#include <string.h>
#include <sstream>
#include <gl/gl.h>
#include <gl/glu.h>
#include <d3d9.h> 
#include <d3dx9.h>

//Windows Specific

HWND            hWnd=NULL;							
HINSTANCE       hInstance;							
MSG				msg;

//OpenGL specific

HGLRC           hRC=NULL;							
HDC             hDC=NULL;							
PIXELFORMATDESCRIPTOR pfd;

//DirectX Specific

LPDIRECT3D9				dx_Object;
D3DPRESENT_PARAMETERS	dx_Params;
LPDIRECT3DDEVICE9		dx_Device;




LPCSTR errmsg;

bool AppRunning=true;


bool OpenGL=false;
bool DirectX=false;

int frame_count=0;

int frame_start;
unsigned int curr_time;
unsigned int start_time;
int fps;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


LRESULT CALLBACK WinProc(HWND han_Wind,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
{
   switch(uint_Message)
     {
         case WM_KEYDOWN:
		 case WM_DESTROY:
         {
             AppRunning = false;
             break;
         }
		 
		 break;
     }

return DefWindowProc(han_Wind,uint_Message,parameter1,parameter2);    	
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


bool Init()
{


		WNDCLASSEX wnd_Structure;

		wnd_Structure.cbSize = sizeof(WNDCLASSEX);
		wnd_Structure.style = CS_HREDRAW | CS_VREDRAW;


		wnd_Structure.lpfnWndProc = WinProc;

		wnd_Structure.cbClsExtra = 0;
		wnd_Structure.cbWndExtra = 0;
		wnd_Structure.hInstance = GetModuleHandle(NULL);
		wnd_Structure.hIcon = NULL;
		wnd_Structure.hCursor = NULL;
		wnd_Structure.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
		wnd_Structure.lpszMenuName = NULL;
		wnd_Structure.lpszClassName = "CLASS";
		wnd_Structure.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
	 
		RegisterClassEx(&wnd_Structure);
	    
		LPCSTR title;
		
		if (OpenGL)  title="Test (OpenGL)";
        if (DirectX) title="Test (DirectX)";

		hWnd=CreateWindowEx(WS_EX_TOPMOST,
							"CLASS",
							title,
		                    WS_VISIBLE
							| WS_OVERLAPPED
							| WS_CAPTION
							| WS_SYSMENU							
							| WS_MINIMIZEBOX
							| WS_POPUPWINDOW 
							,0, 0, 
							1024, 768, 
							NULL, 
							NULL, 
							NULL, 
							NULL);

		if (hWnd==0) 
			{
			 errmsg="Error creating window!";
 			 return false;
			}


		//Initialize OpenGL

		if (OpenGL)
		{

			hDC=GetDC(hWnd); 
			
			ZeroMemory( &pfd, sizeof( pfd ) );
			pfd.nSize = sizeof(pfd);
			pfd.nVersion = 1;
			pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
			pfd.iPixelType = PFD_TYPE_RGBA;
			pfd.cColorBits = 32;
			pfd.cDepthBits = 24;
			pfd.cStencilBits = 8;
			

			int pf=ChoosePixelFormat(hDC,&pfd);

			if (pf==0) 
				{
				 errmsg="Error setting pixel format!";
 				 return false;
				}

			SetPixelFormat( hDC, pf, &pfd );

			hRC = wglCreateContext( hDC );

			if (hRC==0) 
				{
				 errmsg="Error creating render context!";
 				 return false;
				}

			wglMakeCurrent( hDC, hRC );
		}

                //Initialize DirectX

		if (DirectX)
		{
			dx_Object = Direct3DCreate9(D3D_SDK_VERSION);
			if (dx_Object==NULL)
			{
				errmsg="DirectX 9 not supported!";
				return false;
			}
			 
			ZeroMemory( &dx_Params,sizeof(dx_Params));
			dx_Params.Windowed = TRUE;
			dx_Params.SwapEffect = D3DSWAPEFFECT_DISCARD;
			dx_Params.BackBufferFormat = D3DFMT_UNKNOWN;
			//dx_Params.BackBufferFormat = D3DFMT_A8R8G8B8;
			
			dx_Params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
			dx_Params.EnableAutoDepthStencil = true;
			dx_Params.AutoDepthStencilFormat = D3DFMT_D24S8;
			
			
			dx_Object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &dx_Params, &dx_Device);
			if (dx_Device==NULL)
			{
				errmsg="No hardware support for DirectX 9!";
				return false;
			}
						
		}
			  
				



return true;
		
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ShutDown()
{
	if (OpenGL)
	{
		ReleaseDC(hWnd,hDC);
	}

	if (DirectX)
	{
		dx_Device->Release();
	}

	
	DestroyWindow(hWnd);
}
 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Render()
{
	if (OpenGL)
	{
		for (int i=1;i<=100;i++)	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);		
	}

	if (DirectX)
	{
		for (int i=1;i<=100;i++)	dx_Device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
	int res=MessageBox(0,"","OpenGL or DirectX",MB_YESNO);

	if (res==IDYES) OpenGL=true;
    if (res==IDNO) DirectX=true;

	if (!Init())
	{
		MessageBox(0,errmsg,"Error",MB_OK);
		return 0;
	}

	

	while(AppRunning)
	 {
	     Render();
		 
		 if (OpenGL) SwapBuffers(hDC);
		 if (DirectX) dx_Device->Present(NULL, NULL, NULL, NULL);

         frame_count++;
		 
		 curr_time=GetTickCount();

		 if ((curr_time-start_time)>=1000)
		 {
			 fps=frame_count-frame_start;
			 frame_start=frame_count;
			 start_time=curr_time;
			 
			 std::ostringstream myStream;
			 myStream << "fps:" << fps << ";";
			 
			 SetWindowText(hWnd,LPCSTR(myStream.str().c_str()));
		 }


		 if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE))
		 {
			 if(!IsDialogMessage(hWnd,&msg))
			 {
				 DispatchMessage(&msg);
			 }
		 }
	 }


	ShutDown();
  return 0;
}


My specs: GeForce 6600 (latest 64 bit drivers) AthlonXP 64 3000+ 512RAM WinXP 64 bit

Share this post


Link to post
Share on other sites
jsg007    100
Quote:
Original post by Vampyre_Dark
Does it really matter? It's just one call. After the thousands of calls it takes to render any normal scene, I'm sure the differences will be negligible.


Well, I'm just surprised about the big difference (2X). It doesn't seem normal to me...

I only got to the point to clear the screen. I wonder what will happen when I render something.

Share this post


Link to post
Share on other sites
Dancin_Fool    785
It's probably due to vsync, with your directx initialization you have the presentation interval set to immediate which will cause directx to ignore the vsync. This would in turn cause directx to be faster then openGL.

Share this post


Link to post
Share on other sites
V-man    813
It's a bogus measurement. Render something worthwhile. Something that brings the FPS down to around 20 to 100 FPS. This will tell if the driver is good at dealing with your GL or D3D calls.

Share this post


Link to post
Share on other sites
jsg007    100
Quote:
Original post by Dancin_Fool
It's probably due to vsync, with your directx initialization you have the presentation interval set to immediate which will cause directx to ignore the vsync. This would in turn cause directx to be faster then openGL.


I already checked that, vsync is forced off...

Share this post


Link to post
Share on other sites
jsg007    100
Quote:
Original post by V-man
It's a bogus measurement. Render something worthwhile. Something that brings the FPS down to around 20 to 100 FPS. This will tell if the driver is good at dealing with your GL or D3D calls.


As I told I clear the screen 100 times. OpenGL renders 20 fps. DirectX renders 39fps.

Share this post


Link to post
Share on other sites
Promit    13246
Quote:
Original post by jsg007
Quote:
Original post by V-man
It's a bogus measurement. Render something worthwhile. Something that brings the FPS down to around 20 to 100 FPS. This will tell if the driver is good at dealing with your GL or D3D calls.


As I told I clear the screen 100 times. OpenGL renders 20 fps. DirectX renders 39fps.
So? Your test is idiotic. It fabricates a situation that never exists in reality and turns out useless benchmark information.

Come back after you've written something productive.

Share this post


Link to post
Share on other sites
TheGilb    372
For an empty loop you should be looking at more like a few thousand iterations in 1 second. Sorry I cant be more helpful but there's something wrong with the measure.

Share this post


Link to post
Share on other sites
deadstar    536
If you're rendering full environments, should you even be clearing the screen at all?

And although a little cold, Promit has a point. Render a scene that brings your FPS down to, say 50, and THEN perform your 100x test. Simply clearing an already blank scene will produce very inaccurate results.

Share this post


Link to post
Share on other sites
Ademan555    361
The driver could just have an un-optimized clear function, or maybe the d3d driver is "cheating" and notices you're not drawing anything in between the clears and just skips it.


Like everyone else is saying though, this really doesn't mean anything, most games don't clear the screen every frame anyways...

Share this post


Link to post
Share on other sites
jsg007    100
Quote:
Original post by Promit
Quote:
Original post by jsg007
Quote:
Original post by V-man
It's a bogus measurement. Render something worthwhile. Something that brings the FPS down to around 20 to 100 FPS. This will tell if the driver is good at dealing with your GL or D3D calls.


As I told I clear the screen 100 times. OpenGL renders 20 fps. DirectX renders 39fps.
So? Your test is idiotic. It fabricates a situation that never exists in reality and turns out useless benchmark information.

Come back after you've written something productive.


ok,ok, jesus, i was just asking if this is normal, what's you fuckin problem?

and on a high resolution the effect is noticable even with a single call, and I never said it's a fuckin benchmark for fuck's sake...

come back when you can reply something "productive"...

Share this post


Link to post
Share on other sites
Promit    13246
Quote:
Original post by deadstar
If you're rendering full environments, should you even be clearing the screen at all?
Absolutely 100% yes. The driver does a lot more than simply wiping out a buffer when you call clear. (A lot more. I've seen the code.)
Quote:
and on a high resolution the effect is noticable even with a single call, and I never said it's a fuckin benchmark for fuck's sake...
That setup can probably clear a 1600x1200 screen in the vicinity of a thousand times per second anyway. At that speed, a 50% drop is negligible and insignificant.

Like I said, come back when you're actually doing something useful. The driver is not sitting around going "gee, I'd better be on my toes in case he decides to clear the buffer over and over for no reason".

Oh, and cursing at a moderator is usually ill advised.

Share this post


Link to post
Share on other sites
jpetrie    13157
Benchmarks only tell you something about the benchmark context. Your context is pathologically flawed. Try something more realistic and see what you get; "clearing" is not as simple as you might initially think.

Put some stuff in the scene and let us know.

Share this post


Link to post
Share on other sites
dmatter    4844
Quote:
Original post by jsg007
ok,ok, jesus, i was just asking if this is normal

Well the scenario you're testing for is not normal, so yeah I would expect the results to be quirky.

Quote:
and I never said it's a fuckin benchmark for fuck's sake...

None the less it's still a benchmark, just not one of any practical benefit.

If you render several nice large polygon batches and clear the buffers between each frame, then you should find that either OGL and D3D stabilise to about the same performance, or that your OGL implementation will crash and burn indicating that you need to update the driver.

Share this post


Link to post
Share on other sites
ma_hty    100
Quote:
Original post by jsg007
Quote:
Original post by Dancin_Fool
It's probably due to vsync, with your directx initialization you have the presentation interval set to immediate which will cause directx to ignore the vsync. This would in turn cause directx to be faster then openGL.

I already checked that, vsync is forced off...


You did something wrong in your code. As Dancin_Fool have already mentioned, it is due to vsync. You set DirectX to ignore vsync while leaving OpenGL vsync status to its default value. For a NVidiia display card, the default behaviour of OpenGL is synchronizing with vsync.

To get a more reasonable result, you should set DirectX and OpenGL to either "both ignoring vsync" or "both synchronizeing with vsync". If you doing it correctly. You should endup with identical frame rates.

However, even after the correction, the frame rates are still not a valid performance measurement. The GPU have a command queue. Your commands are catched in the command queue first. They are not executed until the queue is full or being told to execute explicitly. Therefore, more than likely, your frame rate measuring program is just measuring the time of uploading commands to GPU without execution if ignoring vsync (or the screen refresh rate if synchronized with vsync).

In either cases, the values are meaningless.

Share this post


Link to post
Share on other sites
Hodgman    51334
What code did you use to disable V-synch in GL?


Quote:
Original post by Promit
Oh, and cursing at a moderator is usually ill advised.

He shouldn't have bit back at you, but you still laid the bait for him by basically calling him an idiot. Pulling out the moderator card doesn't change that.

It also shouldn't mean that you can break a "will not be tolerated" rule and then be so uptight and sensitive about a "should be avoided" rule.

Share this post


Link to post
Share on other sites
ma_hty    100
Quote:
Original post by Hodgman
Quote:
Original post by Promit
Oh, and cursing at a moderator is usually ill advised.

He shouldn't have bit back at you, but you still laid the bait for him by basically calling him an idiot. Pulling out the moderator card doesn't change that.


Promit said the program is idiotic. He never said the one wrote it is an idiot (which are words I really wish to say).

Share this post


Link to post
Share on other sites
Hodgman    51334
Quote:
Original post by ma_hty
Promit said the program is idiotic. He never said the one wrote it is an idiot (which are words I really wish to say).

Yes - he said the program is idiotic, as in, the program is characterized by idiocy, as in, the program's author is also characterized by idiocy, as in, the program's author suffers from extreme mental retardation.

Put yourself in jsg007's shoes and it's easy to see how he took it offensively...

Share this post


Link to post
Share on other sites
ma_hty    100
Hey Hodgman,

I don't think here is the correct venue to discuss discipline. If you are enthusiastic about the discipline discussion, start a new thread in a discussion board for general discussion and ask me to join it (though I'm not interested at all).

Gary

Share this post


Link to post
Share on other sites
Samurai Jack    455
No no no!

Wait. You are using GetTickCount() which runs by default at 60HZ so I'm wondering how do you get 100 FPS ? Okay. Let's put this aside.

If you would like to get the maximum time accurancy you will have to use QueryPerformanenceCounter. This will give you more accurate time results.

Also you have to be careful, that you not clear only the color buffer in DirectX where on the other side you might clean color,stencil and depth buffer as well. I didn't check the code yet, but for such time critical measures GetTickCount is too slow!

Share this post


Link to post
Share on other sites
jsg007    100
I just think the moderator over reacted calling me an idiot and maybe I over reacted to that.

And interestingly my user rating dropped considerably.

This was just a shitty sample since I never used DirectX and was making a simple program to test basic functionality, and I noticed that DirectX clears the buffer much faster, ok? No reason for jumping around.

It's not a benchmark, it does not prove anything.

I know about QueryPerformanenceCounter, and believe it or not this simple Gettickcount counter works fine, but that's not the point anyway.


And because I'm not that experienced programmer is not a reason for you to call me an idiot. Specially I would not expect something like that from the moderator.


As a forum moderator, Mr.Promit, you fail!

Share this post


Link to post
Share on other sites
_the_phantom_    11250
and the thread gets closed.

@Hodgman : You didn't remotely help the situation here, and your convoluted "reasoning" behind why he might take offense... well, it was dumb. Pease don't be doing things like that again, more so when a mod (ie ME) has already told the person in question to cool it.

@jsg007: I asked you to cool it, you apprently haven't.
a) he didn't call YOU and idiot, he called your program idiotic. Please learn to read what has been written not what you think has been written. Too many people take offense at percived slights and, believe me, if Promit thought you were an idiot he would have called you on it.
b) Regardless of what you think your program IS a benchmark as it is timing the differences between to things.
c) Cheap parting shots are not tolerated, more so when you've been asked to cool it and frankly they are just childish; don't do it again.

And before you make a thread complaining about this one being closed I will "remind" you that doing such is against the forum rules.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now