1 // This is brl/bseg/bstm/ocl/algo/bstm_ocl_update.cxx
2 #include <fstream>
3 #include <iostream>
4 #include <algorithm>
5 #include "bstm_ocl_update.h"
6 //:
7 // \file
8 // \brief  A process for updating a model
9 //
10 // \author Ali Osman Ulusoy
11 // \date May 10, 2013
12 
13 #ifdef _MSC_VER
14 #  include "vcl_msvc_warnings.h"
15 #endif
16 #include <bstm/ocl/bstm_opencl_cache.h>
17 #include <bstm/bstm_scene.h>
18 #include <bstm/bstm_block.h>
19 #include <bstm/bstm_data_base.h>
20 #include <bstm/ocl/bstm_ocl_util.h>
21 #include <bstm/bstm_util.h>
22 #include <boxm2/ocl/algo/boxm2_ocl_camera_converter.h>
23 #include "vil/vil_image_view.h"
24 
25 //directory utility
26 #include "vul/vul_timer.h"
27 #include <vcl_where_root_dir.h>
28 #include <bocl/bocl_device.h>
29 #include <bocl/bocl_kernel.h>
30 //
31 #include "vil/vil_save.h"
32 //: Map of kernels should persist between process executions
33 std::map<std::string,std::vector<bocl_kernel*> > bstm_ocl_update::kernels_;
34 
35 //Main public method, updates color model
update(const bstm_scene_sptr & scene,bocl_device_sptr device,const bstm_opencl_cache_sptr & opencl_cache,vpgl_camera_double_sptr cam,const vil_image_view_base_sptr & img,float time,float mog_var,bool update_alpha,bool update_changes_only,const vil_image_view_base_sptr & mask_sptr)36 bool bstm_ocl_update::update(const bstm_scene_sptr&         scene,
37                                 bocl_device_sptr         device,
38                                 const bstm_opencl_cache_sptr&  opencl_cache,
39                                 vpgl_camera_double_sptr  cam,
40                                 const vil_image_view_base_sptr& img,
41                                 float                   time,
42                                 float                   mog_var,
43                                 bool                    update_alpha,
44                                 bool                    update_changes_only,
45                                 const vil_image_view_base_sptr& mask_sptr)
46 {
47 
48   enum {
49      UPDATE_SEGLEN = 0,
50      UPDATE_PREINF = 1,
51      UPDATE_PROC   = 2,
52      UPDATE_BAYES  = 3,
53      UPDATE_CELL   = 4
54    };
55    float transfer_time=0.0f;
56    float gpu_time=0.0f;
57    std::size_t local_threads[2]={8,8};
58    std::size_t global_threads[2]={8,8};
59 
60    //catch a "null" mask (not really null because that throws an error)
61    bool use_mask = false;
62    if ( mask_sptr->ni() == img->ni() && mask_sptr->nj() == img->nj() ) {
63      use_mask = true;
64    }
65 
66    vil_image_view<unsigned char >* mask_map = nullptr;
67    if (use_mask) {
68      mask_map = dynamic_cast<vil_image_view<unsigned char> *>(mask_sptr.ptr());
69      if (!mask_map) {
70        std::cout<<"bstm_update_process:: mask map is not an unsigned char map"<<std::endl;
71        return false;
72      }
73      std::cout << "Update using mask..." << std::endl;
74    }
75 
76    //cache size sanity check
77    std::size_t binCache = opencl_cache.ptr()->bytes_in_cache();
78    std::cout<<"Update MBs in cache: "<<binCache/(1024.0*1024.0)<<std::endl;
79 
80    //make correct data types are here
81    std::string data_type, num_obs_type,options = "";
82    int appTypeSize;
83    if (!validate_appearances(scene, data_type, appTypeSize, num_obs_type, options))
84      return false;
85 
86    // create a command queue.
87    int status=0;
88    cl_command_queue queue = clCreateCommandQueue( device->context(), *(device->device_id()), CL_QUEUE_PROFILING_ENABLE, &status);
89    if (status!=0)
90      return false;
91 
92    // compile the kernel if not already compiled
93    std::vector<bocl_kernel*>& kernels = get_kernels(device, options);
94 
95    //grab input image, establish cl_ni, cl_nj (so global size is divisible by local size)
96    vil_image_view_base_sptr float_img = bstm_util::prepare_input_image(img, true);
97    auto* img_view = static_cast<vil_image_view<float>* >(float_img.ptr());
98    auto cl_ni=(unsigned)RoundUp(img_view->ni(),(int)local_threads[0]);
99    auto cl_nj=(unsigned)RoundUp(img_view->nj(),(int)local_threads[1]);
100    global_threads[0]=cl_ni;
101    global_threads[1]=cl_nj;
102 
103    //set generic cam
104    auto* ray_origins    = new cl_float[4*cl_ni*cl_nj];
105    auto* ray_directions = new cl_float[4*cl_ni*cl_nj];
106    bocl_mem_sptr ray_o_buff = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(cl_float4), ray_origins, "ray_origins buffer");
107    bocl_mem_sptr ray_d_buff = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(cl_float4), ray_directions, "ray_directions buffer");
108    boxm2_ocl_camera_converter::compute_ray_image( device, queue, cam, cl_ni, cl_nj, ray_o_buff, ray_d_buff);
109 
110    //Visibility, Preinf, Norm, and input image buffers
111    auto* vis_buff = new float[cl_ni*cl_nj];
112    auto* pre_buff = new float[cl_ni*cl_nj];
113    auto* norm_buff = new float[cl_ni*cl_nj];
114    auto* input_buff=new float[cl_ni*cl_nj];
115    for (unsigned i=0;i<cl_ni*cl_nj;i++)
116    {
117      vis_buff[i]=1.0f;
118      pre_buff[i]=0.0f;
119      norm_buff[i]=0.0f;
120    }
121 
122    //copy input vals into image
123    int count=0;
124    for (unsigned int j=0;j<cl_nj;++j) {
125      for (unsigned int i=0;i<cl_ni;++i) {
126        input_buff[count] = 0.0f;
127        if ( i<img_view->ni() && j< img_view->nj() )
128          input_buff[count] = (*img_view)(i,j);
129        ++count;
130      }
131    }
132    if (use_mask)
133    {
134      int count = 0;
135      for (unsigned int j=0;j<cl_nj;++j) {
136        for (unsigned int i=0;i<cl_ni;++i) {
137          if ( i<mask_map->ni() && j<mask_map->nj() )
138            if ( (*mask_map)(i,j)==0 ) {
139              input_buff[count] = -1.0f;
140              vis_buff  [count] = -1.0f;
141            }
142          ++count;
143        }
144      }
145    }
146 
147    bocl_mem_sptr in_image = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(float), input_buff, "input image buffer");
148    in_image->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
149 
150    bocl_mem_sptr vis_image = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(float), vis_buff, "vis image buffer");
151    vis_image->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
152 
153    bocl_mem_sptr pre_image = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(float), pre_buff, "pre image buffer");
154    pre_image->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
155 
156    bocl_mem_sptr norm_image = opencl_cache->alloc_mem(cl_ni*cl_nj*sizeof(float), norm_buff, "norm image buffer");
157    norm_image->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
158 
159 
160    // Image Dimensions
161    int img_dim_buff[4];
162    img_dim_buff[0] = 0;
163    img_dim_buff[1] = 0;
164    img_dim_buff[2] = img_view->ni();
165    img_dim_buff[3] = img_view->nj();
166 
167    bocl_mem_sptr img_dim=new bocl_mem(device->context(), img_dim_buff, sizeof(int)*4, "image dims");
168    img_dim->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
169 
170    // Output Array
171    float output_arr[100];
172    for (float & i : output_arr) i = -1.0f;
173    bocl_mem_sptr  cl_output=new bocl_mem(device->context(), output_arr, sizeof(float)*100, "output buffer");
174    cl_output->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
175 
176    // bit lookup buffer
177    cl_uchar lookup_arr[256];
178    bstm_ocl_util::set_bit_lookup(lookup_arr);
179    bocl_mem_sptr lookup=new bocl_mem(device->context(), lookup_arr, sizeof(cl_uchar)*256, "bit lookup buffer");
180    lookup->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
181 
182    // update_alpha boolean buffer
183    cl_int up_alpha[1];
184    up_alpha[0] = update_alpha ? 1 : 0;
185    bocl_mem_sptr up_alpha_mem = new bocl_mem(device->context(), up_alpha, sizeof(up_alpha), "update alpha bool buffer");
186    up_alpha_mem->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
187 
188    // update_alpha boolean buffer
189    cl_int up_changes_only[1];
190    up_changes_only[0] = update_changes_only ? 1 : 0;
191    bocl_mem_sptr up_changes_mem = new bocl_mem(device->context(), up_changes_only, sizeof(up_changes_only), "update changes bool buffer");
192    up_changes_mem->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
193 
194    // app density used for proc_norm_image
195    //Set app_buffer.x = 1.0, if you want uniform background model
196    //Set app_buffer.x = 0, app_buffer.y and app_buffer.z to the mean and sigma of the gaussian for the background model
197    float app_buffer[4]={1.0,0.0,0.00,0.0};
198    bocl_mem_sptr app_density = new bocl_mem(device->context(), app_buffer, sizeof(cl_float4), "app density buffer");
199    app_density->create_buffer(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR);
200 
201    //mog variance, if 0.0f or less, then var of app models will be estimated, otherwise, it will be fixed
202    bocl_mem_sptr mog_var_mem = new bocl_mem(device->context(), &mog_var, sizeof(mog_var), "update gauss variance");
203    mog_var_mem->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
204 
205    cl_int use_mask_buf[1];
206    use_mask_buf[0] = use_mask ? 1 : 0;
207    bocl_mem_sptr use_mask_mem = new bocl_mem(device->context(), use_mask_buf, sizeof(use_mask_buf), "update with mask");
208    use_mask_mem->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
209 
210    cl_float cl_time = 0;
211    bocl_mem_sptr time_mem =new bocl_mem(device->context(), &cl_time, sizeof(cl_float), "time instance buffer");
212    time_mem->create_buffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);
213 
214 
215    // set arguments
216    std::vector<bstm_block_id> vis_order = scene->get_vis_blocks(cam);
217    std::vector<bstm_block_id>::iterator id;
218    for (unsigned int i=0; i<kernels.size(); ++i)
219    {
220      if ( i == UPDATE_PROC ) {
221        bocl_kernel * proc_kern=kernels[i];
222 
223        proc_kern->set_arg( norm_image.ptr() );
224        proc_kern->set_arg( vis_image.ptr() );
225        proc_kern->set_arg( pre_image.ptr());
226        proc_kern->set_arg( img_dim.ptr() );
227        proc_kern->set_arg( in_image.ptr() );
228        proc_kern->set_arg( app_density.ptr() );
229 
230        //execute kernel
231        proc_kern->execute( queue, 2, local_threads, global_threads);
232        int status = clFinish(queue);
233        if (!check_val(status, MEM_FAILURE, "UPDATE EXECUTE FAILED: " + error_to_string(status)))
234          return false;
235        proc_kern->clear_args();
236        proc_kern->release_current_event();
237        continue;
238      }
239 
240      for (id = vis_order.begin(); id != vis_order.end(); ++id)
241      {
242        //choose correct render kernel
243        bocl_kernel* kern = kernels[i];
244 
245        //if the current blk does not contain the queried time, no need to ray cast
246        bstm_block_metadata mdata = scene->get_block_metadata(*id);
247        double local_time;
248        if(!mdata.contains_t(time,local_time))
249          continue;
250        //write cl_time
251        cl_time = (cl_float)local_time;
252        time_mem->write_to_buffer(queue);
253 
254 
255        //grab data from cache
256        vul_timer transfer;
257        bocl_mem* blk       = opencl_cache->get_block(*id);
258        bocl_mem* blk_t     = opencl_cache->get_time_block(*id);
259        bocl_mem* alpha     = opencl_cache->get_data<BSTM_ALPHA>(*id,0,false);
260        bocl_mem* blk_info  = opencl_cache->loaded_block_info();
261        bocl_mem* blk_t_info= opencl_cache->loaded_time_block_info();
262        auto* info_buffer_t = (bstm_scene_info*) blk_t_info->cpu_buffer();
263 
264        //figure out sizes
265        int alphaTypeSize = (int)bstm_data_info::datasize(bstm_data_traits<BSTM_ALPHA>::prefix());
266        int data_buffer_length = alpha->num_bytes() / alphaTypeSize;
267        int num_time_trees = info_buffer_t->tree_buffer_length;
268        info_buffer_t->data_buffer_length = data_buffer_length;
269        blk_t_info->write_to_buffer((queue));
270 
271        //grab MOG
272        int nobsTypeSize = (int)bstm_data_info::datasize(num_obs_type);
273        bocl_mem* mog       = opencl_cache->get_data(*id,data_type,data_buffer_length*appTypeSize,false);
274 
275        //grab AUX
276        int auxTypeSize = (int)bstm_data_info::datasize(bstm_data_traits<BSTM_AUX0>::prefix());
277        bocl_mem *aux0   = opencl_cache->get_data<BSTM_AUX0>(*id, num_time_trees*auxTypeSize,false);
278        bocl_mem *aux1   = opencl_cache->get_data<BSTM_AUX1>(*id, num_time_trees*auxTypeSize,false);
279        bocl_mem *aux2   = opencl_cache->get_data<BSTM_AUX2>(*id, num_time_trees*auxTypeSize,false);
280        bocl_mem *aux3   = opencl_cache->get_data<BSTM_AUX3>(*id, num_time_trees*auxTypeSize,false);
281 
282 
283        transfer_time += (float) transfer.all();
284        if (i==UPDATE_SEGLEN)
285        {
286          aux0->zero_gpu_buffer(queue);
287          aux1->zero_gpu_buffer(queue);
288 
289          kern->set_arg( blk_info );
290          kern->set_arg( blk );
291          kern->set_arg( blk_t );
292          kern->set_arg( alpha );
293          kern->set_arg( aux0 );
294          kern->set_arg( aux1 );
295          kern->set_arg( lookup.ptr() );
296          kern->set_arg( ray_o_buff.ptr() );
297          kern->set_arg( ray_d_buff.ptr() );
298          kern->set_arg( img_dim.ptr() );
299          kern->set_arg( in_image.ptr() );
300          kern->set_arg( time_mem.ptr() );
301          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar16) );//local tree,
302          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar8) ); //local time tree
303          kern->set_local_arg( local_threads[0]*local_threads[1]*10*sizeof(cl_uchar) ); //cumsum buffer, imindex buffer
304 
305          //execute kernel
306          kern->execute(queue, 2, local_threads, global_threads);
307          int status = clFinish(queue);
308          if (!check_val(status, MEM_FAILURE, "UPDATE EXECUTE FAILED: " + error_to_string(status)))
309            return false;
310          gpu_time += kern->exec_time();
311 
312          //clear render kernel args so it can reset em on next execution
313          kern->clear_args();
314          kern->release_current_event();
315        }
316        else if (i==UPDATE_PREINF)
317        {
318 
319 
320          kern->set_arg( blk_info );
321          kern->set_arg( blk );
322          kern->set_arg( blk_t );
323          kern->set_arg( alpha );
324          kern->set_arg( mog );
325          kern->set_arg( aux0 );
326          kern->set_arg( aux1 );
327          kern->set_arg( lookup.ptr() );
328          kern->set_arg( ray_o_buff.ptr() );
329          kern->set_arg( ray_d_buff.ptr() );
330          kern->set_arg( img_dim.ptr() );
331          kern->set_arg( vis_image.ptr() );
332          kern->set_arg( pre_image.ptr() );
333          kern->set_arg( time_mem.ptr() );
334          kern->set_arg( cl_output.ptr() );
335          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar16) );//local tree,
336          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar8) ); //local time tree
337          kern->set_local_arg( local_threads[0]*local_threads[1]*10*sizeof(cl_uchar) ); //cumsum buffer, imindex buffer
338          //execute kernel
339          kern->execute(queue, 2, local_threads, global_threads);
340          int status = clFinish(queue);
341          if (!check_val(status, MEM_FAILURE, "UPDATE EXECUTE FAILED: " + error_to_string(status)))
342            return false;
343          gpu_time += kern->exec_time();
344 
345          //clear render kernel args so it can reset em on next execution
346          kern->clear_args();
347          kern->release_current_event();
348        }
349        else if (i==UPDATE_BAYES)
350        {
351          aux2->zero_gpu_buffer(queue);
352          aux3->zero_gpu_buffer(queue);
353 
354          kern->set_arg( blk_info );
355          kern->set_arg( blk );
356          kern->set_arg( blk_t );
357          kern->set_arg( alpha );
358          kern->set_arg( mog );
359          kern->set_arg( aux0 );
360          kern->set_arg( aux1 );
361          kern->set_arg( aux2 );
362          kern->set_arg( aux3 );
363          kern->set_arg( lookup.ptr() );
364          kern->set_arg( ray_o_buff.ptr() );
365          kern->set_arg( ray_d_buff.ptr() );
366          kern->set_arg( img_dim.ptr() );
367          kern->set_arg( vis_image.ptr() );
368          kern->set_arg( pre_image.ptr() );
369          kern->set_arg( norm_image.ptr() );
370          kern->set_arg( time_mem.ptr() );
371          kern->set_arg( cl_output.ptr() );
372          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar16) );//local tree,
373          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar8) ); //local time tree
374          kern->set_local_arg( local_threads[0]*local_threads[1]*10*sizeof(cl_uchar) ); //cumsum buffer, imindex buffer
375          kern->execute(queue, 2, local_threads, global_threads);
376          int status = clFinish(queue);
377          if (!check_val(status, MEM_FAILURE, "UPDATE EXECUTE FAILED: " + error_to_string(status)))
378            return false;
379          gpu_time += kern->exec_time();
380 
381          //clear render kernel args so it can reset em on next execution
382          kern->clear_args();
383          kern->release_current_event();
384        }
385        else if (i==UPDATE_CELL)
386        {
387          bocl_mem* num_obs   = opencl_cache->get_data(*id,num_obs_type,data_buffer_length*nobsTypeSize,false);
388 
389          bocl_mem *change   = opencl_cache->get_data<BSTM_CHANGE>(*id, num_time_trees*auxTypeSize,false);
390 
391 
392          local_threads[0] = 64;
393          local_threads[1] = 1 ;
394          global_threads[0]= RoundUp(info_buffer_t->tree_buffer_length ,local_threads[0]);
395          global_threads[1]=1;
396 
397          kern->set_arg( blk_t_info );
398          kern->set_arg( blk_t );
399          kern->set_arg( alpha );
400          kern->set_arg( mog );
401          kern->set_arg( num_obs );
402          kern->set_arg( aux0 );
403          kern->set_arg( aux1 );
404          kern->set_arg( aux2 );
405          kern->set_arg( aux3 );
406          kern->set_arg( change );
407 
408          kern->set_arg( use_mask_mem.ptr() );
409          kern->set_arg( mog_var_mem.ptr() );
410          kern->set_arg( time_mem.ptr() );
411          kern->set_arg( up_alpha_mem.ptr() );
412          kern->set_arg( up_changes_mem .ptr() );
413 
414          kern->set_local_arg( local_threads[0]*local_threads[1]*sizeof(cl_uchar8) ); //local time tree
415 
416          //execute kernel
417          kern->execute(queue, 2, local_threads, global_threads);
418          int status = clFinish(queue);
419          if (!check_val(status, MEM_FAILURE, "UPDATE EXECUTE FAILED: " + error_to_string(status)))
420            return false;
421          gpu_time += kern->exec_time();
422 
423          //clear render kernel args so it can reset em on next execution
424          kern->clear_args();
425          kern->release_current_event();
426 
427          //write info to disk
428          alpha->read_to_buffer(queue);
429          mog->read_to_buffer(queue);
430          num_obs->read_to_buffer(queue);
431        }
432 
433      }
434    }
435 
436 
437 
438    delete [] vis_buff;
439    delete [] pre_buff;
440    delete [] norm_buff;
441    delete [] input_buff;
442    delete [] ray_origins;
443    delete [] ray_directions;
444    opencl_cache->unref_mem(in_image.ptr());
445    opencl_cache->unref_mem(vis_image.ptr());
446    opencl_cache->unref_mem(pre_image.ptr());
447    opencl_cache->unref_mem(norm_image.ptr());
448    opencl_cache->unref_mem(ray_o_buff.ptr());
449    opencl_cache->unref_mem(ray_d_buff.ptr());
450 
451    std::cout<<"Gpu time "<<gpu_time<<" transfer time "<<transfer_time<<std::endl;
452    clReleaseCommandQueue(queue);
453    return true;
454 
455 }
456 
457 
458 //Returns vector of color update kernels (and caches them per device
get_kernels(const bocl_device_sptr & device,const std::string & opts,bool)459 std::vector<bocl_kernel*>& bstm_ocl_update::get_kernels(const bocl_device_sptr& device, const std::string& opts, bool  /*isRGB*/)
460 {
461   // compile kernels if not already compiled
462   std::string identifier = device->device_identifier() + opts;
463   if (kernels_.find(identifier) != kernels_.end())
464     return kernels_[identifier];
465 
466   //otherwise compile the kernels
467   std::cout<<"=== bstm_ocl_update::compiling kernels on device "<<identifier<<"==="<<std::endl;
468 
469   std::vector<std::string> src_paths;
470   std::string source_dir = std::string(VCL_SOURCE_ROOT_DIR) + "/contrib/brl/bseg/bstm/ocl/cl/";
471   src_paths.push_back(source_dir + "scene_info.cl");
472   src_paths.push_back(source_dir + "pixel_conversion.cl");
473   src_paths.push_back(source_dir + "bit/bit_tree_library_functions.cl");
474   src_paths.push_back(source_dir + "bit/time_tree_library_functions.cl");
475   src_paths.push_back(source_dir + "backproject.cl");
476   src_paths.push_back(source_dir + "statistics_library_functions.cl");
477   src_paths.push_back(source_dir + "bit/update_kernels.cl");
478   std::vector<std::string> non_ray_src = std::vector<std::string>(src_paths);
479 
480   //push ray trace files
481   src_paths.push_back(source_dir + "atomics_util.cl");
482   src_paths.push_back(source_dir + "update_functors.cl");
483   src_paths.push_back(source_dir + "bit/cast_ray_bit.cl");
484 
485   //compilation options
486   std::string options = opts + " -D ATOMIC_FLOAT ";
487 
488   //populate vector of kernels
489   std::vector<bocl_kernel*> vec_kernels;
490 
491   //seg len pass
492   auto* seg_len = new bocl_kernel();
493   std::string seg_opts = options + " -D SEGLEN -D STEP_CELL=step_cell_seglen(aux_args,data_ptr,data_ptr_tt,d)";
494   seg_len->create_kernel(&device->context(), device->device_id(), src_paths, "seg_len_main", seg_opts, "update::seg_len");
495   vec_kernels.push_back(seg_len);
496 
497 
498   auto* pre_inf = new bocl_kernel();
499   std::string pre_opts = options + " -D PREINF -D STEP_CELL=step_cell_preinf(aux_args,data_ptr,data_ptr_tt,d)";
500   pre_inf->create_kernel(&device->context(), device->device_id(), src_paths, "pre_inf_main", pre_opts, "update::pre_inf");
501   vec_kernels.push_back(pre_inf);
502 
503   //may need DIFF LIST OF SOURCES FOR THIS GUY
504   auto* proc_img = new bocl_kernel();
505   std::string proc_opts = options + " -D PROC_NORM ";
506   proc_img->create_kernel(&device->context(), device->device_id(), non_ray_src, "proc_norm_image", proc_opts, "update::proc_norm_image");
507   vec_kernels.push_back(proc_img);
508 
509   //push back cast_ray_bit
510   auto* bayes_main = new bocl_kernel();
511   std::string bayes_opt = options + " -D BAYES -D STEP_CELL=step_cell_bayes(aux_args,data_ptr,data_ptr_tt,d)";
512   bayes_main->create_kernel(&device->context(), device->device_id(), src_paths, "bayes_main", bayes_opt, "update::bayes_main");
513   vec_kernels.push_back(bayes_main);
514 
515   auto* update = new bocl_kernel();
516   std::string update_opts = options + " -D UPDATE_BIT_SCENE_MAIN ";
517   update->create_kernel(&device->context(), device->device_id(), non_ray_src, "update_bit_scene_main", update_opts, "update::update_main");
518   vec_kernels.push_back(update);
519 
520   //store and return
521   kernels_[identifier] = vec_kernels;
522   return kernels_[identifier];
523 }
524 
525 
526 //makes sure appearance types correspond correctly
validate_appearances(const bstm_scene_sptr & scene,std::string & data_type,int & appTypeSize,std::string & num_obs_type,std::string & options)527 bool bstm_ocl_update::validate_appearances(const bstm_scene_sptr& scene,
528                                             std::string& data_type,
529                                             int& appTypeSize,
530                                             std::string& num_obs_type,
531                                             std::string& options)
532 {
533   std::vector<std::string> apps = scene->appearances();
534   bool foundDataType = false, foundNumObsType = false;
535   for (const auto & app : apps) {
536     if ( app == bstm_data_traits<BSTM_MOG3_GREY >::prefix() )
537     {
538       data_type = app;
539       foundDataType = true;
540       options+= " -D MOG_TYPE_8 ";
541       appTypeSize = (int)bstm_data_info::datasize(bstm_data_traits<BSTM_MOG3_GREY>::prefix());
542     }
543 
544     else if( app == bstm_data_traits<BSTM_NUM_OBS>::prefix())
545     {
546       num_obs_type = app;
547       foundNumObsType = true;
548     }
549   }
550   if (!foundDataType) {
551     std::cout<<"BSTM_OPENCL_VIEW_BASED_UPDATE_PROCESS ERROR: scene doesn't have BSTM_MOG3_GREY data type"<<std::endl;
552     return false;
553   }
554   if (!foundNumObsType) {
555     std::cout<<"BSTM_OPENCL_VIEW_BASED_UPDATE_PROCESS ERROR: scene doesn't have BSTM_NUM_OBS data type"<<std::endl;
556     return false;
557   }
558   return true;
559 }
560