Oxygen Basic

Programming => Example Code => Graphics => Topic started by: Charles Pegge on April 18, 2014, 07:15:15 PM

Title: Opengl Performance / Sleep time
Post by: Charles Pegge on April 18, 2014, 07:15:15 PM

Topic branch from:
http://www.thinbasic.com/community/showthread.php?12414-Benchmarking-against-functional-languages&p=91053#post91053

Thanks Mike,

That indicates to me that the only reliable time measure is from the real-time clock.

But I have a vested interested in dynamic measurements. I want my opengl animations to remain in sync with a quantum of the frame rate, while filling in with a variable sleep period.

If one of the frames is missed, the next scene is time-step calculated to compensate for this, and the sleep period is reduced.

The sleep period is then gradually increased until the next missed frame.

The intended result is smooth animation while running with the minimum CPU load.

It assume that CPU time is the limiting factor, not GPU rendering time

This is what I have so far:

Code: [Select]
'FRAME SYNC SLEEP
===============
static quad   t1,t2
static float fperiod, stime=16.0
static sys fstep, sl
t1=t2
TimeMark t2
fperiod=TimeDiff t2,t1
fstep=1
stime+=.01
if fperiod
  if fperiod>.02 'quantum 60Hz 0.0166
    if stime>1.0
      stime-=1.0
      fstep=round(fperiod*60.0)
    end if
  end if
end if
sl=stime
SetWindowText hWnd, " " str(stime,3)
ang1+=angi1*fstep
if ang1>360 then ang1-=360
'...build scene...
if sl then sleep sl
Title: Re: Opengl Performance / Sleep time
Post by: Peter on April 19, 2014, 05:12:49 AM
Hi Charles,

here's my time measuring, and how I did it.

Code: [Select]
include "sw.inc"
Window 800,600,1

quad t1, t2
quad freq
double elapsed

p = LoadBmp "bmp/pictree.bmp",1

QueryPerformanceFrequency freq
QueryPerformanceCounter t1

for x=0 to 799
for y=0 to 599
    color = GetBmpPixel p,x,y
    r = GetR(color)
    g = GetG(color)
    b = GetB(color)
    SetPixel x,y, RGB(r,g,b)
next
next

QueryPerformanceCounter t2
elapsed = (t2-t1) * 1000.0 / freq

SetCaption "TIME: " + elapsed + " msec"
WaitKey
CloseWindow

.
Title: Re: Opengl Performance / Sleep time
Post by: Peter on April 19, 2014, 05:21:56 AM
Replace this for a fair and beautiful blueish : 
Code: [Select]
SetPixel x,y, RGB(r*.4,g*.6,b*.8)
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky on April 19, 2014, 08:06:45 PM
Hello Charles,

Sorry for being late to answer but my matters took me a little longer than I'd planned. And I also needed time to prepare for the conversation refreshening what was forgotten in the past three years.

So let's start with a Happy Easter to you and the OxygenBasic community! :)

Now to the subject matter. Everything that I have to say is based on my own experience and a hell of a lot of trial and error. Be assured that I've turned over a pile of relevant literature and web data learning my lessons the hard way.


Part I: Sleep() Considerations

While the idea of using Sleep() to control your framerate may seem attractive, it has several serious drawbacks:

1. Besides timing per se you have to deal with similar inherent inaccuracy of Sleep(), which effectively doubles the number of disturbing factors in your rendering loop.

2. For heavily populated and textured scenes, Sleep()'s resolution may need to go down arithmetically to a sub-tick level within the rigid 60 (or 30) FPS constrains imposed by VSYNC. This isn't however possible. The default resolution of Sleep() is 16 ticks for an NT-based kernel and it can only be changed using a call to timeBeginPeriod(n) which resides in Winmm.dll. (Be sure to use a matching call to timeEndPeriod(n) while experimenting or your system clock potentially being used by other concurrent processes may be compromised till the very end of the current session!)

The finest setting of n in this call is 1 tick and you can't go any lower. 1 tick is however very nice for other applications not related to OpenGL, isn't it? :)

