mika91's picture

Multiple GLControl and Texture sharing

Hi,

I'm a beginner with OpenTK, and I find it near perfect !
Thanks for the work !

My application, a 3D surface viewer, need to display the surface in 4 controls, with different point of view.
My VBO, IBO and shader programm are shared (created only once) and it works.
But I can't achieve to share my colormap texture.
First view is ok, but all others are black.
(If i create one texture per view, it works)

Here is the code to load the texture:

       static int OGL_CMAPTEX;
 
       void LoadTexture()
        {
            // Load&Bind the 1D texture for color lookups
            GL.ActiveTexture(TextureUnit.Texture0); // select TMU0
            GL.GenTextures(1, out OGL_CMAPTEX);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureWrapS, (int)(TextureWrapMode)All.ClampToEdge);
 
            using (Bitmap bitmap = new Bitmap("JuliaColorTable.bmp"))
            {
                BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
                                                  System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                GL.TexImage1D(TextureTarget.Texture1D, 0, PixelInternalFormat.Rgb8, data.Width, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr,
                              PixelType.UnsignedByte, data.Scan0);
                bitmap.UnlockBits(data);
            }
        }

and when I use it in the render function:

           GL.BindTexture(TextureTarget.Texture1D, OGL_CMAPTEX);
 
            GL.Uniform1(GL.GetUniformLocation(OGL_SHADER_PRG, "CMAPTEX")    , OGL_CMAPTEX);

So where is my mistake ?
Maybe textures aren't shared resources ?

Thanks


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Textures should be shared along with other resources. Try using a debug version of OpenTK.dll: compile OpenTK.sln, copy the dll to your bin/ folder and run your project. This will print several diagnostic messages (Visual Studio -> "Output" tab at bottom) - please post them here to see if we can find anything.

Note that the debug dll will also throw an exception if it encounters any OpenGL errors, which is very useful for debugging!

mika91's picture

Ok, here comes the debug output:

Une exception de première chance de type 'System.DllNotFoundException' s'est produite dans OpenTK.dll
Une exception de première chance de type 'System.TypeInitializationException' s'est produite dans OpenTK.dll
'OTK.vshost.exe' (Managé) : 'C:\WINDOWS\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll' chargé, chargement des symboles ignoré. Le module est optimisé et l'option du débogueur 'Uniquement mon code' est activée.
Detected configuration: Windows / .Net
Une exception de première chance de type 'System.DllNotFoundException' s'est produite dans OpenTK.dll
DisplayDevice 1 (primary) supports 74 resolutions.
DisplayDevice 2 (secondary) supports 153 resolutions.
Creating default GraphicsMode (32, 16, 0, 0, 0, 2, False).
Creating GraphicsContext.
    Creating GraphicsContext.
        Device context: 1610686031
        Selecting pixel format... GraphicsMode: Index: 11, Color: 24 (8880), Depth: 0, Stencil: 0, Samples: 0, Accum: 64 (16161616), Buffers: 2, Stereo: False
        IWindowInfo: Windows.WindowInfo: Handle 5312552, Parent (Windows.WindowInfo: Handle 1839330, Parent (null))
        GraphicsContextFlags: Default
        Requested version: 1.0
        Loaded opengl32.dll: 1594294272
        OpenGL will be bound to handle: 5312552
        Setting pixel format... 11
        Creating temporary context for wgl extensions.
        Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 8 ms.
        Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 1 ms.
        Using WGL_ARB_create_context... success!
        success! (id: 131072)
    Selecting pixel format (ARB)... success!
    Disposing context 131072.
    Destroying window: Windows.WindowInfo: Handle 1839330, Parent (null)
    GraphicsMode: Index: 8, Color: 32 (8888), Depth: 24, Stencil: 0, Samples: 0, Accum: 64 (16161616), Buffers: 2, Stereo: False
    IWindowInfo: Windows.WindowInfo: Handle 594100, Parent (null)
    GraphicsContextFlags: Default
    Requested version: 1.0
    OpenGL will be bound to handle: 594100
    Setting pixel format... 8
    Using WGL_ARB_create_context... success!
    success! (id: 196608)
Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 1 ms.
Loading extensions for OpenTK.Graphics.OpenGL.GL... 1900 extensions loaded in 181.6842 ms.
Creating GraphicsContext.
    GraphicsMode: Index: 8, Color: 32 (8888), Depth: 24, Stencil: 0, Samples: 0, Accum: 64 (16161616), Buffers: 2, Stereo: False
    IWindowInfo: Windows.WindowInfo: Handle 2756834, Parent (null)
    GraphicsContextFlags: Default
    Requested version: 1.0
    OpenGL will be bound to handle: 2756834
    Setting pixel format... 8
    Using WGL_ARB_create_context... success!
    success! (id: 65537)
    OpenTK.Graphics.GraphicsContext: Sharing state with context {0}: success!
Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 2 ms.
Loading extensions for OpenTK.Graphics.OpenGL.GL... 1900 extensions loaded in 34.1401 ms.
Creating GraphicsContext.
    GraphicsMode: Index: 8, Color: 32 (8888), Depth: 24, Stencil: 0, Samples: 0, Accum: 64 (16161616), Buffers: 2, Stereo: False
    IWindowInfo: Windows.WindowInfo: Handle 5378088, Parent (null)
    GraphicsContextFlags: Default
    Requested version: 1.0
    OpenGL will be bound to handle: 5378088
    Setting pixel format... 8
    Using WGL_ARB_create_context... success!
    success! (id: 65538)
    OpenTK.Graphics.GraphicsContext: Sharing state with context {0}: success!
Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 1 ms.
Loading extensions for OpenTK.Graphics.OpenGL.GL... 1900 extensions loaded in 28.7475 ms.
Creating GraphicsContext.
    GraphicsMode: Index: 8, Color: 32 (8888), Depth: 24, Stencil: 0, Samples: 0, Accum: 64 (16161616), Buffers: 2, Stereo: False
    IWindowInfo: Windows.WindowInfo: Handle 2756628, Parent (null)
    GraphicsContextFlags: Default
    Requested version: 1.0
    OpenGL will be bound to handle: 2756628
    Setting pixel format... 8
    Using WGL_ARB_create_context... success!
    success! (id: 65539)
    OpenTK.Graphics.GraphicsContext: Sharing state with context {0}: success!
