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