Search code examples
c#.netopenglopentk

AccessViolationException on GL.CreateShader with OpenTK


I'm having some trouble getting shaders integrated into my program. Up until this point I have been using the default pipeline but it is no longer able to accomplish all that I want to do. I have gotten some code together that I believe should work.

Code To Create and Compile Shaders:

    public int CompileShaders()
    {

        int vertexShader = GL.CreateShader(ShaderType.VertexShader);
        string shader = System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + @"Shaders\\test.vert");
        GL.ShaderSource(vertexShader, shader);
        GL.CompileShader(vertexShader);

        int fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
        shader = System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + @"Shaders\\test.frag");
        GL.ShaderSource(fragmentShader, shader);
        GL.CompileShader(fragmentShader);

        int shaderProgram = GL.CreateProgram();
        GL.AttachShader(shaderProgram, vertexShader);
        GL.AttachShader(shaderProgram, fragmentShader);
        GL.LinkProgram(shaderProgram);

        GL.DetachShader(shaderProgram, vertexShader);
        GL.DetachShader(shaderProgram, fragmentShader);
        GL.DeleteShader(vertexShader);
        GL.DeleteShader(fragmentShader);

        _shaderProgram = shaderProgram;
        return shaderProgram;
    }

When this code is hit, the first call to GL.CreateShader throws an AccessViolationException. The confusing bit is most of the other articles on this issue deal with a OpenGL context that has not been initialized. However, the GLContext for my program is initialized and used (as in I have already drawn to it and have it on screen) long before this code is run. I also tested running this code in the GLControl Load event handler, where it runs fine.

To go into a bit of detail on the structure of the code, there exsists a GLScene that contains GLLayers. The layers then contain geometry in the form of GLEntities, that can be one of numerous types, GLMesh for example. The code to compile the shaders and maintain a reference to the shader program is part of GLEntity. The GLEntity class and all classes that inherit from it have draw functions that will utilize the shader via the GL.UseProgram command. So the order of events in the program is as follows. The program opens and initializes internal variables as well as the OpenGL context with a viewport. The user then opens a file, at which point geometry is generated and added to the layers in GLScene. After the completion of the geometry generation, the shaders are supposed to compile.

Do any of you have an idea as to what could be causing the issue?

Thank you for your help.

Edit: Added Initialization code for GLContext

 OpenTK.Toolkit.Init();
 InitializeComponent();
 OpenTK.Graphics.GraphicsMode gm = new OpenTK.Graphics.GraphicsMode(32, 24, 8, 8);
 _glControl = new OpenTK.GLControl(gm);           
 winFormsHost.Child = _glControl;

    public void GLControl_Load(object sender, EventArgs e)
    {
        _camera = new GLCamera();
        _camera.Viewport = new Rectangle(0, 0, _mainVM.GLControl.Width, _mainVM.GLControl.Height);
        _logger.Info("Camera initialized");

        _mainVM.LoadSettings();
        _logger.Info("Settings loaded by ViewTool");
    }

Solution

  • Thank you to everyone who gave advice on this issue. After a nights sleep I found the solution to the problem. I was running the code on a separate thread from the main rendering thread. That obviously would not work with the nature of OpenGL.