klim_vlad's picture

[Solved] DispatchCompute invalid operation

Hello everyone.
I've got an issue with Compute Shader execution while an GL error occurs right after DispatchCompute. Struggling with getting more information on this error for couple days already. The OpenGL reference shows that this error shows up only if there is no active program for compute shader stage. As far as I understand the program becomes active after UseProgram(...) with the shader program handle as a parameter. But still - the "Invalid Operation" each time... Nothing helped so far.
The code below is my first attempt to have compute shader working. I used one of the shaders for particles bouncing at a sphere. I removed the sphere object but the particles still have to be moving...

Could you please have a look at the code and advise - where am I wrong? Why this error occuring?
I have my NVIDIA NVS 4200m, the OpenGL v.4.4, Shading Language v.4.4, GL_ARB_compute_shader extension available.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using System.Timers;
 
namespace OpenTKCompute
{
	class GLView : OpenTK.GLControl
	{
		string VertexShaderSource = @"
#version 440 core
precision highp float;
 
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
 
in vec4 in_pos;			// Vertex position
in vec4 in_color;
 
out vec4 color;
 
void main(void)
{
	color = in_color;
	gl_Position = projection_matrix * modelview_matrix * in_pos;
}";
		string FragmentShaderSource = @"
#version 440 core
precision highp float;
 
in vec4 color;
out vec4 out_frag_color;
 
void main(void)
{
	out_frag_color = color;
}";
 
		string ComputeShaderSource = @"
#version 440 core
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
#extension GL_ARB_compute_variable_group_size : enable
 
layout( std140, binding=4 ) buffer Pos
{
    vec4 Positions[];
};
 
layout( std140, binding=5 ) buffer Vel
{
    vec4 Velocities[];
};
 
//layout( local_size_x = 128,  local_size_y = 1, local_size_z = 1 )   in;
layout( local_size_variable )   in;
 
vec3 Bounce( vec3 vin, vec3 n )
{
	vec3 vout = reflect( vin, n );
	return vout;
}
 
vec3 BounceSphere( vec3 p, vec3 v, vec4 s )
{
	vec3 n = normalize( p - s.xyz );
	return Bounce( v, n );
}
 
bool IsInsideSphere( vec3 p, vec4 s )
{
	float r = length( p - s.xyz );
	return  ( r < s.w );
}
 
void main( )
{
	const vec3    G      = vec3( 0.0, -9.8, 0.0 );
	const float  DT      = 0.1;
	const vec4   SPHERE = vec4( -0.1, -0.4, 0.0,  0.6 );
 
	uint  gid = gl_GlobalInvocationID.x;	// the .y and .z are both 1 in this case
 
	vec3 p  = Positions[  gid  ].xyz;
	vec3 v  = Velocities[ gid  ].xyz;
 
	vec3 pp = p + v * DT + 0.5 * DT * DT * G;
	vec3 vp = v + G * DT;
 
	if( IsInsideSphere( pp, SPHERE ) )
	{
		vp = BounceSphere( p, v, SPHERE );
		pp = p + vp * DT + 0.5 * DT * DT * G;
	}
 
	Positions[  gid  ].xyz = pp;
	Velocities[ gid  ].xyz = vp;
}";
		Timer t = new Timer();
		Matrix4 projectionMatrix, modelviewMatrix;
		Vector2 last_mp;
 
		int ComputeShaderProgram, ShaderProgram, ComputeShaderHandle, VertexShaderHandle, FragmentShaderHandle,
			posSSbo, velSSbo, colSSbo,
			modelviewMatrixLocation,
			projectionMatrixLocation,
			EboHandle, VAOHandle;
 
		int[] ids_VBO_data;
 
		struct SPos
		{
			public float x, y, z, w;
		}
 
		struct SVel
		{
			public float x, y, z, w;
		}
 
		SPos[] pos_buffer;
		SVel[] vel_buffer;
		Vector4[] col_buffer;
 
		int pts = 512*256;
		int work_group_size = 128;
 
		Vector3 pos, rot;
 
		protected override void OnCreateControl()
		{
			base.OnCreateControl();
			MakeCurrent();
			this.VSync = false;
			string extensions = GL.GetString(StringName.Extensions);
			if (!extensions.Contains("EXT_geometry_shader4"))
			{
				System.Windows.Forms.MessageBox.Show(
					 "Your video card does not support EXT_geometry_shader4. Please update your drivers.",
					 "EXT_geometry_shader4 not supported",
					 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
				return;
			}
			if (!extensions.Contains("ARB_compute_shader"))
			{
				System.Windows.Forms.MessageBox.Show(
					 "Your video card does not support GL_ARB_compute_shader. Please update your drivers.",
					 "GL_ARB_compute_shader is not supported",
					 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
				return;
			}
			string ver = GL.GetString(StringName.ShadingLanguageVersion);
			ver = GL.GetString(StringName.Version);
			int[] param = new int[256];
 
			ComputeShaderHandle = GL.CreateShader(ShaderType.ComputeShader);
			GL.ShaderSource(ComputeShaderHandle, ComputeShaderSource);
			GL.CompileShader(ComputeShaderHandle);
			ComputeShaderProgram = GL.CreateProgram();
			GL.AttachShader(ComputeShaderProgram, ComputeShaderHandle);
			GL.LinkProgram(ComputeShaderProgram);
			GL.GetProgram(ComputeShaderProgram, GetProgramParameterName.LinkStatus, param);
			ErrorCode er = GL.GetError();
			GL.ValidateProgram(ComputeShaderProgram);
			GL.GetProgram(ComputeShaderProgram, GetProgramParameterName.ValidateStatus, param);
			er = GL.GetError();
			string status = GL.GetProgramInfoLog(ComputeShaderProgram);
			status = GL.GetShaderInfoLog(ComputeShaderHandle);
 
			ShaderProgram = GL.CreateProgram();
 
			VertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
			GL.ShaderSource(VertexShaderHandle, VertexShaderSource);
			GL.CompileShader(VertexShaderHandle);
			GL.AttachShader(ShaderProgram, VertexShaderHandle);
 
			FragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
			GL.ShaderSource(FragmentShaderHandle, FragmentShaderSource);
			GL.CompileShader(FragmentShaderHandle);
			GL.AttachShader(ShaderProgram, FragmentShaderHandle);
 
			GL.LinkProgram(ShaderProgram);
			GL.ValidateProgram(ShaderProgram);
			GL.UseProgram(ShaderProgram);
 
			#region Compute VBO
			Random r = new Random();
			pos_buffer = new SPos[pts];
			for (int i = 0; i < pts; i++)
			{
				pos_buffer[i].x = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].y = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].z = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].w = 1.0f;
			}
			GL.GenBuffers(1, out posSSbo);
			GL.BindBuffer(BufferTarget.ShaderStorageBuffer, posSSbo);
			GL.BufferData<SPos>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(pos_buffer.Length * sizeof(float) * 4),
				pos_buffer, BufferUsageHint.DynamicDraw);
 
			vel_buffer = new SVel[pts];
			for (int i = 0; i < pts; i++)
			{
				vel_buffer[i].x = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].y = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].z = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].w = 1.0f;
			}
			GL.GenBuffers(1, out velSSbo);
			GL.BindBuffer(BufferTarget.ShaderStorageBuffer, velSSbo);
			GL.BufferData<SVel>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(vel_buffer.Length * sizeof(float) * 4),
				vel_buffer, BufferUsageHint.StaticDraw);
 
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 4, posSSbo);
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 5, velSSbo);
 
			col_buffer = new Vector4[pts];
			for (int i = 0; i < pts; i++)
			{
				col_buffer[i].X = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].Y = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].Z = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].W = 1.0f;
			}
 
			GL.GenBuffers(1, out colSSbo);
			GL.BindBuffer(BufferTarget.ArrayBuffer, colSSbo);
			GL.BufferData<Vector4>(BufferTarget.ArrayBuffer,
				new IntPtr(col_buffer.Length * Vector4.SizeInBytes),
				col_buffer, BufferUsageHint.StaticDraw);
 
			#endregion
 
			#region VAO
 
			ids_VBO_data = new int[pts];
			for (int i = 0; i < ids_VBO_data.Length; i++)
				ids_VBO_data[i] = i;
 
			GL.GenBuffers(1, out EboHandle);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, EboHandle);
			GL.BufferData(BufferTarget.ElementArrayBuffer,
				new IntPtr(sizeof(int) * ids_VBO_data.Length),
				ids_VBO_data, BufferUsageHint.DynamicDraw);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
 
			GL.GenVertexArrays(1, out VAOHandle);
			GL.BindVertexArray(VAOHandle);
			int index = 0;
			GL.EnableVertexAttribArray(index);
			GL.BindBuffer(BufferTarget.ArrayBuffer, posSSbo);
			GL.VertexAttribPointer(index, 4, VertexAttribPointerType.Float, true, sizeof(float) * 4, 0);
			GL.BindAttribLocation(ShaderProgram, index, "in_pos");
 
			index = 1;
			GL.EnableVertexAttribArray(index);
			GL.BindBuffer(BufferTarget.ArrayBuffer, colSSbo);
			GL.VertexAttribPointer(index, 4, VertexAttribPointerType.Float, true, Vector4.SizeInBytes, 0);
			GL.BindAttribLocation(ShaderProgram, index, "in_color");
 
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, EboHandle);
			GL.BindVertexArray(0);
 
			#endregion
 
			projectionMatrixLocation = GL.GetUniformLocation(ShaderProgram, "projection_matrix");
			modelviewMatrixLocation = GL.GetUniformLocation(ShaderProgram, "modelview_matrix");
 
			GL.UseProgram(0);
 
			// Other state
			GL.Enable(EnableCap.DepthTest);
			GL.Enable(EnableCap.Blend);
			GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
 
			t.Interval = 1000.0 / 60.0;
			t.Start();
			t.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
 
			pos = new Vector3(0.0f, 0.0f, -5.0f);
		}
 
		private delegate void BoxRefreshDelegate();
		protected void OnTimerElapsed(object sender, ElapsedEventArgs e)
		{
			if (IsHandleCreated)
				if (InvokeRequired)
					try
					{
						BeginInvoke(new BoxRefreshDelegate(Refresh));
					} catch
					{
					}
		}
 
		protected override void OnResize(EventArgs e)
		{
			if (!Created)
				return;
			GL.Viewport(0, 0, Width, Height);
			base.OnResize(e);
		}
 
		protected void UpdateFrame()
		{
			GL.UseProgram(ComputeShaderProgram);
			ErrorCode er = GL.GetError();
			GL.DispatchCompute(pts / work_group_size, 1, 1);
                        // *** The error is coming up right here ***
			er = GL.GetError();
 
			GL.MemoryBarrier(MemoryBarrierFlags.ShaderStorageBarrierBit);
 
			GL.UseProgram(ShaderProgram);
 
			float aspectRatio = (float)Width / (float)Height;
			Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 0.01f, 1000.0f, out projectionMatrix);
			GL.UniformMatrix4(projectionMatrixLocation, false, ref projectionMatrix);
			modelviewMatrix = Matrix4.LookAt(new Vector3(0, 0, -0.1f), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationX(rot.X));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationY(rot.Y));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationZ(rot.Z));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateTranslation(pos));
			GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix);
		}
 
		protected void RenderFrame()
		{
			GL.ClearColor(0.3f, 0.3f, 0.5f, 1.0f);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.AccumBufferBit | ClearBufferMask.DepthBufferBit);
			GL.PointSize(0.1f);
			GL.BindVertexArray(VAOHandle);
			GL.DrawElements(PrimitiveType.Points, ids_VBO_data.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
			GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
			GL.UseProgram(0);
		}
 
		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
		{
			base.OnPaint(e);
			UpdateFrame();
			RenderFrame();
			SwapBuffers();
		}
 
		protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
		{
			base.OnMouseDown(e);
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
				last_mp = new Vector2((float)e.X, (float)e.Y);
		}
 
		protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
		{
			base.OnMouseMove(e);
			Vector2 mp = new Vector2(e.X, e.Y);
			Vector2 dmp = mp - last_mp;
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
			{
				dmp /= 200.0f;
				rot.X += dmp.Y;
				rot.Y += dmp.X;
			}
			if (e.Button == System.Windows.Forms.MouseButtons.Right)
			{
				dmp /= 100.0f;
				pos.X += dmp.X;
				pos.Y += -dmp.Y;
			}
			last_mp = mp;
		}
	}
}

Comments

Comment viewing options

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

Try creating a debug context to retrieve additional debug information:

using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.Runtime.InteropServices;
 
class GLView : GLControl
{
	public GLView()
		: base(GraphicsMode.Default, 1, 0, GraphicsContextFlags.Debug)
	{ }
 
	// The callback delegate must be stored to avoid GC
	DebugProc DebugCallbackInstance = DebugCallback;
 
	static void DebugCallback(DebugSource source, DebugType type, int id,
		DebugSeverity severity, int length, IntPtr message, IntPtr userParam)
	{
		string msg = Marshal.PtrToStringAnsi(message);
		Console.WriteLine("[GL] {0}; {1}; {2}; {3}; {4}",
			source, type, id, severity, msg);
	}
 
	protected override void OnCreateControl()
	{
		base.OnCreateControl();
		MakeCurrent();
		GL.DebugMessageCallback(DebugCallbackInstance, IntPtr.Zero);
		...
	}
}
klim_vlad's picture

Thanks a lot. It did help. Now it works.
I had to set the compute shader fixed workgroup size. Also had to update the buffers using GL.GetBufferSubData.
The updated code is here:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using System.Timers;
using System.Runtime.InteropServices;	
 
namespace OpenTKCompute
{
	class GLView : OpenTK.GLControl
	{
		string VertexShaderSource = @"
#version 440 core
precision highp float;
 
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
 
in vec4 in_pos;			// Vertex position
in vec4 in_color;
 
out vec4 color;
 
void main(void)
{
	color = in_color;
	gl_Position = projection_matrix * modelview_matrix * in_pos;
}";
		string FragmentShaderSource = @"
#version 440 core
precision highp float;
 
in vec4 color;
out vec4 out_frag_color;
 
void main(void)
{
	out_frag_color = color;
}";
 
		string ComputeShaderSource = @"
#version 440 core
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
#extension GL_ARB_compute_variable_group_size : enable
 
layout( std140, binding=4 ) buffer Pos
{
    vec4 Positions[];
};
 
layout( std140, binding=5 ) buffer Vel
{
    vec4 Velocities[];
};
 
//layout( std140, binding=6 ) buffer Col
//{
//    vec4 Colors[];
//};
 
layout( local_size_x = 128,  local_size_y = 1, local_size_z = 1 )   in;
//layout( local_size_variable )   in;
 
vec3 Bounce( vec3 vin, vec3 n )
{
	vec3 vout = reflect( vin, n );
	return vout;
}
 
vec3 BounceSphere( vec3 p, vec3 v, vec4 s )
{
	vec3 n = normalize( p - s.xyz );
	return Bounce( v, n );
}
 
bool IsInsideSphere( vec3 p, vec4 s )
{
	float r = length( p - s.xyz );
	return  ( r < s.w );
}
 
void main( )
{
	const vec3    G      = vec3( 0.0, -0.0098, 0.0 );
	const float  DT      = 0.1;
	const vec4   SPHERE = vec4( -0.1, -0.4, 0.0,  0.6 );
 
	uint  gid = gl_GlobalInvocationID.x;	// the .y and .z are both 1 in this case
 
	vec3 p  = Positions[  gid  ].xyz;
	vec3 v  = Velocities[ gid  ].xyz;
 
	vec3 pp = p + v * DT + 0.5 * DT * DT * G;
	vec3 vp = v + G * DT;
 
	if( IsInsideSphere( pp, SPHERE ) )
	{
		vp = BounceSphere( p, v, SPHERE );
		pp = p + vp * DT + 0.5 * DT * DT * G;
	}
 
	Positions[  gid  ].xyz = pp;
	Velocities[ gid  ].xyz = vp;
}";
		Timer t = new Timer();
		Matrix4 projectionMatrix, modelviewMatrix;
		Vector2 last_mp;
 
		int ComputeShaderProgram, ShaderProgram, ComputeShaderHandle, VertexShaderHandle, FragmentShaderHandle,
			posSSbo, velSSbo, colSSbo,
			modelviewMatrixLocation,
			projectionMatrixLocation,
			EboHandle, VAOHandle;
 
		int[] ids_VBO_data;
 
		struct SPos
		{
			public float x, y, z, w;
		}
 
		struct SVel
		{
			public float x, y, z, w;
		}
 
		SPos[] pos_buffer;
		SVel[] vel_buffer;
		Vector4[] col_buffer;
 
		int pts = 512*512;
		int work_group_size = 128;
 
		Vector3 pos, rot;
 
		static List<string> debug_messages = new List<string>();
 
		public GLView()
			: base(GraphicsMode.Default, 1, 0, GraphicsContextFlags.Debug)
		{ }
 
		// The callback delegate must be stored to avoid GC
		DebugProc DebugCallbackInstance = DebugCallback;
 
		static void DebugCallback(DebugSource source, DebugType type, int id,
			DebugSeverity severity, int length, IntPtr message, IntPtr userParam)
		{
			debug_messages.Add("Source: " + source.ToString() + ", Type: "
				+ type.ToString() + ", Severity: " + severity.ToString() + ", "
				+ Marshal.PtrToStringAnsi(message));
		}
 
		protected override void OnCreateControl()
		{
			base.OnCreateControl();
			MakeCurrent();
 
			GL.Enable(EnableCap.DebugOutput);
			GL.Enable(EnableCap.DebugOutputSynchronous);
			GL.DebugMessageCallback(DebugCallbackInstance, IntPtr.Zero);
 
			this.VSync = false;
			string extensions = GL.GetString(StringName.Extensions);
			if (!extensions.Contains("EXT_geometry_shader4"))
			{
				System.Windows.Forms.MessageBox.Show(
					 "Your video card does not support EXT_geometry_shader4. Please update your drivers.",
					 "EXT_geometry_shader4 not supported",
					 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
				return;
			}
			if (!extensions.Contains("ARB_compute_shader"))
			{
				System.Windows.Forms.MessageBox.Show(
					 "Your video card does not support GL_ARB_compute_shader. Please update your drivers.",
					 "GL_ARB_compute_shader is not supported",
					 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
				return;
			}
			string ver = GL.GetString(StringName.ShadingLanguageVersion);
			ver = GL.GetString(StringName.Version);
			int[] param = new int[256];
 
			ComputeShaderHandle = GL.CreateShader(ShaderType.ComputeShader);
			GL.ShaderSource(ComputeShaderHandle, ComputeShaderSource);
			GL.CompileShader(ComputeShaderHandle);
			ComputeShaderProgram = GL.CreateProgram();
			GL.AttachShader(ComputeShaderProgram, ComputeShaderHandle);
			GL.LinkProgram(ComputeShaderProgram);
			GL.GetProgram(ComputeShaderProgram, GetProgramParameterName.LinkStatus, param);
			ErrorCode er = GL.GetError();
			GL.ValidateProgram(ComputeShaderProgram);
			GL.GetProgram(ComputeShaderProgram, GetProgramParameterName.ValidateStatus, param);
			er = GL.GetError();
			string status = GL.GetProgramInfoLog(ComputeShaderProgram);
			status = GL.GetShaderInfoLog(ComputeShaderHandle);
 
			ShaderProgram = GL.CreateProgram();
 
			VertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
			GL.ShaderSource(VertexShaderHandle, VertexShaderSource);
			GL.CompileShader(VertexShaderHandle);
			GL.AttachShader(ShaderProgram, VertexShaderHandle);
 
			FragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
			GL.ShaderSource(FragmentShaderHandle, FragmentShaderSource);
			GL.CompileShader(FragmentShaderHandle);
			GL.AttachShader(ShaderProgram, FragmentShaderHandle);
 
			GL.LinkProgram(ShaderProgram);
			GL.ValidateProgram(ShaderProgram);
			GL.UseProgram(ShaderProgram);
 
			#region Compute VBO
			Random r = new Random();
			pos_buffer = new SPos[pts];
			for (int i = 0; i < pts; i++)
			{
				pos_buffer[i].x = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].y = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].z = (float)r.Next(-1000, 1000) / 1000.0f;
				pos_buffer[i].w = 1.0f;
			}
			GL.GenBuffers(1, out posSSbo);
			GL.BindBuffer(BufferTarget.ShaderStorageBuffer, posSSbo);
			GL.BufferData<SPos>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(pos_buffer.Length * sizeof(float) * 4),
				pos_buffer, BufferUsageHint.DynamicDraw);
 
