Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pyopencl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Andreas Klöckner
pyopencl
Commits
1d0cf8f9
Commit
1d0cf8f9
authored
11 years ago
by
Andreas Klöckner
Browse files
Options
Downloads
Patches
Plain Diff
Make cffi_cl flake8-clean
parent
d558affc
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
pyopencl/cffi_cl.py
+476
-187
476 additions, 187 deletions
pyopencl/cffi_cl.py
with
476 additions
and
187 deletions
pyopencl/cffi_cl.py
+
476
−
187
View file @
1d0cf8f9
from
pyopencl._cl
import
PooledBuffer
,
MemoryPool
from
__future__
import
division
__copyright__
=
"""
Copyright (C) 2013 Marko Bencun
Copyright (C) 2014 Andreas Kloeckner
"""
__license__
=
"""
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 OR COPYRIGHT HOLDERS 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.
"""
#from pyopencl._cl import PooledBuffer, MemoryPool
import
warnings
import
np
import
ctypes
import
sys
# TODO: can we do without ctypes?
import
ctypes
from
_cffi
import
_ffi
,
_lib
# are we running on pypy?
...
...
@@ -12,6 +42,11 @@ _PYPY = '__pypy__' in sys.builtin_module_names
bitlog2
=
_lib
.
bitlog2
# {{{ wrapper tools
# {{{ _CArray helper classes
class
_CArray
(
object
):
def
__init__
(
self
,
ptr
):
self
.
ptr
=
ptr
...
...
@@ -28,14 +63,124 @@ class _CArray(object):
for
i
in
xrange
(
self
.
size
[
0
]):
yield
self
[
i
]
class
_CArrays
(
_CArray
):
def
__del__
(
self
):
_lib
.
_free2
(
_ffi
.
cast
(
'
void**
'
,
self
.
ptr
[
0
]),
self
.
size
[
0
])
super
(
_CArrays
,
self
).
__del__
()
class
_NoInit
(
object
):
def
__init__
(
self
):
raise
RuntimeError
(
"
This class cannot be instantiated.
"
)
# }}}
# {{{ GetInfo support
def
_generic_info_to_python
(
info
):
type_
=
_ffi
.
string
(
info
.
type
)
value
=
_ffi
.
cast
(
type_
,
info
.
value
)
if
info
.
opaque_class
!=
_lib
.
CLASS_NONE
:
klass
=
{
_lib
.
CLASS_PLATFORM
:
Platform
,
_lib
.
CLASS_DEVICE
:
Device
,
_lib
.
CLASS_KERNEL
:
Kernel
,
_lib
.
CLASS_CONTEXT
:
Context
,
_lib
.
CLASS_BUFFER
:
Buffer
,
_lib
.
CLASS_PROGRAM
:
_Program
,
_lib
.
CLASS_EVENT
:
Event
,
_lib
.
CLASS_COMMAND_QUEUE
:
CommandQueue
}[
info
.
opaque_class
]
def
ci
(
ptr
):
ins
=
_create_instance
(
klass
,
ptr
)
if
info
.
opaque_class
==
_lib
.
CLASS_PROGRAM
:
# TODO: HACK?
from
.
import
Program
return
Program
(
ins
)
return
ins
if
type_
.
endswith
(
'
]
'
):
ret
=
map
(
ci
,
value
)
_lib
.
_free
(
info
.
value
)
return
ret
else
:
return
ci
(
value
)
if
type_
==
'
char*
'
:
ret
=
_ffi
.
string
(
value
)
elif
type_
.
startswith
(
'
char*[
'
):
ret
=
map
(
_ffi
.
string
,
value
)
_lib
.
_free2
(
info
.
value
,
len
(
value
))
elif
type_
.
endswith
(
'
]
'
):
if
type_
.
startswith
(
'
char[
'
):
ret
=
''
.
join
(
a
[
0
]
for
a
in
value
)
elif
type_
.
startswith
(
'
generic_info[
'
):
ret
=
list
(
map
(
_generic_info_to_python
,
value
))
elif
type_
.
startswith
(
'
cl_image_format[
'
):
ret
=
[
ImageFormat
(
imf
.
image_channel_order
,
imf
.
image_channel_data_type
)
for
imf
in
value
]
else
:
ret
=
list
(
value
)
else
:
ret
=
value
[
0
]
if
info
.
dontfree
==
0
:
_lib
.
_free
(
info
.
value
)
return
ret
# }}}
def
_c_obj_list
(
objs
=
None
):
if
objs
is
None
:
return
_ffi
.
NULL
,
0
return
_ffi
.
new
(
'
void *[]
'
,
[
ev
.
ptr
for
ev
in
objs
]),
len
(
objs
)
def
_create_instance
(
cls
,
ptr
):
ins
=
cls
.
__new__
(
cls
)
ins
.
ptr
=
ptr
return
ins
# {{{ common base class
class
_Common
(
object
):
ptr
=
_ffi
.
NULL
@classmethod
def
_c_class_type
(
cls
):
return
getattr
(
_lib
,
'
CLASS_%s
'
%
cls
.
_id
.
upper
())
def
__del__
(
self
):
_lib
.
_delete
(
self
.
ptr
,
self
.
_c_class_type
())
def
__eq__
(
self
,
other
):
return
hash
(
self
)
==
hash
(
other
)
def
__hash__
(
self
):
return
_lib
.
_hash
(
self
.
ptr
,
self
.
_c_class_type
())
def
get_info
(
self
,
param
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
_get_info
(
self
.
ptr
,
self
.
_c_class_type
(),
param
,
info
))
return
_generic_info_to_python
(
info
)
@property
def
int_ptr
(
self
):
return
_lib
.
_int_ptr
(
self
.
ptr
,
self
.
_c_class_type
())
@classmethod
def
from_int_ptr
(
cls
,
int_ptr_value
):
ptr
=
_ffi
.
new
(
'
void **
'
)
_lib
.
_from_int_ptr
(
ptr
,
int_ptr_value
,
getattr
(
_lib
,
'
CLASS_%s
'
%
cls
.
_id
.
upper
()))
#getattr(_lib, '%s__from_int_ptr' % cls._id)(ptr, int_ptr_value)
return
_create_instance
(
cls
,
ptr
[
0
])
# }}}
# }}}
def
get_cl_header_version
():
v
=
_lib
.
get_cl_version
()
...
...
@@ -43,9 +188,49 @@ def get_cl_header_version():
(
v
>>
(
1
*
4
))
&
0xff
)
# {{{ constants
# {{{ expose constants classes like platform_info, device_type, ...
_constants
=
{}
class
_NoInit
(
object
):
def
__init__
(
self
):
raise
RuntimeError
(
"
This class cannot be instantiated.
"
)
# {{{ constant classes
# These will be overwritten below and exist to placate pyflakes.
class
status_code
(
_NoInit
):
pass
class
context_properties
(
_NoInit
):
pass
class
device_type
(
_NoInit
):
pass
class
mem_flags
(
_NoInit
):
pass
class
mem_object_type
(
_NoInit
):
pass
class
channel_order
(
_NoInit
):
pass
class
channel_type
(
_NoInit
):
pass
# }}}
@_ffi.callback
(
'
void(const char*, const char* name, long value)
'
)
def
_constant_callback
(
type_
,
name
,
value
):
s_type
=
_ffi
.
string
(
type_
)
...
...
@@ -55,6 +240,7 @@ _lib.populate_constants(_constant_callback)
for
type_
,
d
in
_constants
.
iteritems
():
locals
()[
type_
]
=
type
(
type_
,
(
_NoInit
,),
d
)
# }}}
...
...
@@ -67,13 +253,19 @@ class Error(Exception):
self
.
what
=
msg
super
(
Error
,
self
).
__init__
(
self
,
msg
)
class
MemoryError
(
Error
):
pass
class
LogicError
(
Error
):
pass
class
RuntimeError
(
Error
):
pass
def
_handle_error
(
error
):
if
error
==
_ffi
.
NULL
:
return
...
...
@@ -92,53 +284,64 @@ def _handle_error(error):
klass
=
RuntimeError
else
:
klass
=
Error
e
=
klass
(
routine
=
_ffi
.
string
(
error
.
routine
),
code
=
error
.
code
,
msg
=
_ffi
.
string
(
error
.
msg
))
e
=
klass
(
routine
=
_ffi
.
string
(
error
.
routine
),
code
=
error
.
code
,
msg
=
_ffi
.
string
(
error
.
msg
))
_lib
.
_free
(
error
.
routine
)
_lib
.
_free
(
error
.
msg
)
_lib
.
_free
(
error
)
raise
e
# }}}
class
_Common
(
object
):
ptr
=
_ffi
.
NULL
@classmethod
def
_c_class_type
(
cls
):
return
getattr
(
_lib
,
'
CLASS_%s
'
%
cls
.
_id
.
upper
())
def
__del__
(
self
):
_lib
.
_delete
(
self
.
ptr
,
self
.
_c_class_type
())
# {{{ Platform
def
__eq__
(
self
,
other
):
return
hash
(
self
)
==
hash
(
other
)
class
Platform
(
_Common
):
_id
=
'
platform
'
# todo: __del__
def
__hash__
(
self
):
return
_lib
.
_hash
(
self
.
ptr
,
self
.
_c_class_type
())
def
get_devices
(
self
,
device_type
=
device_type
.
ALL
):
devices
=
_CArray
(
_ffi
.
new
(
'
void**
'
))
_handle_error
(
_lib
.
platform__get_devices
(
self
.
ptr
,
devices
.
ptr
,
devices
.
size
,
device_type
))
def
get_info
(
self
,
param
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
_get_info
(
self
.
ptr
,
self
.
_c_class_type
(),
param
,
info
))
return
_generic_info_to_python
(
info
)
result
=
[]
for
i
in
xrange
(
devices
.
size
[
0
]):
# TODO why is the cast needed?
device_ptr
=
_ffi
.
cast
(
'
void**
'
,
devices
.
ptr
[
0
])[
i
]
result
.
append
(
_create_instance
(
Device
,
device_ptr
))
return
result
@property
def
int_ptr
(
self
):
return
_lib
.
_int_ptr
(
self
.
ptr
,
self
.
_c_class_type
())
@classmethod
def
from_int_ptr
(
cls
,
int_ptr_value
):
ptr
=
_ffi
.
new
(
'
void **
'
)
_lib
.
_from_int_ptr
(
ptr
,
int_ptr_value
,
getattr
(
_lib
,
'
CLASS_%s
'
%
cls
.
_id
.
upper
()))
#getattr(_lib, '%s__from_int_ptr' % cls._id)(ptr, int_ptr_value)
return
_create_instance
(
cls
,
ptr
[
0
])
def
get_platforms
():
platforms
=
_CArray
(
_ffi
.
new
(
'
void**
'
))
_handle_error
(
_lib
.
get_platforms
(
platforms
.
ptr
,
platforms
.
size
))
result
=
[]
for
i
in
xrange
(
platforms
.
size
[
0
]):
# TODO why is the cast needed?
platform_ptr
=
_ffi
.
cast
(
'
void**
'
,
platforms
.
ptr
[
0
])[
i
]
result
.
append
(
_create_instance
(
Platform
,
platform_ptr
))
return
result
# }}}
# {{{ Device
class
Device
(
_Common
):
_id
=
'
device
'
#
todo
: __del__
#
TODO
: __del__
def
get_info
(
self
,
param
):
return
super
(
Device
,
self
).
get_info
(
param
)
# }}}
# {{{ Context
def
_parse_context_properties
(
properties
):
props
=
[]
if
properties
is
None
:
...
...
@@ -146,16 +349,22 @@ def _parse_context_properties(properties):
for
prop_tuple
in
properties
:
if
len
(
prop_tuple
)
!=
2
:
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
property tuple must have length 2
"
)
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
property tuple must have length 2
"
)
prop
,
value
=
prop_tuple
if
prop
is
None
:
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
invalid context property
"
)
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
invalid context property
"
)
props
.
append
(
prop
)
if
prop
==
context_properties
.
PLATFORM
:
props
.
append
(
value
.
int_ptr
)
elif
prop
==
getattr
(
context_properties
,
"
WGL_HDC_KHR
"
):
# TODO if _WIN32? Why?
# TODO: used to be ifdef _WIN32? Why?
elif
prop
==
getattr
(
context_properties
,
"
WGL_HDC_KHR
"
):
props
.
append
(
value
)
elif
prop
in
[
getattr
(
context_properties
,
key
,
None
)
for
key
in
(
'
CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE
'
,
'
GL_CONTEXT_KHR
'
,
...
...
@@ -163,14 +372,16 @@ def _parse_context_properties(properties):
'
GLX_DISPLAY_KHR
'
,
'
CGL_SHAREGROUP_KHR
'
,
)]:
# TODO: without ctypes?
import
ctypes
val
=
(
ctypes
.
cast
(
value
,
ctypes
.
c_void_p
)).
value
if
val
is
None
:
raise
LogicError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
You most likely have not initialized OpenGL properly.
"
)
raise
LogicError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
You most likely have not initialized OpenGL properly.
"
)
props
.
append
(
val
)
else
:
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
invalid context property
"
)
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
invalid context property
"
)
props
.
append
(
0
)
return
_ffi
.
new
(
'
cl_context_properties[]
'
,
props
)
...
...
@@ -185,92 +396,148 @@ class Context(_Common):
# from device list
if
devices
is
not
None
:
if
dev_type
is
not
None
:
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
one of
'
devices
'
or
'
dev_type
'
must be None
"
)
raise
RuntimeError
(
"
Context
"
,
status_code
.
INVALID_VALUE
,
"
one of
'
devices
'
or
'
dev_type
'
must be None
"
)
ptr_devices
=
_ffi
.
new
(
'
void*[]
'
,
[
device
.
ptr
for
device
in
devices
])
ptr_ctx
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_context
(
ptr_ctx
,
c_props
,
len
(
ptr_devices
),
_ffi
.
cast
(
'
void**
'
,
ptr_devices
)))
_handle_error
(
_lib
.
_create_context
(
ptr_ctx
,
c_props
,
len
(
ptr_devices
),
_ffi
.
cast
(
'
void**
'
,
ptr_devices
)))
else
:
#
from dev_type
else
:
# TODO:
from dev_type
raise
NotImplementedError
()
self
.
ptr
=
ptr_ctx
[
0
]
# }}}
# {{{ CommandQueue
class
CommandQueue
(
_Common
):
_id
=
'
command_queue
'
def
__init__
(
self
,
context
,
device
=
None
,
properties
=
None
):
if
properties
is
None
:
properties
=
0
ptr_command_queue
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_command_queue
(
ptr_command_queue
,
context
.
ptr
,
_ffi
.
NULL
if
device
is
None
else
device
.
ptr
,
properties
))
_handle_error
(
_lib
.
_create_command_queue
(
ptr_command_queue
,
context
.
ptr
,
_ffi
.
NULL
if
device
is
None
else
device
.
ptr
,
properties
))
self
.
ptr
=
ptr_command_queue
[
0
]
class
MemoryObjectHolder
(
_Common
):
pass
class
MemoryObject
(
MemoryObjectHolder
):
pass
def
_c_buffer_from_obj
(
obj
,
writable
=
False
):
"""
Convert a Python object to a tuple (cdata(
'
void *
'
), num_bytes, dummy) to be able to pass
a data stream to a C function. The dummy variable exists only to ensure that the Python object referencing the
C buffer is not garbage collected at the end of this function, making the C buffer itself invalid.
"""
Convert a Python object to a tuple (cdata(
'
void *
'
), num_bytes, dummy)
to be able to pass a data stream to a C function. The dummy variable exists
only to ensure that the Python object referencing the C buffer is not
garbage collected at the end of this function, making the C buffer itself
invalid.
"""
if
_PYPY
:
# {{{ special case: numpy (also works with numpypy)
if
isinstance
(
obj
,
np
.
ndarray
):
# numpy array
return
_ffi
.
cast
(
'
void *
'
,
obj
.
__array_interface__
[
'
data
'
][
0
]),
obj
.
nbytes
,
None
return
(
_ffi
.
cast
(
'
void *
'
,
obj
.
__array_interface__
[
'
data
'
][
0
]),
obj
.
nbytes
,
None
)
if
isinstance
(
obj
,
np
.
generic
):
# numpy scalar
# * obj.__array_interface__ exists in CPython, but the address does not seem to point
# to the actual scalar (not supported/bug?).
#
# * obj.__array_interface__ exists in CPython, but the address does
# not seem to point to the actual scalar (not supported/bug?).
#
# * does not exist (yet?) in numpypy.
s_array
=
np
.
array
([
obj
])
# obj[()] not supported yet by numpypy
return
_ffi
.
cast
(
'
void *
'
,
s_array
.
__array_interface__
[
'
data
'
][
0
]),
s_array
.
nbytes
,
s_array
s_array
=
np
.
array
([
obj
])
# obj[()] not supported yet by numpypy
return
(
_ffi
.
cast
(
'
void *
'
,
s_array
.
__array_interface__
[
'
data
'
][
0
]),
s_array
.
nbytes
,
s_array
)
else
:
raise
LogicError
(
""
,
status_code
.
INVALID_VALUE
,
"
PyOpencl on PyPy only accepts numpy arrays and scalars arguments
"
)
raise
LogicError
(
""
,
status_code
.
INVALID_VALUE
,
"
PyOpencl on PyPy only accepts numpy arrays
"
"
and scalars arguments
"
)
# }}}
# TODO: is there a cross-interpreter solution?
# {{{ fall back to the old CPython buffer protocol API
addr
=
ctypes
.
c_void_p
()
length
=
ctypes
.
c_ssize_t
()
try
:
if
writable
:
status
=
ctypes
.
pythonapi
.
PyObject_AsWriteBuffer
(
ctypes
.
py_object
(
obj
),
ctypes
.
byref
(
addr
),
ctypes
.
byref
(
length
))
status
=
ctypes
.
pythonapi
.
PyObject_AsWriteBuffer
(
ctypes
.
py_object
(
obj
),
ctypes
.
byref
(
addr
),
ctypes
.
byref
(
length
))
else
:
status
=
ctypes
.
pythonapi
.
PyObject_AsReadBuffer
(
ctypes
.
py_object
(
obj
),
ctypes
.
byref
(
addr
),
ctypes
.
byref
(
length
))
status
=
ctypes
.
pythonapi
.
PyObject_AsReadBuffer
(
ctypes
.
py_object
(
obj
),
ctypes
.
byref
(
addr
),
ctypes
.
byref
(
length
))
except
TypeError
:
raise
LogicError
(
""
,
status_code
.
INVALID_VALUE
,
"
PyOpencl does not accept bare Python types as arguments
"
)
raise
LogicError
(
""
,
status_code
.
INVALID_VALUE
,
"
PyOpencl does not accept bare Python types as arguments
"
)
else
:
if
status
:
raise
Exception
(
'
TODO error_already_set
'
)
return
_ffi
.
cast
(
'
void *
'
,
addr
.
value
),
length
.
value
,
None
# }}}
# }}}
# {{{ Buffer
class
Buffer
(
MemoryObject
):
_id
=
'
buffer
'
def
__init__
(
self
,
context
,
flags
,
size
=
0
,
hostbuf
=
None
):
if
hostbuf
is
not
None
and
not
(
flags
&
(
mem_flags
.
USE_HOST_PTR
|
mem_flags
.
COPY_HOST_PTR
)):
warnings
.
warn
(
"'
hostbuf
'
was passed, but no memory flags to make use of it.
"
)
if
hostbuf
is
not
None
and
not
(
flags
&
(
mem_flags
.
USE_HOST_PTR
|
mem_flags
.
COPY_HOST_PTR
)):
warnings
.
warn
(
"'
hostbuf
'
was passed, but no memory flags
"
"
to make use of it.
"
)
c_hostbuf
=
_ffi
.
NULL
if
hostbuf
is
not
None
:
c_hostbuf
,
hostbuf_size
,
_
=
_c_buffer_from_obj
(
hostbuf
,
writable
=
flags
&
mem_flags
.
USE_HOST_PTR
)
c_hostbuf
,
hostbuf_size
,
_
=
_c_buffer_from_obj
(
hostbuf
,
writable
=
flags
&
mem_flags
.
USE_HOST_PTR
)
if
size
>
hostbuf_size
:
raise
RuntimeError
(
"
Buffer
"
,
status_code
.
INVALID_VALUE
,
"
specified size is greater than host buffer size
"
)
raise
RuntimeError
(
"
Buffer
"
,
status_code
.
INVALID_VALUE
,
"
Specified size is greater than host buffer size
"
)
if
size
==
0
:
size
=
hostbuf_size
ptr_buffer
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_buffer
(
ptr_buffer
,
context
.
ptr
,
flags
,
size
,
c_hostbuf
))
_handle_error
(
_lib
.
_create_buffer
(
ptr_buffer
,
context
.
ptr
,
flags
,
size
,
c_hostbuf
))
self
.
ptr
=
ptr_buffer
[
0
]
# }}}
# {{{ Program
class
_Program
(
_Common
):
_id
=
'
program
'
def
__init__
(
self
,
*
args
):
if
len
(
args
)
==
2
:
self
.
_init_source
(
*
args
)
...
...
@@ -279,16 +546,20 @@ class _Program(_Common):
def
_init_source
(
self
,
context
,
src
):
ptr_program
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_program_with_source
(
ptr_program
,
context
.
ptr
,
_ffi
.
new
(
'
char[]
'
,
src
)))
_handle_error
(
_lib
.
_create_program_with_source
(
ptr_program
,
context
.
ptr
,
_ffi
.
new
(
'
char[]
'
,
src
)))
self
.
ptr
=
ptr_program
[
0
]
def
_init_binary
(
self
,
context
,
devices
,
binaries
):
if
len
(
devices
)
!=
len
(
binaries
):
raise
RuntimeError
(
"
create_program_with_binary
"
,
status_code
.
INVALID_VALUE
,
"
device and binary counts don
'
t match
"
)
raise
RuntimeError
(
"
create_program_with_binary
"
,
status_code
.
INVALID_VALUE
,
"
device and binary counts don
'
t match
"
)
ptr_program
=
_ffi
.
new
(
'
void **
'
)
ptr_devices
=
_ffi
.
new
(
'
void*[]
'
,
[
device
.
ptr
for
device
in
devices
])
ptr_binaries
=
[
_ffi
.
new
(
'
char[%i]
'
%
len
(
binary
),
binary
)
for
binary
in
binaries
]
ptr_binaries
=
[
_ffi
.
new
(
'
char[%i]
'
%
len
(
binary
),
binary
)
for
binary
in
binaries
]
binary_sizes
=
_ffi
.
new
(
'
size_t[]
'
,
map
(
len
,
binaries
))
_handle_error
(
_lib
.
_create_program_with_binary
(
...
...
@@ -318,75 +589,21 @@ class _Program(_Common):
ptr_devices
=
_ffi
.
new
(
'
void*[]
'
,
[
device
.
ptr
for
device
in
devices
])
num_devices
=
len
(
devices
)
_handle_error
(
_lib
.
program__build
(
self
.
ptr
,
_ffi
.
new
(
'
char[]
'
,
options
),
num_devices
,
_ffi
.
cast
(
'
void**
'
,
ptr_devices
)))
_handle_error
(
_lib
.
program__build
(
self
.
ptr
,
_ffi
.
new
(
'
char[]
'
,
options
),
num_devices
,
_ffi
.
cast
(
'
void**
'
,
ptr_devices
)))
def
get_build_info
(
self
,
device
,
param
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
program__get_build_info
(
self
.
ptr
,
device
.
ptr
,
param
,
info
))
_handle_error
(
_lib
.
program__get_build_info
(
self
.
ptr
,
device
.
ptr
,
param
,
info
))
return
_generic_info_to_python
(
info
)
class
Platform
(
_Common
):
_id
=
'
platform
'
# todo: __del__
def
get_devices
(
self
,
device_type
=
device_type
.
ALL
):
devices
=
_CArray
(
_ffi
.
new
(
'
void**
'
))
_handle_error
(
_lib
.
platform__get_devices
(
self
.
ptr
,
devices
.
ptr
,
devices
.
size
,
device_type
))
result
=
[]
for
i
in
xrange
(
devices
.
size
[
0
]):
# TODO why is the cast needed?
device_ptr
=
_ffi
.
cast
(
'
void**
'
,
devices
.
ptr
[
0
])[
i
]
result
.
append
(
_create_instance
(
Device
,
device_ptr
))
return
result
def
_generic_info_to_python
(
info
):
type_
=
_ffi
.
string
(
info
.
type
)
value
=
_ffi
.
cast
(
type_
,
info
.
value
)
if
info
.
opaque_class
!=
_lib
.
CLASS_NONE
:
klass
=
{
_lib
.
CLASS_PLATFORM
:
Platform
,
_lib
.
CLASS_DEVICE
:
Device
,
_lib
.
CLASS_KERNEL
:
Kernel
,
_lib
.
CLASS_CONTEXT
:
Context
,
_lib
.
CLASS_BUFFER
:
Buffer
,
_lib
.
CLASS_PROGRAM
:
_Program
,
_lib
.
CLASS_EVENT
:
Event
,
_lib
.
CLASS_COMMAND_QUEUE
:
CommandQueue
}[
info
.
opaque_class
]
# }}}
def
ci
(
ptr
):
ins
=
_create_instance
(
klass
,
ptr
)
if
info
.
opaque_class
==
_lib
.
CLASS_PROGRAM
:
# HACK?
from
.
import
Program
return
Program
(
ins
)
return
ins
if
type_
.
endswith
(
'
]
'
):
ret
=
map
(
ci
,
value
)
_lib
.
_free
(
info
.
value
)
return
ret
else
:
return
ci
(
value
)
if
type_
==
'
char*
'
:
ret
=
_ffi
.
string
(
value
)
elif
type_
.
startswith
(
'
char*[
'
):
ret
=
map
(
_ffi
.
string
,
value
)
_lib
.
_free2
(
info
.
value
,
len
(
value
))
elif
type_
.
endswith
(
'
]
'
):
if
type_
.
startswith
(
'
char[
'
):
ret
=
''
.
join
(
a
[
0
]
for
a
in
value
)
elif
type_
.
startswith
(
'
generic_info[
'
):
ret
=
list
(
map
(
_generic_info_to_python
,
value
))
elif
type_
.
startswith
(
'
cl_image_format[
'
):
ret
=
[
ImageFormat
(
imf
.
image_channel_order
,
imf
.
image_channel_data_type
)
for
imf
in
value
]
else
:
ret
=
list
(
value
)
else
:
ret
=
value
[
0
]
if
info
.
dontfree
==
0
:
_lib
.
_free
(
info
.
value
)
return
ret
# {{{ Kernel
class
Kernel
(
_Common
):
_id
=
'
kernel
'
...
...
@@ -410,23 +627,18 @@ class Kernel(_Common):
def
get_work_group_info
(
self
,
param
,
device
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
kernel__get_work_group_info
(
self
.
ptr
,
param
,
device
.
ptr
,
info
))
_handle_error
(
_lib
.
kernel__get_work_group_info
(
self
.
ptr
,
param
,
device
.
ptr
,
info
))
return
_generic_info_to_python
(
info
)
# }}}
def
get_platforms
():
platforms
=
_CArray
(
_ffi
.
new
(
'
void**
'
))
_handle_error
(
_lib
.
get_platforms
(
platforms
.
ptr
,
platforms
.
size
))
result
=
[]
for
i
in
xrange
(
platforms
.
size
[
0
]):
# TODO why is the cast needed?
platform_ptr
=
_ffi
.
cast
(
'
void**
'
,
platforms
.
ptr
[
0
])[
i
]
result
.
append
(
_create_instance
(
Platform
,
platform_ptr
))
return
resul
t
# {{{ Even
t
class
Event
(
_Common
):
_id
=
'
event
'
def
__init__
(
self
):
pass
...
...
@@ -438,9 +650,19 @@ class Event(_Common):
def
wait
(
self
):
_handle_error
(
_lib
.
event__wait
(
self
.
ptr
))
def
enqueue_nd_range_kernel
(
queue
,
kernel
,
global_work_size
,
local_work_size
,
global_work_offset
=
None
,
wait_for
=
None
,
g_times_l
=
False
):
# }}}
# {{{ enqueue_nd_range_kernel
def
enqueue_nd_range_kernel
(
queue
,
kernel
,
global_work_size
,
local_work_size
,
global_work_offset
=
None
,
wait_for
=
None
,
g_times_l
=
False
):
if
wait_for
is
not
None
:
# TODO: implement wait_for
raise
NotImplementedError
(
"
wait_for
"
)
work_dim
=
len
(
global_work_size
)
if
local_work_size
is
not
None
:
...
...
@@ -483,12 +705,13 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl
))
return
_create_instance
(
Event
,
ptr_event
[
0
])
def
_c_obj_list
(
objs
=
None
):
if
objs
is
None
:
return
_ffi
.
NULL
,
0
return
_ffi
.
new
(
'
void *[]
'
,
[
ev
.
ptr
for
ev
in
objs
]),
len
(
objs
)
# }}}
def
_enqueue_read_buffer
(
queue
,
mem
,
hostbuf
,
device_offset
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
# {{{ _enqueue_*_buffer
def
_enqueue_read_buffer
(
queue
,
mem
,
hostbuf
,
device_offset
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
c_buf
,
size
,
_
=
_c_buffer_from_obj
(
hostbuf
,
writable
=
True
)
ptr_event
=
_ffi
.
new
(
'
void **
'
)
c_wait_for
,
num_wait_for
=
_c_obj_list
(
wait_for
)
...
...
@@ -504,7 +727,9 @@ def _enqueue_read_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, is
))
return
_create_instance
(
Event
,
ptr_event
[
0
])
def
_enqueue_copy_buffer
(
queue
,
src
,
dst
,
byte_count
=-
1
,
src_offset
=
0
,
dst_offset
=
0
,
wait_for
=
None
):
def
_enqueue_copy_buffer
(
queue
,
src
,
dst
,
byte_count
=-
1
,
src_offset
=
0
,
dst_offset
=
0
,
wait_for
=
None
):
ptr_event
=
_ffi
.
new
(
'
void **
'
)
c_wait_for
,
num_wait_for
=
_c_obj_list
(
wait_for
)
_handle_error
(
_lib
.
_enqueue_copy_buffer
(
...
...
@@ -519,7 +744,9 @@ def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offse
))
return
_create_instance
(
Event
,
ptr_event
[
0
])
def
_enqueue_write_buffer
(
queue
,
mem
,
hostbuf
,
device_offset
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
def
_enqueue_write_buffer
(
queue
,
mem
,
hostbuf
,
device_offset
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
c_buf
,
size
,
_
=
_c_buffer_from_obj
(
hostbuf
)
ptr_event
=
_ffi
.
new
(
'
void **
'
)
c_wait_for
,
num_wait_for
=
_c_obj_list
(
wait_for
)
...
...
@@ -535,7 +762,13 @@ def _enqueue_write_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, i
))
return
_create_instance
(
Event
,
ptr_event
[
0
])
def
_enqueue_read_image
(
queue
,
mem
,
origin
,
region
,
hostbuf
,
row_pitch
=
0
,
slice_pitch
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
# }}}
# {{{ _enqueue_*_image
def
_enqueue_read_image
(
queue
,
mem
,
origin
,
region
,
hostbuf
,
row_pitch
=
0
,
slice_pitch
=
0
,
wait_for
=
None
,
is_blocking
=
True
):
c_buf
,
size
,
_
=
_c_buffer_from_obj
(
hostbuf
,
writable
=
True
)
ptr_event
=
_ffi
.
new
(
'
void **
'
)
c_wait_for
,
num_wait_for
=
_c_obj_list
(
wait_for
)
...
...
@@ -553,34 +786,37 @@ def _enqueue_read_image(queue, mem, origin, region, hostbuf, row_pitch=0, slice_
))
return
_create_instance
(
Event
,
ptr_event
[
0
])
# TODO: write_image? copy_image?...
# }}}
def
_create_instance
(
cls
,
ptr
):
ins
=
cls
.
__new__
(
cls
)
ins
.
ptr
=
ptr
return
ins
# {{{ gl interop
def
have_gl
():
return
bool
(
_lib
.
have_gl
())
class
GLBuffer
(
MemoryObject
):
_id
=
'
gl_buffer
'
def
__init__
(
self
,
context
,
flags
,
bufobj
):
ptr
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_from_gl_buffer
(
ptr
,
context
.
ptr
,
flags
,
bufobj
))
_handle_error
(
_lib
.
_create_from_gl_buffer
(
ptr
,
context
.
ptr
,
flags
,
bufobj
))
self
.
ptr
=
ptr
[
0
]
class
GLRenderBuffer
(
MemoryObject
):
_id
=
'
gl_renderbuffer
'
def
__init__
(
self
,
context
,
flags
,
bufobj
):
ptr
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_from_gl_renderbuffer
(
ptr
,
context
.
ptr
,
flags
,
bufobj
))
_handle_error
(
_lib
.
_create_from_gl_renderbuffer
(
ptr
,
context
.
ptr
,
flags
,
bufobj
))
self
.
ptr
=
ptr
[
0
]
def
_create_gl_enqueue
(
what
):
def
enqueue_gl_objects
(
queue
,
mem_objects
,
wait_for
=
None
):
ptr_event
=
_ffi
.
new
(
'
void **
'
)
...
...
@@ -600,12 +836,23 @@ def _create_gl_enqueue(what):
enqueue_acquire_gl_objects
=
_create_gl_enqueue
(
_lib
.
_enqueue_acquire_gl_objects
)
enqueue_release_gl_objects
=
_create_gl_enqueue
(
_lib
.
_enqueue_release_gl_objects
)
# }}}
# {{{ ImageFormat
class
ImageFormat
(
object
):
def
__new__
(
cls
,
channel_order
=
0
,
channel_type
=
0
):
args
=
[
channel_order
,
channel_type
]
cls
=
type
(
cls
.
__name__
,
(
cls
,),
{})
cls
.
channel_order
=
property
(
lambda
self
:
args
[
0
],
lambda
self
,
v
:
args
.
__setitem__
(
0
,
v
))
cls
.
channel_data_type
=
property
(
lambda
self
:
args
[
1
],
lambda
self
,
v
:
args
.
__setitem__
(
1
,
v
))
cls
.
channel_order
=
property
(
lambda
self
:
args
[
0
],
lambda
self
,
v
:
args
.
__setitem__
(
0
,
v
))
cls
.
channel_data_type
=
property
(
lambda
self
:
args
[
1
],
lambda
self
,
v
:
args
.
__setitem__
(
1
,
v
))
return
object
.
__new__
(
cls
)
@property
...
...
@@ -645,7 +892,7 @@ class ImageFormat(object):
channel_type
.
UNSIGNED_INT16
:
2
,
channel_type
.
UNSIGNED_INT32
:
4
,
channel_type
.
HALF_FLOAT
:
2
,
channel_type
.
FLOAT
:
4
,
channel_type
.
FLOAT
:
4
,
}[
self
.
channel_data_type
]
except
KeyError
:
raise
LogicError
(
"
ImageFormat.channel_dtype_size
"
,
...
...
@@ -668,17 +915,23 @@ class ImageFormat(object):
and
self
.
channel_data_type
==
other
.
channel_data_type
)
def
__ne__
(
self
,
other
):
return
not
image_format
_eq
(
self
,
other
)
return
not
self
.
_
_eq
__
(
self
,
other
)
def
__hash__
(
self
):
return
hash
((
ImageFormat
,
self
.
channel_order
,
self
.
channel_data_type
))
def
get_supported_image_formats
(
context
,
flags
,
image_type
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
_get_supported_image_formats
(
context
.
ptr
,
flags
,
image_type
,
info
))
_handle_error
(
_lib
.
_get_supported_image_formats
(
context
.
ptr
,
flags
,
image_type
,
info
))
return
_generic_info_to_python
(
info
)
# }}}
# {{{ Image
class
Image
(
MemoryObject
):
_id
=
'
image
'
...
...
@@ -689,19 +942,21 @@ class Image(MemoryObject):
elif
len
(
args
)
==
6
:
# legacy init for CL 1.1 and older
self
.
_init_legacy
(
*
args
)
else
:
assert
False
def
_init_legacy
(
self
,
context
,
flags
,
format
,
shape
,
pitches
,
buffer
):
if
shape
is
None
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"'
shape
'
must be given
"
)
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"'
shape
'
must be given
"
)
if
buffer
is
None
:
c_buf
,
size
=
_ffi
.
NULL
,
0
else
:
c_buf
,
size
,
_
=
_c_buffer_from_obj
(
buffer
,
writable
=
flags
&
mem_flags
.
USE_HOST_PTR
)
c_buf
,
size
,
_
=
_c_buffer_from_obj
(
buffer
,
writable
=
flags
&
mem_flags
.
USE_HOST_PTR
)
dims
=
len
(
shape
)
if
dims
==
2
:
width
,
height
=
shape
...
...
@@ -710,18 +965,22 @@ class Image(MemoryObject):
try
:
pitch
,
=
pitches
except
ValueError
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid length of pitch tuple
"
)
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid length of pitch tuple
"
)
# check buffer size
if
buffer
is
not
None
and
max
(
pitch
,
width
*
format
.
itemsize
)
*
height
>
size
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
buffer too small
"
)
if
(
buffer
is
not
None
and
max
(
pitch
,
width
*
format
.
itemsize
)
*
height
>
size
):
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
buffer too small
"
)
ptr
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_image_2d
(
ptr
,
context
.
ptr
,
flags
,
_ffi
.
new
(
'
struct _cl_image_format *
'
,
(
format
.
channel_order
,
format
.
channel_data_type
,
)),
_ffi
.
new
(
'
struct _cl_image_format *
'
,
(
format
.
channel_order
,
format
.
channel_data_type
,
)),
width
,
height
,
pitch
,
c_buf
,
size
))
...
...
@@ -733,25 +992,37 @@ class Image(MemoryObject):
try
:
pitch_x
,
pitch_y
=
pitches
except
ValueError
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid length of pitch tuple
"
)
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid length of pitch tuple
"
)
# check buffer size
if
buffer
is
not
None
and
max
(
max
(
pitch_x
,
width
*
format
.
itemsize
)
*
height
,
pitch_y
)
*
depth
>
size
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
buffer too small
"
)
if
(
buffer
is
not
None
and
(
max
(
max
(
pitch_x
,
width
*
format
.
itemsize
)
*
height
,
pitch_y
)
*
depth
>
size
)):
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
buffer too small
"
)
ptr
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_image_3d
(
ptr
,
context
.
ptr
,
flags
,
_ffi
.
new
(
'
struct _cl_image_format *
'
,
(
format
.
channel_order
,
format
.
channel_data_type
,
)),
_ffi
.
new
(
'
struct _cl_image_format *
'
,
(
format
.
channel_order
,
format
.
channel_data_type
,
)),
width
,
height
,
depth
,
pitch_x
,
pitch_y
,
c_buf
,
size
))
self
.
ptr
=
ptr
[
0
]
else
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid dimension
"
);
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
invalid dimension
"
)
def
get_image_info
(
self
,
param
):
info
=
_ffi
.
new
(
'
generic_info *
'
)
_handle_error
(
_lib
.
image__get_image_info
(
self
.
ptr
,
param
,
info
))
...
...
@@ -764,7 +1035,13 @@ class Image(MemoryObject):
elif
self
.
type
==
mem_object_type
.
IMAGE3D
:
return
(
self
.
width
,
self
.
height
,
self
.
depth
)
else
:
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
only images have shapes
"
)
raise
LogicError
(
"
Image
"
,
status_code
.
INVALID_VALUE
,
"
only images have shapes
"
)
# }}}
# {{{ Sampler
class
Sampler
(
_Common
):
_id
=
'
sampler
'
...
...
@@ -779,10 +1056,22 @@ class Sampler(_Common):
filter_mode
))
self
.
ptr
=
ptr
[
0
]
# class GLTexture(Image):
# _id = 'gl_texture'
# def __init__(self, context, flags, texture_target, miplevel, texture, dims):
# ptr = _ffi.new('void **')
# _handle_error(_lib._create_from_gl_texture(ptr, context.ptr, flags, texture_target, miplevel, texture, dims))
# self.ptr = ptr[0]
# }}}
# {{{ GLTexture (TODO)
class
GLTexture
(
Image
):
_id
=
'
gl_texture
'
def
__init__
(
self
,
context
,
flags
,
texture_target
,
miplevel
,
texture
,
dims
):
raise
NotImplementedError
(
"
GLTexture
"
)
ptr
=
_ffi
.
new
(
'
void **
'
)
_handle_error
(
_lib
.
_create_from_gl_texture
(
ptr
,
context
.
ptr
,
flags
,
texture_target
,
miplevel
,
texture
,
dims
))
self
.
ptr
=
ptr
[
0
]
# }}}
# vim: foldmethod=marker
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment