Page 1 of 1

OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 12:20 am
by Didaktik
It is a strange situation.
I compiled the example, and instead of the promised 60 showed 30fps FRAPS.
I reduced the timer but it did not help. Also 2 gedget occupy 25% of the CPU.
Whereas gedget 1 occupies less than 1%.
But with three gedgets FPS drops to 20.

Code: Select all


;
; OpenGL Gadget demonstration
;
; (c) Fantaisie Software
;
; Axis explainations:
;
;             +
;             y
;
;             |
;             |
;  +          |
;  x ---------\
;              \
;               \
;                \ 
;                  z+
;
; So a rotate on the y axis will take the y axis as center. With OpenGL, we can specify
; positive And negative value. Positive values are always in the same sens as the axis
; (like described on the schmatic, with '+' signs)
;

Global RollAxisX.f
Global RollAxisY.f
Global RollAxisZ.f

Global RotateSpeedX.f = 1.0
Global RotateSpeedY.f
Global RotateSpeedZ.f = 1.0

Global ZoomFactor.f = 1.0 ; Distance of the camera. Negative value = zoom back

Procedure DrawCube(Gadget)
  SetGadgetAttribute(Gadget, #PB_OpenGL_SetContext, #True)
  
  glPushMatrix_()                  ; Save the original Matrix coordinates
  glMatrixMode_(#GL_MODELVIEW)

  glTranslatef_(0, 0, ZoomFactor)  ;  move it forward a bit

  glRotatef_ (RollAxisX, 1.0, 0, 0) ; rotate around X axis
  glRotatef_ (RollAxisY, 0, 1.0, 0) ; rotate around Y axis
  glRotatef_ (RollAxisZ, 0, 0, 1.0) ; rotate around Z axis
 
  RollAxisX + RotateSpeedX 
  RollAxisY + RotateSpeedY 
  RollAxisZ + RotateSpeedZ 

  ; clear framebuffer And depth-buffer

  glClear_ (#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)

  ; draw the faces of a cube
  
  ; draw colored faces

  glDisable_(#GL_LIGHTING)
  glBegin_  (#GL_QUADS)
  
  ; Build a face, composed of 4 vertex ! 
  ; glBegin() specify how the vertexes are considered. Here a group of
  ; 4 vertexes (GL_QUADS) form a rectangular surface.

  ; Now, the color stuff: It's r,v,b but with float values which
  ; can go from 0.0 To 1.0 (0 is .. zero And 1.0 is full intensity) 
  
  glNormal3f_ (0,0,1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (0.5,0.5,0.5)   
  glColor3f_  (0,1.0,1.0)         
  glVertex3f_ (-0.5,0.5,0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (-0.5,-0.5,0.5)
  glColor3f_  (0,0,0)
  glVertex3f_ (0.5,-0.5,0.5) 

  ; The other face is the same than the previous one 
  ; except the colour which is nice blue To white gradiant

  glNormal3f_ (0,0,-1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,-0.5,-0.5)
  
  glEnd_()
  
  ; draw shaded faces

  glEnable_(#GL_LIGHTING)
  glEnable_(#GL_LIGHT0)
  glBegin_ (#GL_QUADS)

  glNormal3f_ (   0, 1.0,   0)
  glVertex3f_ ( 0.5, 0.5, 0.5)
  glVertex3f_ ( 0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)

  glNormal3f_ (0,-1.0,0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (-0.5,-0.5,0.5)

  glNormal3f_ (1.0,0,0)
  glVertex3f_ (0.5,0.5,0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,0.5,-0.5)

  glNormal3f_ (-1.0,   0,   0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (-0.5,-0.5, 0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)

  glEnd_()

  glPopMatrix_()
  glFinish_()

  SetGadgetAttribute(Gadget, #PB_OpenGL_FlipBuffers, #True)
EndProcedure


Procedure SetupGL()
    
  glMatrixMode_(#GL_PROJECTION)
  gluPerspective_(30.0, 200/200, 1.0, 10.0) 
  
  ; position viewer
  glMatrixMode_(#GL_MODELVIEW)
  
  glTranslatef_(0, 0, -5.0)
  
  glEnable_(#GL_DEPTH_TEST)   ; Enabled, it slowdown a lot the rendering. It's to be sure than the
                              ; rendered objects are inside the z-buffer.
  
  glEnable_(#GL_CULL_FACE)    ; This will enhance the rendering speed as all the back face will be
                              ; ignored. This works only with CLOSED objects like a cube... Singles
                              ; planes surfaces will be visibles only on one side.
    
  glShadeModel_(#GL_SMOOTH)
EndProcedure


Procedure HandleError (Result, Text$)
  If Result = 0
    MessageRequester("Error", Text$, 0)
    End
  EndIf
EndProcedure

OpenWindow(0, 0, 0, 530, 320, "OpenGL Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

OpenGLGadget(0, 10, 10, 200, 200)
SetupGL()

OpenGLGadget(1, 220, 10, 300, 300)
SetupGL()

AddWindowTimer(0, 1, 16) ; about 60 fps

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Timer
      If EventTimer() = 1
        DrawCube(0)
        DrawCube(1)
      EndIf
  EndSelect
  
Until Event = #PB_Event_CloseWindow




Re: OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 12:50 am
by Didaktik
I tried different options. For example to run the three different programs each with OpenGLGadget. The result is one. All the windows of the FPS drops sharply.

At the same time, I run the examples OGRE, such CubeMapping in quadruplicate and everywhere remains stable 60 FPS.

Re: OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 2:34 pm
by DarkDragon
Did you install the latest GPU drivers (not only DirectX!)? Did you also try to work without the deprecated commands like the fixed function pipeline (e.g. glBegin/glEnd/glVertex/glColor/...) and instead use vertex buffer objects? This way the data won't be transferred every frame onto the GPU.

[EDIT]
Did you also try to work without Window Timers and WaitWindowEvent and instead use WindowEvent and a normal loop?

Re: OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 7:09 pm
by Didaktik
DarkDragon wrote:Did you install the latest GPU drivers (not only DirectX!)? Did you also try to work without the deprecated commands like the fixed function pipeline (e.g. glBegin/glEnd/glVertex/glColor/...) and instead use vertex buffer objects? This way the data won't be transferred every frame onto the GPU.

[EDIT]
Did you also try to work without Window Timers and WaitWindowEvent and instead use WindowEvent and a normal loop?
The latest drivers. I tried it on three different computers.

And how to implement a reliable cycle without a timer? Delay (15)?

Re: OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 8:38 pm
by Samuel
Try getting rid of the AddWindowTimer and changing the Repeat | Until to this code.

Code: Select all

Repeat
  Event = WindowEvent()

    DrawCube(0)
    DrawCube(1)
 
Until Event = #PB_Event_CloseWindow
What's your FPS at now? If you're still getting 30FPS then I'd assume it's a hardware issue with OpenGL's legacy pipeline.
If you're still getting slowdowns would you mind telling us your hardware specs?

Didaktik wrote: At the same time, I run the examples OGRE, such CubeMapping in quadruplicate and everywhere remains stable 60 FPS.
I'm pretty sure Ogre doesn't use outdated commands like glBegin/glEnd when rendering with OpenGL. In order to get better results with the OpenGLGadget you need to modernize the code like DarkDragon suggested.
The Purebasic example is just to show you that it's possible to use OpenGL commands with their gadget.

Re: OpenGLGadget'S too slow

Posted: Fri Sep 02, 2016 9:50 pm
by Didaktik
Samuel wrote:Try getting rid of the AddWindowTimer and changing the Repeat | Until to this code.

Code: Select all

Repeat
  Event = WindowEvent()

    DrawCube(0)
    DrawCube(1)
 
Until Event = #PB_Event_CloseWindow
What's your FPS at now? If you're still getting 30FPS then I'd assume it's a hardware issue with OpenGL's legacy pipeline.
If you're still getting slowdowns would you mind telling us your hardware specs?
Have 30fps too. But one cube have 60fps.

AMD 4core/3Ghz, AMD Radeon 5450, W7x64.

Re: OpenGLGadget'S too slow

Posted: Sat Sep 03, 2016 9:56 pm
by DontTalkToMe
Didaktik wrote:Have 30fps too. But one cube have 60fps.
Not sure what you are saying here.


Nevertheless, try these things in order to see if something changes:
  • keep the loop as suggested by Samuel for now, running at full speed without any timer.
  • try to remove glFinish_() and see if it changes anything.
  • check if you have vsync enabled in any form your driver's control panel, if it's enabled try to set it to "let the application decide" or equivalent.
  • set the vsync in your driver's control panel to disabled for now.
  • add the flag #PB_OpenGL_FlipSynchronization to all the OpenGLGadget()
I don't expect using GL 3.x or greater will change anything, but as a last resort you may try it.


edit

eh, I wrote #PB_OpenGL_FlipSynchronization instead of #PB_OpenGL_NoFlipSynchronization, sorry.
Even if should have been evident from the two points just before that I meant the second one.
Moreover #PB_OpenGL_FlipSynchronization is already the default so it should be even more evident.
Would have been nice to have a reply about each of the points above, what were your actual settings, what was the result changing them, and so on to pinpoint exactly what changes are really required and where. The fact it starts to work like you expect at some point doesn't mean that's the option you should use, because maybe the option which is making it work is required just because you have another option in effect which shouldn't be set in the first place.

This is really not the type of interaction I look for when trying to help someone by writing a list of things to test.
It looks like it's the norm here, almost everyone doesn't know how to properly ask for help and doesn't know how to properly reply to help when given.
I'll strictly avoid all this here in the future. :wink:

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 12:06 am
by DarkDragon
DontTalkToMe wrote:I don't expect using GL 3.x or greater will change anything, but as a last resort you may try it.
If you mean VBOs: they were available since some OpenGL 1.x.

But I'm interested in your vendor and version now. Request them with glGetString, please.

Btw the bit depths of each buffer could play a role. How was the context initialized?

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 5:51 am
by Samuel
Didaktik wrote: Have 30fps too. But one cube have 60fps.
I think I figured out the problem.
Each OpenGLGadget must have a separate context, and since the GPU is a shared resource they end up fighting with each other causing the split FPS.
Instead of multiple gadgets it would be better to use a single gadget and then create viewports to split it.
This way you only have a single context.

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 6:48 am
by DarkDragon
Samuel wrote:
Didaktik wrote: Have 30fps too. But one cube have 60fps.
I think I figured out the problem.
Each OpenGLGadget must have a separate context, and since the GPU is a shared resource they end up fighting with each other causing the split FPS.
Instead of multiple gadgets it would be better to use a single gadget and then create viewports to split it.
This way you only have a single context.
Then it would help using VBOs, because you reduce the bottleneck usage.

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 8:36 am
by pjay
A 60 to 30 fps reduction on rendering a couple of simple cubes is more likely to be caused by the openglgadgets' flip routine waiting for vertical sync - i'd be surprised if this is a GPU or immediate mode limitation.

Try adding #PB_OpenGL_NoFlipSynchronization to the Openglgadget creation flags to prevent this wait state from occurring.
Have 30fps too. But one cube have 60fps.
Be aware that you're adding to the rotation variables (RollAxis#) in the drawcubes() procedure; this means that each additional context render will give you the impression of different render speeds.

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 10:53 am
by applePi
i see 60 fps for the 2 gadgets, and 80 fps for every one alone, may be i have fallen in some tricky pitfall as usual .

regarding the fps measure with glut i have found somewhere in the web long time ago.

Code: Select all

Declare calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
Global fpsGlut.f
#GLUT_ELAPSED_TIME = 700 ; used only for glutget_(#GLUT_ELAPSED_TIME) function
...
Select Event
    Case #PB_Event_Timer
      If EventTimer() = 1
        DrawCube(0)
        calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
        a$="first "+Str(fpsGlut)
        DrawCube(1)
        calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
        SetWindowTitle(0, a$+"        second_ = " + Str(fpsGlut))
      EndIf
  EndSelect
for the glut32.dll can be found here: save it to the windows/system32 or equivalent
https://web.archive.org/web/20140331042 ... /glut.html

my system is i5, with nvidea geforce GT 640. but this test performed in windows xp/32. i will try it in windows 7/x64 tomorrow
regarding the Didaktik card AMD Radeon 5450, i have a card VTX Radeon HD 5450 but fanless card for the Desktops and i was not happy with its performance. so i replaced it with geforce .

the code with the fps measure using glutGet_(#GLUT_ELAPSED_TIME):

Code: Select all

;
; OpenGL Gadget demonstration
;
; (c) Fantaisie Software
;
; Axis explainations:
;
;             +
;             y
;
;             |
;             |
;  +          |
;  x ---------\
;              \
;               \
;                \ 
;                  z+
;
; So a rotate on the y axis will take the y axis as center. With OpenGL, we can specify
; positive And negative value. Positive values are always in the same sens as the axis
; (like described on the schmatic, with '+' signs)


Declare calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
Global fpsGlut.f
#GLUT_ELAPSED_TIME = 700 ; used only for glutget_(#GLUT_ELAPSED_TIME) function


Global RollAxisX.f
Global RollAxisY.f
Global RollAxisZ.f

Global RotateSpeedX.f = 1.0
Global RotateSpeedY.f
Global RotateSpeedZ.f = 1.0

Global ZoomFactor.f = 1.0 ; Distance of the camera. Negative value = zoom back

Procedure DrawCube(Gadget)
  SetGadgetAttribute(Gadget, #PB_OpenGL_SetContext, #True)
  
  glPushMatrix_()                  ; Save the original Matrix coordinates
  glMatrixMode_(#GL_MODELVIEW)

  glTranslatef_(0, 0, ZoomFactor)  ;  move it forward a bit

  glRotatef_ (RollAxisX, 1.0, 0, 0) ; rotate around X axis
  glRotatef_ (RollAxisY, 0, 1.0, 0) ; rotate around Y axis
  glRotatef_ (RollAxisZ, 0, 0, 1.0) ; rotate around Z axis
 
  RollAxisX + RotateSpeedX 
  RollAxisY + RotateSpeedY 
  RollAxisZ + RotateSpeedZ 

  ; clear framebuffer And depth-buffer

  glClear_ (#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)

  ; draw the faces of a cube
  
  ; draw colored faces

  glDisable_(#GL_LIGHTING)
  glBegin_  (#GL_QUADS)
  
  ; Build a face, composed of 4 vertex ! 
  ; glBegin() specify how the vertexes are considered. Here a group of
  ; 4 vertexes (GL_QUADS) form a rectangular surface.

  ; Now, the color stuff: It's r,v,b but with float values which
  ; can go from 0.0 To 1.0 (0 is .. zero And 1.0 is full intensity) 
  
  glNormal3f_ (0,0,1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (0.5,0.5,0.5)   
  glColor3f_  (0,1.0,1.0)         
  glVertex3f_ (-0.5,0.5,0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (-0.5,-0.5,0.5)
  glColor3f_  (0,0,0)
  glVertex3f_ (0.5,-0.5,0.5) 

  ; The other face is the same than the previous one 
  ; except the colour which is nice blue To white gradiant

  glNormal3f_ (0,0,-1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,-0.5,-0.5)
  
  glEnd_()
  
  ; draw shaded faces

  glEnable_(#GL_LIGHTING)
  glEnable_(#GL_LIGHT0)
  glBegin_ (#GL_QUADS)

  glNormal3f_ (   0, 1.0,   0)
  glVertex3f_ ( 0.5, 0.5, 0.5)
  glVertex3f_ ( 0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)

  glNormal3f_ (0,-1.0,0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (-0.5,-0.5,0.5)

  glNormal3f_ (1.0,0,0)
  glVertex3f_ (0.5,0.5,0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,0.5,-0.5)

  glNormal3f_ (-1.0,   0,   0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (-0.5,-0.5, 0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)

  glEnd_()

  glPopMatrix_()
  glFinish_()

  SetGadgetAttribute(Gadget, #PB_OpenGL_FlipBuffers, #True)
EndProcedure


Procedure SetupGL()
    
  glMatrixMode_(#GL_PROJECTION)
  gluPerspective_(30.0, 200/200, 1.0, 10.0) 
  
  ; position viewer
  glMatrixMode_(#GL_MODELVIEW)
  
  glTranslatef_(0, 0, -5.0)
  
  glEnable_(#GL_DEPTH_TEST)   ; Enabled, it slowdown a lot the rendering. It's to be sure than the
                              ; rendered objects are inside the z-buffer.
  
  glEnable_(#GL_CULL_FACE)    ; This will enhance the rendering speed as all the back face will be
                              ; ignored. This works only with CLOSED objects like a cube... Singles
                              ; planes surfaces will be visibles only on one side.
    
  glShadeModel_(#GL_SMOOTH)
EndProcedure


Procedure HandleError (Result, Text$)
  If Result = 0
    MessageRequester("Error", Text$, 0)
    End
  EndIf
EndProcedure

OpenWindow(0, 0, 0, 530, 320, "OpenGL Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

OpenGLGadget(0, 10, 10, 200, 200)
SetupGL()

OpenGLGadget(1, 220, 10, 300, 300)
SetupGL()

AddWindowTimer(0, 1, 16) 
Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Timer
      If EventTimer() = 1
        DrawCube(0)
        calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
        a$="first "+Str(fpsGlut)
        DrawCube(1)
        calculateFPS() ; using glutGet_(#GLUT_ELAPSED_TIME)
        SetWindowTitle(0, a$+"        second_ = " + Str(fpsGlut))
      EndIf
  EndSelect
  
Until Event = #PB_Event_CloseWindow

Procedure calculateFPS() ;Calculates the frames per second
   ;Increase frame count
    Static frameCount
    Static previousTime
    
    frameCount+1
 
    ;Get the number of milliseconds since glutInit called
    ;(Or first call To glutGet(GLUT ELAPSED TIME)).
    currentTime = glutGet_(#GLUT_ELAPSED_TIME);
 
    ;Calculate time passed
    timeInterval = currentTime - previousTime;
 
    If(timeInterval > 1000)
        ;calculate the number of frames per second
        fpsGlut = frameCount / (timeInterval / 1000.0);
 
        ;Set time
        previousTime = currentTime;
 
        ;Reset frame count
        frameCount = 0;
    EndIf
     
  EndProcedure
  

Re: OpenGLGadget'S too slow

Posted: Sun Sep 04, 2016 10:53 am
by Didaktik
pjay wrote:A 60 to 30 fps reduction on rendering a couple of simple cubes is more likely to be caused by the openglgadgets' flip routine waiting for vertical sync - i'd be surprised if this is a GPU or immediate mode limitation.

Try adding #PB_OpenGL_NoFlipSynchronization to the Openglgadget creation flags to prevent this wait state from occurring.
Thank you! You're right!
Hooray! ))