public void SetupClContext() { CanUseDouble = CanUseInterop = false; if (clPlatform == null || comboBoxDevice.SelectedIndex >= clPlatform.Devices.Count) { clDevice = null; clContext = null; return; } try { clDevice = clPlatform.Devices[comboBoxDevice.SelectedIndex]; ComputeContextPropertyList properties = new ComputeContextPropertyList(clPlatform); IGraphicsContextInternal ctx = (IGraphicsContextInternal)GraphicsContext.CurrentContext; properties.Add(new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, ctx.Context.Handle)); properties.Add(new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, OpenGL.wglGetCurrentDC())); properties.Add(new ComputeContextProperty(ComputeContextPropertyName.Platform, clPlatform.Handle.Value)); clContext = new ComputeContext(new ComputeDevice[] { clDevice }, properties, null, IntPtr.Zero); // check the double-extension: CanUseDouble = ClInfo.ExtensionCheck(clContext, "cl_khr_fp64"); CanUseInterop = ClInfo.ExtensionCheck(clContext, "cl_khr_gl_sharing"); ClInfo.LogCLProperties(clContext, true); } catch (Exception exc) { Util.LogFormat("OpenCL error: {0}", exc.Message); clDevice = null; clContext = null; } bool enableDouble = !checkOpenCL.Checked || CanUseDouble; checkDouble.Enabled = enableDouble; checkInterop.Enabled = CanUseInterop; }
/// <summary> /// Prepare OpenCL program, data buffers, etc. /// </summary> public void PrepareClBuffers(bool dirty = true) { clDirty = clDirty || dirty; if (texName == 0 || !checkOpenCL.Checked) { DestroyClBuffers(); return; } if (!clDirty) { return; } DestroyClBuffers(); if (clContext == null) { SetupClContext(); } if (clContext == null) // to be sure { Util.Log("OpenCL error"); clImage = null; clDirty = true; return; } GL.BindTexture(TextureTarget.Texture2D, 0); GL.Finish(); try { // OpenCL C source: string src = ClInfo.ReadSourceFile(CanUseDouble ? "mandel.cl" : "mandelSingle.cl", "090opencl"); if (string.IsNullOrEmpty(src)) { return; } // program & kernel: clProgram = new ComputeProgram(clContext, src); clProgram.Build(clContext.Devices, null, null, IntPtr.Zero); clKernel = clProgram.CreateKernel((checkDouble.Checked && CanUseDouble) ? "mandelDouble" : "mandelSingle"); clCommands = new ComputeCommandQueue(clContext, clContext.Devices[0], ComputeCommandQueueFlags.None); globalWidth = (texWidth + groupSize - 1) & -groupSize; globalHeight = (texHeight + groupSize - 1) & -groupSize; // buffers: // 1. colormap array cmap = new ComputeBuffer <byte>(clContext, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, colormap); bool interopOk = checkInterop.Checked; if (interopOk) { // 2. CL image for OpenGL interop clImage = ComputeImage2D.CreateFromGLTexture2D(clContext, ComputeMemoryFlags.ReadWrite, (int)TextureTarget.Texture2D, 0, texName); if (clImage == null) { Util.Log("OpenCL cannot reference OpenGL texture!"); interopOk = false; } } // 3. CL output array result = new ComputeBuffer <byte>(clContext, ComputeMemoryFlags.ReadWrite, texWidth * texHeight * 4); // synced.. clDirty = false; } catch (Exception exc) { Util.LogFormat("OpenCL build error: {0}", exc.Message); clImage = null; clDirty = true; } }