How draws OpenGL to a Window Handle?
#1 Members - Reputation: 143
Posted 29 August 2012 - 02:55 AM
I would like to know, how a graphics api like opengl finally draws to a window's handle.. i know what a pixelformatdescriptor or a HDC is, but my question is - how draws opengl the final "pixels" to the control / handle, whatever? I downloaded the Mesa GL source code and i'm trying to find something.. but maybe, someone knows a sample or something or another solution for my problem?
#2 Members - Reputation: 1946
Posted 29 August 2012 - 04:18 AM
Bringing the actual pixels on screen is not the task of OpenGL, the actual screen surface (and, in modern times, the entire GPU memory) is owned by the window manager. Once upon a time, the IHV driver used to own everything, but with the advent of compositing desktop managers, even the drivers don't own the resources any more (gotta say thank you to Windows Vista for that mess, which started that thing).
What OpenGL does is, it draws to a buffer which it owns by courtesy of the window manager, and finally it kindly asks for this buffer to be presented.
#3 Members - Reputation: 143
Posted 29 August 2012 - 09:13 AM
Think i will get this working.. because i'd like to get "direct" access to a buffer, without calling gdi or using bitmaps for my raytracer.. such a "step in the middle" costs to much time.
Thanks
#4 Members - Reputation: 1226
Posted 29 August 2012 - 09:32 AM
That last copy (or two) will not be a big impact on a raytracer though, since the actual raytracing would be much more heavy.
I'd recommend you use SDL, set up a 2D framebuffer and draw to that, it should be plenty fast enough.
Its possible you could get slightly more direct access using DirectX api:s.
Edited by Olof Hedman, 29 August 2012 - 09:34 AM.
#5 Members - Reputation: 440
Posted 29 August 2012 - 02:17 PM
#6 Members - Reputation: 143
Posted 30 August 2012 - 12:30 AM
I don't wanted those kind of "direct" access, it was more a question, how OpenGL or DirectX brings the final pixels on the window, just to understand this technique. I tried something like: creating a panel and setting a bitmap as background image, then write to that image - this operation costs ~400ms (C#, my first raytracing approach was written in this, but now, i ported the code in C++ as a library for more speed). And because of this lack of performance, i thought i could get a bit more "direct" access..
#7 Members - Reputation: 440
Posted 30 August 2012 - 07:00 AM
I'm curious though, what exactly took 400ms? A memcpy of your picture?
Edited by powly k, 30 August 2012 - 07:00 AM.
#8 Members - Reputation: 143
Posted 30 August 2012 - 07:22 AM
So this point and the fact, that i had to do unsafe calls to get OpenCL to work with c# and the speed improvement of a c++ language lead me to this solution - to rewrite the Raytracers Core in c++.
And i don't think, C# is very good for such a type of project - because managing all those vectors, colors and rays by the GC is a (for me) to heavy performance lack (leak? lack?).
And my core is finished, and my first (because simpler) solution was a rtContext which has an abstract rtPixelBuffer class which it will output the final pixels. So, in C#, i call "wrtCreateContext(HDC DeviceContext)" via DllImports which creates a "GdiPixelBuffer" and the result is a valid rtContext with a rtPixelBuffer (GdiPixelBuffer)..
#9 Members - Reputation: 1946
Posted 30 August 2012 - 08:32 AM
Raytrace all you want, when a frame is done, make a buffer object, map it, memcpy the frame into it, and unmap it. Tell OpenGL to draw a textured quad, or do a framebuffer blit if you have version 3.2 available. Start raytracing the next frame, and give a f... about what happens otherwise.
A memcpy worth a full screen of 32-bit pixels takes 1.2 to 1.3 milliseconds on my [slow, old] machine. There is some time that the driver will need to push the data over the PCIe (or AGP or whatever you have) bus, too. Assuming the bus is not just busy, that's another 0.6 or 1.2 milliseconds, depending on what kind of bus you have. So... assuming pretty much the worst, let's say 5 milliseconds. So what. First, your "frame budget" at a typical 60 fps is 16,6 milliseconds (can you raytrace something more complicated than 3 spheres at 60 fps? I will bow to you!) and more importantly, those 5 milliseconds are not visible for you because command submission, data submission, and drawing run asynchronously.
If it takes 5 ms to transfer data, then the current frame will of course be shown on screen 5 ms later, but it will never be shown earlier than at the next sync anyway. And, nothing prevents you from already raytracing the next frame during that time.
With vertical sync enabled, your OpenGL thread will normally block inside SwapBuffers (though many recent implementations defer this to the first draw command after SwapBuffers or even let you pre-render 2-3 frames before blocking) until the frame is on screen. That's a kind of "natural" throttle (and a good thing). Still, nothing prevents you to run all your raytracing in a pool of worker threads (producers) to make use of that time. The OpenGL thread may block, or not, you can still pre-render the next frame already.
Edited by samoth, 30 August 2012 - 08:33 AM.
#10 Members - Reputation: 143
Posted 30 August 2012 - 10:46 AM
By the way, i got it working. I searched and found, my solution uses CreateDIBSection and BitBlt and other of those basic GDI functions. And, i think, it works good. After programming this i found an equally method in the SDL Source code
And now, i can call "wrtCreateContext(MyPanel.Handle);" from C# and my library does all the steps necessary to create a GdiPixelBuffer and a rtContext for drawing
#11 Members - Reputation: 2748
Posted 30 August 2012 - 12:23 PM
You can run the tracer on the GPU using OpenCL, Direct Compute, or something like AMP, but a GPU tracer is a very different beast than a CPU tracer -- The problem there is that you need to bundle many rays together on the GPU to get good performance. They usually start out in parallel (or nearly so), and can be packed together, but as they bounce off of surfaces the start to diverge, and no longer traverse the scene in the same way. I vaguely recall from a paper on raytracing with the Cell CPU, that most of the performance came from managing what rays were packed together.
On a CPU you still want to traverse the scene in a similar way to keep the caches warm, but you can cherry-pick and hop around between rays, rather than worrying about packaging them. You can essentially still do this on the GPU too if you're not worries about poor utilization of the hardware. A modern GPU like the 7970 is effectively arranged as 32 processors (compute units) that have 4x 16-wide vector units, so worst-case scenario you've still got 32 processors running at 1 ghz, so even a naive GPU tracer on decent hardware ought to be at least equal to A CPU tracer (say, on a quad-core i7, 3+ Ghz), and even if you do just enough work to keep all 4 vector units per compute unit active, it should be a few times faster.
#12 Members - Reputation: 143
Posted 01 September 2012 - 04:10 AM
Thank you Ravyne, these informations are very good
And finally, i have managed to get my new library to work, and now, its about 10 times faster as before
If someones interested, read more at our (LunaGameWorx) Blog site in the Raytracing section: http://gameworx.org/...acing-articles/
But i think, 740ms per frame is even slow, if i see something like this -> http://dinkla.net/de...p-parallel.html
In the Videos, if the application starts up, they are using only one thread for computing and git 8 Frames per secound! Once again, 10 times faster than mine.. are there some tricks to speed up calculations or function calls in c++ ? And, should i use float or double vectors? My vector struct has double's, because i thought, vectors should have good precision in a raytracer or rasterizer..
Edit: I switched to Release and /Os -> Now i have only 103ms per Frame and ~9Fps ! Awesome =D Maybe, i should write a bit more inline asm code in my vectors Oo
Edit2: Found the SIMD SSE2 Switch, now i'm at 13fps and 71ms per Frame!
Edited by Lunatix, 01 September 2012 - 05:26 AM.






