28#define PYGPU_BUFFER_PROTOCOL
29#define MAX_DIMENSIONS 64
37 Py_ssize_t tot = shape[0];
38 for (
int i = 1; i < shape_len; i++) {
46 const Py_ssize_t shape_a_len,
47 const Py_ssize_t *shape_b,
48 const Py_ssize_t shape_b_len)
53 PyErr_Format(PyExc_BufferError,
"array size does not match");
62 Py_ssize_t *r_shape_len)
64 Py_ssize_t shape_len = 0;
65 if (PyLong_Check(shape_obj)) {
67 if ((r_shape[0] = PyLong_AsSsize_t(shape_obj)) < 1) {
68 PyErr_SetString(PyExc_AttributeError,
"dimension must be greater than or equal to 1");
72 else if (PySequence_Check(shape_obj)) {
73 shape_len = PySequence_Size(shape_obj);
75 PyErr_SetString(PyExc_AttributeError,
80 PyErr_SetString(PyExc_AttributeError,
"sequence must have at least one dimension");
84 for (
int i = 0; i < shape_len; i++) {
85 PyObject *ob = PySequence_GetItem(shape_obj, i);
86 if (!PyLong_Check(ob)) {
87 PyErr_Format(PyExc_TypeError,
88 "invalid dimension %i, expected an int, not a %.200s",
90 Py_TYPE(ob)->tp_name);
95 r_shape[i] = PyLong_AsSsize_t(ob);
99 PyErr_SetString(PyExc_AttributeError,
"dimension must be greater than or equal to 1");
105 PyErr_Format(PyExc_TypeError,
106 "invalid second argument expected a sequence "
107 "or an int, not a %.200s",
108 Py_TYPE(shape_obj)->tp_name);
111 *r_shape_len = shape_len;
117 switch (data_format) {
144 const Py_ssize_t *shape,
152 buffer->
shape =
static_cast<Py_ssize_t *
>(
154 memcpy(buffer->
shape, shape, shape_len *
sizeof(*buffer->
shape));
160 BLI_assert(!PyObject_GC_IsTracked((PyObject *)buffer));
161 PyObject_GC_Track(buffer);
168 if (i >=
self->shape[0] || i < 0) {
169 PyErr_SetString(PyExc_IndexError,
"array index out of range");
175 if (
self->shape_len == 1) {
176 switch (
self->format) {
178 return Py_BuildValue(formatstr,
self->buf.as_float[i]);
180 return Py_BuildValue(formatstr,
self->buf.as_int[i]);
182 return Py_BuildValue(formatstr,
self->buf.as_byte[i]);
186 return Py_BuildValue(formatstr,
self->buf.as_uint[i]);
191 for (
int j = 1; j <
self->shape_len; j++) {
192 offset *=
self->shape[j];
199 self->buf.as_byte + offset);
207 const Py_ssize_t
len =
self->shape[0];
208 PyObject *list = PyList_New(
len);
210 for (Py_ssize_t i = 0; i <
len; i++) {
221 if (
self->shape_len > 1) {
223 list = PyList_New(
len);
225 for (i = 0; i <
len; i++) {
243 PyObject *list = PyList_New(
self->shape_len);
246 for (i = 0; i <
self->shape_len; i++) {
247 PyList_SET_ITEM(list, i, PyLong_FromLong(
self->shape[i]));
256 Py_ssize_t shape_len = 0;
266 size_t size = shape_len *
sizeof(*
self->shape);
267 if (shape_len !=
self->shape_len) {
272 self->shape_len = shape_len;
273 memcpy(
self->shape, shape, size);
279 Py_VISIT(
self->parent);
286 Py_CLEAR(
self->parent);
287 self->buf.as_void =
nullptr;
295 PyObject_GC_UnTrack(
self);
296 Py_CLEAR(
self->parent);
298 else if (
self->buf.as_void) {
304 PyObject_GC_Del(
self);
314 repr = PyUnicode_FromFormat(
"Buffer(%s, %R)", typestr, list);
333 if (end >
self->shape[0]) {
334 end =
self->shape[0];
340 if (!PySequence_Check(seq)) {
341 PyErr_Format(PyExc_TypeError,
342 "buffer[:] = value, invalid assignment. "
343 "Expected a sequence, not an %.200s type",
344 Py_TYPE(seq)->tp_name);
349 if ((
count = PySequence_Size(seq)) != (end - begin)) {
350 PyErr_Format(PyExc_TypeError,
351 "buffer[:] = value, size mismatch in assignment. "
352 "Expected: %d (given: %d)",
359 item = PySequence_GetItem(seq,
count - begin);
378 PyObject *length_ob, *
init =
nullptr;
382 Py_ssize_t shape_len = 0;
384 if (kwds && PyDict_Size(kwds)) {
385 PyErr_SetString(PyExc_TypeError,
"Buffer(): takes no keyword args");
390 if (!PyArg_ParseTuple(
400 if (
init && PyObject_CheckBuffer(
init)) {
403 if (PyObject_GetBuffer(
init, &pybuffer, PyBUF_ND | PyBUF_FORMAT) == -1) {
408 Py_ssize_t *pybuffer_shape = pybuffer.shape;
409 Py_ssize_t pybuffer_ndim = pybuffer.ndim;
410 if (!pybuffer_shape) {
411 pybuffer_shape = &pybuffer.len;
420 PyBuffer_Release(&pybuffer);
430 return (PyObject *)buffer;
442 return self->shape[0];
453 if (end >
self->shape[0]) {
454 end =
self->shape[0];
460 list = PyList_New(end - begin);
470 if (i >=
self->shape[0] || i < 0) {
471 PyErr_SetString(PyExc_IndexError,
"array assignment index out of range");
475 if (
self->shape_len != 1) {
487 switch (
self->format) {
489 return PyArg_Parse(
v,
"f:Expected floats", &
self->buf.as_float[i]) ? 0 : -1;
491 return PyArg_Parse(
v,
"i:Expected ints", &
self->buf.as_int[i]) ? 0 : -1;
493 return PyArg_Parse(
v,
"b:Expected ints", &
self->buf.as_byte[i]) ? 0 : -1;
497 return PyArg_Parse(
v,
"I:Expected unsigned ints", &
self->buf.as_uint[i]) ? 0 : -1;
505 if (PyIndex_Check(item)) {
507 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
508 if (i == -1 && PyErr_Occurred()) {
516 if (PySlice_Check(item)) {
517 Py_ssize_t start, stop, step, slicelength;
519 if (PySlice_GetIndicesEx(item,
self->shape[0], &start, &stop, &step, &slicelength) < 0) {
523 if (slicelength <= 0) {
524 return PyTuple_New(0);
530 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
535 PyExc_TypeError,
"buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
541 if (PyIndex_Check(item)) {
542 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
543 if (i == -1 && PyErr_Occurred()) {
551 if (PySlice_Check(item)) {
552 Py_ssize_t start, stop, step, slicelength;
554 if (PySlice_GetIndicesEx(item,
self->shape[0], &start, &stop, &step, &slicelength) < 0) {
562 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
567 PyExc_TypeError,
"buffer indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
571#if (defined(__GNUC__) && !defined(__clang__))
572# pragma GCC diagnostic push
573# pragma GCC diagnostic ignored "-Wcast-function-type"
580 "return the buffer as a list"},
581 {
nullptr,
nullptr, 0,
nullptr},
584#if (defined(__GNUC__) && !defined(__clang__))
585# pragma GCC diagnostic pop
594 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
616#ifdef PYGPU_BUFFER_PROTOCOL
619 const Py_ssize_t *shape,
620 Py_ssize_t *r_strides)
623 for (
int i = 1; i < shape_len; i++) {
624 r_strides[i] = r_strides[i - 1] * shape[i - 1];
631 if (view ==
nullptr) {
632 PyErr_SetString(PyExc_ValueError,
"nullptr view in getbuffer");
636 memset(view, 0,
sizeof(*view));
638 view->obj = (PyObject *)
self;
639 view->buf = (
void *)
self->buf.as_void;
643 if (flags & PyBUF_FORMAT) {
646 if (flags & PyBUF_ND) {
647 view->ndim =
self->shape_len;
648 view->shape =
self->shape;
650 if (flags & PyBUF_STRIDES) {
651 view->strides =
static_cast<Py_ssize_t *
>(
652 MEM_mallocN(view->ndim *
sizeof(*view->strides),
"BPyGPUBuffer strides"));
656 view->suboffsets =
nullptr;
657 view->internal =
nullptr;
676 pygpu_buffer__tp_doc,
677 ".. class:: Buffer(format, dimensions, data)\n"
679 " For Python access to GPU functions requiring a pointer.\n"
681 " :arg format: Format type to interpret the buffer.\n"
682 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
683 " :type format: str\n"
684 " :arg dimensions: Array describing the dimensions.\n"
685 " :type dimensions: int\n"
686 " :arg data: Optional data array.\n"
687 " :type data: Buffer | Sequence[float] | Sequence[int]\n");
689 PyVarObject_HEAD_INIT(
nullptr, 0)
712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
713 pygpu_buffer__tp_doc,
746 const Py_ssize_t *shape)
758 const Py_ssize_t *shape,
762 if (buffer ==
nullptr) {
size_t GPU_texture_dataformat_size(eGPUDataFormat data_format)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyC_StringEnumItems bpygpu_dataformat_items[]
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
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_to_list(BPyGPUBuffer *self)
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)
static PyObject * pygpu_buffer_to_list_recursive(BPyGPUBuffer *self)
static int pygpu_buffer_dimensions_set(BPyGPUBuffer *self, PyObject *value, void *)
static PyObject * pygpu_buffer_dimensions_get(BPyGPUBuffer *self, void *)
PyTypeObject BPyGPU_BufferType
static PyMappingMethods pygpu_buffer__tp_as_mapping
#define PYGPU_BUFFER_PROTOCOL
static int pygpu_buffer__tp_is_gc(BPyGPUBuffer *self)
static PySequenceMethods pygpu_buffer__tp_as_sequence
static PyObject * pygpu_buffer__sq_item(BPyGPUBuffer *self, Py_ssize_t i)
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 PyObject * pygpu_buffer__tp_repr(BPyGPUBuffer *self)
static Py_ssize_t pygpu_buffer__sq_length(BPyGPUBuffer *self)
static int pygpu_buffer__sq_ass_item(BPyGPUBuffer *self, Py_ssize_t i, PyObject *v)
static void pygpu_buffer__bf_releasebuffer(PyObject *, Py_buffer *view)
static PyObject * pygpu_buffer__mp_subscript(BPyGPUBuffer *self, PyObject *item)
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
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 format: str\n" " :arg dimensions: Array describing the dimensions.\n" " :type dimensions: int\n" " :arg data: Optional data array.\n" " :type data: Buffer | Sequence[float] | Sequence[int]\n")
static int pygpu_buffer__mp_ass_subscript(BPyGPUBuffer *self, PyObject *item, PyObject *value)
static PyObject * pygpu_buffer__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
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 BPyGPUBuffer * pygpu_buffer_make_from_data(PyObject *parent, const eGPUDataFormat format, const int shape_len, const Py_ssize_t *shape, void *buf)
static int pygpu_buffer_ass_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end, PyObject *seq)
static const char * pygpu_buffer_formatstr(eGPUDataFormat data_format)
size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer)
static PyObject * pygpu_buffer_slice(BPyGPUBuffer *self, Py_ssize_t begin, Py_ssize_t end)
static void pygpu_buffer__tp_dealloc(BPyGPUBuffer *self)
static int pygpu_buffer__tp_clear(BPyGPUBuffer *self)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
int PyC_ParseStringEnum(PyObject *o, void *p)
const char * PyC_StringEnum_FindIDFromValue(const PyC_StringEnumItems *items, const int value)
PyObject_VAR_HEAD PyObject * parent
union BPyGPUBuffer::@1342 buf