download: OpenCL.zip from: Nov 16, 2021
import lib's 32/64-bit and the OpenCL specs. are included.
Don't forget the "readme" ;-)
Joshy
Simple test:
The default OpenGL shader from shadertoy.com as OpenCL version:
Code: Select all
#include "cl.bi"
dim as string CODE
CODE &= !"kernel void shader (global uchar4 * pixels, uint width, uint height, float time) \n"
CODE &= !"{\n"
CODE &= !" uint ix = get_global_id(0); \n"
CODE &= !" uint iy = get_global_id(1); \n"
CODE &= !" uint i = ix+width*iy; \n"
CODE &= !" float x = ix/(float)width; \n"
CODE &= !" float y = iy/(float)height; \n"
CODE &= !" uchar r = (uchar)(x*255.f); \n"
CODE &= !" uchar g = (uchar)(y*255.f); \n"
CODE &= !" uchar b = (uchar)(255.f * (0.5f + 0.5f*sin(time))); \n"
CODE &= !" pixels[i] = (uchar4)(b,g,r,255); \n"
CODE &= !"}\n"
dim as zstring ptr pCode = strptr(CODE)
dim as cl_platform_id platform
' get first platform
dim as cl_int status = clGetPlatformIDs(1,@platform,NULL)
' get first device from platform try a GPU device at first
dim as cl_device_id device
status = clGetDeviceIDs(platform,CL_DEVICE_TYPE_GPU,1,@device,NULL)
if status = CL_INVALID_DEVICE_TYPE then
' fallback: try a CPU device also
status = clGetDeviceIDs(Platform,CL_DEVICE_TYPE_CPU,1,@device,NULL)
end if
if status then
print "error: can't create OpenCL device !"
flip : beep : sleep : end 1
end if
' create a device context
dim as cl_context context = clCreateContext(0,1,@device,NULL,NULL,@status)
' create program object in context from sourcecode
dim as cl_program program = clCreateProgramWithSource(context,1,@pCode,NULL,@status)
' compile and link the program
status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL)
if status then
print "error: can't create compile unand link kernel !"
dim as size_t nChars ' get size of log
clGetProgramBuildInfo(program,device,CL_PROGRAM_BUILD_LOG,0,0,@nChars)
dim as string strLog=space(nChars)
' get log from compiler/linker
clGetProgramBuildInfo(program,device,CL_PROGRAM_BUILD_LOG,nChars,strptr(strLog),NULL)
print strLog
flip : beep : sleep : end 1
end if
' create a kernel object
dim as cl_kernel kernel = clCreateKernel(program, "shader", @status)
' get size of workgroup from device
dim as size_t WorkGroupSize
status = clGetKernelWorkGroupInfo(kernel,device,CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t),@WorkGroupSize,NULL)
' calculate local worksize
'(must be workgroupsize div power of two)
dim as size_t LocalSize = WorkGroupSize
while LocalSize*LocalSize > WorkGroupSize
LocalSize shr=1
wend
dim as cl_int GlobalWidth=640,GlobalHeight = GlobalWidth/16*9
' calculate global worksize (should be a multiply of local worksize
GlobalWidth -=GlobalWidth mod LocalSize
GlobalHeight-=GlobalHeight mod LocalSize
screenres GlobalWidth,GlobalHeight,32,2
screenset 1,0
windowtitle "global: " & GlobalWidth & " x " & GlobalHeight & " local: " & LocalSize & " x " & LocalSize & " worksize"
dim as any ptr pixels,img=imagecreate(GlobalWidth,GlobalHeight)
imageinfo img,,,,,pixels
dim as size_t bufSize = GlobalWidth*GlobalHeight*4
dim as size_t globalSizes(...) => {GlobalWidth,GlobalHeight}
dim as size_t localSizes (...) => {LocalSize ,LocalSize}
' create a memory buffer in the context
dim as cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, bufSize, NULL, @status)
' set the parameters of the kernel
status = clSetKernelArg(kernel, 0, sizeof(cl_mem ),@buffer)
status = clSetKernelArg(kernel, 1, sizeof(cl_uint),@GlobalWidth)
status = clSetKernelArg(kernel, 2, sizeof(cl_uint),@GlobalHeight)
' create command queue
dim as cl_command_queue queue = clCreateCommandQueue(context,device,0,@status)
if status then
print "error: can't create a command queue !"
flip : beep : sleep : end 1
end if
dim as integer frames,fps
dim as double tStart=timer
dim as double tLast =tStart
while inkey()=""
dim as single runtime = timer()-tStart
' set the time parameter
status = clSetKernelArg(kernel, 3, sizeof(cl_float),@runtime)
' execute the "2D" kernel
status = clEnqueueNDRangeKernel(queue,kernel,2, NULL, @globalSizes(0), @localSizes(0),0,NULL,NULL)
' read/copy the device buffer in the image buffer
status = clEnqueueReadBuffer (queue,buffer,CL_TRUE,0,bufSize,pixels,0,NULL,NULL)
' draw the runtime and fps in the image
draw string img,(0,0),"fps: " & fps & " time: " & runtime
' put it on the screen
put (0,0),img,PSET
' make hiden page visible
flip
' count the frames
frames+=1
' update every 60 frame the fps
if frames mod 60=0 then
var tNow=timer()
fps=60/(tNow-tLast)
tLast=tNow
end if
wend
' free all resources
clReleaseCommandQueue queue
clReleaseProgram program
clReleaseMemObject buffer
clReleaseContext context