Jump to content

  • Log In with Google      Sign In   
  • Create Account


How draws OpenGL to a Window Handle?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 29 August 2012 - 02:55 AM

Hello!

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?
You like voxels? Then you may like... http://gameworx.org/?p=36

Sponsor:

#2 samoth   Crossbones+   -  Reputation: 4683

Like
3Likes
Like

Posted 29 August 2012 - 04:18 AM

The easy (although not helpful) answer is "it doesn't".

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 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 29 August 2012 - 09:13 AM

Thank you :) This is a good approach / hint! Now, i cann turn on google with a more specific "knowledge" of my problem ;)
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 :)
You like voxels? Then you may like... http://gameworx.org/?p=36

#4 Olof Hedman   Crossbones+   -  Reputation: 2741

Like
1Likes
Like

Posted 29 August 2012 - 09:32 AM

You will never get "direct" access to the actual frame buffer that is displayed on the screen, there will always be "some" step in between.

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 powly k   Members   -  Reputation: 648

Like
2Likes
Like

Posted 29 August 2012 - 02:17 PM

Write your own GPU driver or bootable software, that way you can access all the buffers you want! But seriously, windows gives you GDI and DirectX (and OpenGL) just for these kinds of things, everyone uses them. The big rendering studios, too. When you upload a texture to VRAM, it'll be rendered pretty much as directly as it can.

#6 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 30 August 2012 - 12:30 AM

Very funny, powly K ;)

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..
You like voxels? Then you may like... http://gameworx.org/?p=36

#7 powly k   Members   -  Reputation: 648

Like
0Likes
Like

Posted 30 August 2012 - 07:00 AM

It actually is the way. OpenGL and DirectX are implemented as drivers for the GPU. All drawn things go through the GPU nowadays, so you can't just directly write into screen memory like in DOS and earlier times. I've done some software rendering in the past and used a simple stretchdibits to the window DC - that was more than adequate to do simple things in realtime. Though, you could do your tracer on the GPU altogether, which is what many people nowadays are doing.

I'm curious though, what exactly took 400ms? A memcpy of your picture?

Edited by powly k, 30 August 2012 - 07:00 AM.


#8 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 30 August 2012 - 07:22 AM

When i got the raytracing working again, i will modify my raytracing code a bit and use OpenCL for computing. The thing was, that i had my own "Pixmap" which the final colors where drawn to - and i had to copy this colors (public struct RTColor) to the Bitmap via "MyBitmap.SetPixel(System.Drawing.Color, ..)". This took to long, and i don't wanted to write unsafe code, because i think, if i'm programming in a managed enviroment, one should not use unsafe code until no other solution is left.
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)..
You like voxels? Then you may like... http://gameworx.org/?p=36

#9 samoth   Crossbones+   -  Reputation: 4683

Like
0Likes
Like

Posted 30 August 2012 - 08:32 AM

You should really not worry much about this.

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 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 30 August 2012 - 10:46 AM

samoth: In some cases, you're right - i shouldn't worry about it. But in my case, i want to get experience! I don't even want to look up at those people, who writes librarys like OpenGL or DirectX and think "Theese people must be some kind of gods *_* - no, i want to be one of those people, who know the mechanics behind the scene - just a little bit!

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 :)
You like voxels? Then you may like... http://gameworx.org/?p=36

#11 Ravyne   Crossbones+   -  Reputation: 7116

Like
1Likes
Like

Posted 30 August 2012 - 12:23 PM

Even rendering to system memory in a buffer and doing a BitBlt to copy it to a window handle should not be slow. Last time I ran my code that did exactly that, I could clear a 640x480 buffer with a solid color and send it to a window several thousand times per second. It should not even remotely be your bottleneck in a ray-tracer, and if you do your tracing on the CPU its probably faster this way than copying it out to a texture for OpenGL or DirectX to render.

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 Lunatix   Members   -  Reputation: 143

Like
0Likes
Like

Posted 01 September 2012 - 04:10 AM

Hey!

Thank you Ravyne, these informations are very good Posted Image I will keep this in my mind, if i start with OpenCL.
And finally, i have managed to get my new library to work, and now, its about 10 times faster as before Posted Image

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.

You like voxels? Then you may like... http://gameworx.org/?p=36




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS