Blender V4.3
gpu_py_shader_create_info.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include <Python.h>
13
14#include "BLI_utildefines.h"
15
16#include "GPU_shader.hh"
18
21
22#include "gpu_py.hh"
23#include "gpu_py_shader.hh" /* own include */
24#include "gpu_py_texture.hh"
25
26#define USE_PYGPU_SHADER_INFO_IMAGE_METHOD
27
34
35#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
37
38# define PYDOC_QUALIFIERS \
39 " - ``NO_RESTRICT``\n" \
40 " - ``READ``\n" \
41 " - ``WRITE``\n"
42static const PyC_FlagSet pygpu_qualifiers[] = {
43 {int(Qualifier::NO_RESTRICT), "NO_RESTRICT"},
44 {int(Qualifier::READ), "READ"},
45 {int(Qualifier::WRITE), "WRITE"},
46 {0, nullptr},
47};
48#endif
49
50#define PYDOC_TYPE_LIST \
51 " - ``FLOAT``\n" \
52 " - ``VEC2``\n" \
53 " - ``VEC3``\n" \
54 " - ``VEC4``\n" \
55 " - ``MAT3``\n" \
56 " - ``MAT4``\n" \
57 " - ``UINT``\n" \
58 " - ``UVEC2``\n" \
59 " - ``UVEC3``\n" \
60 " - ``UVEC4``\n" \
61 " - ``INT``\n" \
62 " - ``IVEC2``\n" \
63 " - ``IVEC3``\n" \
64 " - ``IVEC4``\n" \
65 " - ``BOOL``\n"
67 {int(Type::FLOAT), "FLOAT"},
68 {int(Type::VEC2), "VEC2"},
69 {int(Type::VEC3), "VEC3"},
70 {int(Type::VEC4), "VEC4"},
71 {int(Type::MAT3), "MAT3"},
72 {int(Type::MAT4), "MAT4"},
73 {int(Type::UINT), "UINT"},
74 {int(Type::UVEC2), "UVEC2"},
75 {int(Type::UVEC3), "UVEC3"},
76 {int(Type::UVEC4), "UVEC4"},
77 {int(Type::INT), "INT"},
78 {int(Type::IVEC2), "IVEC2"},
79 {int(Type::IVEC3), "IVEC3"},
80 {int(Type::IVEC4), "IVEC4"},
81 {int(Type::BOOL), "BOOL"},
82 {0, nullptr},
83};
84
85#define PYDOC_IMAGE_TYPES \
86 " - ``FLOAT_BUFFER``\n" \
87 " - ``FLOAT_1D``\n" \
88 " - ``FLOAT_1D_ARRAY``\n" \
89 " - ``FLOAT_2D``\n" \
90 " - ``FLOAT_2D_ARRAY``\n" \
91 " - ``FLOAT_3D``\n" \
92 " - ``FLOAT_CUBE``\n" \
93 " - ``FLOAT_CUBE_ARRAY``\n" \
94 " - ``INT_BUFFER``\n" \
95 " - ``INT_1D``\n" \
96 " - ``INT_1D_ARRAY``\n" \
97 " - ``INT_2D``\n" \
98 " - ``INT_2D_ARRAY``\n" \
99 " - ``INT_3D``\n" \
100 " - ``INT_CUBE``\n" \
101 " - ``INT_CUBE_ARRAY``\n" \
102 " - ``UINT_BUFFER``\n" \
103 " - ``UINT_1D``\n" \
104 " - ``UINT_1D_ARRAY``\n" \
105 " - ``UINT_2D``\n" \
106 " - ``UINT_2D_ARRAY``\n" \
107 " - ``UINT_3D``\n" \
108 " - ``UINT_CUBE``\n" \
109 " - ``UINT_CUBE_ARRAY``\n" \
110 " - ``SHADOW_2D``\n" \
111 " - ``SHADOW_2D_ARRAY``\n" \
112 " - ``SHADOW_CUBE``\n" \
113 " - ``SHADOW_CUBE_ARRAY``\n" \
114 " - ``DEPTH_2D``\n" \
115 " - ``DEPTH_2D_ARRAY``\n" \
116 " - ``DEPTH_CUBE``\n" \
117 " - ``DEPTH_CUBE_ARRAY``\n"
119 {int(ImageType::FLOAT_BUFFER), "FLOAT_BUFFER"},
120 {int(ImageType::FLOAT_1D), "FLOAT_1D"},
121 {int(ImageType::FLOAT_1D_ARRAY), "FLOAT_1D_ARRAY"},
122 {int(ImageType::FLOAT_2D), "FLOAT_2D"},
123 {int(ImageType::FLOAT_2D_ARRAY), "FLOAT_2D_ARRAY"},
124 {int(ImageType::FLOAT_3D), "FLOAT_3D"},
125 {int(ImageType::FLOAT_CUBE), "FLOAT_CUBE"},
126 {int(ImageType::FLOAT_CUBE_ARRAY), "FLOAT_CUBE_ARRAY"},
127 {int(ImageType::INT_BUFFER), "INT_BUFFER"},
128 {int(ImageType::INT_1D), "INT_1D"},
129 {int(ImageType::INT_1D_ARRAY), "INT_1D_ARRAY"},
130 {int(ImageType::INT_2D), "INT_2D"},
131 {int(ImageType::INT_2D_ARRAY), "INT_2D_ARRAY"},
132 {int(ImageType::INT_3D), "INT_3D"},
133 {int(ImageType::INT_CUBE), "INT_CUBE"},
134 {int(ImageType::INT_CUBE_ARRAY), "INT_CUBE_ARRAY"},
135 {int(ImageType::INT_2D_ATOMIC), "INT_2D_ATOMIC"},
136 {int(ImageType::INT_2D_ARRAY_ATOMIC), "INT_2D_ARRAY_ATOMIC"},
137 {int(ImageType::INT_3D_ATOMIC), "INT_3D_ATOMIC"},
138 {int(ImageType::UINT_BUFFER), "UINT_BUFFER"},
139 {int(ImageType::UINT_1D), "UINT_1D"},
140 {int(ImageType::UINT_1D_ARRAY), "UINT_1D_ARRAY"},
141 {int(ImageType::UINT_2D), "UINT_2D"},
142 {int(ImageType::UINT_2D_ARRAY), "UINT_2D_ARRAY"},
143 {int(ImageType::UINT_3D), "UINT_3D"},
144 {int(ImageType::UINT_CUBE), "UINT_CUBE"},
145 {int(ImageType::UINT_CUBE_ARRAY), "UINT_CUBE_ARRAY"},
146 {int(ImageType::UINT_2D_ATOMIC), "UINT_2D_ATOMIC"},
147 {int(ImageType::UINT_2D_ARRAY_ATOMIC), "UINT_2D_ARRAY_ATOMIC"},
148 {int(ImageType::UINT_3D_ATOMIC), "UINT_3D_ATOMIC"},
149 {int(ImageType::SHADOW_2D), "SHADOW_2D"},
150 {int(ImageType::SHADOW_2D_ARRAY), "SHADOW_2D_ARRAY"},
151 {int(ImageType::SHADOW_CUBE), "SHADOW_CUBE"},
152 {int(ImageType::SHADOW_CUBE_ARRAY), "SHADOW_CUBE_ARRAY"},
153 {int(ImageType::DEPTH_2D), "DEPTH_2D"},
154 {int(ImageType::DEPTH_2D_ARRAY), "DEPTH_2D_ARRAY"},
155 {int(ImageType::DEPTH_CUBE), "DEPTH_CUBE"},
156 {int(ImageType::DEPTH_CUBE_ARRAY), "DEPTH_CUBE_ARRAY"},
157 {0, nullptr},
158};
159
161 {int(DualBlend::NONE), "NONE"},
162 {int(DualBlend::SRC_0), "SRC_0"},
163 {int(DualBlend::SRC_1), "SRC_1"},
164 {0, nullptr},
165};
166
167#define PYDOC_TEX_FORMAT_ITEMS \
168 " - ``RGBA8UI``\n" \
169 " - ``RGBA8I``\n" \
170 " - ``RGBA8``\n" \
171 " - ``RGBA32UI``\n" \
172 " - ``RGBA32I``\n" \
173 " - ``RGBA32F``\n" \
174 " - ``RGBA16UI``\n" \
175 " - ``RGBA16I``\n" \
176 " - ``RGBA16F``\n" \
177 " - ``RGBA16``\n" \
178 " - ``RG8UI``\n" \
179 " - ``RG8I``\n" \
180 " - ``RG8``\n" \
181 " - ``RG32UI``\n" \
182 " - ``RG32I``\n" \
183 " - ``RG32F``\n" \
184 " - ``RG16UI``\n" \
185 " - ``RG16I``\n" \
186 " - ``RG16F``\n" \
187 " - ``RG16``\n" \
188 " - ``R8UI``\n" \
189 " - ``R8I``\n" \
190 " - ``R8``\n" \
191 " - ``R32UI``\n" \
192 " - ``R32I``\n" \
193 " - ``R32F``\n" \
194 " - ``R16UI``\n" \
195 " - ``R16I``\n" \
196 " - ``R16F``\n" \
197 " - ``R16``\n" \
198 " - ``R11F_G11F_B10F``\n" \
199 " - ``DEPTH32F_STENCIL8``\n" \
200 " - ``DEPTH24_STENCIL8``\n" \
201 " - ``SRGB8_A8``\n" \
202 " - ``RGB16F``\n" \
203 " - ``SRGB8_A8_DXT1``\n" \
204 " - ``SRGB8_A8_DXT3``\n" \
205 " - ``SRGB8_A8_DXT5``\n" \
206 " - ``RGBA8_DXT1``\n" \
207 " - ``RGBA8_DXT3``\n" \
208 " - ``RGBA8_DXT5``\n" \
209 " - ``DEPTH_COMPONENT32F``\n" \
210 " - ``DEPTH_COMPONENT24``\n" \
211 " - ``DEPTH_COMPONENT16``\n"
213
214/* -------------------------------------------------------------------- */
219 PyObject *args,
220 const char *format,
221 Type *r_type,
222 const char **r_name)
223{
225 PyObject *py_name;
226
227 if (!PyArg_ParseTuple(args, format, PyC_ParseStringEnum, &pygpu_type, &py_name)) {
228 return false;
229 }
230
231 const char *name = PyUnicode_AsUTF8(py_name);
232 if (name == nullptr) {
233 return false;
234 }
235
236#ifdef USE_GPU_PY_REFERENCES
237 PyList_Append(self->references, (PyObject *)py_name);
238#endif
239
240 *r_type = (Type)pygpu_type.value_found;
241 *r_name = name;
242 return true;
243}
244
246 /* Wrap. */
247 pygpu_interface_info_smooth_doc,
248 ".. method:: smooth(type, name)\n"
249 "\n"
250 " Add an attribute with qualifier of type *smooth* to the interface block.\n"
251 "\n"
252 " :arg type: One of these types:\n"
253 "\n" PYDOC_TYPE_LIST
254 "\n"
255 " :type type: str\n"
256 " :arg name: name of the attribute.\n"
257 " :type name: str\n");
259{
260 Type type;
261 const char *name;
262 if (!pygpu_interface_info_get_args(self, args, "O&O:smooth", &type, &name)) {
263 return nullptr;
264 }
265
266 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
267 interface->smooth(type, name);
268 Py_RETURN_NONE;
269}
270
272 /* Wrap. */
273 pygpu_interface_info_flat_doc,
274 ".. method:: flat(type, name)\n"
275 "\n"
276 " Add an attribute with qualifier of type ``flat`` to the interface block.\n"
277 "\n"
278 " :arg type: One of these types:\n"
279 "\n" PYDOC_TYPE_LIST
280 "\n"
281 " :type type: str\n"
282 " :arg name: name of the attribute.\n"
283 " :type name: str\n");
285{
286 Type type;
287 const char *name;
288 if (!pygpu_interface_info_get_args(self, args, "O&O:flat", &type, &name)) {
289 return nullptr;
290 }
291
292 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
293 interface->flat(type, name);
294 Py_RETURN_NONE;
295}
296
298 /* Wrap. */
299 pygpu_interface_info_no_perspective_doc,
300 ".. method:: no_perspective(type, name)\n"
301 "\n"
302 " Add an attribute with qualifier of type ``no_perspective`` to the interface block.\n"
303 "\n"
304 " :arg type: One of these types:\n"
305 "\n" PYDOC_TYPE_LIST
306 "\n"
307 " :type type: str\n"
308 " :arg name: name of the attribute.\n"
309 " :type name: str\n");
311 PyObject *args)
312{
313 Type type;
314 const char *name;
315 if (!pygpu_interface_info_get_args(self, args, "O&O:no_perspective", &type, &name)) {
316 return nullptr;
317 }
318
319 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
320 interface->no_perspective(type, name);
321 Py_RETURN_NONE;
322}
323
324static PyMethodDef pygpu_interface_info__tp_methods[] = {
325 {"smooth",
326 (PyCFunction)pygpu_interface_info_smooth,
327 METH_VARARGS,
328 pygpu_interface_info_smooth_doc},
329 {"flat", (PyCFunction)pygpu_interface_info_flat, METH_VARARGS, pygpu_interface_info_flat_doc},
330 {"no_perspective",
332 METH_VARARGS,
333 pygpu_interface_info_no_perspective_doc},
334 {nullptr, nullptr, 0, nullptr},
335};
336
339/* -------------------------------------------------------------------- */
344 /* Wrap. */
345 pygpu_interface_info_name_doc,
346 "Name of the interface block.\n"
347 "\n"
348 ":type: str");
349static PyObject *pygpu_interface_info_name_get(BPyGPUStageInterfaceInfo *self, void * /*closure*/)
350{
351 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
352 return PyUnicode_FromString(interface->name.c_str());
353}
354
356 {"name",
358 (setter) nullptr,
359 pygpu_interface_info_name_doc,
360 nullptr},
361 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
362};
363
366/* -------------------------------------------------------------------- */
370static PyObject *pygpu_interface_info__tp_new(PyTypeObject * /*type*/,
371 PyObject *args,
372 PyObject *kwds)
373{
374 if (kwds) {
375 PyErr_SetString(PyExc_TypeError, "no keywords are expected");
376 return nullptr;
377 }
378
379 const char *name;
380 if (!PyArg_ParseTuple(args, "s:GPUStageInterfaceInfo.__new__*", &name)) {
381 return nullptr;
382 }
383
384 StageInterfaceInfo *interface = new StageInterfaceInfo(name, "");
385 GPUStageInterfaceInfo *interface_info = reinterpret_cast<GPUStageInterfaceInfo *>(interface);
386
387 PyObject *self = BPyGPUStageInterfaceInfo_CreatePyObject(interface_info);
388
389#ifdef USE_GPU_PY_REFERENCES
390 PyObject *py_name = PyTuple_GET_ITEM(args, 0);
391 PyList_Append(((BPyGPUStageInterfaceInfo *)self)->references, py_name);
392#endif
393
394 return self;
395}
396
397#ifdef USE_GPU_PY_REFERENCES
398
399static int pygpu_interface_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
400{
401 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
402 Py_VISIT(py_interface->references);
403 return 0;
404}
405
406static int pygpu_interface_info__tp_clear(PyObject *self)
407{
408 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
409 Py_CLEAR(py_interface->references);
410 return 0;
411}
412
413#endif
414
416{
417 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
418 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(py_interface->interface);
419 delete interface;
420
421#ifdef USE_GPU_PY_REFERENCES
422 PyObject_GC_UnTrack(self);
423 if (py_interface->references) {
424 pygpu_interface_info__tp_clear(self);
425 Py_CLEAR(py_interface->references);
426 }
427#endif
428
429 Py_TYPE(self)->tp_free((PyObject *)self);
430}
431
433 /* Wrap. */
434 pygpu_interface_info__tp_doc,
435 ".. class:: GPUStageInterfaceInfo(name)\n"
436 "\n"
437 " List of varyings between shader stages.\n"
438 "\n"
439 " :arg name: Name of the interface block.\n"
440 " :type value: str\n");
442 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
443 /*tp_name*/ "GPUStageInterfaceInfo",
444 /*tp_basicsize*/ sizeof(BPyGPUStageInterfaceInfo),
445 /*tp_itemsize*/ 0,
447 /*tp_vectorcall_offset*/ 0,
448 /*tp_getattr*/ nullptr,
449 /*tp_setattr*/ nullptr,
450 /*tp_compare*/ nullptr,
451 /*tp_repr*/ nullptr,
452 /*tp_as_number*/ nullptr,
453 /*tp_as_sequence*/ nullptr,
454 /*tp_as_mapping*/ nullptr,
455 /*tp_hash*/ nullptr,
456 /*tp_call*/ nullptr,
457 /*tp_str*/ nullptr,
458 /*tp_getattro*/ nullptr,
459 /*tp_setattro*/ nullptr,
460 /*tp_as_buffer*/ nullptr,
462 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
463#else
464 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
465#endif
466 /*tp_doc*/ pygpu_interface_info__tp_doc,
468 /*tp_traverse*/ pygpu_interface_info__tp_traverse,
469#else
470 /*tp_traverse*/ nullptr,
471#endif
473 /*tp_clear*/ pygpu_interface_info__tp_clear,
474#else
475 /*tp_clear*/ nullptr,
476#endif
477 /*tp_richcompare*/ nullptr,
478 /*tp_weaklistoffset*/ 0,
479 /*tp_iter*/ nullptr,
480 /*tp_iternext*/ nullptr,
482 /*tp_members*/ nullptr,
484 /*tp_base*/ nullptr,
485 /*tp_dict*/ nullptr,
486 /*tp_descr_get*/ nullptr,
487 /*tp_descr_set*/ nullptr,
488 /*tp_dictoffset*/ 0,
489 /*tp_init*/ nullptr,
490 /*tp_alloc*/ nullptr,
492 /*tp_free*/ nullptr,
493 /*tp_is_gc*/ nullptr,
494 /*tp_bases*/ nullptr,
495 /*tp_mro*/ nullptr,
496 /*tp_cache*/ nullptr,
497 /*tp_subclasses*/ nullptr,
498 /*tp_weaklist*/ nullptr,
499 /*tp_del*/ nullptr,
500 /*tp_version_tag*/ 0,
501 /*tp_finalize*/ nullptr,
502 /*tp_vectorcall*/ nullptr,
503};
504
507/* -------------------------------------------------------------------- */
512 /* Wrap. */
513 pygpu_shader_info_vertex_in_doc,
514 ".. method:: vertex_in(slot, type, name)\n"
515 "\n"
516 " Add a vertex shader input attribute.\n"
517 "\n"
518 " :arg slot: The attribute index.\n"
519 " :type slot: int\n"
520 " :arg type: One of these types:\n"
521 "\n" PYDOC_TYPE_LIST
522 "\n"
523 " :type type: str\n"
524 " :arg name: name of the attribute.\n"
525 " :type name: str\n");
527{
528 int slot;
530 const char *param;
531
532 if (!PyArg_ParseTuple(args, "iO&s:vertex_in", &slot, PyC_ParseStringEnum, &pygpu_type, &param)) {
533 return nullptr;
534 }
535
536#ifdef USE_GPU_PY_REFERENCES
537 PyObject *py_name = PyTuple_GET_ITEM(args, 2);
538 PyList_Append(self->references, py_name);
539#endif
540
541 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
542 info->vertex_in(slot, (Type)pygpu_type.value_found, param);
543 Py_RETURN_NONE;
544}
545
547 /* Wrap. */
548 pygpu_shader_info_vertex_out_doc,
549 ".. method:: vertex_out(interface)\n"
550 "\n"
551 " Add a vertex shader output interface block.\n"
552 "\n"
553 " :arg interface: Object describing the block.\n"
554 " :type interface: :class:`gpu.types.GPUStageInterfaceInfo`\n");
557{
559 PyErr_Format(PyExc_TypeError, "Expected a GPUStageInterfaceInfo, got %s", Py_TYPE(o)->tp_name);
560 return nullptr;
561 }
562
563#ifdef USE_GPU_PY_REFERENCES
564 PyList_Append(self->references, (PyObject *)o);
565#endif
566
567 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
568 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(o->interface);
569 info->vertex_out(*interface);
570
571 Py_RETURN_NONE;
572}
573
575 /* Wrap. */
576 pygpu_shader_info_fragment_out_doc,
577 ".. method:: fragment_out(slot, type, name, blend='NONE')\n"
578 "\n"
579 " Specify a fragment output corresponding to a framebuffer target slot.\n"
580 "\n"
581 " :arg slot: The attribute index.\n"
582 " :type slot: int\n"
583 " :arg type: One of these types:\n"
584 "\n" PYDOC_TYPE_LIST
585 "\n"
586 " :type type: str\n"
587 " :arg name: Name of the attribute.\n"
588 " :type name: str\n"
589 " :arg blend: Dual Source Blending Index. It can be 'NONE', 'SRC_0' or 'SRC_1'.\n"
590 " :type blend: str\n");
592 PyObject *args,
593 PyObject *kwds)
594{
595 int slot;
597 const char *name;
598 PyC_StringEnum blend_type = {pygpu_dualblend_items, int(DualBlend::NONE)};
599
600 static const char *_keywords[] = {"slot", "type", "name", "blend", nullptr};
601 static _PyArg_Parser _parser = {
603 "i" /* `slot` */
604 "O&" /* `type` */
605 "s" /* `name` */
606 "|$" /* Optional keyword only arguments. */
607 "O&" /* `blend` */
608 ":fragment_out",
609 _keywords,
610 nullptr,
611 };
612 if (!_PyArg_ParseTupleAndKeywordsFast(args,
613 kwds,
614 &_parser,
615 &slot,
617 &pygpu_type,
618 &name,
620 &blend_type))
621 {
622 return nullptr;
623 }
624
625#ifdef USE_GPU_PY_REFERENCES
626 PyObject *py_name = PyTuple_GET_ITEM(args, 2);
627 PyList_Append(self->references, py_name);
628#endif
629
630 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
631 info->fragment_out(slot, (Type)pygpu_type.value_found, name, (DualBlend)blend_type.value_found);
632
633 Py_RETURN_NONE;
634}
635
637 /* Wrap. */
638 pygpu_shader_info_uniform_buf_doc,
639 ".. method:: uniform_buf(slot, type_name, name)\n"
640 "\n"
641 " Specify a uniform variable whose type can be one of those declared in "
642 ":meth:`gpu.types.GPUShaderCreateInfo.typedef_source`.\n"
643 "\n"
644 " :arg slot: The uniform variable index.\n"
645 " :type slot: int\n"
646 " :arg type_name: Name of the data type. "
647 "It can be a struct type defined in the source passed through the "
648 ":meth:`gpu.types.GPUShaderCreateInfo.typedef_source`.\n"
649 " :type type_name: str\n"
650 " :arg name: The uniform variable name.\n"
651 " :type name: str\n");
653{
654 int slot;
655 const char *type_name;
656 const char *name;
657
658 if (!PyArg_ParseTuple(args, "iss:uniform_buf", &slot, &type_name, &name)) {
659 return nullptr;
660 }
661
662#ifdef USE_GPU_PY_REFERENCES
663 PyList_Append(self->references, PyTuple_GET_ITEM(args, 1)); /* type_name */
664 PyList_Append(self->references, PyTuple_GET_ITEM(args, 2)); /* name */
665#endif
666
667 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
668 info->uniform_buf(slot, type_name, name);
669
670 Py_RETURN_NONE;
671}
672
673#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
675 /* Wrap. */
676 pygpu_shader_info_image_doc,
677 ".. method:: image(slot, format, type, name, qualifiers={'NO_RESTRICT'})\n"
678 "\n"
679 " Specify an image resource used for arbitrary load and store operations.\n"
680 "\n"
681 " :arg slot: The image resource index.\n"
682 " :type slot: int\n"
683 " :arg format: The GPUTexture format that is passed to the shader. Possible values are:\n"
685 " :type format: str\n"
686 " :arg type: The data type describing how the image is to be read in the shader. "
687 "Possible values are:\n"
689 "\n"
690 " :type type: str\n"
691 " :arg name: The image resource name.\n"
692 " :type name: str\n"
693 " :arg qualifiers: Set containing values that describe how the image resource is to be "
694 "read or written. Possible values are:\n"
696 ""
697 " :type qualifiers: set[str]\n");
699 PyObject *args,
700 PyObject *kwds)
701{
702 int slot;
703 PyC_StringEnum pygpu_texformat = {pygpu_textureformat_items};
704 PyC_StringEnum pygpu_imagetype = {pygpu_imagetype_items};
705 const char *name;
706 PyObject *py_qualifiers = nullptr;
707 Qualifier qualifier = Qualifier::NO_RESTRICT;
708
709 static const char *_keywords[] = {"slot", "format", "type", "name", "qualifiers", nullptr};
710 static _PyArg_Parser _parser = {
712 "i" /* `slot` */
713 "O&" /* `format` */
714 "O&" /* `type` */
715 "s" /* `name` */
716 "|$" /* Optional keyword only arguments. */
717 "O" /* `qualifiers` */
718 ":image",
719 _keywords,
720 nullptr,
721 };
722 if (!_PyArg_ParseTupleAndKeywordsFast(args,
723 kwds,
724 &_parser,
725 &slot,
727 &pygpu_texformat,
729 &pygpu_imagetype,
730 &name,
731 &py_qualifiers))
732 {
733 return nullptr;
734 }
735
736 if (py_qualifiers &&
738 pygpu_qualifiers, py_qualifiers, (int *)&qualifier, "shader_info.image") == -1)
739 {
740 return nullptr;
741 }
742
743# ifdef USE_GPU_PY_REFERENCES
744 PyList_Append(self->references, PyTuple_GET_ITEM(args, 3)); /* name */
745# endif
746
747 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
748 info->image(slot,
749 (eGPUTextureFormat)pygpu_texformat.value_found,
750 qualifier,
751 (ImageType)pygpu_imagetype.value_found,
752 name);
753
754 Py_RETURN_NONE;
755}
756#endif
757
759 /* Wrap. */
760 pygpu_shader_info_sampler_doc,
761 ".. method:: sampler(slot, type, name)\n"
762 "\n"
763 " Specify an image texture sampler.\n"
764 "\n"
765 " :arg slot: The image texture sampler index.\n"
766 " :type slot: int\n"
767 " :arg type: The data type describing the format of each sampler unit. Possible values "
768 "are:\n"
770 "\n"
771 " :type type: str\n"
772 " :arg name: The image texture sampler name.\n"
773 " :type name: str\n");
774static PyObject *pygpu_shader_info_sampler(BPyGPUShaderCreateInfo *self, PyObject *args)
775{
776 int slot;
777 PyC_StringEnum pygpu_samplertype = {pygpu_imagetype_items};
778 const char *name;
779
780 if (!PyArg_ParseTuple(
781 args, "iO&s:sampler", &slot, PyC_ParseStringEnum, &pygpu_samplertype, &name))
782 {
783 return nullptr;
784 }
785
786#ifdef USE_GPU_PY_REFERENCES
787 PyList_Append(self->references, PyTuple_GET_ITEM(args, 2)); /* name */
788#endif
789
790 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
791 info->sampler(slot, (ImageType)pygpu_samplertype.value_found, name);
792
793 Py_RETURN_NONE;
794}
795
796static int constant_type_size(Type type)
797{
798 switch (type) {
799 case Type::BOOL:
800 case Type::FLOAT:
801 case Type::INT:
802 case Type::UINT:
803 case Type::UCHAR4:
804 case Type::CHAR4:
805 case Type::VEC3_101010I2:
806 case Type::USHORT2:
807 case Type::SHORT2:
808 return 4;
809 break;
810 case Type::USHORT3:
811 case Type::SHORT3:
812 return 6;
813 break;
814 case Type::VEC2:
815 case Type::UVEC2:
816 case Type::IVEC2:
817 case Type::USHORT4:
818 case Type::SHORT4:
819 return 8;
820 break;
821 case Type::VEC3:
822 case Type::UVEC3:
823 case Type::IVEC3:
824 return 12;
825 break;
826 case Type::VEC4:
827 case Type::UVEC4:
828 case Type::IVEC4:
829 return 16;
830 break;
831 case Type::MAT3:
832 return 36 + 3 * 4;
833 case Type::MAT4:
834 return 64;
835 break;
836 case Type::UCHAR:
837 case Type::CHAR:
838 return 1;
839 break;
840 case Type::UCHAR2:
841 case Type::CHAR2:
842 case Type::USHORT:
843 case Type::SHORT:
844 return 2;
845 break;
846 case Type::UCHAR3:
847 case Type::CHAR3:
848 return 3;
849 break;
850 }
851 BLI_assert(false);
852 return -1;
853}
854
856{
857 int size_prev = 0;
858 int size_last = 0;
859 for (const ShaderCreateInfo::PushConst &uniform : info->push_constants_) {
860 int pad = 0;
861 int size = constant_type_size(uniform.type);
862 if (size_last && size_last != size) {
863 /* Calc pad. */
864 int pack = (size == 8) ? 8 : 16;
865 if (size_last < size) {
866 pad = pack - (size_last % pack);
867 }
868 else {
869 pad = size_prev % pack;
870 }
871 }
872 else if (size == 12) {
873 /* It is still unclear how Vulkan handles padding for `vec3` constants. For now let's follow
874 * the rules of the `std140` layout. */
875 pad = 4;
876 }
877 size_prev += pad + size * std::max(1, uniform.array_size);
878 size_last = size;
879 }
880 return size_prev + (size_prev % 16);
881}
882
884 /* Wrap. */
885 pygpu_shader_info_push_constant_doc,
886 ".. method:: push_constant(type, name, size=0)\n"
887 "\n"
888 " Specify a global access constant.\n"
889 "\n"
890 " :arg type: One of these types:\n"
891 "\n" PYDOC_TYPE_LIST
892 "\n"
893 " :type type: str\n"
894 " :arg name: Name of the constant.\n"
895 " :type name: str\n"
896 " :arg size: If not zero, indicates that the constant is an array with the specified size.\n"
897 " :type size: int\n");
899 PyObject *args,
900 PyObject *kwds)
901{
903 const char *name = nullptr;
904 int array_size = 0;
905
906 static const char *_keywords[] = {"type", "name", "size", nullptr};
907 static _PyArg_Parser _parser = {
909 "O&" /* `type` */
910 "s" /* `name` */
911 "|" /* Optional arguments. */
912 "I" /* `size` */
913 ":push_constant",
914 _keywords,
915 nullptr,
916 };
917 if (!_PyArg_ParseTupleAndKeywordsFast(
918 args, kwds, &_parser, PyC_ParseStringEnum, &pygpu_type, &name, &array_size))
919 {
920 return nullptr;
921 }
922
923#ifdef USE_GPU_PY_REFERENCES
924 PyObject *py_name = PyTuple_GET_ITEM(args, 1);
925 PyList_Append(self->references, py_name);
926#endif
927
928 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
929 info->push_constant((Type)pygpu_type.value_found, name, array_size);
930
931#define VULKAN_LIMIT 128
932 int size = constants_calc_size(info);
933 if (size > VULKAN_LIMIT) {
934 printf("Push constants have a minimum supported size of " STRINGIFY(VULKAN_LIMIT) " bytes, however the constants added so far already reach %d bytes. Consider using UBO.\n", size);
935 }
936#undef VULKAN_LIMIT
937
938 Py_RETURN_NONE;
939}
940
942 /* Wrap. */
943 pygpu_shader_info_vertex_source_doc,
944 ".. method:: vertex_source(source)\n"
945 "\n"
946 " Vertex shader source code written in GLSL.\n"
947 "\n"
948 " Example:\n"
949 "\n"
950 " .. code-block:: python\n"
951 "\n"
952 " \"void main {gl_Position = vec4(pos, 1.0);}\"\n"
953 "\n"
954 " :arg source: The vertex shader source code.\n"
955 " :type source: str\n"
956 "\n"
957 " .. seealso:: `GLSL Cross Compilation "
958 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
960{
961 const char *vertex_source = PyUnicode_AsUTF8(o);
962 if (vertex_source == nullptr) {
963 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
964 return nullptr;
965 }
966
967#ifdef USE_GPU_PY_REFERENCES
968 if (self->vertex_source) {
969 Py_DECREF(self->vertex_source);
970 }
971
972 self->vertex_source = o;
973 Py_INCREF(o);
974#endif
975
976 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
977 info->vertex_source("common_colormanagement_lib.glsl");
979
980 Py_RETURN_NONE;
981}
982
984 /* Wrap. */
985 pygpu_shader_info_compute_source_doc,
986 ".. method:: compute_source(source)\n"
987 "\n"
988 " compute shader source code written in GLSL.\n"
989 "\n"
990 " Example:\n"
991 "\n"
992 " .. code-block:: python\n"
993 "\n"
994 " \"\"\"void main() {\n"
995 " int2 index = int2(gl_GlobalInvocationID.xy);\n"
996 " vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n"
997 " imageStore(img_output, index, color);\n"
998 " }\"\"\"\n"
999 "\n"
1000 " :arg source: The compute shader source code.\n"
1001 " :type source: str\n"
1002 "\n"
1003 " .. seealso:: `GLSL Cross Compilation "
1004 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1006{
1007 const char *compute_source = PyUnicode_AsUTF8(o);
1008 if (compute_source == nullptr) {
1009 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1010 return nullptr;
1011 }
1012
1013#ifdef USE_GPU_PY_REFERENCES
1014 if (self->compute_source) {
1015 Py_DECREF(self->compute_source);
1016 }
1017
1018 self->compute_source = o;
1019 Py_INCREF(o);
1020#endif
1021
1022 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1023 info->compute_source("common_colormanagement_lib.glsl");
1025
1026 Py_RETURN_NONE;
1027}
1028
1030 /* Wrap. */
1031 pygpu_shader_info_fragment_source_doc,
1032 ".. method:: fragment_source(source)\n"
1033 "\n"
1034 " Fragment shader source code written in GLSL.\n"
1035 "\n"
1036 " Example:\n"
1037 "\n"
1038 " .. code-block:: python\n"
1039 "\n"
1040 " \"void main {fragColor = vec4(0.0, 0.0, 0.0, 1.0);}\"\n"
1041 "\n"
1042 " :arg source: The fragment shader source code.\n"
1043 " :type source: str\n"
1044 "\n"
1045 " .. seealso:: `GLSL Cross Compilation "
1046 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1048{
1049 const char *fragment_source = PyUnicode_AsUTF8(o);
1050 if (fragment_source == nullptr) {
1051 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1052 return nullptr;
1053 }
1054
1055#ifdef USE_GPU_PY_REFERENCES
1056 if (self->fragment_source) {
1057 Py_DECREF(self->fragment_source);
1058 }
1059
1060 self->fragment_source = o;
1061 Py_INCREF(o);
1062#endif
1063
1064 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1065 info->fragment_source("common_colormanagement_lib.glsl");
1067
1068 Py_RETURN_NONE;
1069}
1070
1072 /* Wrap. */
1073 pygpu_shader_info_typedef_source_doc,
1074 ".. method:: typedef_source(source)\n"
1075 "\n"
1076 " Source code included before resource declaration. "
1077 "Useful for defining structs used by Uniform Buffers.\n"
1078 "\n"
1079 " Example:\n"
1080 "\n"
1081 ".. code-block:: python\n"
1082 "\n"
1083 " \"struct MyType {int foo; float bar;};\"\n"
1084 "\n"
1085 " :arg source: The source code defining types.\n"
1086 " :type source: str\n");
1088{
1089 const char *typedef_source = PyUnicode_AsUTF8(o);
1090 if (typedef_source == nullptr) {
1091 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1092 return nullptr;
1093 }
1094
1095#ifdef USE_GPU_PY_REFERENCES
1096 if (self->typedef_source) {
1097 Py_DECREF(self->typedef_source);
1098 }
1099
1100 self->typedef_source = o;
1101 Py_INCREF(o);
1102#endif
1103
1104 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1105#if 0
1106 if (info->typedef_sources_.is_empty()) {
1107 info->typedef_source("GPU_shader_shared_utils.hh");
1108 }
1109#endif
1111
1112 Py_RETURN_NONE;
1113}
1114
1116 /* Wrap. */
1117 pygpu_shader_info_define_doc,
1118 ".. method:: define(name, value)\n"
1119 "\n"
1120 " Add a preprocessing define directive. In GLSL it would be something like:\n"
1121 "\n"
1122 ".. code-block:: glsl\n"
1123 "\n"
1124 " #define name value\n"
1125 "\n"
1126 " :arg name: Token name.\n"
1127 " :type name: str\n"
1128 " :arg value: Text that replaces token occurrences.\n"
1129 " :type value: str\n");
1130static PyObject *pygpu_shader_info_define(BPyGPUShaderCreateInfo *self, PyObject *args)
1131{
1132 const char *name;
1133 const char *value = nullptr;
1134
1135 if (!PyArg_ParseTuple(args, "s|s:define", &name, &value)) {
1136 return nullptr;
1137 }
1138
1139#ifdef USE_GPU_PY_REFERENCES
1140 PyList_Append(self->references, PyTuple_GET_ITEM(args, 0)); /* name */
1141 if (value) {
1142 PyList_Append(self->references, PyTuple_GET_ITEM(args, 1)); /* value */
1143 }
1144#endif
1145
1146 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1147 if (value) {
1148 info->define(name, value);
1149 }
1150 else {
1151 info->define(name);
1152 }
1153
1154 Py_RETURN_NONE;
1155}
1156
1158 /* Wrap. */
1159 pygpu_shader_info_local_group_size_doc,
1160 ".. method:: local_group_size(x, y=-1, z=-1)\n"
1161 "\n"
1162 " Specify the local group size for compute shaders.\n"
1163 "\n"
1164 " :arg x: The local group size in the x dimension.\n"
1165 " :type x: int\n"
1166 " :arg y: The local group size in the y dimension. Optional. Defaults to -1.\n"
1167 " :type y: int\n"
1168 " :arg z: The local group size in the z dimension. Optional. Defaults to -1.\n"
1169 " :type z: int\n");
1171{
1172 int x = -1, y = -1, z = -1;
1173
1174 if (!PyArg_ParseTuple(args, "i|ii:local_group_size", &x, &y, &z)) {
1175 return nullptr;
1176 }
1177
1178 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1179 info->local_group_size(x, y, z);
1180
1181 Py_RETURN_NONE;
1182}
1183
1184static PyMethodDef pygpu_shader_info__tp_methods[] = {
1185 {"vertex_in",
1186 (PyCFunction)pygpu_shader_info_vertex_in,
1187 METH_VARARGS,
1188 pygpu_shader_info_vertex_in_doc},
1189 {"vertex_out",
1190 (PyCFunction)pygpu_shader_info_vertex_out,
1191 METH_O,
1192 pygpu_shader_info_vertex_out_doc},
1193 {"fragment_out",
1194 (PyCFunction)(void *)pygpu_shader_info_fragment_out,
1195 METH_VARARGS | METH_KEYWORDS,
1196 pygpu_shader_info_fragment_out_doc},
1197 {"uniform_buf",
1198 (PyCFunction)(void *)pygpu_shader_info_uniform_buf,
1199 METH_VARARGS,
1200 pygpu_shader_info_uniform_buf_doc},
1201#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
1202 {"image",
1203 (PyCFunction)(void *)pygpu_shader_info_image,
1204 METH_VARARGS | METH_KEYWORDS,
1205 pygpu_shader_info_image_doc},
1206#endif
1207 {"sampler",
1208 (PyCFunction)pygpu_shader_info_sampler,
1209 METH_VARARGS,
1210 pygpu_shader_info_sampler_doc},
1211 {"push_constant",
1212 (PyCFunction)(void *)pygpu_shader_info_push_constant,
1213 METH_VARARGS | METH_KEYWORDS,
1214 pygpu_shader_info_push_constant_doc},
1215 {"vertex_source",
1217 METH_O,
1218 pygpu_shader_info_vertex_source_doc},
1219 {"fragment_source",
1221 METH_O,
1222 pygpu_shader_info_fragment_source_doc},
1223 {"compute_source",
1225 METH_O,
1226 pygpu_shader_info_compute_source_doc},
1227 {"typedef_source",
1229 METH_O,
1230 pygpu_shader_info_typedef_source_doc},
1231 {"define", (PyCFunction)pygpu_shader_info_define, METH_VARARGS, pygpu_shader_info_define_doc},
1232 {"local_group_size",
1234 METH_VARARGS,
1235 pygpu_shader_info_local_group_size_doc},
1236 {nullptr, nullptr, 0, nullptr},
1237};
1238
1241/* -------------------------------------------------------------------- */
1245static PyObject *pygpu_shader_info__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds)
1246{
1247 if (PyTuple_Size(args) || kwds) {
1248 PyErr_SetString(PyExc_TypeError, "no args or keywords are expected");
1249 return nullptr;
1250 }
1251
1252 ShaderCreateInfo *info = new ShaderCreateInfo("pyGPU_Shader");
1253 GPUShaderCreateInfo *shader_info = reinterpret_cast<GPUShaderCreateInfo *>(info);
1254
1255 return BPyGPUShaderCreateInfo_CreatePyObject(shader_info);
1256}
1257
1258#ifdef USE_GPU_PY_REFERENCES
1259
1260static int pygpu_shader_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
1261{
1262 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1263 Py_VISIT(py_info->vertex_source);
1264 Py_VISIT(py_info->fragment_source);
1265 Py_VISIT(py_info->compute_source);
1266 Py_VISIT(py_info->references);
1267 return 0;
1268}
1269
1270static int pygpu_shader_info__tp_clear(PyObject *self)
1271{
1272 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1273 Py_CLEAR(py_info->vertex_source);
1274 Py_CLEAR(py_info->fragment_source);
1275 Py_CLEAR(py_info->compute_source);
1276 Py_CLEAR(py_info->references);
1277 return 0;
1278}
1279
1280#endif
1281
1283{
1284 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1285 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(py_info->info);
1286 delete info;
1287
1288#ifdef USE_GPU_PY_REFERENCES
1289 PyObject_GC_UnTrack(self);
1290 if (py_info->references || py_info->vertex_source || py_info->fragment_source) {
1291 pygpu_shader_info__tp_clear(self);
1292 Py_XDECREF(py_info->vertex_source);
1293 Py_XDECREF(py_info->fragment_source);
1294 Py_XDECREF(py_info->compute_source);
1295 Py_XDECREF(py_info->references);
1296 }
1297
1298#endif
1299
1300 Py_TYPE(self)->tp_free((PyObject *)self);
1301}
1302
1304 /* Wrap. */
1305 pygpu_shader_info__tp_doc,
1306 ".. class:: GPUShaderCreateInfo()\n"
1307 "\n"
1308 " Stores and describes types and variables that are used in shader sources.\n");
1309
1311 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1312 /*tp_name*/ "GPUShaderCreateInfo",
1313 /*tp_basicsize*/ sizeof(BPyGPUShaderCreateInfo),
1314 /*tp_itemsize*/ 0,
1315 /*tp_dealloc*/ pygpu_shader_info__tp_dealloc,
1316 /*tp_vectorcall_offset*/ 0,
1317 /*tp_getattr*/ nullptr,
1318 /*tp_setattr*/ nullptr,
1319 /*tp_compare*/ nullptr,
1320 /*tp_repr*/ nullptr,
1321 /*tp_as_number*/ nullptr,
1322 /*tp_as_sequence*/ nullptr,
1323 /*tp_as_mapping*/ nullptr,
1324 /*tp_hash*/ nullptr,
1325 /*tp_call*/ nullptr,
1326 /*tp_str*/ nullptr,
1327 /*tp_getattro*/ nullptr,
1328 /*tp_setattro*/ nullptr,
1329 /*tp_as_buffer*/ nullptr,
1331 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1332#else
1333 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
1334#endif
1335 /*tp_doc*/ pygpu_shader_info__tp_doc,
1337 /*tp_traverse*/ pygpu_shader_info__tp_traverse,
1338#else
1339 /*tp_traverse*/ nullptr,
1340#endif
1342 /*tp_clear*/ pygpu_shader_info__tp_clear,
1343#else
1344 /*tp_clear*/ nullptr,
1345#endif
1346 /*tp_richcompare*/ nullptr,
1347 /*tp_weaklistoffset*/ 0,
1348 /*tp_iter*/ nullptr,
1349 /*tp_iternext*/ nullptr,
1350 /*tp_methods*/ pygpu_shader_info__tp_methods,
1351 /*tp_members*/ nullptr,
1352 /*tp_getset*/ nullptr,
1353 /*tp_base*/ nullptr,
1354 /*tp_dict*/ nullptr,
1355 /*tp_descr_get*/ nullptr,
1356 /*tp_descr_set*/ nullptr,
1357 /*tp_dictoffset*/ 0,
1358 /*tp_init*/ nullptr,
1359 /*tp_alloc*/ nullptr,
1360 /*tp_new*/ pygpu_shader_info__tp_new,
1361 /*tp_free*/ nullptr,
1362 /*tp_is_gc*/ nullptr,
1363 /*tp_bases*/ nullptr,
1364 /*tp_mro*/ nullptr,
1365 /*tp_cache*/ nullptr,
1366 /*tp_subclasses*/ nullptr,
1367 /*tp_weaklist*/ nullptr,
1368 /*tp_del*/ nullptr,
1369 /*tp_version_tag*/ 0,
1370 /*tp_finalize*/ nullptr,
1371 /*tp_vectorcall*/ nullptr,
1372};
1373
1376/* -------------------------------------------------------------------- */
1380PyObject *BPyGPUStageInterfaceInfo_CreatePyObject(GPUStageInterfaceInfo *interface)
1381{
1383
1384#ifdef USE_GPU_PY_REFERENCES
1386 self->references = PyList_New(0);
1387#else
1389#endif
1390
1391 self->interface = interface;
1392
1393 return (PyObject *)self;
1394}
1395
1396PyObject *BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info)
1397{
1399
1400#ifdef USE_GPU_PY_REFERENCES
1402 self->vertex_source = nullptr;
1403 self->fragment_source = nullptr;
1404 self->compute_source = nullptr;
1405 self->typedef_source = nullptr;
1406 self->references = PyList_New(0);
1407#else
1409#endif
1410
1411 self->info = info;
1412 self->constants_total_size = 0;
1413
1414 return (PyObject *)self;
1415}
1416
#define BLI_assert(a)
Definition BLI_assert.h:50
#define STRINGIFY(x)
eGPUTextureFormat
int pad[32 - sizeof(int)]
vertex_source("basic_depth_pointcloud_vert.glsl") .additional_info("draw_pointcloud")
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
input_tx typedef_source("gpu_shader_compositor_type_conversion.glsl") .compute_source("compositor_convert.glsl")
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx output_img compute_source("compositor_cryptomatte_image.glsl") .do_static_compilation(true)
#define printf
fragment_source("eevee_deferred_tile_classify_frag.glsl") .additional_info("eevee_shared"
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define USE_GPU_PY_REFERENCES
#define BPyGPUStageInterfaceInfo_Check(v)
PyObject * BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info)
static PyObject * pygpu_shader_info__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
static PyObject * pygpu_shader_info_vertex_out(BPyGPUShaderCreateInfo *self, BPyGPUStageInterfaceInfo *o)
static PyObject * pygpu_shader_info_uniform_buf(BPyGPUShaderCreateInfo *self, PyObject *args)
static PyObject * pygpu_interface_info__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
#define PYDOC_QUALIFIERS
static PyObject * pygpu_shader_info_compute_source(BPyGPUShaderCreateInfo *self, PyObject *o)
#define PYDOC_TYPE_LIST
static int constant_type_size(Type type)
static PyObject * pygpu_interface_info_smooth(BPyGPUStageInterfaceInfo *self, PyObject *args)
static PyObject * pygpu_shader_info_local_group_size(BPyGPUShaderCreateInfo *self, PyObject *args)
static PyObject * pygpu_interface_info_no_perspective(BPyGPUStageInterfaceInfo *self, PyObject *args)
static PyObject * pygpu_shader_info_vertex_source(BPyGPUShaderCreateInfo *self, PyObject *o)
static PyObject * pygpu_shader_info_fragment_source(BPyGPUShaderCreateInfo *self, PyObject *o)
PyTypeObject BPyGPUStageInterfaceInfo_Type
static PyObject * pygpu_shader_info_push_constant(BPyGPUShaderCreateInfo *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_interface_info_flat(BPyGPUStageInterfaceInfo *self, PyObject *args)
static const PyC_StringEnumItems pygpu_imagetype_items[]
#define VULKAN_LIMIT
static PyObject * pygpu_shader_info_sampler(BPyGPUShaderCreateInfo *self, PyObject *args)
static int constants_calc_size(ShaderCreateInfo *info)
PyObject * BPyGPUStageInterfaceInfo_CreatePyObject(GPUStageInterfaceInfo *interface)
static void pygpu_shader_info__tp_dealloc(PyObject *self)
static PyGetSetDef pygpu_interface_info__tp_getseters[]
static PyObject * pygpu_shader_info_define(BPyGPUShaderCreateInfo *self, PyObject *args)
static PyObject * pygpu_shader_info_fragment_out(BPyGPUShaderCreateInfo *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_shader_info_image(BPyGPUShaderCreateInfo *self, PyObject *args, PyObject *kwds)
static const PyC_StringEnumItems pygpu_dualblend_items[]
const PyC_StringEnumItems pygpu_tex_format_items[]
static PyObject * pygpu_interface_info_name_get(BPyGPUStageInterfaceInfo *self, void *)
#define PYDOC_IMAGE_TYPES
PyTypeObject BPyGPUShaderCreateInfo_Type
static void pygpu_interface_info__tp_dealloc(PyObject *self)
static PyObject * pygpu_shader_info_typedef_source(BPyGPUShaderCreateInfo *self, PyObject *o)
static PyObject * pygpu_shader_info_vertex_in(BPyGPUShaderCreateInfo *self, PyObject *args)
PyDoc_STRVAR(pygpu_interface_info_smooth_doc, ".. method:: smooth(type, name)\n" "\n" " Add an attribute with qualifier of type *smooth* to the interface block.\n" "\n" " :arg type: One of these types:\n" "\n" PYDOC_TYPE_LIST "\n" " :type type: str\n" " :arg name: name of the attribute.\n" " :type name: str\n")
#define PYDOC_TEX_FORMAT_ITEMS
static PyMethodDef pygpu_shader_info__tp_methods[]
static const PyC_FlagSet pygpu_qualifiers[]
static PyMethodDef pygpu_interface_info__tp_methods[]
const PyC_StringEnumItems pygpu_attrtype_items[]
static bool pygpu_interface_info_get_args(BPyGPUStageInterfaceInfo *self, PyObject *args, const char *format, Type *r_type, const char **r_name)
const PyC_StringEnumItems pygpu_textureformat_items[]
format
int PyC_ParseStringEnum(PyObject *o, void *p)
int PyC_FlagSet_ToBitfield(const PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
PyObject_VAR_HEAD GPUShaderCreateInfo * info
PyObject_VAR_HEAD GPUStageInterfaceInfo * interface
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Self & image(int slot, eGPUTextureFormat format, Qualifier qualifiers, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS)
Self & compute_source(StringRefNull filename)
Self & fragment_source(StringRefNull filename)
Self & vertex_in(int slot, Type type, StringRefNull name)
Self & push_constant(Type type, StringRefNull name, int array_size=0)
Self & typedef_source(StringRefNull filename)
Self & fragment_out(int slot, Type type, StringRefNull name, DualBlend blend=DualBlend::NONE, int raster_order_group=-1)
Self & local_group_size(int local_size_x=-1, int local_size_y=-1, int local_size_z=-1)
Self & vertex_out(StageInterfaceInfo &interface)
Self & vertex_source(StringRefNull filename)
Self & sampler(int slot, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS, GPUSamplerState sampler=GPUSamplerState::internal_sampler())
Self & uniform_buf(int slot, StringRefNull type_name, StringRefNull name, Frequency freq=Frequency::PASS)
Self & define(StringRefNull name, StringRefNull value="")
Self & smooth(Type type, StringRefNull _name)
Self & no_perspective(Type type, StringRefNull _name)
Self & flat(Type type, StringRefNull _name)