@@ -357,25 +357,32 @@ void time_kernel_callback(cl_event event, cl_int, void* data) {
357357 CHECK_OPENCL (err, " clReleaseEvent()" );
358358}
359359
360+ static inline bool ends_with (std::string_view str, std::string_view suffix) {
361+ if (str.size () < suffix.size ())
362+ return false ;
363+ return str.compare (str.size () - suffix.size (), suffix.size (), suffix) == 0 ;
364+ }
365+
360366void OpenCLPlatform::launch_kernel (DeviceId dev, const LaunchParams& launch_params) {
361367 if (devices_[dev].is_intel_fpga && launch_params.num_args == 0 ) {
362368 debug (" processing by autorun kernel" );
363369 return ;
364370 }
365371
366372 auto kernel = load_kernel (dev, launch_params.file_name , launch_params.kernel_name );
373+ bool is_spirv = ends_with (launch_params.file_name , " .spv" );
367374
368375 // set up arguments
369- std::vector<cl_mem> kernel_structs (launch_params. num_args ) ;
376+ std::vector<cl_mem> kernel_structs;
370377 for (uint32_t i = 0 ; i < launch_params.num_args ; i++) {
371- if (launch_params.args .types [i] == KernelArgType::Struct) {
378+ if (!is_spirv && launch_params.args .types [i] == KernelArgType::Struct) {
372379 // create a buffer for each structure argument
373380 cl_int err = CL_SUCCESS;
374381 cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR;
375382 cl_mem struct_buf = clCreateBuffer (devices_[dev].ctx , flags, launch_params.args .sizes [i], launch_params.args .data [i], &err);
376383 CHECK_OPENCL (err, " clCreateBuffer()" );
377- kernel_structs[i] = struct_buf;
378- clSetKernelArg (kernel, i, sizeof (cl_mem), &kernel_structs[i] );
384+ kernel_structs. push_back ( struct_buf) ;
385+ clSetKernelArg (kernel, i, sizeof (cl_mem), &struct_buf );
379386 } else {
380387 #ifdef CL_VERSION_2_0
381388 if (launch_params.args .types [i] == KernelArgType::Ptr && devices_[dev].version_major == 2 ) {
@@ -421,11 +428,9 @@ void OpenCLPlatform::launch_kernel(DeviceId dev, const LaunchParams& launch_para
421428 dynamic_profile (dev, launch_params.file_name );
422429
423430 // release temporary buffers for struct arguments
424- for (uint32_t i = 0 ; i < launch_params.num_args ; i++) {
425- if (launch_params.args .types [i] == KernelArgType::Struct) {
426- cl_int err = clReleaseMemObject (kernel_structs[i]);
427- CHECK_OPENCL (err, " clReleaseMemObject()" );
428- }
431+ for (auto tmp : kernel_structs) {
432+ cl_int err = clReleaseMemObject (tmp);
433+ CHECK_OPENCL (err, " clReleaseMemObject()" );
429434 }
430435}
431436
@@ -515,6 +520,21 @@ cl_program OpenCLPlatform::load_program_binary(DeviceId dev, const std::string&
515520 return program;
516521}
517522
523+ cl_program OpenCLPlatform::load_program_il (DeviceId dev, const std::string& filename, const std::string& program_string) const {
524+ #if CL_VERSION_2_1
525+ const size_t program_length = program_string.length ();
526+ const char * program_c_str = program_string.c_str ();
527+ cl_int err = CL_SUCCESS;
528+ cl_program program = clCreateProgramWithIL (devices_[dev].ctx , (const void *)program_c_str, program_length, &err);
529+ CHECK_OPENCL (err, " clCreateProgramWithIL()" );
530+ debug (" Loading IL '%' for OpenCL device %" , filename, dev);
531+
532+ return program;
533+ #else
534+ error (" OpenCL 2.1 or later is required for SPIR-V support." );
535+ #endif
536+ }
537+
518538cl_program OpenCLPlatform::load_program_source (DeviceId dev, const std::string& filename, const std::string& program_string) const {
519539 const size_t program_length = program_string.length ();
520540 const char * program_c_str = program_string.c_str ();
@@ -589,25 +609,28 @@ cl_kernel OpenCLPlatform::load_kernel(DeviceId dev, const std::string& filename,
589609 if (prog_it == prog_cache.end ()) {
590610 opencl_dev.unlock ();
591611
592- if (canonical.extension () != " .cl" )
593- error (" Incorrect extension for kernel file '%' (should be '.cl')" , canonical.string ());
594-
595612 // load file from disk or cache
596613 auto src_path = canonical;
597614 if (opencl_dev.is_intel_fpga )
598615 src_path.replace_extension (" .aocx" );
599616 std::string src_code = runtime_->load_file (src_path.string ());
600617
601- // compile src or load from cache
602- std::string bin = opencl_dev.is_intel_fpga ? src_code : runtime_->load_from_cache (devices_[dev].platform_name + devices_[dev].device_name + src_code);
603- if (bin.empty ()) {
604- program = load_program_source (dev, src_path.string (), src_code);
618+ if (canonical.extension () == " .spv" ) {
619+ program = load_program_il (dev, src_path.string (), src_code);
605620 program = compile_program (dev, program, src_path.string ());
606- runtime_->store_to_cache (devices_[dev].platform_name + devices_[dev].device_name + src_code, program_as_string (program));
607- } else {
608- program = load_program_binary (dev, src_path.string (), bin);
609- program = compile_program (dev, program, src_path.string ());
610- }
621+ } else if (canonical.extension () == " .cl" ) {
622+ // compile src or load from cache
623+ std::string bin = opencl_dev.is_intel_fpga ? src_code : runtime_->load_from_cache (devices_[dev].platform_name + devices_[dev].device_name + src_code);
624+ if (bin.empty ()) {
625+ program = load_program_source (dev, src_path.string (), src_code);
626+ program = compile_program (dev, program, src_path.string ());
627+ runtime_->store_to_cache (devices_[dev].platform_name + devices_[dev].device_name + src_code, program_as_string (program));
628+ } else {
629+ program = load_program_binary (dev, src_path.string (), bin);
630+ program = compile_program (dev, program, src_path.string ());
631+ }
632+ } else
633+ error (" Incorrect extension for kernel file '%' (should be '.cl' or .'spv')" , canonical.string ());
611634
612635 opencl_dev.lock ();
613636 prog_cache[canonical.string ()] = program;
0 commit comments