0
\$\begingroup\$

I have written a benchmark program that compares the performance of OpenGL and DirectX libraries. The problem is that OpenGL gets much lower performance than Direct3D. At the end the program generates a comparison chart. You can look at it here: LINK. As you can see the OpenGL performance is poor compared with Direct3D (I know that FPS's aren't the best method of measuring out there but that was my choise from the begining). Rendered object is a BIG CUBE made of smaller cubes. BIG CUBE passes certain states that are:

  COLOR  
  COLOR + LIGHTS 
  TEXTURE 
  TEXTURE + LIGHTS 
  WIRE 
  TRANSPARENT

OpenGL context uses atioglxx.dll (AMD) and nvoglv32.dll (NVidia) for HW rendering. Now I will provide some code for better view of what and how I am doing things. First of all I'm creating a rendering context that is loaded on WM_CREATE:

GLvoid StartOpenGL(HWND hwnd, HDC * hdC, HGLRC * hrc)
{
  PIXELFORMATDESCRIPTOR pfd;
  int format;
  *hdC = GetDC(hwnd);

  ZeroMemory( &pfd, sizeof( pfd ) );
  pfd.nSize = sizeof( pfd );
  pfd.nVersion = 1;
  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pfd.iPixelType = PFD_TYPE_RGBA;
  pfd.cColorBits = 32;
  pfd.cDepthBits = 24;
  pfd.cStencilBits = 8;
  pfd.iLayerType = PFD_MAIN_PLANE;
  format = ChoosePixelFormat(*hdC, &pfd);
  SetPixelFormat(*hdC, format, &pfd);

  *hrc = wglCreateContext(*hdC);
  wglMakeCurrent(*hdC, *hrc);
}
// also these functions are called on WM_CREATE:
    ApplyTextures();  //load texture
    reshape();        // reshape
    LOADcubeGL();     // load VBO's (for full code check LINK2 on Blockquote)
    ACTIVATEcubeGL(); // activate VBO's (for full code check LINK2 on Blockquote)

Context is destroyed on WM_DESTROY:

GLvoid StopOpenGL(HWND hwnd, HDC hdC, HGLRC hrc)
{
    wglMakeCurrent( NULL, NULL );
    wglDeleteContext( hrc );
    ReleaseDC(hwnd, hdC);
}
// also these functions are called on WM_DESTROY:
KILLcubeGL(); // zero VBO's (for full code check LINK2 on Blockquote)

On WINAPI WinMain I do

animationGL(); // rotate the cube
init();        // inits GLlight
display();     // set view + transformation + rendering the cube object with glEnable(); glDisable(); states
SwapBuffers(hdC);

Here is the LINK2

The BIG CUBE is drawn in display(); stage by:

glNewList(1, GL_COMPILE);
  glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_BYTE, indices);
glEndList();

Now I know that mixing VBO's with display list may cause problems and moreover DirectX 9 doesn't have equivalent for display list but otherwise my OPENGL code runs even slower: at 20FPS! What I am doing wrong?

My DirectX calls look pretty same except that there is no rendering context like OpenGL have. I draw by vertex_buffer->Lock index_buffer->Lock and finaly d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);. My equivalent for OpenGL's PIXELFORMATDESCRIPTOR is:

d3dp.Windowed = TRUE;
d3dp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dp.hDeviceWindow = dxhwnd;
d3dp.BackBufferCount = 1;
d3dp.BackBufferFormat = d3ddm.Format;
d3dp.MultiSampleType = D3DMULTISAMPLE_NONE;  // in OpenGL I set that elsewhere than pfd
d3dp.MultiSampleQuality = 0;
d3dp.BackBufferWidth = width;
d3dp.BackBufferHeight = height;
d3dp.EnableAutoDepthStencil  = TRUE;
d3dp.AutoDepthStencilFormat  = D3DFMT_D24S8;
d3dp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // in OpenGL I use wglSwapIntervalEXT(0);