Load extensions for OpenTK.Platform.Windows.Wgl... 50 extensions loaded in 1 ms.
Loading extensions for OpenTK.Graphics.OpenGL.GL... 1900 extensions loaded in 29.5578 ms.
the Fiddler's picture

Everything appears to be in order, pixel formats are identical and context sharing is reported to succeed.

Are you rendering from four different threads? In that case, make sure you are not binding the texture id before creating it on the "main" context (you can check if a texture id has been allocated with GL.IsTexture()).

Other than that, there is too little information to guess at what the problem might be. Upgrading your drivers might help (driver bugs are not uncommon).

There is one other solution that might work: create four GLControls but render using the context of the first only (i.e. call glControl1.Context.MakeCurrent() on each control in a round-robin fashion). This will avoid the issue of resource sharing completely. There is a forum thread somewhere around here that describes this approach.

In general, multiple contexts should be avoided if possible. Note that Intel cards do not support resource sharing at all.

mika91's picture

Sorry, but I'm a little bit confused with the "Context" notion.

I create 4 GlControls, and use this.MakeCurrent() in the OnResize() and OnPaint() functions.
So how many contexts are there ? four ?

Your solution is to use "glControl1.Context.MakeCurrent()", so only one context will be created ?

Quote:

In general, multiple contexts should be avoided if possible. Note that Intel cards do not support resource sharing at all.

If I understand, building an application with multiple glControls should be avoided ?

the Fiddler's picture

OpenTK creates one context per GLControl, so there are four different contexts. The trick here is to use the first context (from glControl1) to render on all four GLControls sequentially:

glControl1.Context.MakeCurrent(glControl1.WindowInfo);
// render
glControl1.SwapBuffers();
glControl1.Context.MakeCurrent(glControl2.WindowInfo);
// render
glControl1.SwapBuffers();
glControl1.Context.MakeCurrent(glControl3.WindowInfo);
// render
glControl1.SwapBuffers();
...

The contexts for glControl[234] remain unused, avoiding the need for resource sharing (and the headaches that involves).

In general, using multiple contexts should be avoided *unless* you are doing multi-threaded rendering or multi-threaded resource loading. The rule of thumb is "one context per thread".

mika91's picture

Thanks you very much for your time and lessons !
I think I've understood this time ;)

Just a couple of bonus question:

1) Do you have any idea about performance difference between using glcontrol1.Context.MakeCurrent(glControl2.WindowInfo) or glcontrol2.MakeCurrent() ?
I will display 8 or 16 views, and I read that changing/editing context was a slow operation.

2) Maybe for my software, it's easier to manage directly a singleton GraphicsContext with many UserControl.
Or GlControl have some others advantages ? (I'll check the source code tonight)

the Fiddler's picture

You're welcome :)

mika91 wrote:

1) Do you have any idea about performance difference between using glcontrol1.Context.MakeCurrent(glControl2.WindowInfo) or glcontrol2.MakeCurrent() ?
I will display 8 or 16 views, and I read that changing/editing context was a slow operation.

They should perform identically. MakeCurrent *is* a slow operation, which is why many people suggest using a single context with multiple viewports if possible. This will not work with MDI, but if you are working with a single Form, you might be able to use a single GLControl and use GL.Viewport to split it into smaller parts (avoiding all MakeCurrent completely).

Quote:

2) Maybe for my software, it's easier to manage directly a singleton GraphicsContext with many UserControl.
Or GlControl have some others advantages ? (I'll check the source code tonight)

You cannot attach a GraphicsContext to a UserControl directly, because UserControl lacks a pixel format. While possible in theory, fixing this would require some downright ugly code - it's just not worth it.

GLControl will waste some memory on contexts (~50KB on my Nvidia), which I consider acceptable. You might wish to turn off context sharing explicitly if you go down this path:

// before creating any contexts:
GraphicsContext.ShareContexts = false;

This will probably not make a difference, but it *might* allow some drivers to run faster.