Author Topic: Opengl Performance / Sleep time  (Read 11149 times)

0 Members and 1 Guest are viewing this topic.

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #15 on: April 23, 2014, 05:06:03 AM »
No need to hurry, Mike. H2O is an effective cure :)

Mike Lobanovsky

  • Guest
Re: Opengl Performance / Sleep time
« Reply #16 on: April 24, 2014, 08:55:08 AM »
Hello Charles,

I've already done what I wanted. An un-VSYNC'ed rate is over 1000FPS at the default window size and ~400FPS full-screen on my computer. Movement is perfectly smooth and FPS-independent and no visible drop-outs seen at all. VSYNC can be toggled at runtime between 30FPS, 60FPS, and none for test purposes.

I'm finishing off the code and I'll be posting it here with directions for use later on tonight. Seems like I'm back to my usual teetotaler (or better coffee-totaler) self again. :)

See y'all later.

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #17 on: April 24, 2014, 02:59:59 PM »
1000 FPS! I presume that multisampling is only performed once as a form of post-processing.

Mike Lobanovsky

  • Guest
Re: Opengl Performance / Sleep time
« Reply #18 on: April 24, 2014, 05:15:30 PM »
No Charles,

I'm getting 1040FPS without antialiasing but 850FPS under 2x and 700FPS under 4x in the default window. Unlimited full-screen VSYNC yields ~350FPS with 4x antialiasing.

Currently, my technique works excellent under XP for all the three VSYNC settings in both Classic and themed modes.  Object and panel movement is perfectly smooth and absolutely FPS independent. All extra state changes have been moved out of the render proc to their proper places. MainWindow() and WndProc() have been changed to accommodate for the new technique. The scene now uses backface culling to half the load on the OpenGL rendering pipe. The look and feel of the scene remains exactly the same as the original. CPU load doesn't exceed 4% under any of the VSYNC settings.

Vista performance is however much, much worse. Classic exhibits half the XP's FPS rate and is totally unusable due to heavy dropouts under any VSYNC. I don't have Vista Basic on my installation for some reason but Vista Aero which I have works good with no VSYNC and 30FPS VSYNC but still has occasional dropouts at 60FPS VSYNC (one or two per horizontal run of the saucer with <- -> keybuttons).

Classic 7 performs as bad as Vista Classic however the FPS rate is as high as expected. Basic 7 is almost as bad as Classic. Non-VSYNC'ed Aero exhibits occasional droputs (3 or 4 per horizontal run) while 60FPS shows heavy dropouts even without Winmm-controlled Sleep() in the MainWindow()'s loop which is there to bring the CPU load down to a minimum. 30FPS works perfect under Aero 7.

All this shows that canonical OpenGL is heavily system version dependent under Windows, which is however no surprise it being DirectX' rival.

OTOH I don't want to give up because I don't like the idea of using a SetTimer()'s timer even if it's somewhat manually compensated. Neither do I like the idea of rendering being done in WndProc() or message handling being built around blocking GetMessage() calls instead of PeekMessage(PM_REMOVE).

It's too late at night (or early in the morning) to continue but tomorrow I'm planning to try and accomodate your compensation method to get rid of, or at least minimize, my dropouts. Keep your fingers crossed. :)

Why did they abandon XP? I guess they were unhappy about OpenGL's excellent performance on that "obsolete" platform.

P.S. In the meantime, is OxygenBasic thread-safe?
« Last Edit: April 24, 2014, 08:43:52 PM by Mike Lobanovsky »

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #19 on: April 24, 2014, 10:06:23 PM »
Hi Mike,

Many thanks for all your investigations. If Vista / Windows 7 decides to take long holidays or sick-leave between frames, it is probably beyond our control.

The Oxygen run-time is thread-safe using local variables. So procedures which can be called  by more than one thread simultaneously should not use statics without some sort of sync protocol.

The garbage collector is also thread-safe for managing local strings.

Mike Lobanovsky

  • Guest
Re: Opengl Performance / Sleep time
« Reply #20 on: April 25, 2014, 01:17:08 PM »
On a side note, the following seems to be the easiest way to get your primary monitor's current frequency in O2 using the most elementary means at hand, Oxygen- and system-wise (Ole32 and Ddraw DLL's are standard system libraries on any Windows platform):

