Blender V4.3
gpu_py_uniformbuffer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
14#include <Python.h>
15
16#include "BLI_string.h"
17
18#include "GPU_context.hh"
19#include "GPU_uniform_buffer.hh"
20
22
23#include "gpu_py.hh"
24#include "gpu_py_uniformbuffer.hh" /* own include */
25
26/* -------------------------------------------------------------------- */
31{
32 if (UNLIKELY(bpygpu_ub->ubo == nullptr)) {
33 PyErr_SetString(PyExc_ReferenceError,
35 "GPU uniform buffer was freed, no further access is valid");
36#else
37
38 "GPU uniform buffer: internal error");
39#endif
40 return -1;
41 }
42 return 0;
43}
44
45#define BPYGPU_UNIFORMBUF_CHECK_OBJ(bpygpu) \
46 { \
47 if (UNLIKELY(pygpu_uniformbuffer_valid_check(bpygpu) == -1)) { \
48 return nullptr; \
49 } \
50 } \
51 ((void)0)
52
55/* -------------------------------------------------------------------- */
59static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject * /*self*/,
60 PyObject *args,
61 PyObject *kwds)
62{
64
65 GPUUniformBuf *ubo = nullptr;
66 PyObject *pybuffer_obj;
67 char err_out[256] = "unknown error. See console";
68
69 static const char *_keywords[] = {"data", nullptr};
70 static _PyArg_Parser _parser = {
72 "O" /* `data` */
73 ":GPUUniformBuf.__new__",
74 _keywords,
75 nullptr,
76 };
77 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &pybuffer_obj)) {
78 return nullptr;
79 }
80
82 STRNCPY(err_out, "No active GPU context found");
83 }
84 else {
85 Py_buffer pybuffer;
86 if (PyObject_GetBuffer(pybuffer_obj, &pybuffer, PyBUF_SIMPLE) == -1) {
87 /* PyObject_GetBuffer raise a PyExc_BufferError */
88 return nullptr;
89 }
90
91 if ((pybuffer.len % 16) != 0) {
92 STRNCPY(err_out, "UBO is not padded to size of vec4");
93 }
94 else {
95 ubo = GPU_uniformbuf_create_ex(pybuffer.len, pybuffer.buf, "python_uniformbuffer");
96 }
97 PyBuffer_Release(&pybuffer);
98 }
99
100 if (ubo == nullptr) {
101 PyErr_Format(PyExc_RuntimeError, "GPUUniformBuf.__new__(...) failed with '%s'", err_out);
102 return nullptr;
103 }
104
106}
107
109 /* Wrap. */
110 pygpu_uniformbuffer_update_doc,
111 ".. method:: update(data)\n"
112 "\n"
113 " Update the data of the uniform buffer object.\n");
114static PyObject *pygpu_uniformbuffer_update(BPyGPUUniformBuf *self, PyObject *obj)
115{
117
118 Py_buffer pybuffer;
119 if (PyObject_GetBuffer(obj, &pybuffer, PyBUF_SIMPLE) == -1) {
120 /* PyObject_GetBuffer raise a PyExc_BufferError */
121 return nullptr;
122 }
123
124 GPU_uniformbuf_update(self->ubo, pybuffer.buf);
125 PyBuffer_Release(&pybuffer);
126 Py_RETURN_NONE;
127}
128
129#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
131 /* Wrap. */
132 pygpu_uniformbuffer_free_doc,
133 ".. method::free()\n"
134 "\n"
135 " Free the uniform buffer object.\n"
136 " The uniform buffer object will no longer be accessible.\n");
137static PyObject *pygpu_uniformbuffer_free(BPyGPUUniformBuf *self)
138{
140
142 self->ubo = nullptr;
143 Py_RETURN_NONE;
144}
145#endif
146
148{
149 if (self->ubo) {
151 }
152 Py_TYPE(self)->tp_free((PyObject *)self);
153}
154
155static PyGetSetDef pygpu_uniformbuffer__tp_getseters[] = {
156 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
157};
158
159static PyMethodDef pygpu_uniformbuffer__tp_methods[] = {
160 {"update", (PyCFunction)pygpu_uniformbuffer_update, METH_O, pygpu_uniformbuffer_update_doc},
161#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
162 {"free", (PyCFunction)pygpu_uniformbuffer_free, METH_NOARGS, pygpu_uniformbuffer_free_doc},
163#endif
164 {nullptr, nullptr, 0, nullptr},
165};
166
168 /* Wrap. */
169 pygpu_uniformbuffer__tp_doc,
170 ".. class:: GPUUniformBuf(data)\n"
171 "\n"
172 " This object gives access to off uniform buffers.\n"
173 "\n"
174 " :arg data: Data to fill the buffer.\n"
175 " :type data: object exposing buffer interface\n");
176PyTypeObject BPyGPUUniformBuf_Type = {
177 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
178 /*tp_name*/ "GPUUniformBuf",
179 /*tp_basicsize*/ sizeof(BPyGPUUniformBuf),
180 /*tp_itemsize*/ 0,
181 /*tp_dealloc*/ (destructor)BPyGPUUniformBuf__tp_dealloc,
182 /*tp_vectorcall_offset*/ 0,
183 /*tp_getattr*/ nullptr,
184 /*tp_setattr*/ nullptr,
185 /*tp_as_async*/ nullptr,
186 /*tp_repr*/ nullptr,
187 /*tp_as_number*/ nullptr,
188 /*tp_as_sequence*/ nullptr,
189 /*tp_as_mapping*/ nullptr,
190 /*tp_hash*/ nullptr,
191 /*tp_call*/ nullptr,
192 /*tp_str*/ nullptr,
193 /*tp_getattro*/ nullptr,
194 /*tp_setattro*/ nullptr,
195 /*tp_as_buffer*/ nullptr,
196 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
197 /*tp_doc*/ pygpu_uniformbuffer__tp_doc,
198 /*tp_traverse*/ nullptr,
199 /*tp_clear*/ nullptr,
200 /*tp_richcompare*/ nullptr,
201 /*tp_weaklistoffset*/ 0,
202 /*tp_iter*/ nullptr,
203 /*tp_iternext*/ nullptr,
204 /*tp_methods*/ pygpu_uniformbuffer__tp_methods,
205 /*tp_members*/ nullptr,
207 /*tp_base*/ nullptr,
208 /*tp_dict*/ nullptr,
209 /*tp_descr_get*/ nullptr,
210 /*tp_descr_set*/ nullptr,
211 /*tp_dictoffset*/ 0,
212 /*tp_init*/ nullptr,
213 /*tp_alloc*/ nullptr,
215 /*tp_free*/ nullptr,
216 /*tp_is_gc*/ nullptr,
217 /*tp_bases*/ nullptr,
218 /*tp_mro*/ nullptr,
219 /*tp_cache*/ nullptr,
220 /*tp_subclasses*/ nullptr,
221 /*tp_weaklist*/ nullptr,
222 /*tp_del*/ nullptr,
223 /*tp_version_tag*/ 0,
224 /*tp_finalize*/ nullptr,
225 /*tp_vectorcall*/ nullptr,
226};
227
230/* -------------------------------------------------------------------- */
234PyObject *BPyGPUUniformBuf_CreatePyObject(GPUUniformBuf *ubo)
235{
237
239 self->ubo = ubo;
240
241 return (PyObject *)self;
242}
243
246#undef BPYGPU_UNIFORMBUF_CHECK_OBJ
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define UNLIKELY(x)
GPUContext * GPU_context_active_get()
GPUUniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
PyObject * self
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
Definition gpu_py.hh:18
#define BPYGPU_USE_GPUOBJ_FREE_METHOD
static int pygpu_uniformbuffer_valid_check(BPyGPUUniformBuf *bpygpu_ub)
static PyGetSetDef pygpu_uniformbuffer__tp_getseters[]
static PyMethodDef pygpu_uniformbuffer__tp_methods[]
PyDoc_STRVAR(pygpu_uniformbuffer_update_doc, ".. method:: update(data)\n" "\n" " Update the data of the uniform buffer object.\n")
PyObject * BPyGPUUniformBuf_CreatePyObject(GPUUniformBuf *ubo)
#define BPYGPU_UNIFORMBUF_CHECK_OBJ(bpygpu)
static PyObject * pygpu_uniformbuffer_update(BPyGPUUniformBuf *self, PyObject *obj)
static void BPyGPUUniformBuf__tp_dealloc(BPyGPUUniformBuf *self)
static PyObject * pygpu_uniformbuffer__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
PyTypeObject BPyGPUUniformBuf_Type
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
PyObject_HEAD GPUUniformBuf * ubo