                ^CLDevice *device* (or (:device s#) *device*)
                ^CLProgram *program* (or (:program s#) *program*)
                ^CLCommandQueue *queue* (or (:queue s#) *queue*)]
-     (do ~@body))))
+       (do ~@body))))
 
 ;; # CL inquiries & utilities
 
+(defn available-platforms
+  "Returns an array of available CL platforms."
+  [] (into [] (CLPlatform/listCLPlatforms)))
+
+(defn ^CLPlatform select-platform
+  "Returns the platform matching the given filter criteria
+  (see `platform-xxx` filter fns). Without arguments, selects
+  the platform with the latest OpenCL version."
+  ([] (CLPlatform/getDefault))
+  ([f & more] (CLPlatform/getDefault (into-array (cons f more)))))
+
+(defn platform-extensions
+  "Returns a set of OpenCL extension names"
+  [^CLPlatform p] (into #{} (.getExtensions p)))
+
+(defn available-devices
+  "Returns a vector of devices associated with the given context or platform
+  (defaults to current `*context*`). A device type keyword can be specified
+  to filter results optionally."
+  ([ctx-or-platform] (available-devices ctx-or-platform :all))
+  ([ctx-or-platform dev-type]
+     (cond
+      (isa? (type ctx-or-platform) CLContext)
+      (vec (filter #(= (.getType ^CLDevice %) (device-types dev-type))
+                   (.getDevices ^CLContext ctx-or-platform)))
+      (isa? (type ctx-or-platform) CLPlatform)
+      (into [] (.listCLDevices ^CLPlatform ctx-or-platform
+                               (into-array [(device-types dev-type)])))
+      :default
+      (throw (IllegalArgumentException. "Argument is not a CLContext or CLPlatform")))))
+
 (defn ^CLDevice max-device
-  "Returns the maximum FLOPS device for the given `context` (or default `*context*`).
-   An additional device type can be given optionally (see `device-types`)."
+  "Returns the maximum FLOPS device for the given context or platform
+  (default current `*context*`). An additional device type can be given
+  optionally (see `device-types`)."
   ([] (.getMaxFlopsDevice ^CLContext *context*))
-  ([^CLContext ctx] (.getMaxFlopsDevice ctx))
-  ([^CLContext ctx type]
-    (.getMaxFlopsDevice ctx (get device-types type CLDevice$Type/DEFAULT))))
+  ([ctx-or-platform] (.getMaxFlopsDevice ctx-or-platform))
+  ([ctx-or-platform dev-type]
+     (cond
+      (isa? (type ctx-or-platform) CLContext)
+      (.getMaxFlopsDevice ctx-or-platform
+                          (get device-types dev-type CLDevice$Type/DEFAULT))
+      (isa? (type ctx-or-platform) CLPlatform)
+      (.getMaxFlopsDevice ctx-or-platform
+                          (into-array (get device-types dev-type CLDevice$Type/DEFAULT)))
+      :default
+      (throw (IllegalArgumentException. "Argument is not a CLContext or CLPlatform")))))
 
 (defn max-workgroup-size
   "Returns the maximum local workgroup size for the given `kernel` and `device`.


(def device-types
  "Common OpenCL device types."
  {:cpu CLDevice$Type/CPU
   :gpu CLDevice$Type/GPU
   :accelerator CLDevice$Type/ACCELERATOR})


  ([] (build-log *program* *device*))
  ([^CLProgram program] (build-log program *device*))
  ([^CLProgram program ^CLDevice device]
     (.getBuildLog program device)))

(defn build-status
  "Returns the build status of `program` for the given `device`.
