using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using OpenCLNet; using CL = OpenCLNet; namespace OpenCLImageTest { public partial class Form1 : Form { string OpenCLSource; Bitmap TestImage; Bitmap TestImageOutput; // Currently selected platform Platform oclPlatform; // All devices in the currently selected platform Device[] oclDevices; // Currently selected device Device oclDevice; // Currently active context Context oclContext; // Command queue to selected device CommandQueue oclCQ; // Current program+data CL.Program oclProgram; CL.Image OCLInputImage; CL.Image OCLOutputImage; Sampler OCLSampler; Kernel FilterKernel; bool oclFullyInitialized = false; ContextNotify oclContextNotify; List CallBackEventList = new List(); public Form1() { InitializeComponent(); oclContextNotify = new ContextNotify(OpenCLContextNotifyCallBack); } public void SetupOpenCL() { if (OpenCL.NumberOfPlatforms == 0) { MessageBox.Show("OpenCL not available"); Application.Exit(); } } public void PopulateOCLPlatformsComboBox() { comboBoxOpenCLPlatforms.Items.Clear(); for (int platformID = 0; platformID < OpenCL.NumberOfPlatforms; platformID++) { Platform p = OpenCL.GetPlatform(platformID); comboBoxOpenCLPlatforms.Items.Add(p.Vendor+":"+p.Name+" "+p.Version); } } public void PopulateOCLDevicesComboBox(Platform p, DeviceType deviceType) { Device[] devices = p.QueryDevices(deviceType); comboBoxOpenCLDevices.Items.Clear(); foreach (Device d in devices) { comboBoxOpenCLDevices.Items.Add(d.Vendor + " " + d.Name); } } public void CreateContext( Platform platform, Device device ) { IntPtr[] contextProperties = new IntPtr[] { (IntPtr)ContextProperties.PLATFORM, platform.PlatformID, IntPtr.Zero, IntPtr.Zero }; Device[] devices = new Device[] { device }; oclContext = platform.CreateContext(contextProperties, devices, oclContextNotify, IntPtr.Zero); oclCQ = oclContext.CreateCommandQueue(device, CommandQueueProperties.PROFILING_ENABLE); } public void OpenCLContextNotifyCallBack(string errInfo, byte[] privateInfo, IntPtr cb, IntPtr userData) { CallBackEventList.Add( errInfo ); textBoxCallBackEvents.Lines = CallBackEventList.ToArray(); } public void BuildOCLSource(string source) { oclProgram = oclContext.CreateProgramWithSource(source); oclProgram.Build(); FilterKernel = oclProgram.CreateKernel("FilterImage"); } public void CreateOCLImages(Context context) { OCLInputImage = CreateOCLBitmapFromBitmap(TestImage); OCLOutputImage = oclContext.CreateImage2D(MemFlags.WRITE_ONLY, CL.ImageFormat.RGBA8U, panelScaled.Width, panelScaled.Height, 0, IntPtr.Zero); OCLSampler = oclContext.CreateSampler(true, AddressingMode.CLAMP_TO_EDGE, FilterMode.LINEAR); } public void ReleaseDeviceResources() { oclFullyInitialized = false; if (OCLSampler != null) { OCLSampler.Dispose(); OCLSampler = null; } if (OCLInputImage != null) { OCLInputImage.Dispose(); OCLInputImage = null; } if (OCLOutputImage != null) { OCLOutputImage.Dispose(); OCLOutputImage = null; } if (FilterKernel != null) { FilterKernel.Dispose(); FilterKernel = null; } if (oclProgram != null) { oclProgram.Dispose(); oclProgram = null; } if (oclCQ != null) { oclCQ.Dispose(); oclCQ = null; } if (oclContext != null) { oclContext.Dispose(); oclContext = null; } } public void Setup() { TestImage = (Bitmap)Bitmap.FromFile(@"Input0.png"); TestImage = new Bitmap(TestImage, 256, 256); TestImageOutput = new Bitmap(panelScaled.Width, panelScaled.Height, PixelFormat.Format32bppArgb); if (OpenCL.NumberOfPlatforms <= 0) { MessageBox.Show("OpenCL not available"); Application.Exit(); } PopulateOCLPlatformsComboBox(); oclPlatform = OpenCL.GetPlatform(0); comboBoxOpenCLPlatforms.SelectedIndex = 0; } public CL.Image CreateOCLBitmapFromBitmap(Bitmap bitmap) { CL.Image oclImage; BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); oclImage = oclContext.CreateImage2D((MemFlags)((long)MemFlags.READ_ONLY | (long)MemFlags.COPY_HOST_PTR), CL.ImageFormat.RGBA8U, bd.Width, bd.Height, bd.Stride, bd.Scan0); bitmap.UnlockBits(bd); return oclImage; } public unsafe void CopyOCLBitmapToBitmap(Mem oclBitmap, Bitmap bitmap) { IntPtr[] origin = new IntPtr[3]; IntPtr[] region = new IntPtr[3]; Mem buffer; BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); buffer = oclContext.CreateBuffer((MemFlags)((long)MemFlags.WRITE_ONLY | (long)MemFlags.USE_HOST_PTR), bd.Height * bd.Stride, bd.Scan0); origin[0] = (IntPtr)0; origin[1] = (IntPtr)0; origin[2] = (IntPtr)0; region[0] = (IntPtr)bd.Width; region[1] = (IntPtr)bd.Height; region[2] = (IntPtr)1; oclCQ.EnqueueCopyImageToBuffer(oclBitmap, buffer, origin, region, IntPtr.Zero); oclCQ.EnqueueBarrier(); IntPtr p = oclCQ.EnqueueMapBuffer(buffer, true, MapFlags.READ, IntPtr.Zero, (IntPtr)(bd.Height * bd.Stride)); oclCQ.EnqueueUnmapMemObject(buffer, p); oclCQ.Finish(); buffer.Dispose(); bitmap.UnlockBits(bd); } public void ScaleImage() { IntPtr[] globalWorkSize = new IntPtr[3]; globalWorkSize[0] = (IntPtr)TestImageOutput.Width; globalWorkSize[1] = (IntPtr)TestImageOutput.Height; FilterKernel.SetArg(0, 0.0f); FilterKernel.SetArg(1, 0.0f); FilterKernel.SetArg(2, 1.0f); FilterKernel.SetArg(3, 1.0f); FilterKernel.SetArg(4, 0.0f); FilterKernel.SetArg(5, 0.0f); FilterKernel.SetArg(6, 1.0f); FilterKernel.SetArg(7, 1.0f); FilterKernel.SetArg(8, OCLInputImage); FilterKernel.SetArg(9, OCLOutputImage); FilterKernel.SetArg(10, OCLSampler); oclCQ.EnqueueNDRangeKernel(FilterKernel, 2, null, globalWorkSize, null); oclCQ.EnqueueBarrier(); CopyOCLBitmapToBitmap(OCLOutputImage, TestImageOutput); oclCQ.Finish(); } private void Form1_Load(object sender, EventArgs e) { try { Setup(); } catch (OpenCLException ocle) { MessageBox.Show(ocle.Message); Application.Exit(); } } private void buttonScaleImage_Click(object sender, EventArgs e) { if (oclFullyInitialized) { ScaleImage(); } groupBoxScaled.Refresh(); } private void panelOriginal_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (TestImage != null) g.DrawImageUnscaled(TestImage, 0, 0); } private void panelScaled_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (oclFullyInitialized) { if (TestImageOutput != null) g.DrawImageUnscaled(TestImageOutput, 0, 0); } } private void comboBoxOpenCLDevices_SelectedIndexChanged(object sender, EventArgs e) { bool supportsImages; bool supportsImageFormat; try { ReleaseDeviceResources(); panelScaled.Refresh(); oclDevice = oclDevices[comboBoxOpenCLDevices.SelectedIndex]; CreateContext(oclPlatform, oclDevice); supportsImages = oclDevice.ImageSupport; supportsImageFormat = oclContext.SupportsImageFormat(MemFlags.READ_WRITE, MemObjectType.IMAGE2D, ChannelOrder.RGBA, ChannelType.UNSIGNED_INT8); if (oclDevice.ImageSupport && supportsImageFormat) { buttonScaleImage.Enabled = true; labelImageSupportIndicator.Text = "Yes"; OpenCLSource = File.ReadAllText(@"OpenCLFunctions.cl"); BuildOCLSource(OpenCLSource); CreateOCLImages(oclContext); oclFullyInitialized = true; } else { buttonScaleImage.Enabled = false; labelImageSupportIndicator.Text = "No " + (supportsImageFormat ? "(No Image support at all)" : "(Images supported, but no support for RGBA8888)"); oclContext = null; } } catch (OpenCLBuildException oclbe) { MessageBox.Show(this, oclbe.BuildLogs[0], "OpenCL build error"); } catch (OpenCLException ocle) { MessageBox.Show(this, ocle.Message, "OpenCL exception"); } } private void comboBoxOpenCLPlatforms_SelectedIndexChanged(object sender, EventArgs e) { try { ReleaseDeviceResources(); oclPlatform = OpenCL.GetPlatform(comboBoxOpenCLPlatforms.SelectedIndex); oclDevices = oclPlatform.QueryDevices(DeviceType.ALL); PopulateOCLDevicesComboBox(oclPlatform, DeviceType.ALL); if (comboBoxOpenCLDevices.Items.Count > 0) { comboBoxOpenCLDevices.SelectedIndex = 0; } else { oclDevice = null; } } catch (OpenCLException ocle) { MessageBox.Show(this, ocle.Message, "OpenCL exception"); } } } }