Ejemplo n.º 1
0
  protected <T extends CPPObject> Pointer<T> newCPPInstance(
      T instance, final Type type, int constructorId, Object... args) {
    Pointer<T> peer = null;
    try {
      final Class<T> typeClass = Utils.getClass(type);
      NativeLibrary lib = BridJ.getNativeLibrary(typeClass);

      if (BridJ.debug)
        info("Creating C++ instance of type " + type + " with args " + Arrays.asList(args));
      Pointer.Releaser releaser = newCPPReleaser(type, typeClass, lib);

      long size = sizeOf(type, null);
      peer = (Pointer) Pointer.allocateBytes(PointerIO.getInstance(type), size, releaser).as(type);

      DynamicFunction constructor =
          constructorId == SKIP_CONSTRUCTOR
              ? null
              : getConstructor(typeClass, type, lib, constructorId);

      if (lib != null && CPPObject.class.isAssignableFrom(typeClass)) {
        installRegularVTablePtr(type, lib, peer);
      } else {
        // TODO ObjCObject : call alloc on class type !!
      }

      // Setting the C++ template parameters in the instance :
      int templateParametersCount = getTemplateParametersCount(typeClass);
      if (templateParametersCount > 0) {
        Object[] templateArgs = new Object[templateParametersCount];
        System.arraycopy(args, 0, templateArgs, 0, templateParametersCount);
        setTemplateParameters(instance, typeClass, templateArgs);
      }

      // Calling the constructor with the non-template parameters :
      if (constructor != null) {
        Object[] consThisArgs = new Object[args.length - templateParametersCount + 1];
        consThisArgs[0] = peer;
        System.arraycopy(
            args, templateParametersCount, consThisArgs, 1, args.length - templateParametersCount);

        constructor.apply(consThisArgs);
      }

      // Install synthetic virtual table and associate the Java instance to the corresponding native
      // pointer :
      if (CPPObject.class.isAssignableFrom(typeClass)) {
        if (installSyntheticVTablePtr(type, lib, peer))
          BridJ.setJavaObjectFromNativePeer(peer.getPeer(), instance);
      } else {
        // TODO ObjCObject : call alloc on class type !!
      }
      return peer;
    } catch (Exception ex) {
      ex.printStackTrace();
      if (peer != null) {
        peer.release();
      }
      throw new RuntimeException("Failed to allocate new instance of type " + type, ex);
    }
  }
Ejemplo n.º 2
0
  static {
    {
      OpenCLProbeLibrary probe = new OpenCLProbeLibrary();
      try {
        if (!probe.isValid()) {
          String alt;
          if (Platform.is64Bits() && BridJ.getNativeLibraryFile(alt = "atiocl64") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl32") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl") != null) {
            log(
                Level.INFO,
                "Hacking around ATI's weird driver bugs (using atiocl library instead of OpenCL)",
                null);
            BridJ.setNativeLibraryActualName("OpenCL", alt);
          }
        }
      } finally {
        probe = null;
        BridJ.unregister(OpenCLProbeLibrary.class);
      }
    }

    if (debug) {
      String debugArgs = System.getenv(JAVACL_DEBUG_COMPILER_FLAGS_PROP);
      if (debugArgs != null) DEBUG_COMPILER_FLAGS = Arrays.asList(debugArgs.split(" "));
      else if (Platform.isMacOSX()) DEBUG_COMPILER_FLAGS = Arrays.asList("-g");
      else DEBUG_COMPILER_FLAGS = Arrays.asList("-O0", "-g");

      int pid = ProcessUtils.getCurrentProcessId();
      log(
          Level.INFO,
          "Debug mode enabled with compiler flags \""
              + StringUtils.implode(DEBUG_COMPILER_FLAGS, " ")
              + "\" (can be overridden with env. var. JAVACL_DEBUG_COMPILER_FLAGS_PROP)");
      log(
          Level.INFO,
          "You can debug your kernels with GDB using one of the following commands :\n"
              + "\tsudo gdb --tui --pid="
              + pid
              + "\n"
              + "\tsudo ddd --debugger \"gdb --pid="
              + pid
              + "\"\n"
              + "More info here :\n"
              + "\thttp://code.google.com/p/javacl/wiki/DebuggingKernels");
    }
    CL = new OpenCLLibrary();
  }
