glfwSwapBuffers is slow!

matwachich wrote on Thursday, April 26, 2012:

Hello every body!
I’m developping a 2D engin based on OpenGL and GLFW with FreeBasic. It’s not
the first engin I made, and the first was really fast, but the code was really
bad, and not well made.

So i decided to remake the engin, but when i benchmarked this second one, i
saw that it was very slow comparing to the frist!

So I timed the different operations time, and i saw that the problem was from
glfwSwapBuffers!
In the first engin, the time is always very short, but in the new engin, when
i reach about 800 sprites (glBegin(GL_TRIANLE_FANS); 4 glVertex;
glEnd()) the time of glfwSwapBuffers reaches 40ms!!!

So, i’m asking, what can make glfwSwapBuffers so slow???

I’m using in the 2 engins the same version (2.7.4), and the same libglfw.a.

THANKS

elmindreda wrote on Thursday, April 26, 2012:

The GPU and your program are running asynchronously, but for the buffer swap
to work they have to synchronise, which means the GPU driver has to wait until
the GPU has finished rendering everything you told it to before it can return
control to GLFW.

matwachich wrote on Thursday, April 26, 2012:

First, thanks for your answer.

But the problem is that to 2 engins are runing on the same machine (T3400 -
G103M)
I think the only difference between the 2 engins is that the first (the fast
one) is Object Oriented, while the second one (the slow) is made of
standard cdecl exported functions (cause I plane to make it as a DLL)

About the OpenGL initiation and drawing stuff, there are no big differences
between the 2 engins.

This problem is really anoying to me, since i dont understand why it’s
happening.

PS: here is the thread in the FreeBasic’s official forum
(Link)

Thanks

elmindreda wrote on Thursday, April 26, 2012:

Are you perhaps setting the swap interval to different values in the two code
bases?

matwachich wrote on Thursday, April 26, 2012:

No, i already tried to play with the swap interval setting, but there is no
difference, since the FPS drops below 60, it’s only limiting the higher FPS.

I made 2 tests, with minimal codes: one with standard function calls, and
another one with and Object Class, and it’s the same problem.

I must have made something in the older engin that accelerated the whole
things, but i cannot find what!!!

PS: first test (Standard functions)

#include "gl\glfw.bi"
#define QUADS_NBR 1000
glfwInit()
glfwOpenWindow(800, 600, 8, 8, 8, 0, 0, 0, GLFW_WINDOW)
glfwSwapInterval(0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2d(0, 800, 600, 0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_DEPTH_TEST)
glColor4f(1.0, 1.0, 1.0, 1.0)
Dim As Double delta = 0, old_t = 0
Dim As Double tmp = 0, swap_t = 0, draw_t = 0
Dim As Integer frames = 0
While glfwGetWindowParam(GLFW_OPENED) = 1
	delta = glfwGetTime() - old_t
	old_t = glfwGetTime()
	glfwSetWindowTitle("FPS: " + Str(1/delta))
	'''
	glClear(GL_COLOR_BUFFER_BIT)
	tmp = glfwGetTime()
	For i As Integer = 1 To QUADS_NBR
	glBegin(GL_TRIANGLE_FAN)
		glVertex2i(100, 100)
		glVertex2i(300, 100)
		glVertex2i(300, 300)
		glVertex2i(100, 300)
	glEnd()
	Next
	draw_t += glfwGetTime() - tmp
	tmp = glfwGetTime()
	glfwSwapBuffers()
	swap_t += glfwGetTime() - tmp
	frames += 1
WEnd
glfwTerminate()
Print Str(QUADS_NBR) + " quads draw time: " + Str(draw_t/frames) + " - One quad: " + Str((draw_t/frames)/QUADS_NBR)
Print "glfwSwapBuffers() time: " + Str(swap_t/frames)
Sleep

Second test, with a class:

#include "gl\glfw.bi"
Type Sys
	Declare Constructor ()
	Declare Destructor ()
	Declare Sub OpenWindow(As Integer, As Integer)
	Declare Function IsOpened () As Integer
	Declare Sub Draw_Begin ()
	Declare Sub Draw_End ()
	Declare Function GetFps () As Integer
	As Double old_t = 0, delta = 0
End Type
Constructor Sys ()
	glfwInit()
End Constructor
Destructor Sys ()
	glfwTerminate()
End Destructor
Sub Sys.OpenWindow (w As Integer, h As Integer)
	glfwOpenWindow(800, 600, 8, 8, 8, 0, 0, 0, GLFW_WINDOW)
	glfwSwapInterval(0)
	glMatrixMode(GL_PROJECTION)
	glLoadIdentity()
	gluOrtho2d(0, 800, 600, 0)
	glMatrixMode(GL_MODELVIEW)
	glLoadIdentity()
	glDisable(GL_DEPTH_TEST)
	glColor4f(1.0, 1.0, 1.0, 1.0)
End Sub
Function Sys.IsOpened () As Integer
	Return glfwGetWindowParam(GLFW_OPENED)
End Function
Sub Sys.Draw_Begin ()
	glClear(GL_COLOR_BUFFER_BIT)
End Sub
Sub Sys.Draw_End ()
	glfwSwapBuffers()
End Sub
Function Sys.GetFps () As Integer
	This.delta = glfwGetTime() - This.old_t
	This.old_t = glfwGetTime()
	'''
	Return Int(1/This.delta)
End Function
'''
#define QUADS_NBR 1000
Dim As Sys root = Sys()
root.OpenWindow(800, 600)
Dim As Double tmp = 0, swap_t = 0, draw_t = 0
Dim As Integer frames = 0
While root.IsOpened() = 1
	glfwSetWindowTitle("FPS: " + Str(root.GetFps()))
	root.Draw_Begin()
	tmp = glfwGetTime()
	For i As Integer = 1 To QUADS_NBR
	glBegin(GL_TRIANGLE_FAN)
		glVertex2i(100, 100)
		glVertex2i(300, 100)
		glVertex2i(300, 300)
		glVertex2i(100, 300)
	glEnd()
	Next
	draw_t += glfwGetTime() - tmp
	tmp = glfwGetTime()
	root.Draw_End()
	swap_t += glfwGetTime() - tmp
	frames += 1
WEnd
Print Str(QUADS_NBR) + " quads draw time: " + Str(draw_t/frames) + " - One quad: " + Str((draw_t/frames)/QUADS_NBR)
Print "glfwSwapBuffers() time: " + Str(swap_t/frames)
Sleep

The FreeBasic’s syntax is easy to understand (i think!) and easy
traslatable to C/C++

PS: in the 2 codes, with 1000 QUADS, a single glfwSwapBuffers takes 40ms! And
the 1000 glBegin()/glEnd() takes 7.2e-5 => So i can theorically display
about 4.000.000 quads, if glfwSwapBuffers wasn’t so slow!

PS: Configuration: Dual Core T3400 (2.16 GHZ), 3GO DDR2, GeForce G103M with
512MB memory

THANKS FOR YOUR HELP