If you like to download my program: LINK3 (takes 4 min. to pass). To run you need to have VS 2013 Redistributable Packages installed and also DirectX latest drivers.

\$\endgroup\$

closed as off-topic by Trevor Powell, Anko, Vaughan Hilts, Seth Battin, MichaelHouse Apr 22 '14 at 14:04

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Trevor Powell, Anko, Vaughan Hilts, Seth Battin, MichaelHouse
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ Lots of issues here... Display lists are deprecated to begin with. If you are using them, you shouldn't create a new one every frame. You need to use glGenLists to generate a valid ID to use in glNewList. GL_COMPILE means it won't actually execute it at that time anyway. You are using glDrawElements as if you are using client-side arrays. When a buffer is bound to ELEMENT_ARRAY_BUFFER the last parameter is an offset into that buffer, not a pointer. \$\endgroup\$ – bcrist Apr 10 '14 at 22:02
  • 2
    \$\begingroup\$ Looking closer, you're uploading your vertex data to a buffer, but you're never actually using it. You enable client-side arrays but never give OpenGL pointers to your client side data. There's no way this code actually renders properly. Before you benchmark, its usually best to make sure your code is actually working. \$\endgroup\$ – bcrist Apr 10 '14 at 22:18
  • \$\begingroup\$ @bcrist you were right I was never actually using the VBO. It was hard hours for me but thanks to your advices and some tutorials link I have finaly made it! Well there is still a bit difference between the libraries but until now it is the best method for me with no display lists... If you like to see the updated functions go ahead and: link. I am looking forward to improving the code. If someone spots that something else is in the code that needs to be repaired-inform me. Thank you. \$\endgroup\$ – NightKn8 Apr 11 '14 at 3:04
  • \$\begingroup\$ Interleave your vertex data in the buffer. Instead of pos0, pos1, pos1, tex0, tex1, tex2, etc. do pos0,tex0,norm0,... This generally helps for large meshes, not sure how much it will help for a small one. The idea is that when a GPU fetches a vertex, it can fetch the first N bytes rather than data from 5 places that are non-contiguous. \$\endgroup\$ – PatrickB Apr 11 '14 at 22:19
  • \$\begingroup\$ GL_UNSIGNED_BYTE is a very bad choice of index size in the first place. The API supports it, but GPUs don't. The fundamental problem is that it leads to unaligned memory access when fetching indices, the driver can help the GPU to overcome this problem but it will not give good performance. If you enable Debug Output on one of your AMD GPUs, it will basically tell you the same thing I did in the form of a performance warning, only without the explanation. I am sure you must have noticed the smallest index size in D3D is 16-bit? :) \$\endgroup\$ – Andon M. Coleman Apr 16 '14 at 23:12
1
\$\begingroup\$

I can't read all of the source code (dang firewalls), but a display list is something that you compile once, then execute many times. What you're doing is telling OpenGL to regenerate an optimized execution list containing such and such triangle data every frame. That isn't what display lists were* used for -- they originally were more for things like old SGI workstations that could literally compile OpenGL commands into GPU command buffers and execute them. Even if you were executing this code on an SGI machine, this would perform terribly because you're re-creating this display list!

Modern GPUs don't function like this. If your data is in a VBO, doing a display list means OpenGL must read the data back to create it. JUST SAY NO. Do a glDrawElements() and be done with it. Nothing fancy. As an aside, display lists are gone in later versions of GL, so definitely don't use them. It pretty much guarantees problems going forward.

* "were", as in, don't do it now! Ever! No! Nope!

\$\endgroup\$
  • \$\begingroup\$ If I turn off display list the FPS drop under 20 for OpenGL. Look here: link. I call glDrawElements() 8 times what gives 497664 verts to draw at once. GTX 660 should do it smoothly just like in DirectX case. \$\endgroup\$ – NightKn8 Apr 10 '14 at 21:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.