Code: [Select]
  includepath "$\inc\"
  include "console.inc"
 
  extern lib "Ole32.dll"
  sys CoInitialize(LPVOID pvReserved)
  sys CoUninitialize()

  extern lib "Ddraw.dll"
  sys DirectDrawCreate(sys lpGUID, sys lplpDD, sys pUnkOuter)
 
  #define IDirectDraw_Offset_To_GetMonitorFrequency_Method_Ptr 60
 
  sys lpDD1 = 0
  sys freq = 0
 
  CoInitialize 0
 
  if not DirectDrawCreate(0, @lpDD1, 0) then
    call *(*lpDD1+IDirectDraw_Offset_To_GetMonitorFrequency_Method_Ptr) lpDD1, @freq
    print "Your monitor's current frequency is " + freq + "Hz." + cr
  else
    print "Failed to create DirectDraw1 surface. Monitor frequency unknown." + cr
  end if
 
  CoUninitialize
 
  getkey

Very elegant, thanks, Charles! FBSL's BASIC needs two more Peek() function calls in that core line to be used for indirection instead of simple *. :)

I've suddenly discovered similar Vista and 7 frame dropout artifacts (I believe image stutter is a proper term for this phenomenon) in my own XANEngine renderer! My scenes are much more heavily populated so the artifacts are not so outstanding but they are there all right (actually, "all wrong"!). So now it's my personal affair of honor rather than purely sporting interest. The net shows it is considered a common OpenGL driver problem under Windows. I don't recollect noticing them 3 years ago. My nVidia drivers have always been the latest available for all the three Windows flavors. It might be a regression, however noone knows how long-lasting it might be...

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #21 on: April 25, 2014, 05:27:28 PM »
Thanks Mike,

I don't remember ever making a call using a calculated pointer in that way. Good to see different coding styles.

I've squeezed it a little further, but nothing fundamental:

Code: [Select]
  sys CoInitialize lib "Ole32.dll" (sys pvReserved)
  sys CoUninitialize lib "Ole32.dll" ()
  sys DirectDrawCreate lib "Ddraw.dll" (sys lpGUID, lplpDD, pUnkOuter)
  def IDirectDraw_Offset_To_GetMonitorFrequency_Method_Ptr 60
  sys lpDD1
  sys freq
 
  CoInitialize 0
 
  if not DirectDrawCreate 0, @lpDD1, 0
    call *(*lpDD1+IDirectDraw_Offset_To_GetMonitorFrequency_Method_Ptr) lpDD1, @freq
    print "Your monitor's current frequency is " freq "Hz."
  else
    print "Failed to create DirectDraw1 surface. Monitor frequency unknown."
  end if
 
  CoUninitialize

Mike Lobanovsky

  • Guest
Re: Opengl Performance / Sleep time
« Reply #22 on: April 25, 2014, 10:34:24 PM »
Thanks for the mods, Charles!

I like your declarations better but I was sitting in front of some of your includes that used an "extern" notation so I used it as an immediate model for my script.

I looked through the \examples folder but since there wasn't any other COM example but SAPI there, I presumed there weren't any includes for DirectX interfaces in the package either. My experience shows that it saves more of my time to look up some function or interface method proto quickly in the MSDN and use it immediately in my code than hunt for the proper header file and implement the entire interface. Neither do I know what kind of C headers Oxygen can read - either MS VC or gcc. They are different and mostly incompatible with each other.

Yup, I'm already perfectly aware that Oxygen is more "freestyle", syntax-wise, than FBSL ( :) ) and I know about the missing rvalue function call parentheses and print pluses and then's. :) Yet I preferred to formulate the code in a more formal BASIC style. I thought that while other more BASIC-oriented people are reading it, the style shouldn't be too scary or modernistic, especially for newcomers. I'm also using a lot of unnecessary BASIC decorations all the time in my public scripts on the FBSL forum but my personal code is much more laconic than that.

Finally, I prefer to see my console cursor go down the line when the command has been executed. Its blinking on the same line gives me a feeling of incompletion and uncertainty, hence the cr's.

Hope this explains my coding style in this particular script. I was after DirectDraw's WaitForVerticalBlank() method and it was just a proof-of-concept to get what I wanted the quick and dirty way. Regretfully the idea worked perfect under XP as usual but failed again under Vista and 7. Who was that s...o...b... that invented this DWM and compositing?! :(

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #23 on: April 25, 2014, 11:45:20 PM »
I just love playing with syntax. There is so much to discover :)

And I totally agree it is more convenient to lookup specific COM calls than to put the full interface into source code. But how to make it Quick but not Dirty?

