Saturday, January 28, 2017

OpenTK GL.CompileShader System.AccessViolationException was unhandled


Tried to add another shader (Tesselation Control Shader this time) to my program and received the following exception when compiling it with GL.CompileShader
System.AccessViolationException was unhandled
  HResult=-2147467261
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=OpenTK
  StackTrace:
       at OpenTK.Graphics.OpenGL4.GL.CompileShader(Int32 shader)
       at techdump.opengl.Components.MainWindow.CompileShaders() in C:\tfs\techdump\techdump\techdump.opengl\Components\MainWindow.cs:line 58
       at techdump.opengl.Components.MainWindow.OnLoad(EventArgs e) in C:\tfs\techdump\techdump\techdump.opengl\Components\MainWindow.cs:line 38
       at OpenTK.GameWindow.Run(Double updates_per_second, Double frames_per_second)
       at techdump.opengl.Program.Main() in C:\tfs\techdump\techdump\techdump.opengl\Program.cs:line 11
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

So what went wrong? Looking at the variables in the debug I see that the shader was loaded correctly from the file, GL.ShaderSource did not complain.
Been trying to read up on this for the last hour but no luck.

Last resort. As I am on a laptop and have both an Intel(R) HD Graphics 530 chip and a NVIDIA GeForce GTX 960M, I try to switch and start with the NVidia instead. And it works.

To try this, open up your build folder in windows explorer, right click and select, run with graphics processor and then select your NVidia card.
Turns out that NVidia tries to save energy and starting things with the Intel chip if its not a game. Good for battery life, less so for games development :)
This also turns out to solve the issue with version compatibility from a previous post where the work around was to use an older version of OpenGL.

So how to setup so that your visual studio runs with the correct GPU as default?

This seems to be harder than I imagined. But thanksfully there is a solution to this over at drivenbynostalgia.com. Basically they provide a class that you add to your application that registers it with your NVidia drivers and states that it is a game. So go to their site and find the 'sop - setoptimusprofile' section.


Also to note, the SOP solution is x86 only. I got the following exception when trying to run it in 64-bit mode.

System.TypeLoadException was unhandled
  HResult=-2146233054
  Message=Could not load type 'Setting' from assembly 'techdump.opengl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field.
  Source=techdump.opengl
  TypeName=Setting
  StackTrace:
       at techdump.opengl.Components.SOP.SOP_SetProfile(String profileName, String applicationName)
       at techdump.opengl.Program.HandleSop() in C:\tfs\techdump\techdump\techdump.opengl\Program.cs:line 21
       at techdump.opengl.Program.Main() in C:\tfs\techdump\techdump\techdump.opengl\Program.cs:line 12
  InnerException: 

So no x64. So I had to go back to 32 bits. I guess I can live with that :)

Update 2017-01-28
Seems that if you do not close the program correctly X times, the above exception starts throwing again. Trying to start it with Intel chip this time works. After a reboot the NVidia chip works as well.. The OpenTK override Exit does not seem to trigger if you close the window manually. Can be solved by adding following event handler to your OnLoad override.
protected override void OnLoad(EventArgs e)
{
    /// other init code
    Closed += OnClosed;
}

private void OnClosed(object sender, EventArgs eventArgs)
{
    Exit();
}


Hope this helps someone out there :)

No comments:

Post a Comment