From fed6f6e570883d223581c231c5594856795a129f Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Fri, 18 Jun 2010 02:14:06 -0400
Subject: [PATCH] Implement CL 1.1. sub-buffer creation.

---
 doc/make_constants.py                     |  2 +-
 doc/source/index.rst                      |  2 +-
 doc/source/{reference.rst => runtime.rst} | 13 ++++-
 doc/upload-docs.sh                        |  1 +
 src/wrapper/wrap_cl.cpp                   |  9 ++++
 src/wrapper/wrap_cl.hpp                   | 64 ++++++++++++++++++++---
 6 files changed, 79 insertions(+), 12 deletions(-)
 rename doc/source/{reference.rst => runtime.rst} (97%)

diff --git a/doc/make_constants.py b/doc/make_constants.py
index 07d140d9..3b60fc7c 100644
--- a/doc/make_constants.py
+++ b/doc/make_constants.py
@@ -104,7 +104,7 @@ const_ext_lookup = {
         }
 
 cls_ext_lookup = {
-        cl.buffer_create_type: ("CL_1.1", "0.92"),
+        #cl.buffer_create_type: ("CL_1.1", "0.92"),
         }
 
 
diff --git a/doc/source/index.rst b/doc/source/index.rst
index f1f1747f..9fd85142 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -69,7 +69,7 @@ Contents
 .. toctree::
     :maxdepth: 2
 
-    reference
+    runtime
     misc
 
 Note that this guide does not explain OpenCL programming and technology. Please 
diff --git a/doc/source/reference.rst b/doc/source/runtime.rst
similarity index 97%
rename from doc/source/reference.rst
rename to doc/source/runtime.rst
index 349c6e06..238c7268 100644
--- a/doc/source/reference.rst
+++ b/doc/source/runtime.rst
@@ -1,7 +1,7 @@
 .. _reference-doc:
 
-Reference Documentation
-=======================
+OpenCL Platform/Runtime Documentation
+=====================================
 
 Version Queries
 ---------------
@@ -260,6 +260,15 @@ Buffers
 
     :class:`Buffer` is a subclass of :class:`MemoryObject`.
 
+    .. method:: get_sub_region(origin, size, flags=0)
+
+    .. method:: __getitem__(slc)
+
+        *slc* is a :class:`slice` object indicating from which byte index range
+        a sub-buffer is to be created. The *flags* argument of
+        :meth:`get_sub_region` is set to the same flags with which *self* was
+        created.
+
 .. function:: enqueue_read_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, is_blocking=False)
 
     |std-enqueue-blurb|
diff --git a/doc/upload-docs.sh b/doc/upload-docs.sh
index bdc4e689..cd5e34f1 100755
--- a/doc/upload-docs.sh
+++ b/doc/upload-docs.sh
@@ -1,3 +1,4 @@
 #! /bin/sh
 
+cp build/html/runtime.rst build/html/reference.rst
 rsync --progress --verbose --archive --delete build/html/* buster:doc/pyopencl
diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp
index 1d37a053..66d2984a 100644
--- a/src/wrapper/wrap_cl.cpp
+++ b/src/wrapper/wrap_cl.cpp
@@ -464,12 +464,14 @@ BOOST_PYTHON_MODULE(_cl)
     ADD_ATTR(PROFILING_COMMAND_, END);
   }
 
+/* not needed--filled in automatically by implementation.
 #ifdef CL_VERSION_1_1
   {
     py::class_<buffer_create_type> cls("buffer_create_type", py::no_init);
     ADD_ATTR(BUFFER_CREATE_TYPE_, REGION);
   }
 #endif
+*/
 
   // }}}
 
@@ -588,6 +590,13 @@ BOOST_PYTHON_MODULE(_cl)
              py::arg("size")=0,
              py::arg("hostbuf")=py::object()
             )))
