20 #include "../generic/py_capi_utils.h"
26 #define PYGPU_BUFFER_PROTOCOL
27 #define MAX_DIMENSIONS 64
35 Py_ssize_t tot = shape[0];
36 for (
int i = 1; i < shape_len; i++) {
44 const Py_ssize_t shape_a_len,
45 const Py_ssize_t *shape_b,
46 const Py_ssize_t shape_b_len)
50 PyErr_Format(PyExc_BufferError,
"array size does not match");
59 Py_ssize_t *r_shape_len)
61 Py_ssize_t shape_len = 0;
62 if (PyLong_Check(shape_obj)) {
64 if (((r_shape[0] = PyLong_AsLong(shape_obj)) < 1)) {
65 PyErr_SetString(PyExc_AttributeError,
"dimension must be greater than or equal to 1");
69 else if (PySequence_Check(shape_obj)) {
70 shape_len = PySequence_Size(shape_obj);
72 PyErr_SetString(PyExc_AttributeError,
77 PyErr_SetString(PyExc_AttributeError,
"sequence must have at least one dimension");
81 for (
int i = 0; i < shape_len; i++) {
82 PyObject *ob = PySequence_GetItem(shape_obj, i);
83 if (!PyLong_Check(ob)) {
84 PyErr_Format(PyExc_TypeError,
85 "invalid dimension %i, expected an int, not a %.200s",
87 Py_TYPE(ob)->tp_name);
92 r_shape[i] = PyLong_AsLong(ob);
96 PyErr_SetString(PyExc_AttributeError,
"dimension must be greater than or equal to 1");
102 PyErr_Format(PyExc_TypeError,
103 "invalid second argument argument expected a sequence "
104 "or an int, not a %.200s",
105 Py_TYPE(shape_obj)->tp_name);
108 *r_shape_len = shape_len;
114 switch (data_format) {
141 const Py_ssize_t *shape,
148 buffer->shape_len = shape_len;
150 memcpy(
buffer->shape, shape, shape_len *
sizeof(*
buffer->shape));
151 buffer->buf.as_void = buf;
156 PyObject_GC_Track(
buffer);
163 if (i >=
self->shape[0] || i < 0) {
164 PyErr_SetString(PyExc_IndexError,
"array index out of range");
170 if (
self->shape_len == 1) {
171 switch (
self->format) {
173 return Py_BuildValue(formatstr,
self->buf.as_float[i]);
175 return Py_BuildValue(formatstr,
self->buf.as_int[i]);
177 return Py_BuildValue(formatstr,
self->buf.as_byte[i]);
181 return Py_BuildValue(formatstr,
self->buf.as_uint[i]);
186 for (
int j = 1; j <
self->shape_len; j++) {
202 int i,
len =
self->shape[0];
203 PyObject *list = PyList_New(
len);
205 for (i = 0; i <
len; i++) {
216 if (
self->shape_len > 1) {
217 int i,
len =
self->shape[0];
218 list = PyList_New(
len);
220 for (i = 0; i <
len; i++) {
238 PyObject *list = PyList_New(
self->shape_len);
241 for (i = 0; i <
self->shape_len; i++) {
242 PyList_SET_ITEM(list, i, PyLong_FromLong(
self->shape[i]));
251 Py_ssize_t shape_len = 0;
261 size_t size = shape_len *
sizeof(*
self->shape);
262 if (shape_len !=
self->shape_len) {
267 self->shape_len = shape_len;
274 Py_VISIT(
self->parent);
281 Py_CLEAR(
self->parent);
282 self->buf.as_void =
NULL;
290 PyObject_GC_UnTrack(
self);
291 Py_CLEAR(
self->parent);
293 else if (
self->buf.as_void) {
299 PyObject_GC_Del(
self);
309 repr = PyUnicode_FromFormat(
"Buffer(%s, %R)", typestr, list);
328 if (end >
self->shape[0]) {
329 end =
self->shape[0];
335 if (!PySequence_Check(seq)) {
336 PyErr_Format(PyExc_TypeError,
337 "buffer[:] = value, invalid assignment. "
338 "Expected a sequence, not an %.200s type",
339 Py_TYPE(seq)->tp_name);
344 if ((
count = PySequence_Size(seq)) != (end - begin)) {
345 PyErr_Format(PyExc_TypeError,
346 "buffer[:] = value, size mismatch in assignment. "
347 "Expected: %d (given: %d)",
354 item = PySequence_GetItem(seq,
count - begin);
375 Py_ssize_t shape_len = 0;
377 if (kwds && PyDict_Size(kwds)) {
378 PyErr_SetString(PyExc_TypeError,
"Buffer(): takes no keyword args");
383 if (!PyArg_ParseTuple(
392 if (
init && PyObject_CheckBuffer(
init)) {
395 if (PyObject_GetBuffer(
init, &pybuffer, PyBUF_ND | PyBUF_FORMAT) == -1) {
400 Py_ssize_t *pybuffer_shape = pybuffer.shape;
401 Py_ssize_t pybuffer_ndim = pybuffer.ndim;
402 if (!pybuffer_shape) {
403 pybuffer_shape = &pybuffer.len;
412 PyBuffer_Release(&pybuffer);
422 return (PyObject *)
buffer;
429 return self->shape[0];
440 if (end >
self->shape[0]) {
441 end =
self->shape[0];
447 list = PyList_New(end - begin);
457 if (i >=
self->shape[0] || i < 0) {
458 PyErr_SetString(PyExc_IndexError,
"array assignment index out of range");
462 if (
self->shape_len != 1) {
474 switch (
self->format) {
476 return PyArg_Parse(
v,
"f:Expected floats", &
self->buf.as_float[i]) ? 0 : -1;
478 return PyArg_Parse(
v,
"i:Expected ints", &
self->buf.as_int[i]) ? 0 : -1;
480 return PyArg_Parse(
v,
"b:Expected ints", &
self->buf.as_byte[i]) ? 0 : -1;
484 return PyArg_Parse(
v,
"I:Expected unsigned ints", &
self->buf.as_uint[i]) ? 0 : -1;
492 if (PyIndex_Check(item)) {
494 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
495 if (i == -1 && PyErr_Occurred()) {
503 if (PySlice_Check(item)) {
504 Py_ssize_t start, stop, step, slicelength;
506 if (PySlice_GetIndicesEx(item,
self->shape[0], &start, &stop, &step, &slicelength) < 0) {
510 if (slicelength <= 0) {
511 return PyTuple_New(0);
517 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
522 PyExc_TypeError,
"buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
528 if (PyIndex_Check(item)) {
529 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
530 if (i == -1 && PyErr_Occurred()) {
538 if (PySlice_Check(item)) {
539 Py_ssize_t start, stop, step, slicelength;
541 if (PySlice_GetIndicesEx(item,
self->shape[0], &start, &stop, &step, &slicelength) < 0) {
549 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
554 PyExc_TypeError,
"buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
562 "return the buffer as a list"},
580 (ssizessizeargfunc)
NULL,
582 (ssizessizeobjargproc)
NULL,
594 #ifdef PYGPU_BUFFER_PROTOCOL
597 const Py_ssize_t *shape,
598 Py_ssize_t *r_strides)
601 for (
int i = 1; i < shape_len; i++) {
602 r_strides[i] = r_strides[i - 1] * shape[i - 1];
610 PyErr_SetString(PyExc_ValueError,
"NULL view in getbuffer");
616 view->obj = (PyObject *)
self;
617 view->buf = (
void *)
self->buf.as_void;
621 if (flags & PyBUF_FORMAT) {
624 if (flags & PyBUF_ND) {
625 view->ndim =
self->shape_len;
626 view->shape =
self->shape;
628 if (flags & PyBUF_STRIDES) {
651 pygpu_buffer__tp_doc,
652 ".. class:: Buffer(format, dimensions, data)\n"
654 " For Python access to GPU functions requiring a pointer.\n"
656 " :arg format: Format type to interpret the buffer.\n"
657 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
659 " :arg dimensions: Array describing the dimensions.\n"
660 " :type dimensions: int\n"
661 " :arg data: Optional data array.\n"
662 " :type data: sequence\n");
664 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"Buffer",
673 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
674 .tp_doc = pygpu_buffer__tp_doc,
684 const Py_ssize_t *shape)
695 const Py_ssize_t *shape,
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
size_t GPU_texture_dataformat_size(eGPUDataFormat data_format)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
struct PyC_StringEnumItems bpygpu_dataformat_items[]
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
static Py_ssize_t pygpu_buffer_dimensions_tot_elem(const Py_ssize_t *shape, Py_ssize_t shape_len)
static size_t pygpu_buffer_calc_size(const int format, const int shape_len, const Py_ssize_t *shape)
static PyObject * pygpu_buffer__sq_item(BPyGPUBuffer *self, int i)
static PyBufferProcs pygpu_buffer__tp_as_buffer
static int pygpu_buffer__tp_traverse(BPyGPUBuffer *self, visitproc visit, void *arg)
static void pygpu_buffer_strides_calc(const eGPUDataFormat format, const int shape_len, const Py_ssize_t *shape, Py_ssize_t *r_strides)
PyTypeObject BPyGPU_BufferType
static int pygpu_buffer_dimensions_set(BPyGPUBuffer *self, PyObject *value, void *UNUSED(type))
static PyMappingMethods pygpu_buffer__tp_as_mapping
#define PYGPU_BUFFER_PROTOCOL
static PySequenceMethods pygpu_buffer__tp_as_sequence
static PyObject * pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
static bool pygpu_buffer_dimensions_tot_len_compare(const Py_ssize_t *shape_a, const Py_ssize_t shape_a_len, const Py_ssize_t *shape_b, const Py_ssize_t shape_b_len)
static void pygpu_buffer__bf_releasebuffer(PyObject *UNUSED(exporter), Py_buffer *view)
static PyObject * pygpu_buffer_to_list_recursive(BPyGPUBuffer *self)
static int pygpu_buffer__sq_ass_item(BPyGPUBuffer *self, int i, PyObject *v)
static PyObject * pygpu_buffer_dimensions_get(BPyGPUBuffer *self, void *UNUSED(arg))
static int pygpu_buffer__sq_length(BPyGPUBuffer *self)
static PyObject * pygpu_buffer_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end)
static PyObject * pygpu_buffer_to_list(BPyGPUBuffer *self)
static int pygpu_buffer__mp_ass_subscript(BPyGPUBuffer *self, PyObject *item, PyObject *value)
static PyObject * pygpu_buffer__tp_repr(BPyGPUBuffer *self)
static PyMethodDef pygpu_buffer__tp_methods[]
static PyGetSetDef pygpu_buffer_getseters[]
static int pygpu_buffer__bf_getbuffer(BPyGPUBuffer *self, Py_buffer *view, int flags)
static bool pygpu_buffer_pyobj_as_shape(PyObject *shape_obj, Py_ssize_t r_shape[MAX_DIMENSIONS], Py_ssize_t *r_shape_len)
static int pygpu_buffer_ass_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end, PyObject *seq)
size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer)
static BPyGPUBuffer * pygpu_buffer_make_from_data(PyObject *parent, const eGPUDataFormat format, const int shape_len, const Py_ssize_t *shape, void *buf)
static const char * pygpu_buffer_formatstr(eGPUDataFormat data_format)
static PyObject * pygpu_buffer__mp_subscript(BPyGPUBuffer *self, PyObject *item)
static void pygpu_buffer__tp_dealloc(BPyGPUBuffer *self)
PyDoc_STRVAR(pygpu_buffer__tp_doc, ".. class:: Buffer(format, dimensions, data)\n" "\n" " For Python access to GPU functions requiring a pointer.\n" "\n" " :arg format: Format type to interpret the buffer.\n" " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n" " :type type: str\n" " :arg dimensions: Array describing the dimensions.\n" " :type dimensions: int\n" " :arg data: Optional data array.\n" " :type data: sequence\n")
static int pygpu_buffer__tp_clear(BPyGPUBuffer *self)
struct BPyGPUBuffer BPyGPUBuffer
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
int PyC_ParseStringEnum(PyObject *o, void *p)
const char * PyC_StringEnum_FindIDFromValue(const struct PyC_StringEnumItems *items, const int value)