| 
									
										
										
										
											2022-02-11 09:07:11 +11:00
										 |  |  | /* SPDX-License-Identifier: GPL-2.0-or-later */ | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bpygpu | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file defines the uniform buffer functionalities of the 'gpu' module | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-07-20 22:52:31 +10:00
										 |  |  |  * - Use `bpygpu_` for local API. | 
					
						
							|  |  |  |  * - Use `BPyGPU` for public API. | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GPU_context.h"
 | 
					
						
							|  |  |  | #include "GPU_texture.h"
 | 
					
						
							|  |  |  | #include "GPU_uniform_buffer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../generic/py_capi_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_py.h"
 | 
					
						
							|  |  |  | #include "gpu_py_buffer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_py_uniformbuffer.h" /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name GPUUniformBuf Common Utilities
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pygpu_uniformbuffer_valid_check(BPyGPUUniformBuf *bpygpu_ub) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (UNLIKELY(bpygpu_ub->ubo == NULL)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_ReferenceError, | 
					
						
							|  |  |  | #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
 | 
					
						
							|  |  |  |                     "GPU uniform buffer was freed, no further access is valid"); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     "GPU uniform buffer: internal error"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BPYGPU_UNIFORMBUF_CHECK_OBJ(bpygpu) \
 | 
					
						
							|  |  |  |   { \ | 
					
						
							|  |  |  |     if (UNLIKELY(pygpu_uniformbuffer_valid_check(bpygpu) == -1)) { \ | 
					
						
							|  |  |  |       return NULL; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   } \ | 
					
						
							|  |  |  |   ((void)0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name GPUUniformBuf Type
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject *UNUSED(self), | 
					
						
							|  |  |  |                                              PyObject *args, | 
					
						
							|  |  |  |                                              PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BPYGPU_IS_INIT_OR_ERROR_OBJ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GPUUniformBuf *ubo = NULL; | 
					
						
							|  |  |  |   BPyGPUBuffer *pybuffer_obj; | 
					
						
							|  |  |  |   char err_out[256] = "unknown error. See console"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static const char *_keywords[] = {"data", NULL}; | 
					
						
							| 
									
										
										
										
											2022-04-08 09:41:28 +10:00
										 |  |  |   static _PyArg_Parser _parser = { | 
					
						
							|  |  |  |       "O!" /* `data` */ | 
					
						
							|  |  |  |       ":GPUUniformBuf.__new__", | 
					
						
							|  |  |  |       _keywords, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  |   if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &BPyGPU_BufferType, &pybuffer_obj)) { | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-11 16:54:05 -03:00
										 |  |  |   if (!GPU_context_active_get()) { | 
					
						
							|  |  |  |     STRNCPY(err_out, "No active GPU context found"); | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2022-04-11 16:54:05 -03:00
										 |  |  |     size_t size = bpygpu_Buffer_size(pybuffer_obj); | 
					
						
							|  |  |  |     if ((size % 16) != 0) { | 
					
						
							|  |  |  |       STRNCPY(err_out, "UBO is not padded to size of vec4"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       ubo = GPU_uniformbuf_create_ex(size, pybuffer_obj->buf.as_void, "python_uniformbuffer"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ubo == NULL) { | 
					
						
							|  |  |  |     PyErr_Format(PyExc_RuntimeError, "GPUUniformBuf.__new__(...) failed with '%s'", err_out); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return BPyGPUUniformBuf_CreatePyObject(ubo); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(pygpu_uniformbuffer_update_doc, | 
					
						
							| 
									
										
										
										
											2021-07-07 19:41:15 -04:00
										 |  |  |              ".. method:: update(data)\n" | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  |              "\n" | 
					
						
							|  |  |  |              "   Update the data of the uniform buffer object.\n"); | 
					
						
							|  |  |  | static PyObject *pygpu_uniformbuffer_update(BPyGPUUniformBuf *self, PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BPYGPU_UNIFORMBUF_CHECK_OBJ(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!BPyGPU_Buffer_Check(obj)) { | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GPU_uniformbuf_update(self->ubo, ((BPyGPUBuffer *)obj)->buf.as_void); | 
					
						
							|  |  |  |   Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
 | 
					
						
							|  |  |  | PyDoc_STRVAR(pygpu_uniformbuffer_free_doc, | 
					
						
							|  |  |  |              ".. method::free()\n" | 
					
						
							|  |  |  |              "\n" | 
					
						
							|  |  |  |              "   Free the uniform buffer object.\n" | 
					
						
							|  |  |  |              "   The uniform buffer object will no longer be accessible.\n"); | 
					
						
							|  |  |  | static PyObject *pygpu_uniformbuffer_free(BPyGPUUniformBuf *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BPYGPU_UNIFORMBUF_CHECK_OBJ(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GPU_uniformbuf_free(self->ubo); | 
					
						
							|  |  |  |   self->ubo = NULL; | 
					
						
							|  |  |  |   Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void BPyGPUUniformBuf__tp_dealloc(BPyGPUUniformBuf *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (self->ubo) { | 
					
						
							|  |  |  |     GPU_uniformbuf_free(self->ubo); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   Py_TYPE(self)->tp_free((PyObject *)self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef pygpu_uniformbuffer__tp_getseters[] = { | 
					
						
							|  |  |  |     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMethodDef pygpu_uniformbuffer__tp_methods[] = { | 
					
						
							|  |  |  |     {"update", (PyCFunction)pygpu_uniformbuffer_update, METH_O, pygpu_uniformbuffer_update_doc}, | 
					
						
							|  |  |  | #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
 | 
					
						
							|  |  |  |     {"free", (PyCFunction)pygpu_uniformbuffer_free, METH_NOARGS, pygpu_uniformbuffer_free_doc}, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     {NULL, NULL, 0, NULL}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(pygpu_uniformbuffer__tp_doc, | 
					
						
							|  |  |  |              ".. class:: GPUUniformBuf(data)\n" | 
					
						
							|  |  |  |              "\n" | 
					
						
							|  |  |  |              "   This object gives access to off uniform buffers.\n" | 
					
						
							|  |  |  |              "\n" | 
					
						
							|  |  |  |              "   :arg data: Buffer object.\n" | 
					
						
							| 
									
										
										
										
											2021-03-16 12:48:00 -03:00
										 |  |  |              "   :type data: :class:`gpu.types.Buffer`\n"); | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  | PyTypeObject BPyGPUUniformBuf_Type = { | 
					
						
							|  |  |  |     PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUUniformBuf", | 
					
						
							|  |  |  |     .tp_basicsize = sizeof(BPyGPUUniformBuf), | 
					
						
							|  |  |  |     .tp_dealloc = (destructor)BPyGPUUniformBuf__tp_dealloc, | 
					
						
							|  |  |  |     .tp_flags = Py_TPFLAGS_DEFAULT, | 
					
						
							|  |  |  |     .tp_doc = pygpu_uniformbuffer__tp_doc, | 
					
						
							|  |  |  |     .tp_methods = pygpu_uniformbuffer__tp_methods, | 
					
						
							|  |  |  |     .tp_getset = pygpu_uniformbuffer__tp_getseters, | 
					
						
							|  |  |  |     .tp_new = pygpu_uniformbuffer__tp_new, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Public API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BPyGPUUniformBuf_CreatePyObject(GPUUniformBuf *ubo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BPyGPUUniformBuf *self; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   self = PyObject_New(BPyGPUUniformBuf, &BPyGPUUniformBuf_Type); | 
					
						
							|  |  |  |   self->ubo = ubo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (PyObject *)self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef BPYGPU_UNIFORMBUF_CHECK_OBJ
 |