All COM methods can be turned into equates or enumerations:


  COM method index

  def GetMonitorFrequency 15

  generic macro for COM calls:

  def COM call *(*%1+(%2*sizeof sys)) %1,

  calling:

  COM lpDD1 GetMonitorFrequency @freq

Code: [Select]
  sys CoInitialize lib "Ole32.dll" (sys pvReserved)
  sys CoUninitialize lib "Ole32.dll" ()
  sys DirectDrawCreate lib "Ddraw.dll" (sys lpGUID, lplpDD, pUnkOuter)
  sys lpDD1
  sys freq
  def GetMonitorFrequency 15
  def COM call *(*%1+(%2*sizeof sys)) %1,
 
  CoInitialize 0
 
  if not DirectDrawCreate(0, @lpDD1, 0)
    COM lpDD1 GetMonitorFrequency @freq
    print "Your monitor's current frequency is " freq "Hz."
  else
    print ("Failed to create DirectDraw1 surface. Monitor frequency unknown.")
  end if
 
  CoUninitialize

Mike Lobanovsky

  • Guest
Re: Opengl Performance / Sleep time
« Reply #24 on: April 25, 2014, 11:58:20 PM »
Hahahahaha,

Excellent! You aren't satisfied with the existing nearly perfect C-style preprocessor, you're after batch file syntax too! :D

I do like it, really, but how are newbies supposed to decipher this higher coding maths? :D

And yes, sizeof sys is very important here for bitness independence. I omitted it because I'm not sure if MS has even preserved this feature in their DX12. DirectX ANSI C interfaces stopped coming with DX8 IIRC. What comes later is all undecodable C++ stuff so they may throw out all this "legacy" junk altogether any time without prior notice. It turned out WaitForVerticalBlank() doesn't work under Vista and 7 as it used to any more!
« Last Edit: April 26, 2014, 12:11:23 AM by Mike Lobanovsky »

Charles Pegge

  • Guest
Re: Opengl Performance / Sleep time
« Reply #25 on: April 26, 2014, 04:02:40 AM »
Well, I'm one of the newbies :)

Such macros are 'Humpty-Dumpty' expressions, so the definition needs to seen close to where they are used.

Here is your example including the DirectDraw7 Interface implemented as a very simple class. All the parameters are assumed to be sys, so the user must ensure the methods pass the right kind of data.

Code: [Select]
  sys CoInitialize lib "Ole32.dll" (sys pvReserved)
  sys CoUninitialize lib "Ole32.dll" ()
  sys DirectDrawCreate lib "Ddraw.dll" (sys lpGUID, lplpDD, pUnkOuter)
  sys freq

extern virtual
class DirectDraw7
  sys QueryInterface(a, b)
  sys AddRef()
  sys Release()
  sys Compact()
  sys CreateClipper(a, b, c)
  sys CreatePalette(a, b, c, d)
  sys CreateSurface(a, b, c)
  sys DuplicateSurface(a, b)
  sys EnumDisplayModes(a, b, c, d)
  sys EnumSurfaces(a, b, c, d)
  sys FlipToGDISurface()
  sys GetCaps( a, b)
  sys GetDisplayMode(a)
  sys GetFourCCCodes(a, b)
  sys GetGDISurface(a)
  sys GetMonitorFrequency(a)
  sys GetScanLine(a)
  sys GetVerticalBlankStatus(a)
  sys Initialize(sys a)
  sys RestoreDisplayMode()
  sys SetCooperativeLevel(a, b)
  sys SetDisplayMode(a, b, c, d, e)
  sys WaitForVerticalBlank(a, b)
  sys GetAvailableVidMem(a, b, c)
  sys GetSurfaceFromDC(a, b)
  sys RestoreAllSurfaces()
  sys TestCooperativeLevel()
  sys GetDeviceIdentifier(a,b)
  sys StartModeTest(a,b,c)
  sys EvaluateMode(a,b)
end class
end extern

'#recordof DirectDraw7

 
  CoInitialize 0
 
  DirectDraw7 * DD1
  if not DirectDrawCreate(0, @@DD1, 0)
    DD1.GetMonitorFrequency(@freq)
    print ("Your monitor's current frequency is " freq "Hz.")
  else
    print ("Failed to create DirectDraw1 surface. Monitor frequency unknown.")
  end if
 
  CoUninitialize
« Last Edit: April 26, 2014, 04:51:17 AM by Charles Pegge »