[Beignet] [PATCH] separate runtime(libcl.so) and compiler(libgbe.so)

Guo Yejun yejun.guo at intel.com
Thu May 8 16:17:27 PDT 2014


On embedded/handheld devices, storage and memory are scarce, it is
necessary to provide only the OpenCL runtime library with small size,
and only the executable binary kernel will be supported on such device.

At the beginning of process (before function main), OpenCL runtime
(libcl.so) will try to load the compiler (libgbe.so), the system's
behavior is the same as before if successfully loaded, otherwise,
the runtime assumes no OpenCL compiler in the system, and the device
info will be changed as CL_DEVICE_COMPILER_AVAILABLE=false and
CL_DEVICE_PROFILE="EMBEDDED_PROFILE", the clBuildProgram returns
CL_COMPILER_NOT_AVAILABLE if the program is created with
clCreateProgramWithSource, following the OpenCL spec.

To simulate the case without OpenCL compiler, just delete the file
libgbe.so, or export OCL_NON_COMPILER=1.

Some explanation of the binary kernel interpreter (libinterp.a):

libinterp.a is used to interpret the binary kernel inside runtime,
and the runtime library libcl.so is built against libinterp.a.

Since the code to interpret binary kernel is tightly integrated inside
the compiler, to avoid code duplicate, a new file gbe_bin_interpreter.cpp
is created to include some other .cpp files; to make libinterp.a small
(the purpose to make libcl.so small), the macro GBE_COMPILER_AVAILABLE
is used to make only the needed code active when build for libinterp.a.

Signed-off-by: Guo Yejun <yejun.guo at intel.com>
---
 backend/CMakeLists.txt              |  3 ++
 backend/src/CMakeLists.txt          |  8 +++-
 backend/src/GBEConfig.h.in          |  1 +
 backend/src/backend/gen_program.cpp |  9 +++-
 backend/src/backend/program.cpp     | 12 ++++--
 backend/src/backend/program.h       |  3 +-
 backend/src/backend/program.hpp     |  2 +
 backend/src/gbe_bin_interpreter.cpp | 71 ++++++++++++++++++++++++++++++++
 backend/src/ir/image.cpp            | 61 +++++++++++++--------------
 backend/src/ir/sampler.cpp          |  2 +
 backend/src/ocl_common_defines.h    |  5 ++-
 src/CMakeLists.txt                  |  5 ++-
 src/cl_device_id.c                  | 10 +++++
 src/cl_gbe_loader.cpp               | 82 +++++++++++++++++++++++++++++++++++++
 src/cl_gbe_loader.h                 | 32 +++++++++++++++
 src/cl_kernel.h                     |  2 +-
 src/cl_program.c                    |  6 +++
 src/cl_program.h                    |  2 +-
 src/intel/intel_driver.c            |  7 +++-
 utests/setenv.sh.in                 |  1 +
 20 files changed, 281 insertions(+), 43 deletions(-)
 create mode 100644 backend/src/gbe_bin_interpreter.cpp
 create mode 100644 src/cl_gbe_loader.cpp
 create mode 100644 src/cl_gbe_loader.h

diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index dd55a4a..a20f423 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -36,6 +36,8 @@ endif (GBE_DEBUG_MEMORY)
 # Hide all symbols and allows the symbols declared as visible to be exported
 set (CMAKE_C_CXX_FLAGS "-fvisibility=hidden ${CMAKE_C_CXX_FLAGS}")
 
+set (CMAKE_C_CXX_FLAGS -DGBE_COMPILER_AVAILABLE=1)
+
 if (COMPILER STREQUAL "GCC")
   set (CMAKE_C_CXX_FLAGS "${CMAKE_C_CXX_FLAGS} -funroll-loops -Wstrict-aliasing=2 -fstrict-aliasing -msse2 -msse3 -mssse3 -msse4.1 -fPIC -Wall")
   set (CMAKE_C_CXX_FLAGS "${CMAKE_C_CXX_FLAGS}  ${LLVM_CFLAGS}")
