public GraphicsInterop() { var glHandle = ((IGraphicsContextInternal)GraphicsContext.CurrentContext).Context.Handle; var wglHandle = wglGetCurrentDC(); _device = ComputePlatform.Platforms[0].Devices[0]; var p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, Device.Platform.Handle.Value); var p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, glHandle); var p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglHandle); var cpl = new ComputeContextPropertyList(new[] { p1, p2, p3 }); _context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero); _queue = new ComputeCommandQueue(Context, Device, ComputeCommandQueueFlags.None); GL.ClearColor(0f, 0f, 1f, 1f); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); GL.Ortho(0, 1.0f, 0, 1.0f, -1.0f, 1.0f); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.GenBuffers(1, out _pub); GL.Enable(EnableCap.Texture2D); _texture = GL.GenTexture(); }
public void SelectBestDevice() { // This function attempts to find the best platform / device for OpenCL code execution. // The best device is typically not the CPU, nor an integrated GPU. If no GPU is found, // the CPU will be used, but this may limit compatibility, especially for the interop // functionality, but sometimes also for floating point textures. int bestPlatform = -1, bestDevice = -1, bestScore = -1; for (int i = 0; i < ComputePlatform.Platforms.Count; i++) { var platform = ComputePlatform.Platforms[i]; for (int j = 0; j < platform.Devices.Count; j++) { var device = platform.Devices[j]; if (device.Type == ComputeDeviceTypes.Gpu) { // Found a GPU device, prefer this over integrated graphics int score = 1; if (!platform.Name.Contains("Intel")) { score = 10; } if (score > bestScore) { bestPlatform = i; bestDevice = j; bestScore = score; } } else if (bestPlatform == -1) { // Found an OpenCL device, but not a GPU, better than nothing bestPlatform = i; bestDevice = j; } } } if (bestPlatform > -1) { var platform = ComputePlatform.Platforms[bestPlatform]; Console.Write($"Initializing OpenCL... {platform.Name} ({platform.Profile}).\n"); // Try to enable gl interop functionality try { var ctx = (OpenTK.Graphics.IGraphicsContextInternal)OpenTK.Graphics.GraphicsContext.CurrentContext; IntPtr glHandle = ctx.Context.Handle; IntPtr wglHandle = wglGetCurrentDC(); var p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, platform.Handle.Value); var p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, glHandle); var p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglHandle); List <ComputeContextProperty> props = new List <ComputeContextProperty>() { p1, p2, p3 }; ComputeContextPropertyList Properties = new ComputeContextPropertyList(props); context = new ComputeContext(ComputeDeviceTypes.Gpu, Properties, null, IntPtr.Zero); } catch { // if this failed, we'll do without gl interop try { context = new ComputeContext(ComputeDeviceTypes.Gpu, new ComputeContextPropertyList(platform), null, IntPtr.Zero); } catch { // failed to initialize a valid context; report throw new Exception("Failed to initialize OpenCL context"); } } } else { // failed to find an OpenCL device; report throw new Exception("Failed to initialize OpenCL"); } }
// initialize renderer: takes in command line parameters passed by template code public void Init(int rt, bool gpu, int platformIdx) { // pass command line parameters runningTime = rt; useGPU = gpu; gpuPlatform = platformIdx; // initialize accumulator accumulator = new Vector3[screen.width * screen.height]; // setup scene scene = new Scene(); // setup camera camera = new Camera(screen.width, screen.height); gpuCamera = new GPUCamera(camera.pos, camera.p1, camera.p2, camera.p3, camera.up, camera.right, screen.width, screen.height, camera.lensSize); // initialize max threads parallelOptions = new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism = Environment.ProcessorCount * 2; // GPU variables // pick first platform var platform = ComputePlatform.Platforms[gpuPlatform]; // create context with all gpu devices if (GLInterop) { ComputeContextProperty p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, platform.Handle.Value); ComputeContextProperty p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, (GraphicsContext.CurrentContext as IGraphicsContextInternal).Context.Handle); ComputeContextProperty p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglGetCurrentDC()); ComputeContextPropertyList cpl = new ComputeContextPropertyList(new ComputeContextProperty[] { p1, p2, p3 }); context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero); } else { context = new ComputeContext(ComputeDeviceTypes.Gpu, new ComputeContextPropertyList(platform), null, IntPtr.Zero); } var streamReader = new StreamReader("../../program.cl"); string clSource = streamReader.ReadToEnd(); streamReader.Close(); // create program with opencl source program = new ComputeProgram(context, clSource); // compile opencl source try { program.Build(null, null, null, IntPtr.Zero); } catch { Console.Write("error in kernel code:\n"); Console.Write(program.GetBuildLog(context.Devices[0]) + "\n"); } // load chosen kernel from program kernel = program.CreateKernel("device_function"); // create some data data = new int[screen.width * screen.height]; // allocate a memory buffer with the message (the int array) var flags = ComputeMemoryFlags.WriteOnly | ComputeMemoryFlags.UseHostPointer; buffer = new ComputeBuffer<int>(context, flags, data); kernel.SetMemoryArgument(0, buffer); ComputeBuffer<float> skyboxBuffer = new ComputeBuffer<float>(context, flags, Scene.skybox); ComputeBuffer<Sphere> sphereBuffer = new ComputeBuffer<Sphere>(context, flags, Scene.sphere); ComputeBuffer<Sphere> planeBuffer = new ComputeBuffer<Sphere>(context, flags, Scene.planes); kernel.SetMemoryArgument(1, skyboxBuffer); kernel.SetValueArgument(2, gpuCamera); kernel.SetMemoryArgument(4, sphereBuffer); kernel.SetMemoryArgument(5, planeBuffer); kernel.SetValueArgument(6, Scene.light); // create a command queue with first gpu found queue = new ComputeCommandQueue(context, context.Devices[0], 0); ClearAccumulator(); // create a texture to draw to from OpenCL if (GLInterop) { texID = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, texID); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, 512, 512, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.Float, texData); flags = ComputeMemoryFlags.WriteOnly; texBuffer = ComputeImage2D.CreateFromGLTexture2D(context, flags, (int)TextureTarget.Texture2D, 0, texID); } // initialize dataArray int counter = 0; for (int y = 0; y < screen.height; y += 12) { for (int x = 0; x < screen.width; x += 8) { //amount.Add(new DataBundle(x, y, 12, 8)); dataArray[counter] = new DataBundle(x, y, 8, 12); counter++; } } }