Platforms to show: All Mac Windows Linux Cross-Platform

/MacFrameworks/OpenCL/OpenCL Helper 18/OpenCL Helper 18


Required plugins for this example: MBS MacFrameworks Plugin, MBS Picture Plugin

You find this example project in your Plugins Download as a Xojo project file within the examples folder: /MacFrameworks/OpenCL/OpenCL Helper 18/OpenCL Helper 18

This example is the version from Mon, 5th May 2019.

Project "OpenCL Helper 18.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
MenuBar MenuBar1
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem UntitledMenu1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem UntitledMenu0 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class Window1 Inherits Window
Control PushButton1 Inherits PushButton
ControlInstance PushButton1 Inherits PushButton
EventHandler Sub Action() dim f as FolderItem = new FolderItem("Data") dim ocl as OpenCL = new OpenCL const RGBbytes = 3 // Input, use Picture.Open in newer REAL Studio versions dim p1 as Picture = Picture.Open(f.Child("A.png")) dim p2 as Picture = Picture.Open(f.Child("B.png")) dim m1 as MemoryBlock = new MemoryBlock(p1.Width * p1.Height * RGBbytes) call p1.CopyRGBtoMemoryblockMBS(m1, 0) dim m2 as MemoryBlock = new MemoryBlock(p2.Width * p2.Height * RGBbytes) call p2.CopyRGBtoMemoryblockMBS(m2, 0) ocl.AppendInputMemoryBlock(m1) ocl.AppendInputMemoryBlock(m2) // // Output ocl.SetOutputMemorySize(p1.Width * p1.Height * RGBbytes) // // Program template TextArea1.Text = ocl.OpenCLProgramTemplate // Copy this string and use it as a template for writing your OpenCL program in a text editor // Program f = new FolderItem("Programs") f = f.Child("Blend.cl") 'dim tis as TextInputStream = TextInputStream.Open(f) dim tis as TextInputStream = f.OpenAsTextFile ocl.Source = tis.ReadAll TextArea2.Text = ocl.Source // // Run ocl.Run // Results dim p as Picture = MemoryblockRGBtoPictureMBS(ocl.OutputMemoryBlock, 0, p1.Width, p2.Width) pic1 = p Canvas1.Invalidate End EventHandler
End Control
Control Canvas1 Inherits Canvas
ControlInstance Canvas1 Inherits Canvas
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect) if pic1 <> nil then g.DrawPicture pic1, 0, 0 end if End EventHandler
End Control
Control PushButton2 Inherits PushButton
ControlInstance PushButton2 Inherits PushButton
EventHandler Sub Action() dim f as FolderItem = new FolderItem("Data") dim ocl as OpenCL = new OpenCL const kOutputHeightWidth = 256 const RGBbytes = 3 // Input dim p1 as Picture = f.Child("pattern_154.png").OpenAsPicture 'dim p1 as Picture = Picture.Open(f.Child("pattern_154.png")) // http://www.squidfingers.com/patterns/ dim m1 as MemoryBlock = new MemoryBlock(p1.Width * p1.Height * RGBbytes) call p1.CopyRGBtoMemoryblockMBS(m1, 0) ocl.AppendInputMemoryBlock(m1, "tile") ocl.AppendInputInt32(p1.Width * RGBbytes, "tileWidth") ocl.AppendInputInt32(p1.Height, "tileHeight") ocl.AppendInputInt32(kOutputHeightWidth * RGBbytes, "outputWidth") // // Output ocl.SetOutputMemorySize(kOutputHeightWidth * kOutputHeightWidth * RGBbytes) // // Program template TextArea1.Text = ocl.OpenCLProgramTemplate // Copy this string and use it as a template for writing your OpenCL program in a text editor // Program f = new FolderItem("Programs") f = f.Child("Tile.cl") dim tis as TextInputStream = f.OpenAsTextFile 'dim tis as TextInputStream = TextInputStream.Open(f) ocl.Source = tis.ReadAll TextArea2.Text = ocl.Source // // Run ocl.Run // Results dim p as Picture = MemoryblockRGBtoPictureMBS(ocl.OutputMemoryBlock, 0, kOutputHeightWidth, kOutputHeightWidth) 'Canvas2.Graphics.DrawPicture(p, 0, 0) pic2 = p canvas2.Invalidate End EventHandler
End Control
Control Canvas2 Inherits Canvas
ControlInstance Canvas2 Inherits Canvas
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect) if pic2 <> nil then g.DrawPicture pic2, 0, 0 end if End EventHandler
End Control
Control TextArea1 Inherits TextArea
ControlInstance TextArea1 Inherits TextArea
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control TextArea2 Inherits TextArea
ControlInstance TextArea2 Inherits TextArea
End Control
Control Label2 Inherits Label
ControlInstance Label2 Inherits Label
End Control
Control Canvas3 Inherits Canvas
ControlInstance Canvas3 Inherits Canvas
End Control
Property Pic1 As Picture
Property Pic2 As Picture
End Class
Class OpenCL
ComputedProperty OpenCLProgramTemplate As String
Sub Get() // Copy the returned string and use it as a template for writing your OpenCL program in a text editor dim s as String dim i as Integer s = "// See a quick reference for OpenCL language here: http://www.khronos.org/files/opencl-quick-reference-card.pdf" + EndOfLine + EndOfLine // Function signature s = s + "__kernel " + kDefaultKernelName + "(" for i = 0 to me.Input.Ubound s = s + me.Input(i).GetParameterDeclaration + "," next s = s + me.Output.GetParameterDeclaration + " ) {" + EndOfLine // // Function block s = s + " int i = get_global_id(0);" + EndOfLine s = s + " if (i < outputCount) {" + EndOfLine s = s + " output[i] = 0; // Do something interesting here!" + EndOfLine s = s + " }" + EndOfLine // // End s = s + "}" + EndOfLine Return s End Get
End ComputedProperty
ComputedProperty OutputMemoryBlock As MemoryBlock
Sub Get() if me.Output = nil then Return nil Return me.Output.Data End Get
End ComputedProperty
Const kDefaultKernelName = "square"
Sub AppendInputInt32(value as Int32, parameterName as String = "") dim o as OpenCLDataInt32 = new OpenCLDataInt32(value) me.Input.Append(o) if parameterName <> "" then o.ParameterName = parameterName else // Assign a default name o.ParameterName = "input" + Str(me.Input.Ubound + 1) end End Sub
Sub AppendInputMemoryBlock(mb as MemoryBlock, parameterName as String = "") dim o as OpenCLDataMemoryBlock = new OpenCLDataMemoryBlock(mb, mb.Size) me.Input.Append(o) if parameterName <> "" then o.ParameterName = parameterName else // Assign a default name o.ParameterName = "input" + Str(me.Input.Ubound + 1) end End Sub
Sub Run() dim i as Integer dim devices(-1) as CLDeviceMBS = OpenCLMBS.AllDevices(CLDeviceMBS.kDeviceTypeGPU) if devices.Ubound = -1 then Return dim device as CLDeviceMBS = devices(0) // we use first one dim context as new CLContextMBS(device, CLContextMBS.kErrorModeLogMessagesToSystemLog) dim queue as new CLCommandQueueMBS(context, device, 0) dim program as new CLProgramMBS(context, me.Source) program.BuildProgram if program.LastError <> 0 then MsgBox "Error: Failed to build program executable" + EndOfLine + EndOfLine + Program.BuildLog(device) Return end if // Create the compute kernel in the program we wish to run dim kernel as new clKernelMBS(program, kDefaultKernelName) // Create the input and output arrays in device memory for our calculation 'dim inputCL(-1) as CLMemMBS for i = 0 to me.Input.Ubound me.Input(i).CreateCLMemory(context, CLMEMMBS.kMemoryReadOnly) next me.Output.CreateCLMemory(context, CLMEMMBS.kMemoryWriteOnly) // // Write our data set into the input array in device memory for i = 0 to me.Input.Ubound me.Input(i).WriteCLMemory(queue) next // Set the arguments to our compute kernel dim ii as Integer = 0 for i = 0 to me.Input.Ubound ii = ii + me.Input(i).SetKernelArguments(kernel, ii) next ii = ii + me.Output.SetKernelArguments(kernel, ii) // Get the maximum work-group size for executing the kernel on the device dim maxWorkGroupCount as integer = kernel.GetKernelWorkGroupSize(Device) // Execute the kernel over the entire range of the data set queue.EnqueueNDRangeKernel(kernel, me.Output.DataCount, maxWorkGroupCount) // Wait for the command queue to get serviced before reading back results queue.finish // Read the results from the device queue.EnqueueReadBuffer(me.Output.DataCL, 0, me.Output.Data.Size, me.Output.Data) // Clean up for i = 0 to me.Input.Ubound me.Input(i).ClearCLMemory next me.Output.ClearCLMemory // End Sub
Sub SetOutputMemory(mb as MemoryBlock) me.Output = new OpenCLDataMemoryBlock(mb, mb.Size) me.Output.ParameterName = "output" End Sub
Sub SetOutputMemorySize(size as Integer) dim mb as MemoryBlock = new MemoryBlock(size) me.SetOutputMemory(mb) End Sub
Property Private Input() As OpenCLData
Property Private Output As OpenCLDataMemoryBlock
Property Source As String
End Class
Class OpenCLData
Sub ClearCLMemory() End Sub
Sub CreateCLMemory(context as CLContextMBS, flags as UInt64) End Sub
Function GetParameterDeclaration() As String End Function
Function SetKernelArguments(kernel as clKernelMBS, argumentOffset as Integer) As Integer End Function
Sub WriteCLMemory(queue as CLCommandQueueMBS) End Sub
Property ParameterName As String
End Class
Class OpenCLDataMemoryBlock Inherits OpenCLData
Sub ClearCLMemory() me.DataCL = nil End Sub
Sub Constructor(theData as MemoryBlock, theDataCount as Integer) me.Data = theData me.DataCount = theDataCount // Number of items in the memory block (i.e., number of bytes, number of ints, number of floats, etc. Not the same as MemoryBlock.Size if data is anything other than bytes.) End Sub
Sub CreateCLMemory(context as CLContextMBS, flags as UInt64) me.DataCL = new CLMemMBS(context, flags, me.Data.Size) End Sub
Function GetParameterDeclaration() As String Return " __global uchar* " + me.ParameterName + ", const unsigned int " + me.ParameterName + "Count" End Function
Function SetKernelArguments(kernel as clKernelMBS, argumentOffset as Integer) As Integer kernel.SetKernelArgMem(argumentOffset, me.DataCL) // Input data buffer kernel.SetKernelArgInt32(argumentOffset + 1, me.DataCount) // Number of data items in buffer Return 2 End Function
Sub WriteCLMemory(queue as CLCommandQueueMBS) queue.EnqueueWriteBuffer(me.DataCL, 0, me.Data.Size, me.Data) End Sub
Property Data As MemoryBlock
Property DataCL As CLMemMBS
Property DataCount As Integer
End Class
Class OpenCLDataInt32 Inherits OpenCLData
Sub Constructor(v as Int32) me.Value = v End Sub
Function GetParameterDeclaration() As String Return " const unsigned int " + me.ParameterName End Function
Function SetKernelArguments(kernel as clKernelMBS, argumentOffset as Integer) As Integer kernel.SetKernelArgInt32(argumentOffset, me.Value) Return 1 End Function
Property Value As Integer
End Class
End Project

See also:

The items on this page are in the following plugins: MBS MacFrameworks Plugin.


The biggest plugin in space...