Blender  V2.93
gpu_py_shader.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 
24 #include <Python.h>
25 
26 #include "BLI_utildefines.h"
27 
28 #include "GPU_shader.h"
29 #include "GPU_texture.h"
30 #include "GPU_uniform_buffer.h"
31 
32 #include "../generic/py_capi_utils.h"
33 #include "../generic/python_utildefines.h"
34 #include "../mathutils/mathutils.h"
35 
36 #include "gpu_py.h"
37 #include "gpu_py_texture.h"
38 #include "gpu_py_uniformbuffer.h"
39 #include "gpu_py_vertex_format.h"
40 
41 #include "gpu_py_shader.h" /* own include */
42 
43 /* -------------------------------------------------------------------- */
47 static const struct PyC_StringEnumItems pygpu_shader_builtin_items[] = {
48  {GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"},
49  {GPU_SHADER_2D_FLAT_COLOR, "2D_FLAT_COLOR"},
50  {GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"},
51  {GPU_SHADER_2D_IMAGE, "2D_IMAGE"},
52  {GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"},
53  {GPU_SHADER_3D_FLAT_COLOR, "3D_FLAT_COLOR"},
54  {GPU_SHADER_3D_SMOOTH_COLOR, "3D_SMOOTH_COLOR"},
55  {GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, "3D_POLYLINE_UNIFORM_COLOR"},
56  {0, NULL},
57 };
58 
60  const char *name,
61  const char *error_prefix)
62 {
63  const int uniform = GPU_shader_get_uniform(shader, name);
64 
65  if (uniform == -1) {
66  PyErr_Format(PyExc_ValueError, "%s: uniform %.32s not found", error_prefix, name);
67  }
68 
69  return uniform;
70 }
71 
74 /* -------------------------------------------------------------------- */
78 static PyObject *pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
79 {
81 
82  struct {
83  const char *vertexcode;
84  const char *fragcode;
85  const char *geocode;
86  const char *libcode;
87  const char *defines;
88  } params = {0};
89 
90  static const char *_keywords[] = {
91  "vertexcode", "fragcode", "geocode", "libcode", "defines", NULL};
92 
93  static _PyArg_Parser _parser = {"ss|$sss:GPUShader.__new__", _keywords, 0};
94  if (!_PyArg_ParseTupleAndKeywordsFast(args,
95  kwds,
96  &_parser,
97  &params.vertexcode,
98  &params.fragcode,
99  &params.geocode,
100  &params.libcode,
101  &params.defines)) {
102  return NULL;
103  }
104 
106  params.vertexcode, params.fragcode, params.geocode, params.libcode, params.defines);
107 
108  if (shader == NULL) {
109  PyErr_SetString(PyExc_Exception, "Shader Compile Error, see console for more details");
110  return NULL;
111  }
112 
113  return BPyGPUShader_CreatePyObject(shader, false);
114 }
115 
117  pygpu_shader_bind_doc,
118  ".. method:: bind()\n"
119  "\n"
120  " Bind the shader object. Required to be able to change uniforms of this shader.\n");
121 static PyObject *pygpu_shader_bind(BPyGPUShader *self)
122 {
123  GPU_shader_bind(self->shader);
124  Py_RETURN_NONE;
125 }
126 
127 PyDoc_STRVAR(pygpu_shader_uniform_from_name_doc,
128  ".. method:: uniform_from_name(name)\n"
129  "\n"
130  " Get uniform location by name.\n"
131  "\n"
132  " :param name: Name of the uniform variable whose location is to be queried.\n"
133  " :type name: str\n"
134  " :return: Location of the uniform variable.\n"
135  " :rtype: int\n");
136 static PyObject *pygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg)
137 {
138  const char *name = PyUnicode_AsUTF8(arg);
139  if (name == NULL) {
140  return NULL;
141  }
142 
143  const int uniform = pygpu_shader_uniform_location_get(
144  self->shader, name, "GPUShader.get_uniform");
145 
146  if (uniform == -1) {
147  return NULL;
148  }
149 
150  return PyLong_FromLong(uniform);
151 }
152 
154  pygpu_shader_uniform_block_from_name_doc,
155  ".. method:: uniform_block_from_name(name)\n"
156  "\n"
157  " Get uniform block location by name.\n"
158  "\n"
159  " :param name: Name of the uniform block variable whose location is to be queried.\n"
160  " :type name: str\n"
161  " :return: The location of the uniform block variable.\n"
162  " :rtype: int\n");
163 static PyObject *pygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg)
164 {
165  const char *name = PyUnicode_AsUTF8(arg);
166  if (name == NULL) {
167  return NULL;
168  }
169 
170  const int uniform = GPU_shader_get_uniform_block(self->shader, name);
171 
172  if (uniform == -1) {
173  PyErr_Format(PyExc_ValueError, "GPUShader.get_uniform_block: uniform %.32s not found", name);
174  return NULL;
175  }
176 
177  return PyLong_FromLong(uniform);
178 }
179 
180 static bool pygpu_shader_uniform_vector_impl(PyObject *args,
181  int elem_size,
182  int *r_location,
183  int *r_length,
184  int *r_count,
185  Py_buffer *r_pybuffer)
186 {
187  PyObject *buffer;
188 
189  *r_count = 1;
190  if (!PyArg_ParseTuple(
191  args, "iOi|i:GPUShader.uniform_vector_*", r_location, &buffer, r_length, r_count)) {
192  return false;
193  }
194 
195  if (PyObject_GetBuffer(buffer, r_pybuffer, PyBUF_SIMPLE) == -1) {
196  /* PyObject_GetBuffer raise a PyExc_BufferError */
197  return false;
198  }
199 
200  if (r_pybuffer->len != (*r_length * *r_count * elem_size)) {
201  PyErr_SetString(PyExc_BufferError, "GPUShader.uniform_vector_*: buffer size does not match.");
202  return false;
203  }
204 
205  return true;
206 }
207 
208 PyDoc_STRVAR(pygpu_shader_uniform_vector_float_doc,
209  ".. method:: uniform_vector_float(location, buffer, length, count)\n"
210  "\n"
211  " Set the buffer to fill the uniform.\n"
212  "\n"
213  " :param location: Location of the uniform variable to be modified.\n"
214  " :type location: int\n"
215  " :param buffer: The data that should be set. Can support the buffer protocol.\n"
216  " :type buffer: sequence of floats\n"
217  " :param length: Size of the uniform data type:\n\n"
218  " - 1: float\n"
219  " - 2: vec2 or float[2]\n"
220  " - 3: vec3 or float[3]\n"
221  " - 4: vec4 or float[4]\n"
222  " - 9: mat3\n"
223  " - 16: mat4\n"
224  " :type length: int\n"
225  " :param count: Specifies the number of elements, vector or matrices that are to "
226  "be modified.\n"
227  " :type count: int\n");
228 static PyObject *pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args)
229 {
230  int location, length, count;
231 
232  Py_buffer pybuffer;
233 
235  args, sizeof(float), &location, &length, &count, &pybuffer)) {
236  return NULL;
237  }
238 
239  GPU_shader_uniform_vector(self->shader, location, length, count, pybuffer.buf);
240 
241  PyBuffer_Release(&pybuffer);
242 
243  Py_RETURN_NONE;
244 }
245 
246 PyDoc_STRVAR(pygpu_shader_uniform_vector_int_doc,
247  ".. method:: uniform_vector_int(location, buffer, length, count)\n"
248  "\n"
249  " See GPUShader.uniform_vector_float(...) description.\n");
250 static PyObject *pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args)
251 {
252  int location, length, count;
253 
254  Py_buffer pybuffer;
255 
257  args, sizeof(int), &location, &length, &count, &pybuffer)) {
258  return NULL;
259  }
260 
261  GPU_shader_uniform_vector_int(self->shader, location, length, count, pybuffer.buf);
262 
263  PyBuffer_Release(&pybuffer);
264 
265  Py_RETURN_NONE;
266 }
267 
268 PyDoc_STRVAR(pygpu_shader_uniform_bool_doc,
269  ".. method:: uniform_bool(name, seq)\n"
270  "\n"
271  " Specify the value of a uniform variable for the current program object.\n"
272  "\n"
273  " :param name: Name of the uniform variable whose value is to be changed.\n"
274  " :type name: str\n"
275  " :param seq: Value that will be used to update the specified uniform variable.\n"
276  " :type seq: sequence of bools\n");
277 static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args)
278 {
279  const char *error_prefix = "GPUShader.uniform_bool";
280 
281  struct {
282  const char *id;
283  PyObject *seq;
284  } params;
285 
286  if (!PyArg_ParseTuple(args, "sO:GPUShader.uniform_bool", &params.id, &params.seq)) {
287  return NULL;
288  }
289 
290  int values[4];
291  int length;
292  int ret;
293  {
294  PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
295  if (seq_fast == NULL) {
296  PyErr_Format(PyExc_TypeError,
297  "%s: expected a sequence, got %s",
298  error_prefix,
299  Py_TYPE(params.seq)->tp_name);
300  ret = -1;
301  }
302  else {
303  length = PySequence_Fast_GET_SIZE(seq_fast);
304  if (length == 0 || length > 4) {
305  PyErr_Format(PyExc_TypeError,
306  "%s: invalid sequence length. expected 1..4, got %d",
307  error_prefix,
308  length);
309  ret = -1;
310  }
311  else {
312  ret = PyC_AsArray_FAST(values, seq_fast, length, &PyLong_Type, false, error_prefix);
313  }
314  Py_DECREF(seq_fast);
315  }
316  }
317  if (ret == -1) {
318  return NULL;
319  }
320 
321  const int location = pygpu_shader_uniform_location_get(self->shader, params.id, error_prefix);
322 
323  if (location == -1) {
324  return NULL;
325  }
326 
327  GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
328 
329  Py_RETURN_NONE;
330 }
331 
332 PyDoc_STRVAR(pygpu_shader_uniform_float_doc,
333  ".. method:: uniform_float(name, value)\n"
334  "\n"
335  " Specify the value of a uniform variable for the current program object.\n"
336  "\n"
337  " :param name: Name of the uniform variable whose value is to be changed.\n"
338  " :type name: str\n"
339  " :param value: Value that will be used to update the specified uniform variable.\n"
340  " :type value: single number or sequence of numbers\n");
341 static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args)
342 {
343  const char *error_prefix = "GPUShader.uniform_float";
344 
345  struct {
346  const char *id;
347  PyObject *seq;
348  } params;
349 
350  if (!PyArg_ParseTuple(args, "sO:GPUShader.uniform_float", &params.id, &params.seq)) {
351  return NULL;
352  }
353 
354  float values[16];
355  int length;
356 
357  if (PyFloat_Check(params.seq)) {
358  values[0] = (float)PyFloat_AsDouble(params.seq);
359  length = 1;
360  }
361  else if (PyLong_Check(params.seq)) {
362  values[0] = (float)PyLong_AsDouble(params.seq);
363  length = 1;
364  }
365  else if (MatrixObject_Check(params.seq)) {
366  MatrixObject *mat = (MatrixObject *)params.seq;
367  if (BaseMath_ReadCallback(mat) == -1) {
368  return NULL;
369  }
370  if ((mat->num_row != mat->num_col) || !ELEM(mat->num_row, 3, 4)) {
371  PyErr_SetString(PyExc_ValueError, "Expected 3x3 or 4x4 matrix");
372  return NULL;
373  }
374  length = mat->num_row * mat->num_col;
375  memcpy(values, mat->matrix, sizeof(float) * length);
376  }
377  else {
378  length = mathutils_array_parse(values, 2, 16, params.seq, "");
379  if (length == -1) {
380  return NULL;
381  }
382  }
383 
384  if (!ELEM(length, 1, 2, 3, 4, 9, 16)) {
385  PyErr_SetString(PyExc_TypeError,
386  "Expected a single float or a sequence of floats of length 1..4, 9 or 16.");
387  return NULL;
388  }
389 
390  const int location = pygpu_shader_uniform_location_get(self->shader, params.id, error_prefix);
391 
392  if (location == -1) {
393  return NULL;
394  }
395 
396  GPU_shader_uniform_vector(self->shader, location, length, 1, values);
397 
398  Py_RETURN_NONE;
399 }
400 
401 PyDoc_STRVAR(pygpu_shader_uniform_int_doc,
402  ".. method:: uniform_int(name, seq)\n"
403  "\n"
404  " Specify the value of a uniform variable for the current program object.\n"
405  "\n"
406  " :param name: name of the uniform variable whose value is to be changed.\n"
407  " :type name: str\n"
408  " :param seq: Value that will be used to update the specified uniform variable.\n"
409  " :type seq: sequence of numbers\n");
410 static PyObject *pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args)
411 {
412  const char *error_prefix = "GPUShader.uniform_int";
413 
414  struct {
415  const char *id;
416  PyObject *seq;
417  } params;
418 
419  if (!PyArg_ParseTuple(args, "sO:GPUShader.uniform_int", &params.id, &params.seq)) {
420  return NULL;
421  }
422 
423  int values[4];
424  int length;
425  int ret;
426 
427  if (PyLong_Check(params.seq)) {
428  values[0] = PyC_Long_AsI32(params.seq);
429  length = 1;
430  ret = 0;
431  }
432  else {
433  PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
434  if (seq_fast == NULL) {
435  PyErr_Format(PyExc_TypeError,
436  "%s: expected a sequence, got %s",
437  error_prefix,
438  Py_TYPE(params.seq)->tp_name);
439  ret = -1;
440  }
441  else {
442  length = PySequence_Fast_GET_SIZE(seq_fast);
443  if (length == 0 || length > 4) {
444  PyErr_Format(PyExc_TypeError,
445  "%s: invalid sequence length. expected 1..4, got %d",
446  error_prefix,
447  length);
448  ret = -1;
449  }
450  else {
451  ret = PyC_AsArray_FAST(values, seq_fast, length, &PyLong_Type, false, error_prefix);
452  }
453  Py_DECREF(seq_fast);
454  }
455  }
456  if (ret == -1) {
457  return NULL;
458  }
459 
460  const int location = pygpu_shader_uniform_location_get(self->shader, params.id, error_prefix);
461 
462  if (location == -1) {
463  return NULL;
464  }
465 
466  GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
467 
468  Py_RETURN_NONE;
469 }
470 
471 PyDoc_STRVAR(pygpu_shader_uniform_sampler_doc,
472  ".. method:: uniform_sampler(name, texture)\n"
473  "\n"
474  " Specify the value of a texture uniform variable for the current GPUShader.\n"
475  "\n"
476  " :param name: name of the uniform variable whose texture is to be specified.\n"
477  " :type name: str\n"
478  " :param texture: Texture to attach.\n"
479  " :type texture: :class:`gpu.types.GPUTexture`\n");
480 static PyObject *pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args)
481 {
482  const char *name;
483  BPyGPUTexture *py_texture;
484  if (!PyArg_ParseTuple(
485  args, "sO!:GPUShader.uniform_sampler", &name, &BPyGPUTexture_Type, &py_texture)) {
486  return NULL;
487  }
488 
489  int slot = GPU_shader_get_texture_binding(self->shader, name);
490  GPU_texture_bind(py_texture->tex, slot);
491  GPU_shader_uniform_1i(self->shader, name, slot);
492 
493  Py_RETURN_NONE;
494 }
495 
497  pygpu_shader_uniform_block_doc,
498  ".. method:: uniform_block(name, ubo)\n"
499  "\n"
500  " Specify the value of an uniform buffer object variable for the current GPUShader.\n"
501  "\n"
502  " :param name: name of the uniform variable whose UBO is to be specified.\n"
503  " :type name: str\n"
504  " :param ubo: Uniform Buffer to attach.\n"
505  " :type texture: :class:`gpu.types.GPUUniformBuf`\n");
506 static PyObject *pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args)
507 {
508  const char *name;
509  BPyGPUUniformBuf *py_ubo;
510  if (!PyArg_ParseTuple(
511  args, "sO!:GPUShader.uniform_block", &name, &BPyGPUUniformBuf_Type, &py_ubo)) {
512  return NULL;
513  }
514 
515  int slot = GPU_shader_get_uniform_block(self->shader, name);
516  if (slot == -1) {
517  PyErr_SetString(
518  PyExc_BufferError,
519  "GPUShader.uniform_buffer: uniform block not found, make sure the name is correct");
520  return NULL;
521  }
522 
523  GPU_uniformbuf_bind(py_ubo->ubo, slot);
524  GPU_shader_uniform_1i(self->shader, name, slot);
525 
526  Py_RETURN_NONE;
527 }
528 
530  pygpu_shader_attr_from_name_doc,
531  ".. method:: attr_from_name(name)\n"
532  "\n"
533  " Get attribute location by name.\n"
534  "\n"
535  " :param name: The name of the attribute variable whose location is to be queried.\n"
536  " :type name: str\n"
537  " :return: The location of an attribute variable.\n"
538  " :rtype: int\n");
539 static PyObject *pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg)
540 {
541  const char *name = PyUnicode_AsUTF8(arg);
542  if (name == NULL) {
543  return NULL;
544  }
545 
546  const int attr = GPU_shader_get_attribute(self->shader, name);
547 
548  if (attr == -1) {
549  PyErr_Format(PyExc_ValueError, "GPUShader.attr_from_name: attribute %.32s not found", name);
550  return NULL;
551  }
552 
553  return PyLong_FromLong(attr);
554 }
555 
556 PyDoc_STRVAR(pygpu_shader_calc_format_doc,
557  ".. method:: calc_format()\n"
558  "\n"
559  " Build a new format based on the attributes of the shader.\n"
560  "\n"
561  " :return: vertex attribute format for the shader\n"
562  " :rtype: :class:`gpu.types.GPUVertFormat`\n");
563 static PyObject *pygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
564 {
566  GPU_vertformat_from_shader(&ret->fmt, self->shader);
567  return (PyObject *)ret;
568 }
569 
570 static struct PyMethodDef pygpu_shader__tp_methods[] = {
571  {"bind", (PyCFunction)pygpu_shader_bind, METH_NOARGS, pygpu_shader_bind_doc},
572  {"uniform_from_name",
573  (PyCFunction)pygpu_shader_uniform_from_name,
574  METH_O,
575  pygpu_shader_uniform_from_name_doc},
576  {"uniform_block_from_name",
578  METH_O,
579  pygpu_shader_uniform_block_from_name_doc},
580  {"uniform_vector_float",
582  METH_VARARGS,
583  pygpu_shader_uniform_vector_float_doc},
584  {"uniform_vector_int",
585  (PyCFunction)pygpu_shader_uniform_vector_int,
586  METH_VARARGS,
587  pygpu_shader_uniform_vector_int_doc},
588  {"uniform_bool",
589  (PyCFunction)pygpu_shader_uniform_bool,
590  METH_VARARGS,
591  pygpu_shader_uniform_bool_doc},
592  {"uniform_float",
593  (PyCFunction)pygpu_shader_uniform_float,
594  METH_VARARGS,
595  pygpu_shader_uniform_float_doc},
596  {"uniform_int",
597  (PyCFunction)pygpu_shader_uniform_int,
598  METH_VARARGS,
599  pygpu_shader_uniform_int_doc},
600  {"uniform_sampler",
601  (PyCFunction)pygpu_shader_uniform_sampler,
602  METH_VARARGS,
603  pygpu_shader_uniform_sampler_doc},
604  {"uniform_block",
605  (PyCFunction)pygpu_shader_uniform_block,
606  METH_VARARGS,
607  pygpu_shader_uniform_block_doc},
608  {"attr_from_name",
609  (PyCFunction)pygpu_shader_attr_from_name,
610  METH_O,
611  pygpu_shader_attr_from_name_doc},
612  {"format_calc",
613  (PyCFunction)pygpu_shader_calc_format,
614  METH_NOARGS,
615  pygpu_shader_calc_format_doc},
616  {NULL, NULL, 0, NULL},
617 };
618 
620  pygpu_shader_program_doc,
621  "The name of the program object for use by the OpenGL API (read-only).\n\n:type: int");
622 static PyObject *pygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
623 {
624  return PyLong_FromLong(GPU_shader_get_program(self->shader));
625 }
626 
627 static PyGetSetDef pygpu_shader__tp_getseters[] = {
628  {"program", (getter)pygpu_shader_program_get, (setter)NULL, pygpu_shader_program_doc, NULL},
629  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
630 };
631 
633 {
634  if (self->is_builtin == false) {
635  GPU_shader_free(self->shader);
636  }
637  Py_TYPE(self)->tp_free((PyObject *)self);
638 }
639 
641  pygpu_shader__tp_doc,
642  ".. class:: GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None)\n"
643  "\n"
644  " GPUShader combines multiple GLSL shaders into a program used for drawing.\n"
645  " It must contain a vertex and fragment shaders, with an optional geometry shader.\n"
646  "\n"
647  " The GLSL ``#version`` directive is automatically included at the top of shaders,\n"
648  " and set to 330. Some preprocessor directives are automatically added according to\n"
649  " the Operating System or availability: ``GPU_ATI``, ``GPU_NVIDIA`` and ``GPU_INTEL``.\n"
650  "\n"
651  " The following extensions are enabled by default if supported by the GPU:\n"
652  " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array``\n"
653  " and ``GL_ARB_shader_draw_parameters``.\n"
654  "\n"
655  " For drawing user interface elements and gizmos, use\n"
656  " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``\n"
657  " to transform the output sRGB colors to the frame-buffer color-space.\n"
658  "\n"
659  " :param vertexcode: Vertex shader code.\n"
660  " :type vertexcode: str\n"
661  " :param fragcode: Fragment shader code.\n"
662  " :type value: str\n"
663  " :param geocode: Geometry shader code.\n"
664  " :type value: str\n"
665  " :param libcode: Code with functions and presets to be shared between shaders.\n"
666  " :type value: str\n"
667  " :param defines: Preprocessor directives.\n"
668  " :type value: str\n");
669 PyTypeObject BPyGPUShader_Type = {
670  PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUShader",
671  .tp_basicsize = sizeof(BPyGPUShader),
672  .tp_dealloc = (destructor)pygpu_shader__tp_dealloc,
673  .tp_flags = Py_TPFLAGS_DEFAULT,
674  .tp_doc = pygpu_shader__tp_doc,
675  .tp_methods = pygpu_shader__tp_methods,
676  .tp_getset = pygpu_shader__tp_getseters,
677  .tp_new = pygpu_shader__tp_new,
678 };
679 
682 /* -------------------------------------------------------------------- */
686 PyDoc_STRVAR(pygpu_shader_unbind_doc,
687  ".. function:: unbind()\n"
688  "\n"
689  " Unbind the bound shader object.\n");
690 static PyObject *pygpu_shader_unbind(BPyGPUShader *UNUSED(self))
691 {
693  Py_RETURN_NONE;
694 }
695 
696 PyDoc_STRVAR(pygpu_shader_from_builtin_doc,
697  ".. function:: from_builtin(pygpu_shader_name)\n"
698  "\n"
699  " Shaders that are embedded in the blender internal code.\n"
700  " They all read the uniform ``mat4 ModelViewProjectionMatrix``,\n"
701  " which can be edited by the :mod:`gpu.matrix` module.\n"
702  " For more details, you can check the shader code with the\n"
703  " :func:`gpu.shader.code_from_builtin` function.\n"
704  "\n"
705  " :param pygpu_shader_name: One of these builtin shader names:\n\n"
706  " - ``2D_UNIFORM_COLOR``\n"
707  " - ``2D_FLAT_COLOR``\n"
708  " - ``2D_SMOOTH_COLOR``\n"
709  " - ``2D_IMAGE``\n"
710  " - ``3D_UNIFORM_COLOR``\n"
711  " - ``3D_FLAT_COLOR``\n"
712  " - ``3D_SMOOTH_COLOR``\n"
713  " :type pygpu_shader_name: str\n"
714  " :return: Shader object corresponding to the given name.\n"
715  " :rtype: :class:`bpy.types.GPUShader`\n");
716 static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg)
717 {
719 
720  struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items};
721  if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) {
722  return NULL;
723  }
724 
726 
727  return BPyGPUShader_CreatePyObject(shader, true);
728 }
729 
730 PyDoc_STRVAR(pygpu_shader_code_from_builtin_doc,
731  ".. function:: code_from_builtin(pygpu_shader_name)\n"
732  "\n"
733  " Exposes the internal shader code for query.\n"
734  "\n"
735  " :param pygpu_shader_name: One of these builtin shader names:\n\n"
736  " - ``2D_UNIFORM_COLOR``\n"
737  " - ``2D_FLAT_COLOR``\n"
738  " - ``2D_SMOOTH_COLOR``\n"
739  " - ``2D_IMAGE``\n"
740  " - ``3D_UNIFORM_COLOR``\n"
741  " - ``3D_FLAT_COLOR``\n"
742  " - ``3D_SMOOTH_COLOR``\n"
743  " :type pygpu_shader_name: str\n"
744  " :return: Vertex, fragment and geometry shader codes.\n"
745  " :rtype: dict\n");
746 static PyObject *pygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg)
747 {
748  const char *vert;
749  const char *frag;
750  const char *geom;
751  const char *defines;
752 
753  PyObject *item, *r_dict;
754 
755  struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items};
756  if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) {
757  return NULL;
758  }
759 
761  pygpu_bultinshader.value_found, &vert, &frag, &geom, &defines);
762 
763  r_dict = PyDict_New();
764 
765  PyDict_SetItemString(r_dict, "vertex_shader", item = PyUnicode_FromString(vert));
766  Py_DECREF(item);
767 
768  PyDict_SetItemString(r_dict, "fragment_shader", item = PyUnicode_FromString(frag));
769  Py_DECREF(item);
770 
771  if (geom) {
772  PyDict_SetItemString(r_dict, "geometry_shader", item = PyUnicode_FromString(geom));
773  Py_DECREF(item);
774  }
775  if (defines) {
776  PyDict_SetItemString(r_dict, "defines", item = PyUnicode_FromString(defines));
777  Py_DECREF(item);
778  }
779  return r_dict;
780 }
781 
782 static struct PyMethodDef pygpu_shader_module__tp_methods[] = {
783  {"unbind", (PyCFunction)pygpu_shader_unbind, METH_NOARGS, pygpu_shader_unbind_doc},
784  {"from_builtin",
785  (PyCFunction)pygpu_shader_from_builtin,
786  METH_O,
787  pygpu_shader_from_builtin_doc},
788  {"code_from_builtin",
789  (PyCFunction)pygpu_shader_code_from_builtin,
790  METH_O,
791  pygpu_shader_code_from_builtin_doc},
792  {NULL, NULL, 0, NULL},
793 };
794 
795 PyDoc_STRVAR(pygpu_shader_module__tp_doc,
796  "This module provides access to GPUShader internal functions.\n"
797  "\n"
798  ".. rubric:: Built-in shaders\n"
799  "\n"
800  "All built-in shaders have the ``mat4 ModelViewProjectionMatrix`` uniform.\n"
801  "The value of it can only be modified using the :class:`gpu.matrix` module.\n"
802  "\n"
803  "2D_UNIFORM_COLOR\n"
804  " :Attributes: vec3 pos\n"
805  " :Uniforms: vec4 color\n"
806  "2D_FLAT_COLOR\n"
807  " :Attributes: vec3 pos, vec4 color\n"
808  " :Uniforms: none\n"
809  "2D_SMOOTH_COLOR\n"
810  " :Attributes: vec3 pos, vec4 color\n"
811  " :Uniforms: none\n"
812  "2D_IMAGE\n"
813  " :Attributes: vec3 pos, vec2 texCoord\n"
814  " :Uniforms: sampler2D image\n"
815  "3D_UNIFORM_COLOR\n"
816  " :Attributes: vec3 pos\n"
817  " :Uniforms: vec4 color\n"
818  "3D_FLAT_COLOR\n"
819  " :Attributes: vec3 pos, vec4 color\n"
820  " :Uniforms: none\n"
821  "3D_SMOOTH_COLOR\n"
822  " :Attributes: vec3 pos, vec4 color\n"
823  " :Uniforms: none\n");
824 static PyModuleDef pygpu_shader_module_def = {
825  PyModuleDef_HEAD_INIT,
826  .m_name = "gpu.shader",
827  .m_doc = pygpu_shader_module__tp_doc,
828  .m_methods = pygpu_shader_module__tp_methods,
829 };
830 
833 /* -------------------------------------------------------------------- */
837 PyObject *BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin)
838 {
839  BPyGPUShader *self;
840 
841  self = PyObject_New(BPyGPUShader, &BPyGPUShader_Type);
842  self->shader = shader;
843  self->is_builtin = is_builtin;
844 
845  return (PyObject *)self;
846 }
847 
848 PyObject *bpygpu_shader_init(void)
849 {
850  PyObject *submodule;
851 
852  submodule = PyModule_Create(&pygpu_shader_module_def);
853 
854  return submodule;
855 }
856 
typedef float(TangentPoint)[2]
#define UNUSED(x)
#define ELEM(...)
_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
void GPU_shader_unbind(void)
Definition: gpu_shader.cc:516
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:551
void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length, int arraysize, const int *value)
Definition: gpu_shader.cc:623
struct GPUShader GPUShader
Definition: GPU_shader.h:33
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
Definition: gpu_shader.cc:639
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, const float *value)
Definition: gpu_shader.cc:617
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:592
GPUShader * GPU_shader_create_from_python(const char *vertcode, const char *fragcode, const char *geomcode, const char *libcode, const char *defines)
Definition: gpu_shader.cc:387
int GPU_shader_get_program(GPUShader *shader)
Definition: gpu_shader.cc:606
GPUShader * GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
void GPU_shader_bind(GPUShader *shader)
Definition: gpu_shader.cc:494
void GPU_shader_get_builtin_shader_code(eGPUBuiltinShader shader, const char **r_vert, const char **r_frag, const char **r_geom, const char **r_defines)
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:571
@ GPU_SHADER_3D_SMOOTH_COLOR
Definition: GPU_shader.h:215
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:223
@ GPU_SHADER_2D_SMOOTH_COLOR
Definition: GPU_shader.h:185
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:200
@ GPU_SHADER_3D_FLAT_COLOR
Definition: GPU_shader.h:208
@ GPU_SHADER_2D_IMAGE
Definition: GPU_shader.h:186
@ GPU_SHADER_2D_FLAT_COLOR
Definition: GPU_shader.h:178
int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:585
void GPU_shader_free(GPUShader *shader)
Definition: gpu_shader.cc:365
void GPU_texture_bind(GPUTexture *tex, int unit)
Definition: gpu_texture.cc:415
void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *shader)
PyObject * self
Definition: bpy_driver.c:185
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
Definition: gpu_py.h:28
static PyObject * pygpu_shader_bind(BPyGPUShader *self)
static PyObject * pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg)
static PyObject * pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
Definition: gpu_py_shader.c:78
static PyObject * pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args)
static struct PyMethodDef pygpu_shader__tp_methods[]
static PyObject * pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
static PyObject * pygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args)
PyTypeObject BPyGPUShader_Type
static struct PyMethodDef pygpu_shader_module__tp_methods[]
static PyObject * pygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
static bool pygpu_shader_uniform_vector_impl(PyObject *args, int elem_size, int *r_location, int *r_length, int *r_count, Py_buffer *r_pybuffer)
static PyObject * pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args)
static void pygpu_shader__tp_dealloc(BPyGPUShader *self)
static PyObject * pygpu_shader_unbind(BPyGPUShader *UNUSED(self))
PyObject * bpygpu_shader_init(void)
PyObject * BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin)
static PyModuleDef pygpu_shader_module_def
PyDoc_STRVAR(pygpu_shader_bind_doc, ".. method:: bind()\n" "\n" " Bind the shader object. Required to be able to change uniforms of this shader.\n")
static const struct PyC_StringEnumItems pygpu_shader_builtin_items[]
Definition: gpu_py_shader.c:47
static PyGetSetDef pygpu_shader__tp_getseters[]
static PyObject * pygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg)
static int pygpu_shader_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix)
Definition: gpu_py_shader.c:59
struct BPyGPUShader BPyGPUShader
PyTypeObject BPyGPUTexture_Type
PyTypeObject BPyGPUUniformBuf_Type
PyObject * BPyGPUVertFormat_CreatePyObject(GPUVertFormat *fmt)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
__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
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:118
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:128
#define MatrixObject_Check(v)
int PyC_ParseStringEnum(PyObject *o, void *p)
int PyC_AsArray_FAST(void *array, PyObject *value_fast, const Py_ssize_t length, const PyTypeObject *type, const bool is_double, const char *error_prefix)
Definition: py_capi_utils.c:59
return ret
PyObject_HEAD struct GPUTexture * tex
PyObject_HEAD struct GPUUniformBuf * ubo