195 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			195 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /*
 | ||
|  |  * This program is free software; you can redistribute it and/or | ||
|  |  * modify it under the terms of the GNU General Public License | ||
|  |  * as published by the Free Software Foundation; either version 2 | ||
|  |  * of the License, or (at your option) any later version. | ||
|  |  * | ||
|  |  * This program is distributed in the hope that it will be useful, | ||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  |  * GNU General Public License for more details. | ||
|  |  * | ||
|  |  * You should have received a copy of the GNU General Public License | ||
|  |  * along with this program; if not, write to the Free Software Foundation, | ||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
|  |  */ | ||
|  | 
 | ||
|  | /** \file
 | ||
|  |  * \ingroup bpygpu | ||
|  |  * | ||
|  |  * This file defines the uniform buffer functionalities of the 'gpu' module | ||
|  |  * | ||
|  |  * - Use ``bpygpu_`` for local API. | ||
|  |  * - Use ``BPyGPU`` for public API. | ||
|  |  */ | ||
|  | 
 | ||
|  | #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}; | ||
|  |   static _PyArg_Parser _parser = {"O!:GPUUniformBuf.__new__", _keywords, 0}; | ||
|  |   if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &BPyGPU_BufferType, &pybuffer_obj)) { | ||
|  |     return NULL; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (GPU_context_active_get()) { | ||
|  |     ubo = GPU_uniformbuf_create_ex( | ||
|  |         bpygpu_Buffer_size(pybuffer_obj), pybuffer_obj->buf.as_void, "python_uniformbuffer"); | ||
|  |   } | ||
|  |   else { | ||
|  |     STRNCPY(err_out, "No active GPU context found"); | ||
|  |   } | ||
|  | 
 | ||
|  |   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, | ||
|  |              ".. method::update(data)\n" | ||
|  |              "\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" | ||
|  |              "   :type data: `Buffer`\n"); | ||
|  | 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
 |