Ejemplo n.º 3
0
/**
 * Entry point class for the OpenCL4Java Object-oriented wrappers around the OpenCL API.<br>
 *
 * @author Olivier Chafik
 */
public class JavaCL {

  static final boolean debug =
      "true".equals(System.getProperty("javacl.debug"))
          || "1".equals(System.getenv("JAVACL_DEBUG"));
  static final boolean verbose =
      debug
          || "true".equals(System.getProperty("javacl.verbose"))
          || "1".equals(System.getenv("JAVACL_VERBOSE"));
  static final int minLogLevel = Level.WARNING.intValue();

  static final String JAVACL_DEBUG_COMPILER_FLAGS_PROP = "JAVACL_DEBUG_COMPILER_FLAGS";
  static List<String> DEBUG_COMPILER_FLAGS;

  static boolean shouldLog(Level level) {
    return verbose || level.intValue() >= minLogLevel;
  }

  static boolean log(Level level, String message, Throwable ex) {
    if (!shouldLog(level)) return true;
    Logger.getLogger(JavaCL.class.getSimpleName()).log(level, message, ex);
    return true;
  }

  static boolean log(Level level, String message) {
    log(level, message, null);
    return true;
  }

  private static int getPlatformIDs(
      int count, Pointer<cl_platform_id> out, Pointer<Integer> pCount) {
    try {
      return CL.clIcdGetPlatformIDsKHR(count, out, pCount);
    } catch (Throwable th) {
      return CL.clGetPlatformIDs(count, out, pCount);
    }
  }

  @org.bridj.ann.Library("OpenCLProbe")
  @org.bridj.ann.Convention(org.bridj.ann.Convention.Style.StdCall)
  public static class OpenCLProbeLibrary {
    static {
      BridJ.setNativeLibraryActualName("OpenCLProbe", "OpenCL");
      BridJ.register();
    }

    @org.bridj.ann.Optional
    public static synchronized native int clGetPlatformIDs(
        int cl_uint1,
        Pointer<OpenCLLibrary.cl_platform_id> cl_platform_idPtr1,
        Pointer<Integer> cl_uintPtr1);

    @org.bridj.ann.Optional
    public static synchronized native int clIcdGetPlatformIDsKHR(
        int cl_uint1,
        Pointer<OpenCLLibrary.cl_platform_id> cl_platform_idPtr1,
        Pointer<Integer> cl_uintPtr1);

    public boolean isValid() {
      Pointer<Integer> pCount = allocateInt();
      int err;
      try {
        err = clIcdGetPlatformIDsKHR(0, null, pCount);
      } catch (Throwable th) {
        try {
          err = clGetPlatformIDs(0, null, pCount);
        } catch (Throwable th2) {
          return false;
        }
      }
      return err == OpenCLLibrary.CL_SUCCESS && pCount.get() > 0;
    }
  }

  static final OpenCLLibrary CL;

  static {
    {
      OpenCLProbeLibrary probe = new OpenCLProbeLibrary();
      try {
        if (!probe.isValid()) {
          String alt;
          if (Platform.is64Bits() && BridJ.getNativeLibraryFile(alt = "atiocl64") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl32") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl") != null) {
            log(
                Level.INFO,
                "Hacking around ATI's weird driver bugs (using atiocl library instead of OpenCL)",
                null);
            BridJ.setNativeLibraryActualName("OpenCL", alt);
          }
        }
      } finally {
        probe = null;
        BridJ.unregister(OpenCLProbeLibrary.class);
      }
    }

