Blender  V2.93
gpu_py_buffer.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
26 #include <Python.h>
27 
28 #include "BLI_utildefines.h"
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "GPU_texture.h"
33 
34 #include "../generic/py_capi_utils.h"
35 
36 #include "gpu_py.h"
37 
38 #include "gpu_py_buffer.h"
39 
40 // #define PYGPU_BUFFER_PROTOCOL
41 
42 /* -------------------------------------------------------------------- */
46 static bool pygpu_buffer_dimensions_compare(int ndim,
47  const Py_ssize_t *shape_a,
48  const Py_ssize_t *shape_b)
49 {
50  return (bool)memcmp(shape_a, shape_b, ndim * sizeof(Py_ssize_t));
51 }
52 
53 static const char *pygpu_buffer_formatstr(eGPUDataFormat data_format)
54 {
55  switch (data_format) {
56  case GPU_DATA_FLOAT:
57  return "f";
58  case GPU_DATA_INT:
59  return "i";
60  case GPU_DATA_UINT:
61  return "I";
62  case GPU_DATA_UBYTE:
63  return "B";
64  case GPU_DATA_UINT_24_8:
66  return "I";
67  default:
68  break;
69  }
70  return NULL;
71 }
72 
75 /* -------------------------------------------------------------------- */
79 static BPyGPUBuffer *pygpu_buffer_make_from_data(PyObject *parent,
80  const eGPUDataFormat format,
81  const int shape_len,
82  const Py_ssize_t *shape,
83  void *buf)
84 {
85  BPyGPUBuffer *buffer = (BPyGPUBuffer *)_PyObject_GC_New(&BPyGPU_BufferType);
86 
87  buffer->parent = NULL;
88  buffer->format = format;
89  buffer->shape_len = shape_len;
90  buffer->shape = MEM_mallocN(shape_len * sizeof(*buffer->shape), "BPyGPUBuffer shape");
91  memcpy(buffer->shape, shape, shape_len * sizeof(*buffer->shape));
92  buffer->buf.as_void = buf;
93 
94  if (parent) {
95  Py_INCREF(parent);
96  buffer->parent = parent;
97  PyObject_GC_Track(buffer);
98  }
99  return buffer;
100 }
101 
102 static PyObject *pygpu_buffer__sq_item(BPyGPUBuffer *self, int i)
103 {
104  if (i >= self->shape[0] || i < 0) {
105  PyErr_SetString(PyExc_IndexError, "array index out of range");
106  return NULL;
107  }
108 
109  const char *formatstr = pygpu_buffer_formatstr(self->format);
110 
111  if (self->shape_len == 1) {
112  switch (self->format) {
113  case GPU_DATA_FLOAT:
114  return Py_BuildValue(formatstr, self->buf.as_float[i]);
115  case GPU_DATA_INT:
116  return Py_BuildValue(formatstr, self->buf.as_int[i]);
117  case GPU_DATA_UBYTE:
118  return Py_BuildValue(formatstr, self->buf.as_byte[i]);
119  case GPU_DATA_UINT:
120  case GPU_DATA_UINT_24_8:
122  return Py_BuildValue(formatstr, self->buf.as_uint[i]);
123  }
124  }
125  else {
126  int offset = i * GPU_texture_dataformat_size(self->format);
127  for (int j = 1; j < self->shape_len; j++) {
128  offset *= self->shape[j];
129  }
130 
131  return (PyObject *)pygpu_buffer_make_from_data((PyObject *)self,
132  self->format,
133  self->shape_len - 1,
134  self->shape + 1,
135  self->buf.as_byte + offset);
136  }
137 
138  return NULL;
139 }
140 
141 static PyObject *pygpu_buffer_to_list(BPyGPUBuffer *self)
142 {
143  int i, len = self->shape[0];
144  PyObject *list = PyList_New(len);
145 
146  for (i = 0; i < len; i++) {
147  PyList_SET_ITEM(list, i, pygpu_buffer__sq_item(self, i));
148  }
149 
150  return list;
151 }
152 
154 {
155  PyObject *list;
156 
157  if (self->shape_len > 1) {
158  int i, len = self->shape[0];
159  list = PyList_New(len);
160 
161  for (i = 0; i < len; i++) {
162  /* "BPyGPUBuffer *sub_tmp" is a temporary object created just to be read for nested lists.
163  * That is why it is decremented/freed soon after.
164  * TODO: For efficiency, avoid creating #BPyGPUBuffer when creating nested lists. */
165  BPyGPUBuffer *sub_tmp = (BPyGPUBuffer *)pygpu_buffer__sq_item(self, i);
166  PyList_SET_ITEM(list, i, pygpu_buffer_to_list_recursive(sub_tmp));
167  Py_DECREF(sub_tmp);
168  }
169  }
170  else {
171  list = pygpu_buffer_to_list(self);
172  }
173 
174  return list;
175 }
176 
177 static PyObject *pygpu_buffer_dimensions(BPyGPUBuffer *self, void *UNUSED(arg))
178 {
179  PyObject *list = PyList_New(self->shape_len);
180  int i;
181 
182  for (i = 0; i < self->shape_len; i++) {
183  PyList_SET_ITEM(list, i, PyLong_FromLong(self->shape[i]));
184  }
185 
186  return list;
187 }
188 
189 static int pygpu_buffer__tp_traverse(BPyGPUBuffer *self, visitproc visit, void *arg)
190 {
191  Py_VISIT(self->parent);
192  return 0;
193 }
194 
196 {
197  Py_CLEAR(self->parent);
198  return 0;
199 }
200 
202 {
203  if (self->parent) {
204  PyObject_GC_UnTrack(self);
205  Py_CLEAR(self->parent);
206  }
207  else {
208  MEM_freeN(self->buf.as_void);
209  }
210 
211  MEM_freeN(self->shape);
212 
213  PyObject_GC_Del(self);
214 }
215 
216 static PyObject *pygpu_buffer__tp_repr(BPyGPUBuffer *self)
217 {
218  PyObject *repr;
219 
220  PyObject *list = pygpu_buffer_to_list_recursive(self);
221  const char *typestr = PyC_StringEnum_FindIDFromValue(bpygpu_dataformat_items, self->format);
222 
223  repr = PyUnicode_FromFormat("Buffer(%s, %R)", typestr, list);
224  Py_DECREF(list);
225 
226  return repr;
227 }
228 
229 static int pygpu_buffer__sq_ass_item(BPyGPUBuffer *self, int i, PyObject *v);
230 
232  Py_ssize_t begin,
233  Py_ssize_t end,
234  PyObject *seq)
235 {
236  PyObject *item;
237  int count, err = 0;
238 
239  if (begin < 0) {
240  begin = 0;
241  }
242  if (end > self->shape[0]) {
243  end = self->shape[0];
244  }
245  if (begin > end) {
246  begin = end;
247  }
248 
249  if (!PySequence_Check(seq)) {
250  PyErr_Format(PyExc_TypeError,
251  "buffer[:] = value, invalid assignment. "
252  "Expected a sequence, not an %.200s type",
253  Py_TYPE(seq)->tp_name);
254  return -1;
255  }
256 
257  /* re-use count var */
258  if ((count = PySequence_Size(seq)) != (end - begin)) {
259  PyErr_Format(PyExc_TypeError,
260  "buffer[:] = value, size mismatch in assignment. "
261  "Expected: %d (given: %d)",
262  count,
263  end - begin);
264  return -1;
265  }
266 
267  for (count = begin; count < end; count++) {
268  item = PySequence_GetItem(seq, count - begin);
269  if (item) {
270  err = pygpu_buffer__sq_ass_item(self, count, item);
271  Py_DECREF(item);
272  }
273  else {
274  err = -1;
275  }
276  if (err) {
277  break;
278  }
279  }
280  return err;
281 }
282 
283 #define MAX_DIMENSIONS 64
284 static PyObject *pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
285 {
286  PyObject *length_ob, *init = NULL;
288  Py_ssize_t shape[MAX_DIMENSIONS];
289 
290  Py_ssize_t i, shape_len = 0;
291 
292  if (kwds && PyDict_Size(kwds)) {
293  PyErr_SetString(PyExc_TypeError, "Buffer(): takes no keyword args");
294  return NULL;
295  }
296 
297  const struct PyC_StringEnum pygpu_dataformat = {bpygpu_dataformat_items, GPU_DATA_FLOAT};
298  if (!PyArg_ParseTuple(
299  args, "O&O|O: Buffer", PyC_ParseStringEnum, &pygpu_dataformat, &length_ob, &init)) {
300  return NULL;
301  }
302 
303  if (PyLong_Check(length_ob)) {
304  shape_len = 1;
305  if (((shape[0] = PyLong_AsLong(length_ob)) < 1)) {
306  PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1");
307  return NULL;
308  }
309  }
310  else if (PySequence_Check(length_ob)) {
311  shape_len = PySequence_Size(length_ob);
312  if (shape_len > MAX_DIMENSIONS) {
313  PyErr_SetString(PyExc_AttributeError,
314  "too many dimensions, max is " STRINGIFY(MAX_DIMENSIONS));
315  return NULL;
316  }
317  if (shape_len < 1) {
318  PyErr_SetString(PyExc_AttributeError, "sequence must have at least one dimension");
319  return NULL;
320  }
321 
322  for (i = 0; i < shape_len; i++) {
323  PyObject *ob = PySequence_GetItem(length_ob, i);
324  if (!PyLong_Check(ob)) {
325  PyErr_Format(PyExc_TypeError,
326  "invalid dimension %i, expected an int, not a %.200s",
327  i,
328  Py_TYPE(ob)->tp_name);
329  Py_DECREF(ob);
330  return NULL;
331  }
332  shape[i] = PyLong_AsLong(ob);
333  Py_DECREF(ob);
334 
335  if (shape[i] < 1) {
336  PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1");
337  return NULL;
338  }
339  }
340  }
341  else {
342  PyErr_Format(PyExc_TypeError,
343  "invalid second argument argument expected a sequence "
344  "or an int, not a %.200s",
345  Py_TYPE(length_ob)->tp_name);
346  return NULL;
347  }
348 
349  if (init && PyObject_CheckBuffer(init)) {
350  Py_buffer pybuffer;
351 
352  if (PyObject_GetBuffer(init, &pybuffer, PyBUF_ND | PyBUF_FORMAT) == -1) {
353  /* PyObject_GetBuffer raise a PyExc_BufferError */
354  return NULL;
355  }
356 
357  if (shape_len != pybuffer.ndim ||
358  !pygpu_buffer_dimensions_compare(shape_len, shape, pybuffer.shape)) {
359  PyErr_Format(PyExc_TypeError, "array size does not match");
360  }
361  else {
363  init, pygpu_dataformat.value_found, pybuffer.ndim, shape, pybuffer.buf);
364  }
365 
366  PyBuffer_Release(&pybuffer);
367  }
368  else {
369  buffer = BPyGPU_Buffer_CreatePyObject(pygpu_dataformat.value_found, shape, shape_len, NULL);
370  if (init && pygpu_buffer_ass_slice(buffer, 0, shape[0], init)) {
371  Py_DECREF(buffer);
372  return NULL;
373  }
374  }
375 
376  return (PyObject *)buffer;
377 }
378 
379 /* BPyGPUBuffer sequence methods */
380 
382 {
383  return self->shape[0];
384 }
385 
386 static PyObject *pygpu_buffer_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end)
387 {
388  PyObject *list;
389  Py_ssize_t count;
390 
391  if (begin < 0) {
392  begin = 0;
393  }
394  if (end > self->shape[0]) {
395  end = self->shape[0];
396  }
397  if (begin > end) {
398  begin = end;
399  }
400 
401  list = PyList_New(end - begin);
402 
403  for (count = begin; count < end; count++) {
404  PyList_SET_ITEM(list, count - begin, pygpu_buffer__sq_item(self, count));
405  }
406  return list;
407 }
408 
409 static int pygpu_buffer__sq_ass_item(BPyGPUBuffer *self, int i, PyObject *v)
410 {
411  if (i >= self->shape[0] || i < 0) {
412  PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
413  return -1;
414  }
415 
416  if (self->shape_len != 1) {
418 
419  if (row) {
420  const int ret = pygpu_buffer_ass_slice(row, 0, self->shape[1], v);
421  Py_DECREF(row);
422  return ret;
423  }
424 
425  return -1;
426  }
427 
428  switch (self->format) {
429  case GPU_DATA_FLOAT:
430  return PyArg_Parse(v, "f:Expected floats", &self->buf.as_float[i]) ? 0 : -1;
431  case GPU_DATA_INT:
432  return PyArg_Parse(v, "i:Expected ints", &self->buf.as_int[i]) ? 0 : -1;
433  case GPU_DATA_UBYTE:
434  return PyArg_Parse(v, "b:Expected ints", &self->buf.as_byte[i]) ? 0 : -1;
435  case GPU_DATA_UINT:
436  case GPU_DATA_UINT_24_8:
438  return PyArg_Parse(v, "b:Expected ints", &self->buf.as_uint[i]) ? 0 : -1;
439  default:
440  return 0; /* should never happen */
441  }
442 }
443 
444 static PyObject *pygpu_buffer__mp_subscript(BPyGPUBuffer *self, PyObject *item)
445 {
446  if (PyIndex_Check(item)) {
447  Py_ssize_t i;
448  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
449  if (i == -1 && PyErr_Occurred()) {
450  return NULL;
451  }
452  if (i < 0) {
453  i += self->shape[0];
454  }
455  return pygpu_buffer__sq_item(self, i);
456  }
457  if (PySlice_Check(item)) {
458  Py_ssize_t start, stop, step, slicelength;
459 
460  if (PySlice_GetIndicesEx(item, self->shape[0], &start, &stop, &step, &slicelength) < 0) {
461  return NULL;
462  }
463 
464  if (slicelength <= 0) {
465  return PyTuple_New(0);
466  }
467  if (step == 1) {
468  return pygpu_buffer_slice(self, start, stop);
469  }
470 
471  PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
472  return NULL;
473  }
474 
475  PyErr_Format(
476  PyExc_TypeError, "buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
477  return NULL;
478 }
479 
480 static int pygpu_buffer__mp_ass_subscript(BPyGPUBuffer *self, PyObject *item, PyObject *value)
481 {
482  if (PyIndex_Check(item)) {
483  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
484  if (i == -1 && PyErr_Occurred()) {
485  return -1;
486  }
487  if (i < 0) {
488  i += self->shape[0];
489  }
490  return pygpu_buffer__sq_ass_item(self, i, value);
491  }
492  if (PySlice_Check(item)) {
493  Py_ssize_t start, stop, step, slicelength;
494 
495  if (PySlice_GetIndicesEx(item, self->shape[0], &start, &stop, &step, &slicelength) < 0) {
496  return -1;
497  }
498 
499  if (step == 1) {
500  return pygpu_buffer_ass_slice(self, start, stop, value);
501  }
502 
503  PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
504  return -1;
505  }
506 
507  PyErr_Format(
508  PyExc_TypeError, "buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
509  return -1;
510 }
511 
512 static PyMethodDef pygpu_buffer__tp_methods[] = {
513  {"to_list",
514  (PyCFunction)pygpu_buffer_to_list_recursive,
515  METH_NOARGS,
516  "return the buffer as a list"},
517  {NULL, NULL, 0, NULL},
518 };
519 
520 static PyGetSetDef pygpu_buffer_getseters[] = {
521  {"dimensions", (getter)pygpu_buffer_dimensions, NULL, NULL, NULL},
522  {NULL, NULL, NULL, NULL, NULL},
523 };
524 
525 static PySequenceMethods pygpu_buffer__tp_as_sequence = {
526  (lenfunc)pygpu_buffer__sq_length, /*sq_length */
527  (binaryfunc)NULL, /*sq_concat */
528  (ssizeargfunc)NULL, /*sq_repeat */
529  (ssizeargfunc)pygpu_buffer__sq_item, /*sq_item */
530  (ssizessizeargfunc)NULL, /*sq_slice, deprecated, handled in pygpu_buffer__sq_item */
531  (ssizeobjargproc)pygpu_buffer__sq_ass_item, /*sq_ass_item */
532  (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated handled in pygpu_buffer__sq_ass_item */
533  (objobjproc)NULL, /* sq_contains */
534  (binaryfunc)NULL, /* sq_inplace_concat */
535  (ssizeargfunc)NULL, /* sq_inplace_repeat */
536 };
537 
538 static PyMappingMethods pygpu_buffer__tp_as_mapping = {
539  (lenfunc)pygpu_buffer__sq_length,
540  (binaryfunc)pygpu_buffer__mp_subscript,
541  (objobjargproc)pygpu_buffer__mp_ass_subscript,
542 };
543 
544 #ifdef PYGPU_BUFFER_PROTOCOL
545 static void pygpu_buffer_strides_calc(const eGPUDataFormat format,
546  const int shape_len,
547  const Py_ssize_t *shape,
548  Py_ssize_t *r_strides)
549 {
550  r_strides[0] = GPU_texture_dataformat_size(format);
551  for (int i = 1; i < shape_len; i++) {
552  r_strides[i] = r_strides[i - 1] * shape[i - 1];
553  }
554 }
555 
556 /* Here is the buffer interface function */
557 static int pygpu_buffer__bf_getbuffer(BPyGPUBuffer *self, Py_buffer *view, int flags)
558 {
559  if (view == NULL) {
560  PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
561  return -1;
562  }
563 
564  view->obj = (PyObject *)self;
565  view->buf = (void *)self->buf.as_void;
566  view->len = bpygpu_Buffer_size(self);
567  view->readonly = 0;
568  view->itemsize = GPU_texture_dataformat_size(self->format);
569  view->format = pygpu_buffer_formatstr(self->format);
570  view->ndim = self->shape_len;
571  view->shape = self->shape;
572  view->strides = MEM_mallocN(view->ndim * sizeof(*view->strides), "BPyGPUBuffer strides");
573  pygpu_buffer_strides_calc(self->format, view->ndim, view->shape, view->strides);
574  view->suboffsets = NULL;
575  view->internal = NULL;
576 
577  Py_INCREF(self);
578  return 0;
579 }
580 
581 static void pygpu_buffer__bf_releasebuffer(PyObject *UNUSED(exporter), Py_buffer *view)
582 {
583  MEM_SAFE_FREE(view->strides);
584 }
585 
586 static PyBufferProcs pygpu_buffer__tp_as_buffer = {
587  (getbufferproc)pygpu_buffer__bf_getbuffer,
588  (releasebufferproc)pygpu_buffer__bf_releasebuffer,
589 };
590 #endif
591 
593  pygpu_buffer__tp_doc,
594  ".. class:: Buffer(format, dimensions, data)\n"
595  "\n"
596  " For Python access to GPU functions requiring a pointer.\n"
597  "\n"
598  " :arg format: Format type to interpret the buffer.\n"
599  " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
600  " :type type: str\n"
601  " :arg dimensions: Array describing the dimensions.\n"
602  " :type dimensions: int\n"
603  " :arg data: Optional data array.\n"
604  " :type data: sequence\n");
605 PyTypeObject BPyGPU_BufferType = {
606  PyVarObject_HEAD_INIT(NULL, 0).tp_name = "Buffer",
607  .tp_basicsize = sizeof(BPyGPUBuffer),
608  .tp_dealloc = (destructor)pygpu_buffer__tp_dealloc,
609  .tp_repr = (reprfunc)pygpu_buffer__tp_repr,
610  .tp_as_sequence = &pygpu_buffer__tp_as_sequence,
611  .tp_as_mapping = &pygpu_buffer__tp_as_mapping,
612 #ifdef PYGPU_BUFFER_PROTOCOL
613  .tp_as_buffer = &pygpu_buffer__tp_as_buffer,
614 #endif
615  .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
616  .tp_doc = pygpu_buffer__tp_doc,
617  .tp_traverse = (traverseproc)pygpu_buffer__tp_traverse,
618  .tp_clear = (inquiry)pygpu_buffer__tp_clear,
619  .tp_methods = pygpu_buffer__tp_methods,
620  .tp_getset = pygpu_buffer_getseters,
621  .tp_new = pygpu_buffer__tp_new,
622 };
623 
624 static size_t pygpu_buffer_calc_size(const int format,
625  const int shape_len,
626  const Py_ssize_t *shape)
627 {
628  size_t r_size = GPU_texture_dataformat_size(format);
629 
630  for (int i = 0; i < shape_len; i++) {
631  r_size *= shape[i];
632  }
633 
634  return r_size;
635 }
636 
638 {
639  return pygpu_buffer_calc_size(buffer->format, buffer->shape_len, buffer->shape);
640 }
641 
650  const Py_ssize_t *shape,
651  const int shape_len,
652  void *buffer)
653 {
654  if (buffer == NULL) {
655  size_t size = pygpu_buffer_calc_size(format, shape_len, shape);
656  buffer = MEM_callocN(size, "BPyGPUBuffer buffer");
657  }
658 
659  return pygpu_buffer_make_from_data(NULL, format, shape_len, shape, buffer);
660 }
661 
#define STRINGIFY(x)
#define UNUSED(x)
static AppView * view
_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)
Definition: gpu_texture.cc:621
eGPUDataFormat
Definition: GPU_texture.h:171
@ GPU_DATA_UINT_24_8
Definition: GPU_texture.h:176
@ GPU_DATA_INT
Definition: GPU_texture.h:173
@ GPU_DATA_10_11_11_REV
Definition: GPU_texture.h:177
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:175
@ GPU_DATA_UINT
Definition: GPU_texture.h:174
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:172
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
Definition: bpy_driver.c:185
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static FT_Error err
Definition: freetypefont.c:52
struct PyC_StringEnumItems bpygpu_dataformat_items[]
Definition: gpu_py.c:52
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
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 int pygpu_buffer__tp_traverse(BPyGPUBuffer *self, visitproc visit, void *arg)
PyTypeObject BPyGPU_BufferType
static bool pygpu_buffer_dimensions_compare(int ndim, const Py_ssize_t *shape_a, const Py_ssize_t *shape_b)
Definition: gpu_py_buffer.c:46
#define MAX_DIMENSIONS
static PyMappingMethods pygpu_buffer__tp_as_mapping
static PySequenceMethods pygpu_buffer__tp_as_sequence
static PyObject * pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
static PyObject * pygpu_buffer_to_list_recursive(BPyGPUBuffer *self)
static int pygpu_buffer__sq_ass_item(BPyGPUBuffer *self, int i, PyObject *v)
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_ass_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end, PyObject *seq)
static PyObject * pygpu_buffer_dimensions(BPyGPUBuffer *self, void *UNUSED(arg))
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)
Definition: gpu_py_buffer.c:79
static const char * pygpu_buffer_formatstr(eGPUDataFormat data_format)
Definition: gpu_py_buffer.c:53
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
int count
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
int PyC_ParseStringEnum(PyObject *o, void *p)
const char * PyC_StringEnum_FindIDFromValue(const struct PyC_StringEnumItems *items, const int value)
return ret
uint len