+#ifdef CL_VERSION_1_1
+      .def("get_sub_region", &cls::get_sub_region,
+          (py::args("origin", "size"), py::arg("flags")=0),
+          py::return_value_policy<py::manage_new_object>())
+      .def("__getitem__", &cls::getitem,
+          py::return_value_policy<py::manage_new_object>())
+#endif
       ;
   }
 
diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp
index 0dc5edf3..ea4c0ccc 100644
--- a/src/wrapper/wrap_cl.hpp
+++ b/src/wrapper/wrap_cl.hpp
@@ -1074,42 +1074,90 @@ namespace pyopencl
       buffer(cl_mem mem, bool retain, py::object *hostbuf=0)
         : memory_object(mem, retain, hostbuf)
       { }
+
+#ifdef CL_VERSION_1_1
+      buffer *get_sub_region(
+          size_t origin, size_t size, cl_mem_flags flags) const
+      {
+        cl_buffer_region region = { origin, size};
+        cl_int status_code;
+        cl_mem mem = clCreateSubBuffer(data(), flags, 
+            CL_BUFFER_CREATE_TYPE_REGION, &region, &status_code);
+
+        PYOPENCL_PRINT_CALL_TRACE("clCreateSubBuffer");
+        if (status_code != CL_SUCCESS)
+          throw pyopencl::error("Buffer.get_sub_region", status_code);
+
+        try
+        {
+          return new buffer(mem, false);
+        }
+        catch (...)
+        {
+          PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
+          throw;
+        }
+      }
+
+      buffer *getitem(py::object slc) const
+      {
+        Py_ssize_t start, end, stride, length;
+
+        size_t my_length;
+        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
+            (data(), CL_MEM_SIZE, sizeof(my_length), &my_length, 0));
+
+        if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject *>(slc.ptr()),
+              my_length, &start, &end, &stride, &length) != 0)
+          throw py::error_already_set();
+
+        if (stride != 1)
+          throw pyopencl::error("Buffer.__getitem__", CL_INVALID_VALUE,
+              "Buffer slice must have stride 1");
+
+        cl_mem_flags my_flags;
+        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
+            (data(), CL_MEM_FLAGS, sizeof(my_flags), &my_flags, 0));
+
+        return get_sub_region(start, end, my_flags);
+      }
+#endif
   };
 
 
 
 
-  memory_object *create_buffer(
+  buffer *create_buffer(
       context &ctx,
       cl_mem_flags flags,
       size_t size,
-      py::object buffer
+      py::object py_hostbuf
       )
   {
-    if (buffer.ptr() != Py_None && 
+    if (py_hostbuf.ptr() != Py_None && 
         !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)))
       PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, "
           "but no memory flags to make use of it.");
 
     void *buf = 0;
     py::object *retained_buf_obj = 0;
-    if (buffer.ptr() != Py_None)
+    if (py_hostbuf.ptr() != Py_None)
     {
       PYOPENCL_BUFFER_SIZE_T len;
       if (flags & CL_MEM_USE_HOST_PTR)
       {
-        if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
+        if (PyObject_AsWriteBuffer(py_hostbuf.ptr(), &buf, &len))
           throw py::error_already_set();
       }
       else
       {
         if (PyObject_AsReadBuffer(
-              buffer.ptr(), const_cast<const void **>(&buf), &len))
+              py_hostbuf.ptr(), const_cast<const void **>(&buf), &len))
           throw py::error_already_set();
       }
 
       if (flags & CL_MEM_USE_HOST_PTR)
-        retained_buf_obj = &buffer;
+        retained_buf_obj = &py_hostbuf;
 
       if (size > size_t(len))
         throw pyopencl::error("Buffer", CL_INVALID_VALUE,
@@ -1127,7 +1175,7 @@ namespace pyopencl
 
     try
     {
-      return new memory_object(mem, false, retained_buf_obj);
+      return new buffer(mem, false, retained_buf_obj);
     }
     catch (...)
     {
-- 
GitLab