View Full Version : Chapter 3, example 1: Buffers and subbuffers

Petr Schreiber
11-11-2012, 20:27
After a longer pause, new example based on the mighty book by Mr. Scarpino.

The chapter 3 explains concept of buffers and subbuffers. These names cover memory objects, which are passed to computing kernel as input or output structures.
In ThinBASIC programming, you would pass a parameter to function. In OpenCL, as the code runs on other device, you pass pointer to buffer or sub-buffer.

Buffers are blocks of memory, supported since OpenCL 1.0.
SubBuffers are smaller blocks of memory, mapped inside buffers, supported since OpenCL 1.1.

This caused me a bit of headache, because my GPU does not have OpenCL 1.1 support. But my CPU does. That made the original sample stop, because it checked only 1 platform, like this:

/* Identify a platform */
clGetPlatformIDs(1, platform, byVal Null)

If this platform was OpenCL 1.0, the example crashed later, making me desperate, howling on the Moon... you know it.

But there is a way out of the valley of crying programmers - by modifying the proposed create_device routine to something with more power:

going through all platforms, all devices
checking for OpenCL 1.1 support on device, not platform level
in case no device found, it halts early, not later in code

This results in the birth of monster, but... it will work on more PCs:

/* Find a GPU or CPU associated with the available platforms */
Function create_device(minMajorVersion As Long, minMinorVersion As Long, Optional sReason As String) As tcl_device_id

tcl_platform_id platforms()
tcl_platform_id platform
tcl_uint num_platforms

tcl_device_id dev
tcl_int ErrCl

/* Find number of platforms */
ErrCL = clGetPlatformIDs(1, ByVal NULL, num_platforms)
If (ErrCL < 0) Then
pError("Couldn't find any platforms.")
APP_SetReturnCode(1) : WaitKey : Exit Function
End If

/* Access all installed platforms */
ReDim platforms(num_platforms)
clGetPlatformIDs(num_platforms, platforms, ByVal NULL)

Long p
Long majorVersion
Long minorVersion
Dim versionCL As Asciiz * 512

For p = 1 To num_platforms
platform = platforms(p)

/* Access a device */
ErrCl = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, dev, ByVal NULL)
ErrCl = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, dev, ByVal NULL)
End If

If (ErrCl < 0) Then
perror("Couldn't access any devices")
APP_SetReturnCode(1) : WaitKey : Exit Function
End If

/* Testing for version */
CL_DEVICE_VERSION, SizeOf(versionCL), ByVal VarPtr(versionCL), ByVal NULL)

versionCL = Parse$(versionCL, " ", 2)

majorVersion = Parse$(versionCL, ".", 1)
minorVersion = Parse$(versionCL, ".", 2)

If majorVersion*1000 + minorVersion*100 >= minMajorVersion*1000 + minMinorVersion*100 Then
Return dev
End If

/* No device/platform found */
perror("No device with OpenCL v"+minMajorVersion+"."+minMinorVersion+" found" + IIf$(StrPtr(sReason), $CRLF+sReason, ""))
APP_SetReturnCode(1) : WaitKey : Stop

Return dev

End Function

The example is a typical learning one - nothing complex, but solid test of creating buffers and subbuffers inside of them, no computation is performed but pointers to memory are reported instead.

You will need the latest ThinBASIC and OpenCL headers (http://www.thinbasic.com/community/showthread.php?10159-OpenCL-Headers-Updated-Sep-15-2011) to run it + of course modern GPU or CPU (http://www.thinbasic.com/community/showthread.php?10161-OpenCL-Supported-hardware).