    if (debug) {
      String debugArgs = System.getenv(JAVACL_DEBUG_COMPILER_FLAGS_PROP);
      if (debugArgs != null) DEBUG_COMPILER_FLAGS = Arrays.asList(debugArgs.split(" "));
      else if (Platform.isMacOSX()) DEBUG_COMPILER_FLAGS = Arrays.asList("-g");
      else DEBUG_COMPILER_FLAGS = Arrays.asList("-O0", "-g");

      int pid = ProcessUtils.getCurrentProcessId();
      log(
          Level.INFO,
          "Debug mode enabled with compiler flags \""
              + StringUtils.implode(DEBUG_COMPILER_FLAGS, " ")
              + "\" (can be overridden with env. var. JAVACL_DEBUG_COMPILER_FLAGS_PROP)");
      log(
          Level.INFO,
          "You can debug your kernels with GDB using one of the following commands :\n"
              + "\tsudo gdb --tui --pid="
              + pid
              + "\n"
              + "\tsudo ddd --debugger \"gdb --pid="
              + pid
              + "\"\n"
              + "More info here :\n"
              + "\thttp://code.google.com/p/javacl/wiki/DebuggingKernels");
    }
    CL = new OpenCLLibrary();
  }

  /** List the OpenCL implementations that contain at least one GPU device. */
  public static CLPlatform[] listGPUPoweredPlatforms() {
    CLPlatform[] platforms = listPlatforms();
    List<CLPlatform> out = new ArrayList<CLPlatform>(platforms.length);
    for (CLPlatform platform : platforms) {
      if (platform.listGPUDevices(true).length > 0) out.add(platform);
    }
    return out.toArray(new CLPlatform[out.size()]);
  }
  /** Lists all available OpenCL implementations. */
  public static CLPlatform[] listPlatforms() {
    Pointer<Integer> pCount = allocateInt();
    error(getPlatformIDs(0, null, pCount));

    int nPlats = pCount.get();
    if (nPlats == 0) return new CLPlatform[0];

    Pointer<cl_platform_id> ids = allocateTypedPointers(cl_platform_id.class, nPlats);

    error(getPlatformIDs(nPlats, ids, null));
    CLPlatform[] platforms = new CLPlatform[nPlats];

    for (int i = 0; i < nPlats; i++) {
      platforms[i] = new CLPlatform(ids.get(i));
    }
    return platforms;
  }

  /**
   * Creates an OpenCL context formed of the provided devices.<br>
   * It is generally not a good idea to create a context with more than one device, because much
   * data is shared between all the devices in the same context.
   *
   * @param devices devices that are to form the new context
   * @return new OpenCL context
   */
  public static CLContext createContext(
      Map<CLPlatform.ContextProperties, Object> contextProperties, CLDevice... devices) {
    return devices[0].getPlatform().createContext(contextProperties, devices);
  }

  /**
   * Allows the implementation to release the resources allocated by the OpenCL compiler. <br>
   * This is a hint from the application and does not guarantee that the compiler will not be used
   * in the future or that the compiler will actually be unloaded by the implementation. <br>
   * Calls to Program.build() after unloadCompiler() will reload the compiler, if necessary, to
   * build the appropriate program executable.
   */
  public static void unloadCompiler() {
    error(CL.clUnloadCompiler());
  }

  /**
   * Returns the "best" OpenCL device (currently, the one that has the largest amount of compute
   * units).<br>
   * For more control on what is to be considered a better device, please use the {@link
   * JavaCL#getBestDevice(CLPlatform.DeviceFeature[]) } variant.<br>
   * This is currently equivalent to <code>getBestDevice(MaxComputeUnits)</code>
   */
  public static CLDevice getBestDevice() {
    return getBestDevice(CLPlatform.DeviceFeature.MaxComputeUnits);
  }
  /**
   * Returns the "best" OpenCL device based on the comparison of the provided prioritized device
   * feature.<br>
   * The returned device does not necessarily exhibit the features listed in preferredFeatures, but
   * it has the best ordered composition of them.<br>
   * For instance on a system with a GPU and a CPU device, <code>
   * JavaCL.getBestDevice(CPU, MaxComputeUnits)</code> will return the CPU device, but on another
   * system with two GPUs and no CPU device it will return the GPU that has the most compute units.
   */
  public static CLDevice getBestDevice(CLPlatform.DeviceFeature... preferredFeatures) {
    List<CLDevice> devices = new ArrayList<CLDevice>();
    for (CLPlatform platform : listPlatforms())
      devices.addAll(Arrays.asList(platform.listAllDevices(true)));
    return CLPlatform.getBestDevice(Arrays.asList(preferredFeatures), devices);
  }
  /** Creates an OpenCL context with the "best" device (see {@link JavaCL#getBestDevice() }) */
  public static CLContext createBestContext() {
    return createBestContext(DeviceFeature.MaxComputeUnits);
  }

  /**
   * Creates an OpenCL context with the "best" device based on the comparison of the provided
   * prioritized device feature (see {@link JavaCL#getBestDevice(CLPlatform.DeviceFeature...) })
   */
  public static CLContext createBestContext(CLPlatform.DeviceFeature... preferredFeatures) {
    CLDevice device = getBestDevice(preferredFeatures);
    return device.getPlatform().createContext(null, device);
  }

  /**
   * Creates an OpenCL context able to share entities with the current OpenGL context.
   *
   * @throws RuntimeException if JavaCL is unable to create an OpenGL-shared OpenCL context.
   */
  public static CLContext createContextFromCurrentGL() {
    RuntimeException first = null;
    for (CLPlatform platform : listPlatforms()) {
      try {
        CLContext ctx = platform.createContextFromCurrentGL();
        if (ctx != null) return ctx;
      } catch (RuntimeException ex) {
        if (first == null) first = ex;
      }
    }
    throw new RuntimeException(
        "Failed to create an OpenCL context based on the current OpenGL context", first);
  }

  static File userJavaCLDir = new File(new File(System.getProperty("user.home")), ".javacl");
  static File userCacheDir = new File(userJavaCLDir, "cache");

  static synchronized File createTempFile(String prefix, String suffix, String category) {
    File dir = new File(userJavaCLDir, category);
    dir.mkdirs();
    try {
      return File.createTempFile(prefix, suffix, dir);
    } catch (IOException ex) {
      throw new RuntimeException(
          "Failed to create a temporary directory for category '"
              + category
              + "' in "
              + userJavaCLDir
              + ": "
              + ex.getMessage(),
          ex);
    }
  }

  static synchronized File createTempDirectory(String prefix, String suffix, String category) {
    File file = createTempFile(prefix, suffix, category);
    file.delete();
    file.mkdir();
    return file;
  }
}
Ejemplo n.º 4
0
  DynamicFunction getConstructor(
      final Class<?> typeClass, final Type type, NativeLibrary lib, int constructorId) {
    Pair<Type, Integer> key = new Pair<Type, Integer>(type, constructorId);
    DynamicFunction constructor = constructors.get(key);
    if (constructor == null) {
      try {
        final Constructor<?> constr;
        try {
          constr = findConstructor(typeClass, constructorId, true);

          if (debug) BridJ.info("Found constructor for " + Utils.toString(type) + " : " + constr);
        } catch (NoSuchMethodException ex) {
          if (debug) BridJ.info("No constructor for " + Utils.toString(type));
          return null;
        }
        Symbol symbol =
            lib == null
                ? null
                : lib.getFirstMatchingSymbol(
                    new SymbolAccepter() {
                      public boolean accept(Symbol symbol) {
                        return symbol.matchesConstructor(
                            constr.getDeclaringClass() == Utils.getClass(type)
                                ? type
                                : constr.getDeclaringClass() /* TODO */,
                            constr);
                      }
                    });
        if (symbol == null) {
          if (debug)
            BridJ.info("No matching constructor for " + Utils.toString(type) + " (" + constr + ")");
          return null;
        }

        if (debug) info("Registering constructor " + constr + " as " + symbol.getName());

        // TODO do something with these args !
        int templateParametersCount = getTemplateParametersCount(typeClass);

        Class<?>[] consParamTypes = constr.getParameterTypes();
        Class<?>[] consThisParamTypes =
            new Class[consParamTypes.length + 1 - templateParametersCount];
        consThisParamTypes[0] = Pointer.class;
        System.arraycopy(
            consParamTypes,
            templateParametersCount,
            consThisParamTypes,
            1,
            consParamTypes.length - templateParametersCount);

        DynamicFunctionFactory constructorFactory =
            getDynamicFunctionFactory(lib, Style.ThisCall, void.class, consThisParamTypes);

        constructor = constructorFactory.newInstance(pointerToAddress(symbol.getAddress()));
        constructors.put(key, constructor);
      } catch (Throwable th) {
        th.printStackTrace();
        throw new RuntimeException(
            "Unable to create constructor " + constructorId + " for " + type + " : " + th, th);
      }
    }
    return constructor;
  }