OSDN Git Service

merge from MikuMikuStudio nativebullet.
[mikumikustudio/libgdx-mikumikustudio.git] / extensions / gdx-bullet / jni / src / bullet / MiniCL / MiniCL.cpp
1 /*
2    Copyright (C) 2010 Sony Computer Entertainment Inc.
3    All rights reserved.
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose, 
8 including commercial applications, and to alter it and redistribute it freely, 
9 subject to the following restrictions:
10
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14
15 */
16
17
18 #include "MiniCL/cl.h"
19 #define __PHYSICS_COMMON_H__ 1
20 #ifdef _WIN32
21 #include "BulletMultiThreaded/Win32ThreadSupport.h"
22 #endif
23
24 #include "BulletMultiThreaded/PlatformDefinitions.h"
25 #ifdef USE_PTHREADS
26 #include "BulletMultiThreaded/PosixThreadSupport.h"
27 #endif
28
29
30 #include "BulletMultiThreaded/SequentialThreadSupport.h"
31 #include "MiniCLTaskScheduler.h"
32 #include "MiniCLTask/MiniCLTask.h"
33 #include "LinearMath/btMinMax.h"
34 #include <stdio.h>
35 #include <stddef.h>
36
37 //#define DEBUG_MINICL_KERNELS 1
38
39 static const char* spPlatformID = "MiniCL, SCEA";
40 static const char* spDriverVersion= "1.0";
41
42 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs(
43         cl_uint           num_entries,
44     cl_platform_id *  platforms,
45     cl_uint *         num_platforms ) CL_API_SUFFIX__VERSION_1_0
46 {
47         if(platforms != NULL)
48         {
49                 if(num_entries <= 0)
50                 {
51                         return CL_INVALID_VALUE; 
52                 }
53                 *((const char**)platforms) = spPlatformID;
54         }
55         if(num_platforms != NULL)
56         {
57                 *num_platforms = 1;
58         }
59         return CL_SUCCESS;
60 }
61
62
63 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
64         cl_platform_id   platform, 
65         cl_platform_info param_name,
66         size_t           param_value_size, 
67         void *           param_value,
68         size_t *         param_value_size_ret) CL_API_SUFFIX__VERSION_1_0
69 {
70         char* pId = (char*)platform;
71         if(strcmp(pId, spPlatformID))
72         {
73                         return CL_INVALID_PLATFORM; 
74         }
75         switch(param_name)
76         {
77         case CL_PLATFORM_VERSION:
78                 {
79                         if(param_value_size < (strlen(spDriverVersion) + 1))
80                         {
81                                 return CL_INVALID_VALUE; 
82                         }
83                         strcpy((char*)param_value, spDriverVersion);
84                         if(param_value_size_ret != NULL)
85                         {
86                                 *param_value_size_ret = strlen(spDriverVersion) + 1;
87                         }
88                         break;
89                 }
90                 case CL_PLATFORM_NAME:
91                 case CL_PLATFORM_VENDOR :
92                         if(param_value_size < (strlen(spPlatformID) + 1))
93                         {
94                                 return CL_INVALID_VALUE; 
95                         }
96                         strcpy((char*)param_value, spPlatformID);
97                         if(param_value_size_ret != NULL)
98                         {
99                                 *param_value_size_ret = strlen(spPlatformID) + 1;
100                         }
101                         break;
102                 default : 
103                         return CL_INVALID_VALUE; 
104         }
105         return CL_SUCCESS;
106 }
107
108
109
110
111 CL_API_ENTRY cl_int CL_API_CALL clGetDeviceInfo(
112         cl_device_id            device ,
113         cl_device_info          param_name ,
114         size_t                  param_value_size ,
115         void *                  param_value ,
116         size_t *                param_value_size_ret) CL_API_SUFFIX__VERSION_1_0
117 {
118
119         switch (param_name)
120         {
121         case CL_DEVICE_NAME:
122                 {
123                         char deviceName[] = "MiniCL CPU";
124                         unsigned int nameLen = (unsigned int)strlen(deviceName)+1;
125                         btAssert(param_value_size>strlen(deviceName));
126                         if (nameLen < param_value_size)
127                         {
128                                 const char* cpuName = "MiniCL CPU";
129                                 sprintf((char*)param_value,"%s",cpuName);
130                         } else
131                         {
132                                 printf("error: param_value_size should be at least %d, but it is %zu\n",nameLen,param_value_size);
133                                 return CL_INVALID_VALUE; 
134                         }
135                         break;
136                 }
137         case CL_DEVICE_TYPE:
138                 {
139                         if (param_value_size>=sizeof(cl_device_type))
140                         {
141                                 cl_device_type* deviceType = (cl_device_type*)param_value;
142                                 *deviceType = CL_DEVICE_TYPE_CPU;
143                         } else
144                         {
145                                 printf("error: param_value_size should be at least %zu\n",sizeof(cl_device_type));
146                                 return CL_INVALID_VALUE; 
147                         }
148                         break;
149                 }
150         case CL_DEVICE_MAX_COMPUTE_UNITS:
151                 {
152                         if (param_value_size>=sizeof(cl_uint))
153                         {
154                                 cl_uint* numUnits = (cl_uint*)param_value;
155                                 *numUnits= 4;
156                         } else
157                         {
158                                 printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint));
159                                 return CL_INVALID_VALUE; 
160                         }
161
162                         break;
163                 }
164         case CL_DEVICE_MAX_WORK_ITEM_SIZES:
165                 {
166                         size_t workitem_size[3];
167
168                         if (param_value_size>=sizeof(workitem_size))
169                         {
170                                 size_t* workItemSize = (size_t*)param_value;
171                                 workItemSize[0] = 64;
172                                 workItemSize[1] = 24;
173                                 workItemSize[2] = 16;
174                         } else
175                         {
176                                 printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint));
177                                 return CL_INVALID_VALUE; 
178                         }
179                         break;
180                 }
181         case CL_DEVICE_MAX_CLOCK_FREQUENCY:
182                 {
183                          cl_uint* clock_frequency = (cl_uint*)param_value;
184                          *clock_frequency = 3*1024;
185                         break;
186                 }
187
188         case CL_DEVICE_VENDOR   :
189                 {
190                         if(param_value_size < (strlen(spPlatformID) + 1))
191                         {
192                                 return CL_INVALID_VALUE; 
193                         }
194                         strcpy((char*)param_value, spPlatformID);
195                         if(param_value_size_ret != NULL)
196                         {
197                                 *param_value_size_ret = strlen(spPlatformID) + 1;
198                         }
199                         break;
200                 }
201         case CL_DRIVER_VERSION:
202                 {
203                         if(param_value_size < (strlen(spDriverVersion) + 1))
204                         {
205                                 return CL_INVALID_VALUE; 
206                         }
207                         strcpy((char*)param_value, spDriverVersion);
208                         if(param_value_size_ret != NULL)
209                         {
210                                 *param_value_size_ret = strlen(spDriverVersion) + 1;
211                         }
212
213                         break;
214                 }
215         case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
216                 {
217                          cl_uint* maxDimensions = (cl_uint*)param_value;
218                          *maxDimensions = 1;
219                          break;
220                 }
221                 case CL_DEVICE_MAX_WORK_GROUP_SIZE:
222                 {
223                          cl_uint* maxWorkGroupSize = (cl_uint*)param_value;
224                          *maxWorkGroupSize = 128;//1;
225                          break;
226                 }
227                 case CL_DEVICE_ADDRESS_BITS:
228                 {
229                          cl_uint* addressBits = (cl_uint*)param_value;
230                          *addressBits= 32; //@todo: should this be 64 for 64bit builds?
231                          break;
232                 }
233                 case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
234                         {
235                                 cl_ulong* maxMemAlloc = (cl_ulong*)param_value;
236                                 *maxMemAlloc= 512*1024*1024; //this "should be enough for everyone" ?
237                          break;
238                         }
239                 case CL_DEVICE_GLOBAL_MEM_SIZE:
240                         {
241                                 cl_ulong* maxMemAlloc = (cl_ulong*)param_value;
242                                 *maxMemAlloc= 1024*1024*1024; //this "should be enough for everyone" ?
243                          break;
244                         }
245
246                 case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
247                         {
248                         cl_bool* error_correction_support = (cl_bool*)param_value;
249                         *error_correction_support = CL_FALSE;
250                         break;
251                         }
252
253                 case CL_DEVICE_LOCAL_MEM_TYPE:
254                         {
255                         cl_device_local_mem_type* local_mem_type = (cl_device_local_mem_type*)param_value;
256                         *local_mem_type = CL_GLOBAL;
257                         break;
258                         }
259                 case CL_DEVICE_LOCAL_MEM_SIZE:
260                         {
261                                 cl_ulong* localmem = (cl_ulong*) param_value;
262                                 *localmem = 32*1024;
263                                 break;
264                         }
265
266                 case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
267                         {
268                                 cl_ulong* localmem = (cl_ulong*) param_value;
269                                 *localmem = 64*1024;
270                                 break;
271                         }
272                 case CL_DEVICE_QUEUE_PROPERTIES:
273                         {
274                                 cl_command_queue_properties* queueProp = (cl_command_queue_properties*) param_value;
275                                 memset(queueProp,0,param_value_size);
276
277                                 break;
278                         }
279                 case CL_DEVICE_IMAGE_SUPPORT:
280                         {
281                                 cl_bool* imageSupport = (cl_bool*) param_value;
282                                 *imageSupport = CL_FALSE;
283                                 break;
284                         }
285
286                 case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
287                 case CL_DEVICE_MAX_READ_IMAGE_ARGS:
288                         {
289                                 cl_uint* imageArgs = (cl_uint*) param_value;
290                                 *imageArgs = 0;
291                                 break;
292                         }
293                 case CL_DEVICE_IMAGE3D_MAX_DEPTH:
294                 case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
295                 case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
296                 case CL_DEVICE_IMAGE3D_MAX_WIDTH:
297                 case CL_DEVICE_IMAGE2D_MAX_WIDTH:
298                         {
299                                 size_t* maxSize = (size_t*) param_value;
300                                 *maxSize = 0;
301                                 break;
302                         }
303
304                 case CL_DEVICE_EXTENSIONS:
305                         {
306                                 char* extensions = (char*) param_value;
307                                 *extensions = 0;
308                                 break;
309                         }
310
311                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
312                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
313                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
314                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
315                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
316                 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
317                         {
318                                 cl_uint* width  = (cl_uint*) param_value;
319                                 *width = 1;
320                                 break;
321                         }
322                         
323         default:
324                 {
325                         printf("error: unsupported param_name:%d\n",param_name);
326                 }
327         }
328
329
330         return 0;
331 }
332
333 CL_API_ENTRY cl_int CL_API_CALL clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0
334 {
335         return 0;
336 }
337
338
339
340 CL_API_ENTRY cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0
341 {
342         return 0;
343 }
344
345 CL_API_ENTRY cl_int CL_API_CALL clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0
346 {
347         return 0;
348 }
349
350 CL_API_ENTRY cl_int CL_API_CALL clReleaseKernel(cl_kernel   /* kernel */) CL_API_SUFFIX__VERSION_1_0
351 {
352         return 0;
353 }
354
355
356 // Enqueued Commands APIs
357 CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue     command_queue ,
358                     cl_mem               buffer ,
359                     cl_bool             /* blocking_read */,
360                     size_t               offset ,
361                     size_t               cb , 
362                     void *               ptr ,
363                     cl_uint             /* num_events_in_wait_list */,
364                     const cl_event *    /* event_wait_list */,
365                     cl_event *          /* event */) CL_API_SUFFIX__VERSION_1_0
366 {
367         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
368
369         ///wait for all work items to be completed
370         scheduler->flush();
371
372         memcpy(ptr,(char*)buffer + offset,cb);
373         return 0;
374 }
375
376
377 CL_API_ENTRY cl_int clGetProgramBuildInfo(cl_program            /* program */,
378                       cl_device_id          /* device */,
379                       cl_program_build_info /* param_name */,
380                       size_t                /* param_value_size */,
381                       void *                /* param_value */,
382                       size_t *              /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
383 {
384
385         return 0;
386 }
387
388
389 // Program Object APIs
390 CL_API_ENTRY cl_program
391 clCreateProgramWithSource(cl_context         context ,
392                           cl_uint           /* count */,
393                           const char **     /* strings */,
394                           const size_t *    /* lengths */,
395                           cl_int *          errcode_ret ) CL_API_SUFFIX__VERSION_1_0
396 {
397         *errcode_ret = CL_SUCCESS;
398         return (cl_program)context;
399 }
400
401 CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue     command_queue ,
402                     cl_mem               buffer ,
403                     cl_bool             /* blocking_read */,
404                     size_t              offset,
405                     size_t               cb , 
406                     const void *         ptr ,
407                     cl_uint             /* num_events_in_wait_list */,
408                     const cl_event *    /* event_wait_list */,
409                     cl_event *          /* event */) CL_API_SUFFIX__VERSION_1_0
410 {
411         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
412
413         ///wait for all work items to be completed
414         scheduler->flush();
415
416         memcpy((char*)buffer + offset, ptr,cb);
417         return 0;
418 }
419
420 CL_API_ENTRY cl_int CL_API_CALL clFlush(cl_command_queue  command_queue)
421 {
422         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
423         ///wait for all work items to be completed
424         scheduler->flush();
425         return 0;
426 }
427
428
429 CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */,
430                        cl_kernel         clKernel ,
431                        cl_uint           work_dim ,
432                        const size_t *   /* global_work_offset */,
433                        const size_t *    global_work_size ,
434                        const size_t *   /* local_work_size */,
435                        cl_uint          /* num_events_in_wait_list */,
436                        const cl_event * /* event_wait_list */,
437                        cl_event *       /* event */) CL_API_SUFFIX__VERSION_1_0
438 {
439
440         
441         MiniCLKernel* kernel = (MiniCLKernel*) clKernel;
442         for (unsigned int ii=0;ii<work_dim;ii++)
443         {
444                 int maxTask = kernel->m_scheduler->getMaxNumOutstandingTasks();
445                 int numWorkItems = global_work_size[ii];
446
447 //              //at minimum 64 work items per task
448 //              int numWorkItemsPerTask = btMax(64,numWorkItems / maxTask);
449                 int numWorkItemsPerTask = numWorkItems / maxTask;
450                 if (!numWorkItemsPerTask) numWorkItemsPerTask = 1;
451
452                 for (int t=0;t<numWorkItems;)
453                 {
454                         //Performance Hint: tweak this number during benchmarking
455                         int endIndex = (t+numWorkItemsPerTask) < numWorkItems ? t+numWorkItemsPerTask : numWorkItems;
456                         kernel->m_scheduler->issueTask(t, endIndex, kernel);
457                         t = endIndex;
458                 }
459         }
460 /*
461
462         void* bla = 0;
463
464         scheduler->issueTask(bla,2,3);
465         scheduler->flush();
466
467         */
468
469         return 0;
470 }
471
472 #define LOCAL_BUF_SIZE 32768
473 static int sLocalMemBuf[LOCAL_BUF_SIZE * 4 + 16];
474 static int* spLocalBufCurr = NULL;
475 static int sLocalBufUsed = LOCAL_BUF_SIZE; // so it will be reset at the first call
476 static void* localBufMalloc(int size)
477 {
478         int size16 = (size + 15) >> 4; // in 16-byte units
479         if((sLocalBufUsed + size16) > LOCAL_BUF_SIZE)
480         { // reset
481                 spLocalBufCurr = sLocalMemBuf;
482                 while((size_t)spLocalBufCurr & 0x0F) spLocalBufCurr++; // align to 16 bytes
483                 sLocalBufUsed = 0;
484         }
485         void* ret = spLocalBufCurr;
486         spLocalBufCurr += size16 * 4;
487         sLocalBufUsed += size;
488         return ret;
489 }
490
491
492
493 CL_API_ENTRY cl_int CL_API_CALL clSetKernelArg(cl_kernel    clKernel ,
494                cl_uint      arg_index ,
495                size_t       arg_size ,
496                const void *  arg_value ) CL_API_SUFFIX__VERSION_1_0
497 {
498         MiniCLKernel* kernel = (MiniCLKernel* ) clKernel;
499         btAssert(arg_size <= MINICL_MAX_ARGLENGTH);
500         if (arg_index>MINI_CL_MAX_ARG)
501         {
502                 printf("error: clSetKernelArg arg_index (%u) exceeds %u\n",arg_index,MINI_CL_MAX_ARG);
503         } else
504         {
505                 if (arg_size>MINICL_MAX_ARGLENGTH)
506                 //if (arg_size != MINICL_MAX_ARGLENGTH)
507                 {
508                         printf("error: clSetKernelArg argdata too large: %zu (maximum is %zu)\n",arg_size,MINICL_MAX_ARGLENGTH);
509                 } 
510                 else
511                 {
512                         if(arg_value == NULL)
513                         {       // this is only for __local memory qualifier
514                                 void* ptr = localBufMalloc(arg_size);
515                                 kernel->m_argData[arg_index] = ptr;
516                         }
517                         else
518                         {
519                                 memcpy(&(kernel->m_argData[arg_index]), arg_value, arg_size);
520                         }
521                         kernel->m_argSizes[arg_index] = arg_size;
522                         if(arg_index >= kernel->m_numArgs)
523                         {
524                                 kernel->m_numArgs = arg_index + 1;
525                                 kernel->updateLauncher();
526                         }
527                 }
528         }
529         return 0;
530 }
531
532 // Kernel Object APIs
533 CL_API_ENTRY cl_kernel CL_API_CALL clCreateKernel(cl_program       program ,
534                const char *     kernel_name ,
535                cl_int *         errcode_ret ) CL_API_SUFFIX__VERSION_1_0
536 {
537         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) program;
538         int nameLen = strlen(kernel_name);
539         if(nameLen >= MINI_CL_MAX_KERNEL_NAME)
540         {
541                 *errcode_ret = CL_INVALID_KERNEL_NAME;
542                 return NULL;
543         }
544
545         MiniCLKernel* kernel = new MiniCLKernel();
546
547         strcpy(kernel->m_name, kernel_name);
548         kernel->m_numArgs = 0;
549
550         //kernel->m_kernelProgramCommandId = scheduler->findProgramCommandIdByName(kernel_name);
551         //if (kernel->m_kernelProgramCommandId>=0)
552         //{
553         //      *errcode_ret = CL_SUCCESS;
554         //} else
555         //{
556         //      *errcode_ret = CL_INVALID_KERNEL_NAME;
557         //}
558         kernel->m_scheduler = scheduler;
559         if(kernel->registerSelf() == NULL)
560         {
561                 *errcode_ret = CL_INVALID_KERNEL_NAME;
562                 delete kernel;
563                 return NULL;
564         }
565         else
566         {
567                 *errcode_ret = CL_SUCCESS;
568         }
569
570         return (cl_kernel)kernel;
571
572 }
573
574
575 CL_API_ENTRY cl_int CL_API_CALL clBuildProgram(cl_program           /* program */,
576                cl_uint              /* num_devices */,
577                const cl_device_id * /* device_list */,
578                const char *         /* options */, 
579                void (*pfn_notify)(cl_program /* program */, void * /* user_data */),
580                void *               /* user_data */) CL_API_SUFFIX__VERSION_1_0
581 {
582         return CL_SUCCESS;
583 }
584
585 CL_API_ENTRY cl_program CL_API_CALL clCreateProgramWithBinary(cl_context                     context ,
586                           cl_uint                        /* num_devices */,
587                           const cl_device_id *           /* device_list */,
588                           const size_t *                 /* lengths */,
589                           const unsigned char **         /* binaries */,
590                           cl_int *                       /* binary_status */,
591                           cl_int *                       /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0
592 {
593         return (cl_program)context;
594 }
595
596
597 // Memory Object APIs
598 CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context   /* context */,
599                cl_mem_flags flags ,
600                size_t       size,
601                void *       host_ptr ,
602                cl_int *     errcode_ret ) CL_API_SUFFIX__VERSION_1_0
603 {
604         cl_mem buf = (cl_mem)malloc(size);
605         if ((flags&CL_MEM_COPY_HOST_PTR) && host_ptr)
606         {
607                 memcpy(buf,host_ptr,size);
608         }
609         *errcode_ret = 0;
610         return buf;
611 }
612
613 // Command Queue APIs
614 CL_API_ENTRY cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context                      context , 
615                      cl_device_id                   /* device */, 
616                      cl_command_queue_properties    /* properties */,
617                      cl_int *                        errcode_ret ) CL_API_SUFFIX__VERSION_1_0
618 {
619         *errcode_ret = 0;
620         return (cl_command_queue) context;
621 }
622
623 extern CL_API_ENTRY cl_int CL_API_CALL clGetContextInfo(cl_context         /* context */, 
624                  cl_context_info    param_name , 
625                  size_t             param_value_size , 
626                  void *             param_value, 
627                  size_t *           param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0
628 {
629
630         switch (param_name)
631         {
632         case CL_CONTEXT_DEVICES:
633                 {
634                         if (!param_value_size)
635                         {
636                                 *param_value_size_ret = 13;
637                         } else
638                         {
639                                 const char* testName = "MiniCL_Test.";
640                                 sprintf((char*)param_value,"%s",testName);
641                         }
642                         break;
643                 };
644         default:
645                 {
646                         printf("unsupported\n");
647                 }
648         }
649         
650         return 0;
651 }
652
653
654
655 CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * /* properties */,
656                         cl_device_type           device_type ,
657                         void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
658                         void *                  /* user_data */,
659                         cl_int *                 errcode_ret ) CL_API_SUFFIX__VERSION_1_0
660 {
661         int maxNumOutstandingTasks = 4;
662 //      int maxNumOutstandingTasks = 2;
663 //      int maxNumOutstandingTasks = 1;
664         gMiniCLNumOutstandingTasks = maxNumOutstandingTasks;
665         const int maxNumOfThreadSupports = 8;
666         static int sUniqueThreadSupportIndex = 0;
667         static const char* sUniqueThreadSupportName[maxNumOfThreadSupports] = 
668         {
669                 "MiniCL_0", "MiniCL_1", "MiniCL_2", "MiniCL_3", "MiniCL_4", "MiniCL_5", "MiniCL_6", "MiniCL_7" 
670         };
671
672         btThreadSupportInterface* threadSupport = 0;
673
674         if (device_type==CL_DEVICE_TYPE_DEBUG)
675         {
676                 SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory);
677                 threadSupport = new SequentialThreadSupport(stc);
678         } else
679         {
680
681 #if _WIN32
682         btAssert(sUniqueThreadSupportIndex < maxNumOfThreadSupports);
683         const char* bla = "MiniCL";
684         threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
685 //                                                              bla,
686                                                                 sUniqueThreadSupportName[sUniqueThreadSupportIndex++],
687                                                                 processMiniCLTask, //processCollisionTask,
688                                                                 createMiniCLLocalStoreMemory,//createCollisionLocalStoreMemory,
689                                                                 maxNumOutstandingTasks));
690 #else
691
692 #ifdef USE_PTHREADS
693                 PosixThreadSupport::ThreadConstructionInfo constructionInfo("PosixThreads",
694                                                                                                                                         processMiniCLTask,
695                                                                                                                                         createMiniCLLocalStoreMemory,
696                                                                                                                                         maxNumOutstandingTasks);
697                 threadSupport = new PosixThreadSupport(constructionInfo);
698
699 #else
700         ///todo: add posix thread support for other platforms
701         SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory);
702         threadSupport = new SequentialThreadSupport(stc);
703 #endif //USE_PTHREADS
704 #endif
705
706         }
707         
708         
709         MiniCLTaskScheduler* scheduler = new MiniCLTaskScheduler(threadSupport,maxNumOutstandingTasks);
710
711         *errcode_ret = 0;
712         return (cl_context)scheduler;
713 }
714
715 CL_API_ENTRY cl_int CL_API_CALL
716 clGetDeviceIDs(cl_platform_id   /* platform */,
717                cl_device_type   /* device_type */, 
718                cl_uint          /* num_entries */, 
719                cl_device_id *   /* devices */, 
720                cl_uint *        /* num_devices */) CL_API_SUFFIX__VERSION_1_0
721 {
722         return 0;
723 }
724
725 CL_API_ENTRY cl_context CL_API_CALL
726 clCreateContext(const cl_context_properties *  properties ,
727                 cl_uint                        num_devices ,
728                 const cl_device_id *           devices ,
729                  void (*pfn_notify)(const char *, const void *, size_t, void *),
730                 void *                         user_data ,
731                 cl_int *                       errcode_ret ) CL_API_SUFFIX__VERSION_1_0
732 {
733         
734         return  clCreateContextFromType(properties,CL_DEVICE_TYPE_ALL,pfn_notify,user_data,errcode_ret);
735 }
736
737 CL_API_ENTRY cl_int CL_API_CALL clReleaseContext(cl_context  context ) CL_API_SUFFIX__VERSION_1_0
738 {
739
740         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) context;
741         
742         btThreadSupportInterface* threadSupport = scheduler->getThreadSupportInterface();
743         delete scheduler;
744         delete threadSupport;
745         
746         return 0;
747 }
748 extern CL_API_ENTRY cl_int CL_API_CALL
749 clFinish(cl_command_queue command_queue ) CL_API_SUFFIX__VERSION_1_0
750 {
751         MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
752         ///wait for all work items to be completed
753         scheduler->flush();
754         return CL_SUCCESS;
755 }
756
757 extern CL_API_ENTRY cl_int CL_API_CALL 
758 clGetProgramInfo(cl_program         /* program */,
759                  cl_program_info    /* param_name */,
760                  size_t             /* param_value_size */,
761                  void *             /* param_value */,
762                  size_t *           /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
763 {
764    return 0;
765 }
766
767 extern CL_API_ENTRY cl_int CL_API_CALL
768 clGetKernelWorkGroupInfo(cl_kernel                   kernel ,
769                          cl_device_id               /* device */,
770                          cl_kernel_work_group_info  wgi/* param_name */,
771                          size_t   sz                  /* param_value_size */,
772                          void *     ptr                /* param_value */,
773                          size_t *                   /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
774 {
775         if((wgi == CL_KERNEL_WORK_GROUP_SIZE)
776          &&(sz == sizeof(size_t))
777          &&(ptr != NULL))
778         {
779                 MiniCLKernel* miniCLKernel = (MiniCLKernel*)kernel;
780                 MiniCLTaskScheduler* scheduler = miniCLKernel->m_scheduler;
781                 *((size_t*)ptr) = scheduler->getMaxNumOutstandingTasks();
782                 return CL_SUCCESS;
783         }
784         else
785         {
786                 return CL_INVALID_VALUE;
787         }
788 }