clover: Define platform class and merge with device_registry.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 6 Apr 2013 12:35:00 +0000 (14:35 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 13 Apr 2013 12:20:16 +0000 (14:20 +0200)
Null platform IDs are OK according to the spec, but some applications have
been reported to get paranoid and assume that our NULL platform is unusable.

As it doesn't hurt to have device enumeration separate from the rest of the
device code (quite the opposite, it makes the code cleaner), make the API use
an actual platform object that keeps track of the available devices instead of
the former NULL pointer.

Reported-and-reviewed-by: Tom Stellard <thomas.stellard@amd.com>
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
src/gallium/state_trackers/clover/Makefile.am
src/gallium/state_trackers/clover/api/context.cpp
src/gallium/state_trackers/clover/api/device.cpp
src/gallium/state_trackers/clover/api/platform.cpp
src/gallium/state_trackers/clover/core/device.cpp
src/gallium/state_trackers/clover/core/device.hpp
src/gallium/state_trackers/clover/core/platform.cpp [new file with mode: 0644]
src/gallium/state_trackers/clover/core/platform.hpp [new file with mode: 0644]

index 33ff03d77ee2c5ee20f1fcaf3fa3b0e15ee7515f..b4c197ab139d712368d0c7edecadc6550aaf5338 100644 (file)
@@ -50,6 +50,8 @@ libclover_la_SOURCES = \
        core/format.cpp \
        core/memory.hpp \
        core/memory.cpp \
+       core/platform.hpp \
+       core/platform.cpp \
        core/resource.hpp \
        core/resource.cpp \
        core/sampler.hpp \
index 80afb6bf4ec20a773fcaa129e212cbc7470d3862..99b9566640133bcdbec075e2fb8f02dd9b120172 100644 (file)
@@ -41,8 +41,7 @@ clCreateContext(const cl_context_properties *props, cl_uint num_devs,
       throw error(CL_INVALID_DEVICE);
 
    for (auto p : mprops) {
-      if (!(p.first == CL_CONTEXT_PLATFORM &&
-            (cl_platform_id)p.second == NULL))
+      if (p.first != CL_CONTEXT_PLATFORM)
          throw error(CL_INVALID_PROPERTY);
    }
 
@@ -61,17 +60,25 @@ clCreateContextFromType(const cl_context_properties *props,
                         cl_device_type type,
                         void (CL_CALLBACK *pfn_notify)(
                            const char *, const void *, size_t, void *),
-                        void *user_data, cl_int *errcode_ret) {
+                        void *user_data, cl_int *errcode_ret) try {
+   cl_platform_id platform;
+   cl_uint num_platforms;
    cl_device_id dev;
    cl_int ret;
 
-   ret = clGetDeviceIDs(0, type, 1, &dev, 0);
-   if (ret) {
-      ret_error(errcode_ret, ret);
-      return NULL;
-   }
+   ret = clGetPlatformIDs(1, &platform, &num_platforms);
+   if (ret || !num_platforms)
+      throw error(CL_INVALID_PLATFORM);
+
+   ret = clGetDeviceIDs(platform, type, 1, &dev, 0);
+   if (ret)
+      throw error(CL_DEVICE_NOT_FOUND);
 
    return clCreateContext(props, 1, &dev, pfn_notify, user_data, errcode_ret);
+
+} catch(error &e) {
+   ret_error(errcode_ret, e);
+   return NULL;
 }
 
 PUBLIC cl_int
index cf68d0fc18c4d109adf247bb8c829a7a56c31568..cd8095d3c7ecc7c6948524a499abe648f0e13134 100644 (file)
 //
 
 #include "api/util.hpp"
+#include "core/platform.hpp"
 #include "core/device.hpp"
 
 using namespace clover;
 
-static device_registry registry;
-
 PUBLIC cl_int
 clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type,
                cl_uint num_entries, cl_device_id *devices,
                cl_uint *num_devices) {
    std::vector<cl_device_id> devs;
 
-   if (platform != NULL)
-      return CL_INVALID_PLATFORM;
-
    if ((!num_entries && devices) ||
        (!num_devices && !devices))
       return CL_INVALID_VALUE;
 
    // Collect matching devices
-   for (device &dev : registry) {
+   for (device &dev : *platform) {
       if (((device_type & CL_DEVICE_TYPE_DEFAULT) &&
-           &dev == &registry.front()) ||
+           &dev == &platform->front()) ||
           (device_type & dev.type()))
          devs.push_back(&dev);
    }
@@ -223,13 +219,15 @@ clGetDeviceInfo(cl_device_id dev, cl_device_info param,
       return string_property(buf, size, size_ret, "FULL_PROFILE");
 
    case CL_DEVICE_VERSION:
-      return string_property(buf, size, size_ret, "OpenCL 1.1 MESA " PACKAGE_VERSION);
+      return string_property(buf, size, size_ret,
+                             "OpenCL 1.1 MESA " PACKAGE_VERSION);
 
    case CL_DEVICE_EXTENSIONS:
       return string_property(buf, size, size_ret, "");
 
    case CL_DEVICE_PLATFORM:
-      return scalar_property<cl_platform_id>(buf, size, size_ret, NULL);
+      return scalar_property<cl_platform_id>(buf, size, size_ret,
+                                             &dev->platform);
 
    case CL_DEVICE_HOST_UNIFIED_MEMORY:
       return scalar_property<cl_bool>(buf, size, size_ret, CL_TRUE);
index f99b6949356326834e00fbf758b2c6197e114edb..90111c7e2dc87b1255e915376b6adaf4e91b45a5 100644 (file)
 //
 
 #include "api/util.hpp"
+#include "core/platform.hpp"
 
 using namespace clover;
 
+static platform __platform;
+
 PUBLIC cl_int
 clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms,
                  cl_uint *num_platforms) {
@@ -34,7 +37,7 @@ clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms,
    if (num_platforms)
       *num_platforms = 1;
    if (platforms)
-      *platforms = NULL;
+      *platforms = &__platform;
 
    return CL_SUCCESS;
 }
@@ -42,7 +45,7 @@ clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms,
 PUBLIC cl_int
 clGetPlatformInfo(cl_platform_id platform, cl_platform_info param_name,
                   size_t size, void *buf, size_t *size_ret) {
-   if (platform != NULL)
+   if (platform != &__platform)
       return CL_INVALID_PLATFORM;
 
    switch (param_name) {
index d93a1f6ac6c42a1ffbc4f49f5ae789082ee1d4fb..fde8135cbeb403c160985f007e2a7797ee5166c9 100644 (file)
@@ -38,15 +38,18 @@ namespace {
    }
 }
 
-_cl_device_id::_cl_device_id(pipe_loader_device *ldev) : ldev(ldev) {
+_cl_device_id::_cl_device_id(clover::platform &platform,
+                             pipe_loader_device *ldev) :
+   platform(platform), ldev(ldev) {
    pipe = pipe_loader_create_screen(ldev, PIPE_SEARCH_DIR);
    if (!pipe || !pipe->get_param(pipe, PIPE_CAP_COMPUTE))
       throw error(CL_INVALID_DEVICE);
 }
 
-_cl_device_id::_cl_device_id(_cl_device_id &&dev) : pipe(dev.pipe), ldev(dev.ldev) {
-   dev.ldev = NULL;
+_cl_device_id::_cl_device_id(_cl_device_id &&dev) :
+   platform(dev.platform), pipe(dev.pipe), ldev(dev.ldev) {
    dev.pipe = NULL;
+   dev.ldev = NULL;
 }
 
 _cl_device_id::~_cl_device_id() {
@@ -56,6 +59,16 @@ _cl_device_id::~_cl_device_id() {
       pipe_loader_release(&ldev, 1);
 }
 
+_cl_device_id &
+_cl_device_id::operator=(_cl_device_id dev) {
+   assert(&platform == &dev.platform);
+
+   std::swap(pipe, dev.pipe);
+   std::swap(ldev, dev.ldev);
+
+   return *this;
+}
+
 cl_device_type
 _cl_device_id::type() const {
    switch (ldev->type) {
@@ -179,16 +192,3 @@ _cl_device_id::ir_target() const {
                                                     PIPE_COMPUTE_CAP_IR_TARGET);
    return { target.data() };
 }
-
-device_registry::device_registry() {
-   int n = pipe_loader_probe(NULL, 0);
-   std::vector<pipe_loader_device *> ldevs(n);
-
-   pipe_loader_probe(&ldevs.front(), n);
-
-   for (pipe_loader_device *ldev : ldevs) {
-      try {
-         devs.emplace_back(ldev);
-      } catch (error &) {}
-   }
-}
index 5b92751cbcde0cef307c327709417700e38f9ba0..09c3a1cc4ddce245fb0bb52c1686b250934897b9 100644 (file)
 
 namespace clover {
    typedef struct _cl_device_id device;
+   typedef struct _cl_platform_id platform;
    class root_resource;
    class hard_event;
 }
 
 struct _cl_device_id {
 public:
-   _cl_device_id(pipe_loader_device *ldev);
+   _cl_device_id(clover::platform &platform, pipe_loader_device *ldev);
    _cl_device_id(_cl_device_id &&dev);
    _cl_device_id(const _cl_device_id &dev) = delete;
    ~_cl_device_id();
 
+   _cl_device_id &operator=(_cl_device_id dev);
+
    cl_device_type type() const;
    cl_uint vendor_id() const;
    size_t max_images_read() const;
@@ -70,41 +73,11 @@ public:
    friend std::set<cl_image_format>
    clover::supported_formats(cl_context, cl_mem_object_type);
 
+   clover::platform &platform;
+
 private:
    pipe_screen *pipe;
    pipe_loader_device *ldev;
 };
 
-namespace clover {
-   ///
-   /// Container of all the compute devices that are available in the
-   /// system.
-   ///
-   class device_registry {
-   public:
-      typedef std::vector<device>::iterator iterator;
-
-      device_registry();
-
-      iterator begin() {
-         return devs.begin();
-      }
-
-      iterator end() {
-         return devs.end();
-      }
-
-      device &front() {
-         return devs.front();
-      }
-
-      device &back() {
-         return devs.back();
-      }
-
-   protected:
-      std::vector<device> devs;
-   };
-}
-
 #endif
diff --git a/src/gallium/state_trackers/clover/core/platform.cpp b/src/gallium/state_trackers/clover/core/platform.cpp
new file mode 100644 (file)
index 0000000..a17b992
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright 2012 Francisco Jerez
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+#include "core/platform.hpp"
+
+using namespace clover;
+
+_cl_platform_id::_cl_platform_id() {
+   int n = pipe_loader_probe(NULL, 0);
+   std::vector<pipe_loader_device *> ldevs(n);
+
+   pipe_loader_probe(&ldevs.front(), n);
+
+   for (pipe_loader_device *ldev : ldevs) {
+      try {
+         devs.emplace_back(*this, ldev);
+      } catch (error &) {}
+   }
+}
diff --git a/src/gallium/state_trackers/clover/core/platform.hpp b/src/gallium/state_trackers/clover/core/platform.hpp
new file mode 100644 (file)
index 0000000..eeb6d60
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Copyright 2013 Francisco Jerez
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+#ifndef __CORE_PLATFORM_HPP__
+#define __CORE_PLATFORM_HPP__
+
+#include <vector>
+
+#include "core/base.hpp"
+#include "core/device.hpp"
+
+namespace clover {
+   typedef struct _cl_platform_id platform;
+}
+
+struct _cl_platform_id {
+public:
+   typedef std::vector<clover::device>::iterator iterator;
+
+   _cl_platform_id();
+
+   ///
+   /// Container of all compute devices that are available in the platform.
+   ///
+   /// @{
+   iterator begin() {
+      return devs.begin();
+   }
+
+   iterator end() {
+      return devs.end();
+   }
+
+   clover::device &front() {
+      return devs.front();
+   }
+
+   clover::device &back() {
+      return devs.back();
+   }
+   /// @}
+
+protected:
+   std::vector<clover::device> devs;
+};
+
+#endif