			vel_buffer = new SVel[pts];
			for (int i = 0; i < pts; i++)
			{
				vel_buffer[i].x = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].y = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].z = (float)r.Next(-10, 10) / 1000.0f;
				vel_buffer[i].w = 1.0f;
			}
			GL.GenBuffers(1, out velSSbo);
			GL.BindBuffer(BufferTarget.ShaderStorageBuffer, velSSbo);
			GL.BufferData<SVel>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(vel_buffer.Length * sizeof(float) * 4),
				vel_buffer, BufferUsageHint.StaticDraw);
 
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 4, posSSbo);
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 5, velSSbo);
 
			col_buffer = new Vector4[pts];
			for (int i = 0; i < pts; i++)
			{
				col_buffer[i].X = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].Y = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].Z = (float)r.Next(0, 1000) / 1000.0f;
				col_buffer[i].W = 1.0f;
			}
 
			GL.GenBuffers(1, out colSSbo);
			GL.BindBuffer(BufferTarget.ArrayBuffer, colSSbo);
			GL.BufferData<Vector4>(BufferTarget.ArrayBuffer,
				new IntPtr(col_buffer.Length * Vector4.SizeInBytes),
				col_buffer, BufferUsageHint.StaticDraw);
 
			#endregion
 
			#region VAO
 
			ids_VBO_data = new int[pts];
			for (int i = 0; i < ids_VBO_data.Length; i++)
				ids_VBO_data[i] = i;
 
			GL.GenBuffers(1, out EboHandle);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, EboHandle);
			GL.BufferData(BufferTarget.ElementArrayBuffer,
				new IntPtr(sizeof(int) * ids_VBO_data.Length),
				ids_VBO_data, BufferUsageHint.DynamicDraw);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
 
			GL.GenVertexArrays(1, out VAOHandle);
			GL.BindVertexArray(VAOHandle);
			int index = 0;
			GL.EnableVertexAttribArray(index);
			GL.BindBuffer(BufferTarget.ArrayBuffer, posSSbo);
			GL.VertexAttribPointer(index, 4, VertexAttribPointerType.Float, true, sizeof(float) * 4, 0);
			GL.BindAttribLocation(ShaderProgram, index, "in_pos");
 
			index = 1;
			GL.EnableVertexAttribArray(index);
			GL.BindBuffer(BufferTarget.ArrayBuffer, colSSbo);
			GL.VertexAttribPointer(index, 4, VertexAttribPointerType.Float, true, Vector4.SizeInBytes, 0);
			GL.BindAttribLocation(ShaderProgram, index, "in_color");
 
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, EboHandle);
			GL.BindVertexArray(0);
 
			#endregion
 
			projectionMatrixLocation = GL.GetUniformLocation(ShaderProgram, "projection_matrix");
			modelviewMatrixLocation = GL.GetUniformLocation(ShaderProgram, "modelview_matrix");
 
			GL.UseProgram(0);
 
			// Other state
			GL.Enable(EnableCap.DepthTest);
			GL.Enable(EnableCap.Blend);
			GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
 
			t.Interval = 1000.0 / 60.0;
			t.Start();
			t.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
 
			pos = new Vector3(0.0f, 0.0f, -5.0f);
		}
 
		private delegate void BoxRefreshDelegate();
		protected void OnTimerElapsed(object sender, ElapsedEventArgs e)
		{
			if (IsHandleCreated)
				if (InvokeRequired)
					try
					{
						BeginInvoke(new BoxRefreshDelegate(Refresh));
					} catch
					{
					}
		}
 
		protected override void OnResize(EventArgs e)
		{
			if (!Created)
				return;
			GL.Viewport(0, 0, Width, Height);
			base.OnResize(e);
		}
 
		protected void UpdateFrame()
		{
			GL.UseProgram(ComputeShaderProgram);
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 4, posSSbo);
			GL.BufferData<SPos>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(pos_buffer.Length * sizeof(float) * 4),
				pos_buffer, BufferUsageHint.DynamicDraw);
 
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 5, velSSbo);
			GL.BufferData<SVel>(BufferTarget.ShaderStorageBuffer,
				new IntPtr(vel_buffer.Length * sizeof(float) * 4),
				vel_buffer, BufferUsageHint.StaticDraw);
 
			GL.DispatchCompute(pts / work_group_size, 1, 1);
			GL.MemoryBarrier(MemoryBarrierFlags.ShaderStorageBarrierBit);
 
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 4, posSSbo);
			GL.GetBufferSubData<SPos>(BufferTarget.ShaderStorageBuffer,
				IntPtr.Zero, new IntPtr(pts * sizeof(float) * 4), pos_buffer);
 
			GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 5, velSSbo);
			GL.GetBufferSubData<SVel>(BufferTarget.ShaderStorageBuffer,
				IntPtr.Zero, new IntPtr(pts * sizeof(float) * 4), vel_buffer);			
 
			GL.UseProgram(ShaderProgram);
 
			float aspectRatio = (float)Width / (float)Height;
			Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 0.01f, 1000.0f, out projectionMatrix);
			GL.UniformMatrix4(projectionMatrixLocation, false, ref projectionMatrix);
			modelviewMatrix = Matrix4.LookAt(new Vector3(0, 0, -0.1f), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationX(rot.X));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationY(rot.Y));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateRotationZ(rot.Z));
			modelviewMatrix = Matrix4.Mult(modelviewMatrix, Matrix4.CreateTranslation(pos));
			GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix);
		}
 
		protected void RenderFrame()
		{
			GL.ClearColor(0.3f, 0.3f, 0.5f, 1.0f);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.AccumBufferBit | ClearBufferMask.DepthBufferBit);
 
			GL.PointSize(0.1f);
			GL.BindVertexArray(VAOHandle);
			GL.DrawElements(PrimitiveType.Points, ids_VBO_data.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
			GL.UseProgram(0);
		}
 
		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
		{
			base.OnPaint(e);
			UpdateFrame();
			RenderFrame();
			SwapBuffers();
		}
 
		protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
		{
			base.OnMouseDown(e);
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
				last_mp = new Vector2((float)e.X, (float)e.Y);
		}
 
		protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
		{
			base.OnMouseMove(e);
			Vector2 mp = new Vector2(e.X, e.Y);
			Vector2 dmp = mp - last_mp;
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
			{
				dmp /= 200.0f;
				rot.X += dmp.Y;
				rot.Y += dmp.X;
			}
			if (e.Button == System.Windows.Forms.MouseButtons.Right)
			{
				dmp /= 100.0f;
				pos.X += dmp.X;
				pos.Y += -dmp.Y;
			}
			last_mp = mp;
		}
	}
}
the Fiddler's picture

Awesome! Would you mind if I added this code to OpenTK.Examples?

klim_vlad's picture

Sure, please add it.

Thanks again.