@@ -99,6 +101,7 @@ include_directories (${CMAKE_CURRENT_BINARY_DIR})
 add_subdirectory (src)
 set(LOCAL_PCH_OBJECT_DIR ${LOCAL_PCH_OBJECT_DIR} PARENT_SCOPE)
 set(LOCAL_PCM_OBJECT_DIR ${LOCAL_PCM_OBJECT_DIR} PARENT_SCOPE)
+set(LOCAL_GBE_OBJECT_DIR ${LOCAL_GBE_OBJECT_DIR} PARENT_SCOPE)
 set (GBE_BIN_GENERATER
      OCL_PCM_PATH=${LOCAL_PCM_OBJECT_DIR} OCL_PCH_PATH=${LOCAL_PCH_OBJECT_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src/gbe_bin_generater
      PARENT_SCOPE)
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 3bb31e5..ec83814 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -172,7 +172,7 @@ endif (GBE_USE_BLOB)
 include_directories (.)
 link_directories (${LLVM_LIBRARY_DIRS})
 include_directories(${LLVM_INCLUDE_DIRS})
-add_library (gbe STATIC ${GBE_SRC})
+add_library (gbe SHARED ${GBE_SRC})
 
 # for pre compiled module library.
 set (pcm_lib "beignet.bc")
@@ -190,6 +190,8 @@ target_link_libraries(
                       ${CMAKE_THREAD_LIBS_INIT}
                       ${CMAKE_DL_LIBS})
 
+add_library(interp STATIC gbe_bin_interpreter.cpp)
+
 if (LLVM_VERSION_NODOT VERSION_EQUAL 34)
   find_library(TERMINFO NAMES tinfo ncurses)
   if (${TERMINFO} STREQUAL TERMINFO-NOTFOUND)
@@ -204,7 +206,7 @@ link_directories (${LLVM_LIBRARY_DIR})
 ADD_EXECUTABLE(gbe_bin_generater gbe_bin_generater.cpp)
 TARGET_LINK_LIBRARIES(gbe_bin_generater gbe)
 
-#install (TARGETS gbe LIBRARY DESTINATION lib)
+install (TARGETS gbe LIBRARY DESTINATION ${LIB_INSTALL_DIR}/beignet)
 #install (FILES backend/program.h DESTINATION include/gen)
 install (FILES ${ocl_blob_file} DESTINATION ${LIB_INSTALL_DIR}/beignet)
 install (FILES ${pch_object} DESTINATION ${LIB_INSTALL_DIR}/beignet)
@@ -213,9 +215,11 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib} DESTINATION ${LIB_INSTALL_
 # file to libcl and utests.
 set (LOCAL_PCH_OBJECT_DIR "${local_pch_object}:${beignet_install_path}/ocl_stdlib.h.pch" PARENT_SCOPE)
 set (LOCAL_PCM_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib}:${beignet_install_path}/${pcm_lib}" PARENT_SCOPE)
+set (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE)
 
 set (PCH_OBJECT_DIR "${beignet_install_path}/ocl_stdlib.h.pch")
 set (PCM_OBJECT_DIR "${beignet_install_path}/${pcm_lib}")
+set (GBE_OBJECT_DIR "${beignet_install_path}/libgbe.so")
 configure_file (
   "GBEConfig.h.in"
   "GBEConfig.h"
diff --git a/backend/src/GBEConfig.h.in b/backend/src/GBEConfig.h.in
index 5bc09b8..ad24390 100644
--- a/backend/src/GBEConfig.h.in
+++ b/backend/src/GBEConfig.h.in
@@ -3,3 +3,4 @@
 #define LIBGBE_VERSION_MINOR @LIBGBE_VERSION_MINOR@
 #define PCH_OBJECT_DIR "@PCH_OBJECT_DIR@"
 #define PCM_OBJECT_DIR "@PCM_OBJECT_DIR@"
+#define GBE_OBJECT_DIR "@GBE_OBJECT_DIR@"
diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index dd03153..fd96eea 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -52,6 +52,7 @@ namespace gbe {
   size_t GenKernel::getCodeSize(void) const { return insnNum * sizeof(GenInstruction); }
 
   void GenKernel::printStatus(int indent, std::ostream& outs) {
+#ifdef GBE_COMPILER_AVAILABLE
     Kernel::printStatus(indent, outs);
 
     FILE *f = fopen("/dev/null", "w");
@@ -69,6 +70,7 @@ namespace gbe {
     setbuffer(f, NULL, 0);
     delete [] buf;
     fclose(f);
+#endif
   }
 
   GenProgram::~GenProgram(void) {}
@@ -87,7 +89,7 @@ namespace gbe {
   };
 
   Kernel *GenProgram::compileKernel(const ir::Unit &unit, const std::string &name, bool relaxMath) {
-
+#ifdef GBE_COMPILER_AVAILABLE
     // Be careful when the simdWidth is forced by the programmer. We can see it
     // when the function already provides the simd width we need to use (i.e.
     // non zero)
@@ -131,6 +133,9 @@ namespace gbe {
 
     GBE_ASSERTM(kernel != NULL, "Fail to compile kernel, may need to increase reserved registers for spilling.");
     return kernel;
+#else
+    return NULL;
+#endif
   }
 
   static gbe_program genProgramNewFromBinary(uint32_t deviceID, const char *binary, size_t size) {
@@ -176,6 +181,7 @@ namespace gbe {
   {
     using namespace gbe;
     GenProgram *program = GBE_NEW(GenProgram, deviceID);
+#ifdef GBE_COMPILER_AVAILABLE
     std::string error;
     // Try to compile the program
     if (program->buildFromLLVMFile(fileName, error, optLevel) == false) {
@@ -187,6 +193,7 @@ namespace gbe {
       GBE_DELETE(program);
       return NULL;
     }
+#endif
     // Everything run fine
     return (gbe_program) program;
   }
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index bdc7d34..121e237 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -100,6 +100,7 @@ namespace gbe {
     if (constantSet) delete constantSet;
   }
 
+#ifdef GBE_COMPILER_AVAILABLE
   BVAR(OCL_OUTPUT_GEN_IR, false);
 
   bool Program::buildFromLLVMFile(const char *fileName, std::string &error, int optLevel) {
@@ -139,6 +140,7 @@ namespace gbe {
     }
     return true;
   }
+#endif
 
 #define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
 #define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
@@ -511,6 +513,7 @@ namespace gbe {
     GBE_SAFE_DELETE(program);
   }
 
+#ifdef GBE_COMPILER_AVAILABLE
   BVAR(OCL_OUTPUT_BUILD_LOG, false);
   SVAR(OCL_PCH_PATH, PCH_OBJECT_DIR);
   SVAR(OCL_PCM_PATH, PCM_OBJECT_DIR);
@@ -847,6 +850,7 @@ namespace gbe {
     remove(clName.c_str());
     return p;
   }
+#endif
 
   static size_t programGetGlobalConstantSize(gbe_program gbeProgram) {
     if (gbeProgram == NULL) return 0;
@@ -1042,9 +1046,11 @@ GBE_EXPORT_SYMBOL gbe_kernel_get_sampler_data_cb *gbe_kernel_get_sampler_data =
 GBE_EXPORT_SYMBOL gbe_kernel_get_compile_wg_size_cb *gbe_kernel_get_compile_wg_size = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_get_image_size_cb *gbe_kernel_get_image_size = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_get_image_data_cb *gbe_kernel_get_image_data = NULL;
-GBE_EXPORT_SYMBOL gbe_set_image_base_index_cb *gbe_set_image_base_index = NULL;
+GBE_EXPORT_SYMBOL gbe_set_image_base_index_cb *gbe_set_image_base_index_compiler = NULL;
+GBE_EXPORT_SYMBOL gbe_set_image_base_index_cb *gbe_set_image_base_index_interp = NULL;
 GBE_EXPORT_SYMBOL gbe_get_image_base_index_cb *gbe_get_image_base_index = NULL;
 
+#ifdef GBE_COMPILER_AVAILABLE
 namespace gbe
 {
   /* Use pre-main to setup the call backs */
@@ -1080,7 +1086,7 @@ namespace gbe
       gbe_kernel_get_image_size = gbe::kernelGetImageSize;
       gbe_kernel_get_image_data = gbe::kernelGetImageData;
       gbe_get_image_base_index = gbe::getImageBaseIndex;
-      gbe_set_image_base_index = gbe::setImageBaseIndex;
+      gbe_set_image_base_index_compiler = gbe::setImageBaseIndex;
       genSetupCallBacks();
       llvm::llvm_start_multithreaded();
     }
@@ -1095,4 +1101,4 @@ namespace gbe
 
   static CallBackInitializer cbInitializer;
 } /* namespace gbe */
-
+#endif
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index d90ada3..7b56f93 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -98,7 +98,8 @@ typedef struct ImageInfo {
 } ImageInfo;
 
 typedef void (gbe_set_image_base_index_cb)(uint32_t base_idx);
-extern gbe_set_image_base_index_cb *gbe_set_image_base_index;
+extern gbe_set_image_base_index_cb *gbe_set_image_base_index_compiler;
+extern gbe_set_image_base_index_cb *gbe_set_image_base_index_interp;
 
 typedef uint32_t (gbe_get_image_base_index_cb)();
 extern gbe_get_image_base_index_cb *gbe_get_image_base_index;
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index fe945a6..6bb1529 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -112,12 +112,14 @@ namespace gbe {
     INLINE uint32_t getSLMSize(void) const { return this->slmSize; }
     /*! set constant buffer size and return the cb curbe offset */
     int32_t setConstBufSize(uint32_t argID, size_t sz) {
+#ifdef GBE_COMPILER_AVAILABLE
       if(argID >= argNum) return -1;
       if(args[argID].type != GBE_ARG_CONSTANT_PTR) return -1;
       if(args[argID].bufSize != sz) {
         args[argID].bufSize = sz;
         return ctx->allocConstBuf(argID);
       }
+#endif
       return -1;
     }
     /*! Set sampler set. */
diff --git a/backend/src/gbe_bin_interpreter.cpp b/backend/src/gbe_bin_interpreter.cpp
new file mode 100644
index 0000000..bd160c3
--- /dev/null
+++ b/backend/src/gbe_bin_interpreter.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sys/alloc.cpp"
+#include "sys/cvar.cpp"
+#include "sys/assert.cpp"
+#include "sys/platform.cpp"
+#include "ir/constant.cpp"
+
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#undef GBE_COMPILER_AVAILABLE
+#include "backend/program.cpp"
+#include "backend/gen_program.cpp"
+#include "ir/sampler.cpp"
+#include "ir/image.cpp"
+
+struct BinInterpCallBackInitializer
+{
+  BinInterpCallBackInitializer() {
+    gbe_program_new_from_binary = gbe::genProgramNewFromBinary;
+    gbe_program_get_kernel_num = gbe::programGetKernelNum;
+    gbe_program_get_kernel_by_name = gbe::programGetKernelByName;
+    gbe_program_get_kernel = gbe::programGetKernel;
+    gbe_kernel_get_code_size = gbe::kernelGetCodeSize;
+    gbe_kernel_get_code = gbe::kernelGetCode;
+    gbe_kernel_get_arg_num = gbe::kernelGetArgNum;
+    gbe_kernel_get_curbe_size = gbe::kernelGetCurbeSize;
+    gbe_kernel_get_sampler_size = gbe::kernelGetSamplerSize;
+    gbe_kernel_get_compile_wg_size = gbe::kernelGetCompileWorkGroupSize;
+    gbe_kernel_get_stack_size = gbe::kernelGetStackSize;
+    gbe_kernel_get_image_size = gbe::kernelGetImageSize;
+    gbe_kernel_get_name = gbe::kernelGetName;
+    gbe_kernel_get_arg_type = gbe::kernelGetArgType;
+    gbe_kernel_get_arg_size = gbe::kernelGetArgSize;
+    gbe_kernel_get_simd_width = gbe::kernelGetSIMDWidth;
+    gbe_kernel_get_scratch_size = gbe::kernelGetScratchSize;
+    gbe_kernel_use_slm = gbe::kernelUseSLM;
+    gbe_kernel_get_required_work_group_size = gbe::kernelGetRequiredWorkGroupSize;
+    gbe_kernel_get_curbe_offset = gbe::kernelGetCurbeOffset;
+    gbe_kernel_get_slm_size = gbe::kernelGetSLMSize;
+    gbe_kernel_get_arg_align = gbe::kernelGetArgAlign;
+    gbe_program_get_global_constant_size = gbe::programGetGlobalConstantSize;
+    gbe_program_delete = gbe::programDelete;
+    gbe_program_get_global_constant_data = gbe::programGetGlobalConstantData;
+    gbe_kernel_get_sampler_data = gbe::kernelGetSamplerData;
+    gbe_kernel_get_image_data = gbe::kernelGetImageData;
+    gbe_get_image_base_index = gbe::getImageBaseIndex;
+    gbe_set_image_base_index_interp = gbe::setImageBaseIndex;
+  }
+
+  ~BinInterpCallBackInitializer() {
+  }
+};
+
+static struct BinInterpCallBackInitializer binInterpCB;
diff --git a/backend/src/ir/image.cpp b/backend/src/ir/image.cpp
index 8c34d70..ee80a3d 100644
--- a/backend/src/ir/image.cpp
+++ b/backend/src/ir/image.cpp
@@ -64,16 +64,6 @@ namespace ir {
     setInfoOffset4Type(imageInfo, key.type, offset);
   }
 
-  Register ImageSet::appendInfo(ImageInfoKey key, Context *ctx)
-  {
-    auto it = infoRegMap.find(key.data);
-    if (it != infoRegMap.end())
-      return it->second;
-    Register reg = ctx->reg(FAMILY_DWORD);
-    infoRegMap.insert(std::make_pair(key.data, reg));
-    return reg;
-  }
-
   void ImageSet::clearInfo()
   {
     struct ImageInfo *imageInfo;
@@ -87,26 +77,6 @@ namespace ir {
     }
   }
 
-  void ImageSet::append(Register imageReg, Context *ctx)
-  {
-    ir::FunctionArgument *arg =  ctx->getFunction().getArg(imageReg);
-    GBE_ASSERTM(arg && arg->type == ir::FunctionArgument::IMAGE, "Append an invalid reg to image set.");
-    GBE_ASSERTM(regMap.find(imageReg) == regMap.end(), "Append the same image reg twice.");
-
-    int32_t id = ctx->getFunction().getArgID(arg);
-    struct ImageInfo *imageInfo = GBE_NEW(struct ImageInfo);
-    imageInfo->arg_idx = id;
-    imageInfo->idx = regMap.size() + gbe_get_image_base_index();
-    imageInfo->wSlot = -1;
-    imageInfo->hSlot = -1;
-    imageInfo->depthSlot = -1;
-    imageInfo->dataTypeSlot = -1;
-    imageInfo->channelOrderSlot = -1;
-    imageInfo->dimOrderSlot = -1;
-    regMap.insert(std::make_pair(imageReg, imageInfo));
-    indexMap.insert(std::make_pair(imageInfo->idx, imageInfo));
-  }
-
   const int32_t ImageSet::getInfoOffset(ImageInfoKey key) const
   {
     auto it = indexMap.find(key.index);
@@ -271,6 +241,37 @@ namespace ir {
    outs << spaces << "------------- End ImageSet -------------" << "\n";
   }
 
+#ifdef GBE_COMPILER_AVAILABLE
+  Register ImageSet::appendInfo(ImageInfoKey key, Context *ctx)
+  {
+    auto it = infoRegMap.find(key.data);
+    if (it != infoRegMap.end())
+      return it->second;
+    Register reg = ctx->reg(FAMILY_DWORD);
+    infoRegMap.insert(std::make_pair(key.data, reg));
+    return reg;
+  }
+
+  void ImageSet::append(Register imageReg, Context *ctx)
+  {
+    ir::FunctionArgument *arg =  ctx->getFunction().getArg(imageReg);
+    GBE_ASSERTM(arg && arg->type == ir::FunctionArgument::IMAGE, "Append an invalid reg to image set.");
+    GBE_ASSERTM(regMap.find(imageReg) == regMap.end(), "Append the same image reg twice.");
+
+    int32_t id = ctx->getFunction().getArgID(arg);
+    struct ImageInfo *imageInfo = GBE_NEW(struct ImageInfo);
+    imageInfo->arg_idx = id;
+    imageInfo->idx = regMap.size() + gbe_get_image_base_index();
+    imageInfo->wSlot = -1;
+    imageInfo->hSlot = -1;
+    imageInfo->depthSlot = -1;
+    imageInfo->dataTypeSlot = -1;
+    imageInfo->channelOrderSlot = -1;
+    imageInfo->dimOrderSlot = -1;
+    regMap.insert(std::make_pair(imageReg, imageInfo));
+    indexMap.insert(std::make_pair(imageInfo->idx, imageInfo));
+  }
+#endif
 
 } /* namespace ir */
 } /* namespace gbe */
diff --git a/backend/src/ir/sampler.cpp b/backend/src/ir/sampler.cpp
index b67c1b7..1406ff6 100644
--- a/backend/src/ir/sampler.cpp
+++ b/backend/src/ir/sampler.cpp
@@ -27,6 +27,7 @@
 namespace gbe {
 namespace ir {
 
+#ifdef GBE_COMPILER_AVAILABLE
   uint8_t SamplerSet::appendReg(uint32_t key, Context *ctx) {
     uint8_t samplerSlot = samplerMap.size();
     samplerMap.insert(std::make_pair(key, samplerSlot));
@@ -61,6 +62,7 @@ namespace ir {
     }
     return appendReg(SAMPLER_ID(id), ctx);
   }
+#endif
 
 #define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
 #define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
diff --git a/backend/src/ocl_common_defines.h b/backend/src/ocl_common_defines.h
index b736a88..52f5365 100644
--- a/backend/src/ocl_common_defines.h
+++ b/backend/src/ocl_common_defines.h
@@ -1,6 +1,7 @@
 // This file includes defines that are common to both kernel code and
 // the NVPTX back-end.
-
+#ifndef __OCL_COMMON_DEFINES__
+#define __OCL_COMMON_DEFINES__
 //
 // Common defines for Image intrinsics
 // Channel order
@@ -121,3 +122,5 @@ typedef enum clk_sampler_type {
 // Memory synchronization
 #define CLK_LOCAL_MEM_FENCE     (1 << 0)
 #define CLK_GLOBAL_MEM_FENCE    (1 << 1)
+
+#endif   /* __OCL_COMMON_DEFINES__ */
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8164a44..211c8a3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ set(OPENCL_SRC
     cl_alloc.c
     cl_kernel.c
     cl_program.c
+    cl_gbe_loader.cpp
     cl_sampler.c
     cl_event.c
     cl_enqueue.c
@@ -73,12 +74,14 @@ link_directories (${LLVM_LIBRARY_DIR})
 add_library(cl SHARED ${OPENCL_SRC})
 target_link_libraries(
                       cl
-                      gbe
+                      interp
                       ${XLIB_LIBRARY}
                       ${XEXT_LIBRARIES}
                       ${XFIXES_LIBRARIES}
                       ${DRM_INTEL_LIBRARIES}
                       ${DRM_LIBRARIES}
+                      ${CMAKE_THREAD_LIBS_INIT}
+                      ${CMAKE_DL_LIBS}
                       ${OPENGL_LIBRARIES}
                       ${OPTIONAL_EGL_LIBRARY})
 install (TARGETS cl LIBRARY DESTINATION ${LIB_INSTALL_DIR}/beignet)
diff --git a/src/cl_device_id.c b/src/cl_device_id.c
index 42ae19e..4bde4f0 100644
--- a/src/cl_device_id.c
+++ b/src/cl_device_id.c
@@ -26,6 +26,7 @@
 #include "cl_khr_icd.h"
 #include "cl_thread.h"
 #include "CL/cl.h"
+#include "cl_gbe_loader.h"
 
 #include <assert.h>
 #include <stdio.h>
@@ -219,6 +220,15 @@ baytrail_t_device_break:
       printf("cl_get_gt_device(): error, unknown device: %x\n", device_id);
   }
 
+  if (!CompilerSupported()) {
+    if (ret != NULL) {
+      ret->compiler_available = CL_FALSE;
+      //ret->linker_available = CL_FALSE;
+      ret->profile = "EMBEDDED_PROFILE";
+      ret->profile_sz = strlen(ret->profile) + 1;
+    }
+  }
+
   return ret;
 }
 
diff --git a/src/cl_gbe_loader.cpp b/src/cl_gbe_loader.cpp
new file mode 100644
index 0000000..da83c9a
--- /dev/null
+++ b/src/cl_gbe_loader.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <dlfcn.h>
+#include <string.h>
+#include "cl_gbe_loader.h"
+#include "backend/src/GBEConfig.h"
+
+struct GbeLoaderInitializer
+{
+  GbeLoaderInitializer() {
+    inited = false;
+
+    const char* nonCompiler = getenv("OCL_NON_COMPILER");
+    if (nonCompiler != NULL) {
+      if (strcmp(nonCompiler, "1") == 0)
+        return;
+    }
+
+    const char* gbePath = getenv("OCL_GBE_PATH");
+    if (gbePath == NULL)
+      gbePath = GBE_OBJECT_DIR;
+
+    dlh = dlopen(gbePath, RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
+    if (dlh != NULL) {
+      gbe_program_new_from_source = *(gbe_program_new_from_source_cb **)dlsym(dlh, "gbe_program_new_from_source");
+      if (gbe_program_new_from_source == NULL)
+        return;
+
+      gbe_program_serialize_to_binary = *(gbe_program_serialize_to_binary_cb **)dlsym(dlh, "gbe_program_serialize_to_binary");
+      if (gbe_program_serialize_to_binary == NULL)
+        return;
+
+      gbe_program_new_from_llvm = *(gbe_program_new_from_llvm_cb **)dlsym(dlh, "gbe_program_new_from_llvm");
+      if (gbe_program_new_from_llvm == NULL)
+        return;
+
+      //gbe_kernel_set_const_buffer_size is not used by runttime
+      gbe_kernel_set_const_buffer_size = *(gbe_kernel_set_const_buffer_size_cb **)dlsym(dlh, "gbe_kernel_set_const_buffer_size");
+      if (gbe_kernel_set_const_buffer_size == NULL)
+        return;
+
+      gbe_set_image_base_index_compiler = *(gbe_set_image_base_index_cb **)dlsym(dlh, "gbe_set_image_base_index_compiler");
+      if (gbe_set_image_base_index_compiler == NULL)
+        return;
+
+      inited = true;
+    }
+  }
+
+  ~GbeLoaderInitializer() {
+    if (dlh != NULL)
+      dlclose(dlh);
+  }
+
+  bool inited;
+  void *dlh;
+};
+
+static struct GbeLoaderInitializer gbeLoader;
+
+int CompilerSupported()
+{
+  if (gbeLoader.inited)
+    return 1;
+  else
+    return 0;
+}
diff --git a/src/cl_gbe_loader.h b/src/cl_gbe_loader.h
new file mode 100644
index 0000000..50ec55b
--- /dev/null
+++ b/src/cl_gbe_loader.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __CL_GBE_LOADER_H__
+#define __CL_GBE_LOADER_H__
+
+#include "program.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int CompilerSupported();
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CL_GBE_LOADER_H__ */
diff --git a/src/cl_kernel.h b/src/cl_kernel.h
index fb509a2..8d0e566 100644
--- a/src/cl_kernel.h
+++ b/src/cl_kernel.h
@@ -22,7 +22,7 @@
 
 #include "cl_internals.h"
 #include "cl_driver.h"
-#include "program.h"
+#include "cl_gbe_loader.h"
 #include "CL/cl.h"
 
 #include <stdint.h>
diff --git a/src/cl_program.c b/src/cl_program.c
index 184d6b5..c4e85d1 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -24,6 +24,7 @@
 #include "cl_alloc.h"
 #include "cl_utils.h"
 #include "cl_khr_icd.h"
+#include "cl_gbe_loader.h"
 #include "CL/cl.h"
 #include "CL/cl_intel.h"
 
@@ -326,6 +327,11 @@ cl_program_build(cl_program p, const char *options)
   }
 
   if (p->source_type == FROM_SOURCE) {
+    if (!CompilerSupported()) {
+      err = CL_COMPILER_NOT_AVAILABLE;
+      goto error;
+    }
+
     p->opaque = gbe_program_new_from_source(p->ctx->device->vendor_id, p->source, p->build_log_max_sz, options, p->build_log, &p->build_log_sz);
     if (UNLIKELY(p->opaque == NULL)) {
       if (p->build_log_sz > 0 && strstr(p->build_log, "error: error reading 'options'"))
diff --git a/src/cl_program.h b/src/cl_program.h
index a6d75da..4218efd 100644
--- a/src/cl_program.h
+++ b/src/cl_program.h
@@ -21,7 +21,7 @@
 #define __CL_PROGRAM_H__
 
 #include "cl_internals.h"
-#include "program.h"
+#include "cl_gbe_loader.h"
 #include "CL/cl.h"
 
 #include <stdint.h>
diff --git a/src/intel/intel_driver.c b/src/intel/intel_driver.c
index 7fd2bf3..1faffb8 100644
--- a/src/intel/intel_driver.c
+++ b/src/intel/intel_driver.c
@@ -380,7 +380,8 @@ cl_intel_driver_delete(intel_driver_t *driver)
   intel_driver_terminate(driver);
   intel_driver_delete(driver);
 }
-#include "program.h"
+
+#include "cl_gbe_loader.h"
 static intel_driver_t*
 cl_intel_driver_new(cl_context_prop props)
 {
@@ -390,7 +391,9 @@ cl_intel_driver_new(cl_context_prop props)
   /* We use the first 2 slots(0,1) for all the bufs.
    * Notify the gbe this base index, thus gbe can avoid conflicts
    * when it allocates slots for images*/
-  gbe_set_image_base_index(3);
+  if (CompilerSupported())
+    gbe_set_image_base_index_compiler(3);
+  gbe_set_image_base_index_interp(3);
 exit:
   return driver;
 error:
diff --git a/utests/setenv.sh.in b/utests/setenv.sh.in
index ad77369..95f468b 100644
--- a/utests/setenv.sh.in
+++ b/utests/setenv.sh.in
@@ -3,3 +3,4 @@
 export OCL_PCM_PATH=@LOCAL_PCM_OBJECT_DIR@
 export OCL_PCH_PATH=@LOCAL_PCH_OBJECT_DIR@
 export OCL_KERNEL_PATH=@CMAKE_CURRENT_SOURCE_DIR@/../kernels
+export OCL_GBE_PATH=@LOCAL_GBE_OBJECT_DIR@
-- 
1.8.3.2



More information about the Beignet mailing list