3. An excellent Windows OpenGL implementation by nVidia (you have an nVidia video card, haven't you?) is a multi-threaded application that has its own timing facilities and optimum strategies targeting the fastest (and smoothest) rendering on a given HW platform.

For example, if you open up your nVidia Control Center, you may find the following setting there (that's my Vista setup with the latest nVidia drivers installed):
(http://storage6.static.itmages.ru/i/14/0420/s_1397964007_4012156_9ec7809518.png) (http://itmages.ru/image/view/1625981/9ec78095)

As you see, OpenGL can spawn (of course depending on your CPU) up to 4 additional threads to pre-calculate and pre-render in advance up to 4 frames of your video flow. Clear enough, it can do it only if the remaining time slice so permits. Meddling with Sleep() in the program code may severely compromize OpenGL's abilities to self-control.

There may appear other unexpected bottlenecks in OpenGL depending on whether it has sufficient time to perform all the tasks scheduled for the current time- and render-frame for the given system settings and a particular rendering strategy (immediate mode, display lists, VBO's, shaders) and its dependencies.

So Sleep() is too rough an instrument to slice OpenGL with except some very rare cases where its current implementation is not flexible enough to give us what we need. Such cases are usually labeled with "upgrade your hardware" verdict.


Conclusion

Subsequent Parts will follow depending on how our discussion is going to develop. All my illustrations and explanations (but not the source code, sorry) will be based on i) the most stringent conditions our XANEngine has ever faced, and ii) on the real-world data from the Resident Evil 5: Lost in Nightmares (Playstation 2) game package.

You can download a freeware version of Resident Evil 5 Benchmark Edition (http://downloads.guru3d.com/downloadget.php?id=2331&file=1&evp=d499542ec7a2b4a1b65330211a240779) for desktop PC's to see how poor your computer hardware really is by Capcom Ltd.'s standards:

(http://storage6.static.itmages.ru/i/14/0420/s_1397966373_1345042_e7e3db2869.png) (http://itmages.ru/image/view/1625991/e7e3db28)

I remember I was so dissatisfied with their verdict that I accepted my French friend's invitation to join him in the XANEngine project without hesitation to show the Japs how terribly wrong they were with their miserable attempts to lure us into buying their overpriced Playstations. :)
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 20, 2014, 03:27:26 AM
Thanks Mike,

I confirm that Opengl, when left to its own devices, takes care of frame timing and economical use of CPU time, without the aid of sleep.

This scene (examples/opengl/CraftControl.o2bas) is a useful test model for timing. Currently it runs at 2..4 % of CPU time (Task Manager), and takes 0.02.. 0.04 milliseconds to render (Client side/QueryPerformanceCounter).

Even when the Windows Timer message is set to 10 msec, Frames are missed. About 2 are dropped per second. It is useful to be able to detect when this happens and compensate movement accordingly.


.
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky on April 20, 2014, 04:02:35 AM
Hehe, a nice toy you have here! The file is however called ControlCraft.o2bas... :)

1. It loads my 4-core CPU up to 50% which would equal ~100% on a Core2 Duo.

2. I see absolutely no frame drop-outs whatsoever. Movement is perfectly smooth.

3. Knobs won't turn around the dial completely but within ~90 degrees from approx. 1 o'clock to some 5 or 6 o'clock only.

Fraps gives perfectly stable 60FPS. Any comments?

P.S. Is the light source supposed to be moving? Don't see it on the UFO's surface but the shadow beneath the hull goes round in circles...

[UPD] That's when my nVidia Control Center settings are set to "Settings controlled by application" (I'm currently under XP and my Control Center is in Russian; I have to translate) - that's the top option selected. When the bottom option is selected and its slider is set to "Optimize for speed" (that effectively overrides your programmatic VSYNC), the rate can reach 150FPS full-screen but it also fluctuates severely when I move my mouse across the screen. Also, when the mouse moves over the console, the UFO starts to jerk on its way. But the CPU load is close to nil! Still any comments? What do you see on your monitor under all these conditions? Should I switch to Vista to go on testing?
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 20, 2014, 05:57:53 AM
Mike,

It's a pseudo shadow :)

The controls are only there for earthlings, of course.

I'm not sure whether you have the latest openglsceneframe. so I attach it here (for the inc folder). In this configuration, there is no glfinish, which whacked it up to 34% CPU usage on my quad core . In any case, it should be sufficient to comment out glfinish

PS: the knobs only respond to vertical drag, not yet rotary or horizontal. They are intended for something .. maybe the stereo.


.
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky on April 20, 2014, 05:03:56 PM
Sorry Charles,

I just missed the most recent O2 update. Now I'm seeing better CPU performance but it's still absolutely unnatural.

I need some more time to examine your entire rendering loop. I think its implementation is not optimal as a whole. Yup, dropouts are more noticeable under Vista than under XP or 7. I'll come back to the topic as soon as I'm ready with my proposals, OK?
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 20, 2014, 08:20:41 PM
Thanks for all your attention, Mike.

I think the frame loop is now a clean run for rendering. The windows timer can be set somewhere between 10.. 12 milliseconds - significantly less than 16, anyway. Otherwise missed frames escalate rapidly. I see no perceptible jitter on the saucer movement.

There are several frame modes to choose from. These are selected to eliminate unnecessary frame rendering. Here, we are only concerned with ActiveFrame

The key macros for Active Frame mode:

Code: [Select]
  macro TimeFrame
  ===============
  static sys   countn
  static float FramePeriod,stepn
  scope
  static quad   t1,t2
  stepn=1
  t1=t2
  TimeMark t2
  if t1
    FramePeriod=TimeDiff t2,t1
    if FramePeriod>.02              'quantum 60Hz 0.0166
      stepn=round(FramePeriod*60.0) 'moment scale
      countn+=stepn-1               'count missed frames
    end if
  end if
  end scope
  end macro


  macro NewFrame()
  ===================
  glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
  glEnable GL_DEPTH_TEST
  glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
  glEnable GL_BLEND
  glPolygonMode GL_FRONT_AND_BACK, GL_FILL
  glEnable GL_NORMALIZE
  glLoadIdentity
  end macro
  '
  macro ActiveFrame()
  ===================
  TimeFrame
  SnapShots(hwnd) 'Ctrl-P take snapshot
  NewFrame
  end macro

TimeFrame only provides timing data to the app.

Frame building is further elaborated by single-shot list compiling, and object-picking passes

Title: Re: Opengl Performance / Sleep time
Post by: Aurel on April 20, 2014, 09:40:16 PM
Where is the source code of this example  ???
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 21, 2014, 01:37:22 AM
Hi Aurel,

It is part of inc/OpenglSceneFrame.inc
and we are testing examples/opengl/ControlCraft.o2bas
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky on April 21, 2014, 01:50:58 AM
Hello Charles,

On skimming through the sources, I think I should note the following:
-- while the solution seems to work more or less stable with a few hundred polies in view, still it depends on SetTimer() by implication;
-- the rendering loop is located in WndProc() while canonically it should be part of MainWindow()'s while/wend loop outside its if/else/endif conditional, that is occupy the remaining portion of the loop e.g. similar to Glut's Render() (=OnIdle()) callback. All Windows messages in the queue must have absolute priority over OpenGL until the entire queue is executed while OpenGL stands by, the timing procedure being supposed to further compensate for the lag that message execution might've introduced;
-- a lot of unnecessary OpenGL state changes are performed in each frame.

1. SetTimer() is OK for simple demos, examples, and proof of concept. But it's alien to OpenGL and may be the cause of race conditions. OpenGL is designed to operate at maximum speeds possible on a given HW platform and using non-native means to control its throughput may be detrimental for general-case solutions.

WM_TIMER has one of the lowest priorities among the entire range of messages in the message pipe. IIRC there's only one message that has a yet lower priority and that's WM_PAINT which may drop out of (be ignored by) the message pipe completely. The same goes about WM_TIMER; if the whole bunch of other messages and pending tasks take longer to execute than WM_TIMER's period, then the current WM_TIMER will be ignored (dropped out) till the next one comes and has a chance to execute. Similarly, if WM_TIMER's associated procedure is still executing while another WM_TIMER comes, that later message will be ignored and gone unnoticed.

2. I have a strong suspicion the entire FPS limiting is built around that SetTimer() setup. So far I haven't been able to locate a call to wglSwapIntervalEXT() that's OpenGL's only native means to synchronize its renders with the primary monitor's vertical retrace signal. Perhaps I'm simply missing it; there are a lot of includes I'm not familiar with yet.

3. There are many OpenGL states that, once set, are preserved till the very end of the program if only some specific entity in the scene, e.g. an OpenGL custom material, doesn't require a specific change of this or that parameter. If that happens, it is then the entity's task to switch the state back to what is supposed to be the parameter's default throughout the rest of the program. Otherwise, there's absolutely no need to re-set these states in every frame rendered.

Reducing the number of OpenGL state changes per frame is the programmer's most important strategic task. An extra glXXXXX() function call may seem irrelevant at the terrific speeds of a JIT compiler but it may intrinsically spawn to life thousands of code lines buried inside the OpenGL driver libraries. We're seeing only the top of the iceberg that may send our Titanic to the bottom in no time.

I can re-write this particular example to a minimum of how it should look from my perspective keeping its functionality intact, if you want me to. I will also comment my actions where needed. In case you're satisfied with the results, it may be expanded to interface with the solutions in other existing O2 includes. I'll refactor parts of  ControlCraft.o2bas, OpenglSceneFrame.inc, ControlPanels.inc, and WinUtil.inc.

If that's OK with you, please tell me:

1. Is a call to wglSwapIntervalEXT() still buried somewhere in nested includes?

1. Do you have an nVidia Control Center installed?

2. Do you have Fraps installed (window captions and console print are far too slow to monitor the FPS rate unobtrusively)?
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 21, 2014, 06:23:25 AM
Mike,

My code is very changeable at present, and I am about to hook in real-time audio synth, but your ideas are very welcome, and I can try them out quite easily.

I tried putting the rendering call into the message loop, but without success. The frames are empty apart from the background color. Calling from wndproc is efficient - WM_TIMER is of course hopelessly inaccurate but serves as a 'tickler' to maintain a steady stream of messages.

Is a call to wglSwapIntervalEXT() still buried somewhere in nested includes?
I am testing it (after wglMakeCurrent)  but no difference in dropped frames.
Yes I believe it has made a difference. I only see dropped frames when the window is moved or resized.

1. Do you have an nVidia Control Center installed?
Yes, I am using the default settings

2. Do you have Fraps installed (window captions and console print are far too slow to monitor the FPS rate unobtrusively)?
Yes, I've installed it.
- then some disagreeable adware accompanied it and disrupted my browser, so I had to remove it.
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 21, 2014, 01:24:43 PM
Location of wglSwapIntervalEXT in inc/openglSceneFrame.inc

  case WM_CREATE
  '
  'SETUP DEVICE CONTEXT AND RENDER CONTEXT
  '
  if minCreate then exit function
  hDC=GetDC hwnd
  SelectPixelformat()
  hRC = wglCreateContext hDC
  wglMakeCurrent hDC, hRC
  sys p=wglgetprocaddress "wglSwapIntervalEXT" : call p 1
  #ifdef fontA
  BuildFont hWnd, hDC, hRC,fontA,1024
  #endif
  #ifdef fontB
  BuildFont hWnd, hDC, hRC,fontB,1280
  #endif
  ! Initialize(sys hWnd) : Initialize hWnd
  SetWindowText hwnd,title

  act=2


No dropped frames (60fps), except at startup, or adjusting window. Occasionally when running at full-screen
CPU load: 3..5%
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky on April 21, 2014, 01:32:57 PM
Very nice results, Charles, thanks a lot for the info. Yet I'm all set to try and implement my own solution tonight and I'll come back with it some time tomorrow.

[UPD on April 23] I'm sorry but yesterday I had two of my old friends drop in at my place quite unexpectedly so my creative potential is still close to nil. I will however come back to this topic as soon as I'm able to do away with my residual hangover. :)
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 23, 2014, 05:06:03 AM
No need to hurry, Mike. H2O is an effective cure :)
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky 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.
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge on April 24, 2014, 02:59:59 PM
1000 FPS! I presume that multisampling is only performed once as a form of post-processing.
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky 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?
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge 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.
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky 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...
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge 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
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky 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?! :(
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge 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
Title: Re: Opengl Performance / Sleep time
Post by: Mike Lobanovsky 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!
Title: Re: Opengl Performance / Sleep time
Post by: Charles Pegge 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