Blender V5.0
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
11
12#include <Python.h>
13
14#include "BLI_utildefines.h"
15
16#include "GPU_shader.hh"
18
20#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
21
22#include "gpu_py_shader.hh" /* own include */
23#include "gpu_py_texture.hh"
24
25#define USE_PYGPU_SHADER_INFO_IMAGE_METHOD
26
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_t), "FLOAT"},
68 {int(Type::float2_t), "VEC2"},
69 {int(Type::float3_t), "VEC3"},
70 {int(Type::float4_t), "VEC4"},
71 {int(Type::float3x3_t), "MAT3"},
72 {int(Type::float4x4_t), "MAT4"},
73 {int(Type::uint_t), "UINT"},
74 {int(Type::uint2_t), "UVEC2"},
75 {int(Type::uint3_t), "UVEC3"},
76 {int(Type::uint4_t), "UVEC4"},
77 {int(Type::int_t), "INT"},
78 {int(Type::int2_t), "IVEC2"},
79 {int(Type::int3_t), "IVEC3"},
80 {int(Type::int4_t), "IVEC4"},
81 {int(Type::bool_t), "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::FloatBuffer), "FLOAT_BUFFER"},
120 {int(ImageType::Float1D), "FLOAT_1D"},
121 {int(ImageType::Float1DArray), "FLOAT_1D_ARRAY"},
122 {int(ImageType::Float2D), "FLOAT_2D"},
123 {int(ImageType::Float2DArray), "FLOAT_2D_ARRAY"},
124 {int(ImageType::Float3D), "FLOAT_3D"},
125 {int(ImageType::FloatCube), "FLOAT_CUBE"},
126 {int(ImageType::FloatCubeArray), "FLOAT_CUBE_ARRAY"},
127 {int(ImageType::IntBuffer), "INT_BUFFER"},
128 {int(ImageType::Int1D), "INT_1D"},
129 {int(ImageType::Int1DArray), "INT_1D_ARRAY"},
130 {int(ImageType::Int2D), "INT_2D"},
131 {int(ImageType::Int2DArray), "INT_2D_ARRAY"},
132 {int(ImageType::Int3D), "INT_3D"},
133 {int(ImageType::IntCube), "INT_CUBE"},
134 {int(ImageType::IntCubeArray), "INT_CUBE_ARRAY"},
135 {int(ImageType::AtomicInt2D), "INT_2D_ATOMIC"},
136 {int(ImageType::AtomicInt2DArray), "INT_2D_ARRAY_ATOMIC"},
137 {int(ImageType::AtomicInt3D), "INT_3D_ATOMIC"},
138 {int(ImageType::UintBuffer), "UINT_BUFFER"},
139 {int(ImageType::Uint1D), "UINT_1D"},
140 {int(ImageType::Uint1DArray), "UINT_1D_ARRAY"},
141 {int(ImageType::Uint2D), "UINT_2D"},
142 {int(ImageType::Uint2DArray), "UINT_2D_ARRAY"},
143 {int(ImageType::Uint3D), "UINT_3D"},
144 {int(ImageType::UintCube), "UINT_CUBE"},
145 {int(ImageType::UintCubeArray), "UINT_CUBE_ARRAY"},
146 {int(ImageType::AtomicUint2D), "UINT_2D_ATOMIC"},
147 {int(ImageType::AtomicUint2DArray), "UINT_2D_ARRAY_ATOMIC"},
148 {int(ImageType::AtomicUint3D), "UINT_3D_ATOMIC"},
149 {int(ImageType::Shadow2D), "SHADOW_2D"},
150 {int(ImageType::Shadow2DArray), "SHADOW_2D_ARRAY"},
151 {int(ImageType::ShadowCube), "SHADOW_CUBE"},
152 {int(ImageType::ShadowCubeArray), "SHADOW_CUBE_ARRAY"},
153 {int(ImageType::Depth2D), "DEPTH_2D"},
154 {int(ImageType::Depth2DArray), "DEPTH_2D_ARRAY"},
155 {int(ImageType::DepthCube), "DEPTH_CUBE"},
156 {int(ImageType::DepthCubeArray), "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
168 {int(DepthWrite::UNCHANGED), "UNCHANGED"},
169 {int(DepthWrite::ANY), "ANY"},
170 {int(DepthWrite::GREATER), "GREATER"},
171 {int(DepthWrite::LESS), "LESS"},
172 {0, nullptr},
173};
174
175#define PYDOC_TEX_FORMAT_ITEMS \
176 " - ``RGBA8UI``\n" \
177 " - ``RGBA8I``\n" \
178 " - ``RGBA8``\n" \
179 " - ``RGBA32UI``\n" \
180 " - ``RGBA32I``\n" \
181 " - ``RGBA32F``\n" \
182 " - ``RGBA16UI``\n" \
183 " - ``RGBA16I``\n" \
184 " - ``RGBA16F``\n" \
185 " - ``RGBA16``\n" \
186 " - ``RG8UI``\n" \
187 " - ``RG8I``\n" \
188 " - ``RG8``\n" \
189 " - ``RG32UI``\n" \
190 " - ``RG32I``\n" \
191 " - ``RG32F``\n" \
192 " - ``RG16UI``\n" \
193 " - ``RG16I``\n" \
194 " - ``RG16F``\n" \
195 " - ``RG16``\n" \
196 " - ``R8UI``\n" \
197 " - ``R8I``\n" \
198 " - ``R8``\n" \
199 " - ``R32UI``\n" \
200 " - ``R32I``\n" \
201 " - ``R32F``\n" \
202 " - ``R16UI``\n" \
203 " - ``R16I``\n" \
204 " - ``R16F``\n" \
205 " - ``R16``\n" \
206 " - ``R11F_G11F_B10F``\n" \
207 " - ``DEPTH32F_STENCIL8``\n" \
208 " - ``DEPTH24_STENCIL8`` (deprecated, use ``DEPTH32F_STENCIL8``)\n" \
209 " - ``SRGB8_A8``\n" \
210 " - ``RGB16F``\n" \
211 " - ``SRGB8_A8_DXT1``\n" \
212 " - ``SRGB8_A8_DXT3``\n" \
213 " - ``SRGB8_A8_DXT5``\n" \
214 " - ``RGBA8_DXT1``\n" \
215 " - ``RGBA8_DXT3``\n" \
216 " - ``RGBA8_DXT5``\n" \
217 " - ``DEPTH_COMPONENT32F``\n" \
218 " - ``DEPTH_COMPONENT24`` (deprecated, use ``DEPTH_COMPONENT32F``)\n" \
219 " - ``DEPTH_COMPONENT16``\n"
221
222/* -------------------------------------------------------------------- */
225
227 PyObject *args,
228 const char *format,
229 Type *r_type,
230 const char **r_name)
231{
233 PyObject *py_name;
234
235 if (!PyArg_ParseTuple(args, format, PyC_ParseStringEnum, &pygpu_type, &py_name)) {
236 return false;
237 }
238
239 const char *name = PyUnicode_AsUTF8(py_name);
240 if (name == nullptr) {
241 return false;
242 }
243
244#ifdef USE_GPU_PY_REFERENCES
245 PyList_Append(self->references, py_name);
246#endif
247
248 *r_type = (Type)pygpu_type.value_found;
249 *r_name = name;
250 return true;
251}
252
254 /* Wrap. */
255 pygpu_interface_info_smooth_doc,
256 ".. method:: smooth(type, name)\n"
257 "\n"
258 " Add an attribute with qualifier of type *smooth* to the interface block.\n"
259 "\n"
260 " :arg type: One of these types:\n"
261 "\n" PYDOC_TYPE_LIST
262 "\n"
263 " :type type: str\n"
264 " :arg name: name of the attribute.\n"
265 " :type name: str\n");
267{
268 Type type;
269 const char *name;
270 if (!pygpu_interface_info_get_args(self, args, "O&O:smooth", &type, &name)) {
271 return nullptr;
272 }
273
274 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
275 interface->smooth(type, name);
276 Py_RETURN_NONE;
277}
278
280 /* Wrap. */
281 pygpu_interface_info_flat_doc,
282 ".. method:: flat(type, name)\n"
283 "\n"
284 " Add an attribute with qualifier of type ``flat`` to the interface block.\n"
285 "\n"
286 " :arg type: One of these types:\n"
287 "\n" PYDOC_TYPE_LIST
288 "\n"
289 " :type type: str\n"
290 " :arg name: name of the attribute.\n"
291 " :type name: str\n");
293{
294 Type type;
295 const char *name;
296 if (!pygpu_interface_info_get_args(self, args, "O&O:flat", &type, &name)) {
297 return nullptr;
298 }
299
300 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
301 interface->flat(type, name);
302 Py_RETURN_NONE;
303}
304
306 /* Wrap. */
307 pygpu_interface_info_no_perspective_doc,
308 ".. method:: no_perspective(type, name)\n"
309 "\n"
310 " Add an attribute with qualifier of type ``no_perspective`` to the interface block.\n"
311 "\n"
312 " :arg type: One of these types:\n"
313 "\n" PYDOC_TYPE_LIST
314 "\n"
315 " :type type: str\n"
316 " :arg name: name of the attribute.\n"
317 " :type name: str\n");
319 PyObject *args)
320{
321 Type type;
322 const char *name;
323 if (!pygpu_interface_info_get_args(self, args, "O&O:no_perspective", &type, &name)) {
324 return nullptr;
325 }
326
327 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
328 interface->no_perspective(type, name);
329 Py_RETURN_NONE;
330}
331
332static PyMethodDef pygpu_interface_info__tp_methods[] = {
333 {"smooth",
334 (PyCFunction)pygpu_interface_info_smooth,
335 METH_VARARGS,
336 pygpu_interface_info_smooth_doc},
337 {"flat", (PyCFunction)pygpu_interface_info_flat, METH_VARARGS, pygpu_interface_info_flat_doc},
338 {"no_perspective",
340 METH_VARARGS,
341 pygpu_interface_info_no_perspective_doc},
342 {nullptr, nullptr, 0, nullptr},
343};
344
346
347/* -------------------------------------------------------------------- */
350
352 /* Wrap. */
353 pygpu_interface_info_name_doc,
354 "Name of the interface block.\n"
355 "\n"
356 ":type: str\n");
357static PyObject *pygpu_interface_info_name_get(BPyGPUStageInterfaceInfo *self, void * /*closure*/)
358{
359 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(self->interface);
360 return PyC_UnicodeFromStdStr(interface->name);
361}
362
364 {"name",
366 (setter) nullptr,
367 pygpu_interface_info_name_doc,
368 nullptr},
369 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
370};
371
373
374/* -------------------------------------------------------------------- */
377
378static PyObject *pygpu_interface_info__tp_new(PyTypeObject * /*type*/,
379 PyObject *args,
380 PyObject *kwds)
381{
382 if (kwds) {
383 PyErr_SetString(PyExc_TypeError, "no keywords are expected");
384 return nullptr;
385 }
386
387 const char *name;
388 if (!PyArg_ParseTuple(args, "s:GPUStageInterfaceInfo.__new__*", &name)) {
389 return nullptr;
390 }
391
393 GPUStageInterfaceInfo *interface_info = reinterpret_cast<GPUStageInterfaceInfo *>(interface);
394
395 PyObject *self = BPyGPUStageInterfaceInfo_CreatePyObject(interface_info);
396
397#ifdef USE_GPU_PY_REFERENCES
398 PyObject *py_name = PyTuple_GET_ITEM(args, 0);
399 PyList_Append(((BPyGPUStageInterfaceInfo *)self)->references, py_name);
400#endif
401
402 return self;
403}
404
405#ifdef USE_GPU_PY_REFERENCES
406
407static int pygpu_interface_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
408{
409 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
410 Py_VISIT(py_interface->references);
411 return 0;
412}
413
415{
416 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
417 Py_CLEAR(py_interface->references);
418 return 0;
419}
420
421#endif
422
424{
425 BPyGPUStageInterfaceInfo *py_interface = reinterpret_cast<BPyGPUStageInterfaceInfo *>(self);
426 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(py_interface->interface);
427 delete interface;
428
429#ifdef USE_GPU_PY_REFERENCES
430 PyObject_GC_UnTrack(self);
431 if (py_interface->references) {
433 Py_CLEAR(py_interface->references);
434 }
435#endif
436
437 Py_TYPE(self)->tp_free(self);
438}
439
441 /* Wrap. */
442 pygpu_interface_info__tp_doc,
443 ".. class:: GPUStageInterfaceInfo(name)\n"
444 "\n"
445 " List of varyings between shader stages.\n"
446 "\n"
447 " :arg name: Name of the interface block.\n"
448 " :type value: str\n");
450 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
451 /*tp_name*/ "GPUStageInterfaceInfo",
452 /*tp_basicsize*/ sizeof(BPyGPUStageInterfaceInfo),
453 /*tp_itemsize*/ 0,
455 /*tp_vectorcall_offset*/ 0,
456 /*tp_getattr*/ nullptr,
457 /*tp_setattr*/ nullptr,
458 /*tp_compare*/ nullptr,
459 /*tp_repr*/ nullptr,
460 /*tp_as_number*/ nullptr,
461 /*tp_as_sequence*/ nullptr,
462 /*tp_as_mapping*/ nullptr,
463 /*tp_hash*/ nullptr,
464 /*tp_call*/ nullptr,
465 /*tp_str*/ nullptr,
466 /*tp_getattro*/ nullptr,
467 /*tp_setattro*/ nullptr,
468 /*tp_as_buffer*/ nullptr,
470 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
471#else
472 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
473#endif
474 /*tp_doc*/ pygpu_interface_info__tp_doc,
476 /*tp_traverse*/ pygpu_interface_info__tp_traverse,
477#else
478 /*tp_traverse*/ nullptr,
479#endif
482#else
483 /*tp_clear*/ nullptr,
484#endif
485 /*tp_richcompare*/ nullptr,
486 /*tp_weaklistoffset*/ 0,
487 /*tp_iter*/ nullptr,
488 /*tp_iternext*/ nullptr,
490 /*tp_members*/ nullptr,
492 /*tp_base*/ nullptr,
493 /*tp_dict*/ nullptr,
494 /*tp_descr_get*/ nullptr,
495 /*tp_descr_set*/ nullptr,
496 /*tp_dictoffset*/ 0,
497 /*tp_init*/ nullptr,
498 /*tp_alloc*/ nullptr,
500 /*tp_free*/ nullptr,
501 /*tp_is_gc*/ nullptr,
502 /*tp_bases*/ nullptr,
503 /*tp_mro*/ nullptr,
504 /*tp_cache*/ nullptr,
505 /*tp_subclasses*/ nullptr,
506 /*tp_weaklist*/ nullptr,
507 /*tp_del*/ nullptr,
508 /*tp_version_tag*/ 0,
509 /*tp_finalize*/ nullptr,
510 /*tp_vectorcall*/ nullptr,
511};
512
514
515/* -------------------------------------------------------------------- */
518
520 /* Wrap. */
521 pygpu_shader_info_vertex_in_doc,
522 ".. method:: vertex_in(slot, type, name)\n"
523 "\n"
524 " Add a vertex shader input attribute.\n"
525 "\n"
526 " :arg slot: The attribute index.\n"
527 " :type slot: int\n"
528 " :arg type: One of these types:\n"
529 "\n" PYDOC_TYPE_LIST
530 "\n"
531 " :type type: str\n"
532 " :arg name: name of the attribute.\n"
533 " :type name: str\n");
535{
536 int slot;
538 const char *param;
539
540 if (!PyArg_ParseTuple(args, "iO&s:vertex_in", &slot, PyC_ParseStringEnum, &pygpu_type, &param)) {
541 return nullptr;
542 }
543
544#ifdef USE_GPU_PY_REFERENCES
545 PyObject *py_name = PyTuple_GET_ITEM(args, 2);
546 PyList_Append(self->references, py_name);
547#endif
548
549 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
550 info->vertex_in(slot, (Type)pygpu_type.value_found, param);
551 Py_RETURN_NONE;
552}
553
555 /* Wrap. */
556 pygpu_shader_info_vertex_out_doc,
557 ".. method:: vertex_out(interface)\n"
558 "\n"
559 " Add a vertex shader output interface block.\n"
560 "\n"
561 " :arg interface: Object describing the block.\n"
562 " :type interface: :class:`gpu.types.GPUStageInterfaceInfo`\n");
565{
567 PyErr_Format(PyExc_TypeError, "Expected a GPUStageInterfaceInfo, got %s", Py_TYPE(o)->tp_name);
568 return nullptr;
569 }
570
571#ifdef USE_GPU_PY_REFERENCES
572 PyList_Append(self->references, (PyObject *)o);
573#endif
574
575 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
576 StageInterfaceInfo *interface = reinterpret_cast<StageInterfaceInfo *>(o->interface);
577 info->vertex_out(*interface);
578
579 Py_RETURN_NONE;
580}
581
583 /* Wrap. */
584 pygpu_shader_info_fragment_out_doc,
585 ".. method:: fragment_out(slot, type, name, *, blend='NONE')\n"
586 "\n"
587 " Specify a fragment output corresponding to a framebuffer target slot.\n"
588 "\n"
589 " :arg slot: The attribute index.\n"
590 " :type slot: int\n"
591 " :arg type: One of these types:\n"
592 "\n" PYDOC_TYPE_LIST
593 "\n"
594 " :type type: str\n"
595 " :arg name: Name of the attribute.\n"
596 " :type name: str\n"
597 " :arg blend: Dual Source Blending Index. It can be 'NONE', 'SRC_0' or 'SRC_1'.\n"
598 " :type blend: str\n");
600 PyObject *args,
601 PyObject *kwds)
602{
603 int slot;
605 const char *name;
606 PyC_StringEnum blend_type = {pygpu_dualblend_items, int(DualBlend::NONE)};
607
608 static const char *_keywords[] = {"slot", "type", "name", "blend", nullptr};
609 static _PyArg_Parser _parser = {
611 "i" /* `slot` */
612 "O&" /* `type` */
613 "s" /* `name` */
614 "|$" /* Optional keyword only arguments. */
615 "O&" /* `blend` */
616 ":fragment_out",
617 _keywords,
618 nullptr,
619 };
620 if (!_PyArg_ParseTupleAndKeywordsFast(args,
621 kwds,
622 &_parser,
623 &slot,
625 &pygpu_type,
626 &name,
628 &blend_type))
629 {
630 return nullptr;
631 }
632
633#ifdef USE_GPU_PY_REFERENCES
634 PyObject *py_name = PyTuple_GET_ITEM(args, 2);
635 PyList_Append(self->references, py_name);
636#endif
637
638 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
639 info->fragment_out(slot, (Type)pygpu_type.value_found, name, (DualBlend)blend_type.value_found);
640
641 Py_RETURN_NONE;
642}
643
645 /* Wrap. */
646 pygpu_shader_info_depth_write_doc,
647 ".. method:: depth_write(value)\n"
648 "\n"
649 " Specify a depth write behavior when modifying gl_FragDepth.\n"
650 "\n"
651 " There is a common optimization for GPUs that relies on an early depth\n"
652 " test to be run before the fragment shader so that the shader evaluation\n"
653 " can be skipped if the fragment ends up being discarded because it is occluded.\n"
654 "\n"
655 " This optimization does not affect the final rendering, and is typically\n"
656 " possible when the fragment does not change the depth programmatically.\n"
657 " There are, however a class of operations on the depth in the shader which\n"
658 " could still be performed while allowing the early depth test to operate.\n"
659 "\n"
660 " This function alters the behavior of the optimization to allow those operations\n"
661 " to be performed.\n"
662 "\n"
663 " :arg value: Depth write value. "
664 "It can be 'UNCHANGED' (default), 'ANY', 'GREATER' or 'LESS'.\n"
665 " :UNCHANGED: disables depth write in a fragment shader and execution of the"
666 "fragments can be optimized away.\n"
667 " :ANY: enables depth write in a fragment shader for any fragments\n"
668 " :GREATER: enables depth write in a fragment shader for depth values that"
669 "are greater than the depth value in the output buffer.\n"
670 " :LESS: enables depth write in a fragment shader for depth values that"
671 "are less than the depth value in the output buffer.\n"
672 " :type blend: str\n");
674{
675 PyC_StringEnum depth_write = {pygpu_depth_write_items, int(DepthWrite::UNCHANGED)};
676 if (!PyC_ParseStringEnum(args, &depth_write)) {
677 return nullptr;
678 }
679
680 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
681 info->depth_write(DepthWrite(depth_write.value_found));
682
683 Py_RETURN_NONE;
684}
685
687 /* Wrap. */
688 pygpu_shader_info_uniform_buf_doc,
689 ".. method:: uniform_buf(slot, type_name, name)\n"
690 "\n"
691 " Specify a uniform variable whose type can be one of those declared in "
692 ":meth:`gpu.types.GPUShaderCreateInfo.typedef_source`.\n"
693 "\n"
694 " :arg slot: The uniform variable index.\n"
695 " :type slot: int\n"
696 " :arg type_name: Name of the data type. "
697 "It can be a struct type defined in the source passed through the "
698 ":meth:`gpu.types.GPUShaderCreateInfo.typedef_source`.\n"
699 " :type type_name: str\n"
700 " :arg name: The uniform variable name.\n"
701 " :type name: str\n");
703{
704 int slot;
705 const char *type_name;
706 const char *name;
707
708 if (!PyArg_ParseTuple(args, "iss:uniform_buf", &slot, &type_name, &name)) {
709 return nullptr;
710 }
711
712#ifdef USE_GPU_PY_REFERENCES
713 PyList_Append(self->references, PyTuple_GET_ITEM(args, 1)); /* type_name */
714 PyList_Append(self->references, PyTuple_GET_ITEM(args, 2)); /* name */
715#endif
716
717 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
718 info->uniform_buf(slot, type_name, name);
719
720 Py_RETURN_NONE;
721}
722
723#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
725 /* Wrap. */
726 pygpu_shader_info_image_doc,
727 ".. method:: image(slot, format, type, name, *, qualifiers={'NO_RESTRICT'})\n"
728 "\n"
729 " Specify an image resource used for arbitrary load and store operations.\n"
730 "\n"
731 " :arg slot: The image resource index.\n"
732 " :type slot: int\n"
733 " :arg format: The GPUTexture format that is passed to the shader. Possible "
734 "values are:\n"
736 " :type format: str\n"
737 " :arg type: The data type describing how the image is to be read in the shader. "
738 "Possible values are:\n"
740 "\n"
741 " :type type: str\n"
742 " :arg name: The image resource name.\n"
743 " :type name: str\n"
744 " :arg qualifiers: Set containing values that describe how the image resource is to be "
745 "read or written. Possible values are:\n"
747 ""
748 " :type qualifiers: set[str]\n");
750 PyObject *args,
751 PyObject *kwds)
752{
753 int slot;
754 PyC_StringEnum pygpu_texformat = {pygpu_textureformat_items};
755 PyC_StringEnum pygpu_imagetype = {pygpu_imagetype_items};
756 const char *name;
757 PyObject *py_qualifiers = nullptr;
758 Qualifier qualifier = Qualifier::no_restrict;
759
760 static const char *_keywords[] = {"slot", "format", "type", "name", "qualifiers", nullptr};
761 static _PyArg_Parser _parser = {
763 "i" /* `slot` */
764 "O&" /* `format` */
765 "O&" /* `type` */
766 "s" /* `name` */
767 "|$" /* Optional keyword only arguments. */
768 "O" /* `qualifiers` */
769 ":image",
770 _keywords,
771 nullptr,
772 };
773 if (!_PyArg_ParseTupleAndKeywordsFast(args,
774 kwds,
775 &_parser,
776 &slot,
778 &pygpu_texformat,
780 &pygpu_imagetype,
781 &name,
782 &py_qualifiers))
783 {
784 return nullptr;
785 }
786
787 if (py_qualifiers &&
789 pygpu_qualifiers, py_qualifiers, (int *)&qualifier, "shader_info.image") == -1)
790 {
791 return nullptr;
792 }
793
794 if (pygpu_texformat.value_found == GPU_DEPTH24_STENCIL8_DEPRECATED) {
795 pygpu_texformat.value_found = int(blender::gpu::TextureFormat::SFLOAT_32_DEPTH_UINT_8);
796 PyErr_WarnEx(
797 PyExc_DeprecationWarning, "'DEPTH24_STENCIL8' is deprecated. Use 'DEPTH32F_STENCIL8'.", 1);
798 }
799 if (pygpu_texformat.value_found == GPU_DEPTH_COMPONENT24_DEPRECATED) {
800 pygpu_texformat.value_found = int(blender::gpu::TextureFormat::SFLOAT_32_DEPTH);
801 PyErr_WarnEx(PyExc_DeprecationWarning,
802 "'DEPTH_COMPONENT24' is deprecated. Use 'DEPTH_COMPONENT32F'.",
803 1);
804 }
805
806# ifdef USE_GPU_PY_REFERENCES
807 PyList_Append(self->references, PyTuple_GET_ITEM(args, 3)); /* name */
808# endif
809
810 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
811 info->image(slot,
813 qualifier,
815 name);
816
817 Py_RETURN_NONE;
818}
819#endif
820
822 /* Wrap. */
823 pygpu_shader_info_sampler_doc,
824 ".. method:: sampler(slot, type, name)\n"
825 "\n"
826 " Specify an image texture sampler.\n"
827 "\n"
828 " :arg slot: The image texture sampler index.\n"
829 " :type slot: int\n"
830 " :arg type: The data type describing the format of each sampler unit. Possible values "
831 "are:\n"
833 "\n"
834 " :type type: str\n"
835 " :arg name: The image texture sampler name.\n"
836 " :type name: str\n");
837static PyObject *pygpu_shader_info_sampler(BPyGPUShaderCreateInfo *self, PyObject *args)
838{
839 int slot;
840 PyC_StringEnum pygpu_samplertype = {pygpu_imagetype_items};
841 const char *name;
842
843 if (!PyArg_ParseTuple(
844 args, "iO&s:sampler", &slot, PyC_ParseStringEnum, &pygpu_samplertype, &name))
845 {
846 return nullptr;
847 }
848
849#ifdef USE_GPU_PY_REFERENCES
850 PyList_Append(self->references, PyTuple_GET_ITEM(args, 2)); /* name */
851#endif
852
853 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
854 info->sampler(slot, (ImageType)pygpu_samplertype.value_found, name);
855
856 Py_RETURN_NONE;
857}
858
859static int constant_type_size(Type type)
860{
861 switch (type) {
862 case Type::bool_t:
863 case Type::float_t:
864 case Type::int_t:
865 case Type::uint_t:
866 case Type::uchar4_t:
867 case Type::char4_t:
868 case Type::float3_10_10_10_2_t:
869 case Type::ushort2_t:
870 case Type::short2_t:
871 return 4;
872 break;
873 case Type::ushort3_t:
874 case Type::short3_t:
875 return 6;
876 break;
877 case Type::float2_t:
878 case Type::uint2_t:
879 case Type::int2_t:
880 case Type::ushort4_t:
881 case Type::short4_t:
882 return 8;
883 break;
884 case Type::float3_t:
885 case Type::uint3_t:
886 case Type::int3_t:
887 return 12;
888 break;
889 case Type::float4_t:
890 case Type::uint4_t:
891 case Type::int4_t:
892 return 16;
893 break;
894 case Type::float3x3_t:
895 return 36 + 3 * 4;
896 case Type::float4x4_t:
897 return 64;
898 break;
899 case Type::uchar_t:
900 case Type::char_t:
901 return 1;
902 break;
903 case Type::uchar2_t:
904 case Type::char2_t:
905 case Type::ushort_t:
906 case Type::short_t:
907 return 2;
908 break;
909 case Type::uchar3_t:
910 case Type::char3_t:
911 return 3;
912 break;
913 }
914 BLI_assert(false);
915 return -1;
916}
917
919{
920 int size_prev = 0;
921 int size_last = 0;
922 for (const ShaderCreateInfo::PushConst &uniform : info->push_constants_) {
923 int pad = 0;
924 int size = constant_type_size(uniform.type);
925 if (size_last && size_last != size) {
926 /* Calc pad. */
927 int pack = (size == 8) ? 8 : 16;
928 if (size_last < size) {
929 pad = pack - (size_last % pack);
930 }
931 else {
932 pad = size_prev % pack;
933 }
934 }
935 else if (size == 12) {
936 /* It is still unclear how Vulkan handles padding for `vec3` constants. For now let's follow
937 * the rules of the `std140` layout. */
938 pad = 4;
939 }
940 size_prev += pad + size * std::max(1, uniform.array_size);
941 size_last = size;
942 }
943 return size_prev + (size_prev % 16);
944}
945
947 /* Wrap. */
948 pygpu_shader_info_push_constant_doc,
949 ".. method:: push_constant(type, name, size=0)\n"
950 "\n"
951 " Specify a global access constant.\n"
952 "\n"
953 " :arg type: One of these types:\n"
954 "\n" PYDOC_TYPE_LIST
955 "\n"
956 " :type type: str\n"
957 " :arg name: Name of the constant.\n"
958 " :type name: str\n"
959 " :arg size: If not zero, indicates that the constant is an array with the specified size.\n"
960 " :type size: int\n");
962 PyObject *args,
963 PyObject *kwds)
964{
966 const char *name = nullptr;
967 int array_size = 0;
968
969 static const char *_keywords[] = {"type", "name", "size", nullptr};
970 static _PyArg_Parser _parser = {
972 "O&" /* `type` */
973 "s" /* `name` */
974 "|" /* Optional arguments. */
975 "I" /* `size` */
976 ":push_constant",
977 _keywords,
978 nullptr,
979 };
980 if (!_PyArg_ParseTupleAndKeywordsFast(
981 args, kwds, &_parser, PyC_ParseStringEnum, &pygpu_type, &name, &array_size))
982 {
983 return nullptr;
984 }
985
986#ifdef USE_GPU_PY_REFERENCES
987 PyObject *py_name = PyTuple_GET_ITEM(args, 1);
988 PyList_Append(self->references, py_name);
989#endif
990
991 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
992 info->push_constant((Type)pygpu_type.value_found, name, array_size);
993
994#define VULKAN_LIMIT 128
995 int size = constants_calc_size(info);
996 if (size > VULKAN_LIMIT) {
997 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);
998 }
999#undef VULKAN_LIMIT
1000
1001 Py_RETURN_NONE;
1002}
1003
1005 /* Wrap. */
1006 pygpu_shader_info_vertex_source_doc,
1007 ".. method:: vertex_source(source)\n"
1008 "\n"
1009 " Vertex shader source code written in GLSL.\n"
1010 "\n"
1011 " Example:\n"
1012 "\n"
1013 " .. code-block:: python\n"
1014 "\n"
1015 " \"void main {gl_Position = vec4(pos, 1.0);}\"\n"
1016 "\n"
1017 " :arg source: The vertex shader source code.\n"
1018 " :type source: str\n"
1019 "\n"
1020 " .. seealso:: `GLSL Cross Compilation "
1021 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1023{
1024 const char *vertex_source = PyUnicode_AsUTF8(o);
1025 if (vertex_source == nullptr) {
1026 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1027 return nullptr;
1028 }
1029
1030#ifdef USE_GPU_PY_REFERENCES
1031 if (self->vertex_source) {
1032 Py_DECREF(self->vertex_source);
1033 }
1034
1035 self->vertex_source = o;
1036 Py_INCREF(o);
1037#endif
1038
1039 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1040 info->vertex_source("draw_colormanagement_lib.glsl");
1041 info->vertex_source_generated = vertex_source;
1042
1043 Py_RETURN_NONE;
1044}
1045
1047 /* Wrap. */
1048 pygpu_shader_info_compute_source_doc,
1049 ".. method:: compute_source(source)\n"
1050 "\n"
1051 " compute shader source code written in GLSL.\n"
1052 "\n"
1053 " Example:\n"
1054 "\n"
1055 " .. code-block:: python\n"
1056 "\n"
1057 " \"\"\"void main() {\n"
1058 " int2 index = int2(gl_GlobalInvocationID.xy);\n"
1059 " vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1060 " imageStore(img_output, index, color);\n"
1061 " }\"\"\"\n"
1062 "\n"
1063 " :arg source: The compute shader source code.\n"
1064 " :type source: str\n"
1065 "\n"
1066 " .. seealso:: `GLSL Cross Compilation "
1067 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1069{
1070 const char *compute_source = PyUnicode_AsUTF8(o);
1071 if (compute_source == nullptr) {
1072 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1073 return nullptr;
1074 }
1075
1076#ifdef USE_GPU_PY_REFERENCES
1077 if (self->compute_source) {
1078 Py_DECREF(self->compute_source);
1079 }
1080
1081 self->compute_source = o;
1082 Py_INCREF(o);
1083#endif
1084
1085 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1086 info->compute_source("draw_colormanagement_lib.glsl");
1087 info->compute_source_generated = compute_source;
1088
1089 Py_RETURN_NONE;
1090}
1091
1093 /* Wrap. */
1094 pygpu_shader_info_fragment_source_doc,
1095 ".. method:: fragment_source(source)\n"
1096 "\n"
1097 " Fragment shader source code written in GLSL.\n"
1098 "\n"
1099 " Example:\n"
1100 "\n"
1101 " .. code-block:: python\n"
1102 "\n"
1103 " \"void main {fragColor = vec4(0.0, 0.0, 0.0, 1.0);}\"\n"
1104 "\n"
1105 " :arg source: The fragment shader source code.\n"
1106 " :type source: str\n"
1107 "\n"
1108 " .. seealso:: `GLSL Cross Compilation "
1109 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1111{
1112 const char *fragment_source = PyUnicode_AsUTF8(o);
1113 if (fragment_source == nullptr) {
1114 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1115 return nullptr;
1116 }
1117
1118#ifdef USE_GPU_PY_REFERENCES
1119 if (self->fragment_source) {
1120 Py_DECREF(self->fragment_source);
1121 }
1122
1123 self->fragment_source = o;
1124 Py_INCREF(o);
1125#endif
1126
1127 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1128 info->fragment_source("draw_colormanagement_lib.glsl");
1129 info->fragment_source_generated = fragment_source;
1130
1131 Py_RETURN_NONE;
1132}
1133
1135 /* Wrap. */
1136 pygpu_shader_info_typedef_source_doc,
1137 ".. method:: typedef_source(source)\n"
1138 "\n"
1139 " Source code included before resource declaration. "
1140 "Useful for defining structs used by Uniform Buffers.\n"
1141 "\n"
1142 " Example:\n"
1143 "\n"
1144 " .. code-block:: python\n"
1145 "\n"
1146 " \"struct MyType {int foo; float bar;};\"\n"
1147 "\n"
1148 " :arg source: The source code defining types.\n"
1149 " :type source: str\n");
1151{
1152 const char *typedef_source = PyUnicode_AsUTF8(o);
1153 if (typedef_source == nullptr) {
1154 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1155 return nullptr;
1156 }
1157
1158#ifdef USE_GPU_PY_REFERENCES
1159 if (self->typedef_source) {
1160 Py_DECREF(self->typedef_source);
1161 }
1162
1163 self->typedef_source = o;
1164 Py_INCREF(o);
1165#endif
1166
1167 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1168#if 0
1169 if (info->typedef_sources_.is_empty()) {
1170 info->typedef_source("GPU_shader_shared_utils.hh");
1171 }
1172#endif
1173 info->typedef_source_generated = typedef_source;
1174
1175 Py_RETURN_NONE;
1176}
1177
1179 /* Wrap. */
1180 pygpu_shader_info_define_doc,
1181 ".. method:: define(name, value)\n"
1182 "\n"
1183 " Add a preprocessing define directive. In GLSL it would be something like:\n"
1184 "\n"
1185 " .. code-block:: glsl\n"
1186 "\n"
1187 " #define name value\n"
1188 "\n"
1189 " :arg name: Token name.\n"
1190 " :type name: str\n"
1191 " :arg value: Text that replaces token occurrences.\n"
1192 " :type value: str\n");
1193static PyObject *pygpu_shader_info_define(BPyGPUShaderCreateInfo *self, PyObject *args)
1194{
1195 const char *name;
1196 const char *value = nullptr;
1197
1198 if (!PyArg_ParseTuple(args, "s|s:define", &name, &value)) {
1199 return nullptr;
1200 }
1201
1202#ifdef USE_GPU_PY_REFERENCES
1203 PyList_Append(self->references, PyTuple_GET_ITEM(args, 0)); /* name */
1204 if (value) {
1205 PyList_Append(self->references, PyTuple_GET_ITEM(args, 1)); /* value */
1206 }
1207#endif
1208
1209 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1210 if (value) {
1211 info->define(name, value);
1212 }
1213 else {
1214 info->define(name);
1215 }
1216
1217 Py_RETURN_NONE;
1218}
1219
1221 /* Wrap. */
1222 pygpu_shader_info_local_group_size_doc,
1223 ".. method:: local_group_size(x, y=1, z=1)\n"
1224 "\n"
1225 " Specify the local group size for compute shaders.\n"
1226 "\n"
1227 " :arg x: The local group size in the x dimension.\n"
1228 " :type x: int\n"
1229 " :arg y: The local group size in the y dimension. Optional. Defaults to 1.\n"
1230 " :type y: int\n"
1231 " :arg z: The local group size in the z dimension. Optional. Defaults to 1.\n"
1232 " :type z: int\n");
1234{
1235 int x = -1, y = 1, z = 1;
1236
1237 if (!PyArg_ParseTuple(args, "i|ii:local_group_size", &x, &y, &z)) {
1238 return nullptr;
1239 }
1240
1241 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1242 info->local_group_size(x, y, z);
1243
1244 Py_RETURN_NONE;
1245}
1246
1247static PyMethodDef pygpu_shader_info__tp_methods[] = {
1248 {"vertex_in",
1249 (PyCFunction)pygpu_shader_info_vertex_in,
1250 METH_VARARGS,
1251 pygpu_shader_info_vertex_in_doc},
1252 {"vertex_out",
1253 (PyCFunction)pygpu_shader_info_vertex_out,
1254 METH_O,
1255 pygpu_shader_info_vertex_out_doc},
1256 {"depth_write",
1257 (PyCFunction)(void *)pygpu_shader_info_depth_write,
1258 METH_O,
1259 pygpu_shader_info_depth_write_doc},
1260 {"fragment_out",
1261 (PyCFunction)(void *)pygpu_shader_info_fragment_out,
1262 METH_VARARGS | METH_KEYWORDS,
1263 pygpu_shader_info_fragment_out_doc},
1264 {"uniform_buf",
1265 (PyCFunction)(void *)pygpu_shader_info_uniform_buf,
1266 METH_VARARGS,
1267 pygpu_shader_info_uniform_buf_doc},
1268#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
1269 {"image",
1270 (PyCFunction)(void *)pygpu_shader_info_image,
1271 METH_VARARGS | METH_KEYWORDS,
1272 pygpu_shader_info_image_doc},
1273#endif
1274 {"sampler",
1275 (PyCFunction)pygpu_shader_info_sampler,
1276 METH_VARARGS,
1277 pygpu_shader_info_sampler_doc},
1278 {"push_constant",
1279 (PyCFunction)(void *)pygpu_shader_info_push_constant,
1280 METH_VARARGS | METH_KEYWORDS,
1281 pygpu_shader_info_push_constant_doc},
1282 {"vertex_source",
1284 METH_O,
1285 pygpu_shader_info_vertex_source_doc},
1286 {"fragment_source",
1288 METH_O,
1289 pygpu_shader_info_fragment_source_doc},
1290 {"compute_source",
1292 METH_O,
1293 pygpu_shader_info_compute_source_doc},
1294 {"typedef_source",
1296 METH_O,
1297 pygpu_shader_info_typedef_source_doc},
1298 {"define", (PyCFunction)pygpu_shader_info_define, METH_VARARGS, pygpu_shader_info_define_doc},
1299 {"local_group_size",
1301 METH_VARARGS,
1302 pygpu_shader_info_local_group_size_doc},
1303 {nullptr, nullptr, 0, nullptr},
1304};
1305
1307
1308/* -------------------------------------------------------------------- */
1311
1312static PyObject *pygpu_shader_info__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds)
1313{
1314 if (PyTuple_Size(args) || kwds) {
1315 PyErr_SetString(PyExc_TypeError, "no args or keywords are expected");
1316 return nullptr;
1317 }
1318
1319 ShaderCreateInfo *info = new ShaderCreateInfo("pyGPU_Shader");
1320 GPUShaderCreateInfo *shader_info = reinterpret_cast<GPUShaderCreateInfo *>(info);
1321
1322 return BPyGPUShaderCreateInfo_CreatePyObject(shader_info);
1323}
1324
1325#ifdef USE_GPU_PY_REFERENCES
1326
1327static int pygpu_shader_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
1328{
1329 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1330 Py_VISIT(py_info->vertex_source);
1331 Py_VISIT(py_info->fragment_source);
1332 Py_VISIT(py_info->compute_source);
1333 Py_VISIT(py_info->references);
1334 return 0;
1335}
1336
1338{
1339 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1340 Py_CLEAR(py_info->vertex_source);
1341 Py_CLEAR(py_info->fragment_source);
1342 Py_CLEAR(py_info->compute_source);
1343 Py_CLEAR(py_info->references);
1344 return 0;
1345}
1346
1347#endif
1348
1350{
1351 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1352 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(py_info->info);
1353 delete info;
1354
1355#ifdef USE_GPU_PY_REFERENCES
1356 PyObject_GC_UnTrack(self);
1357 if (py_info->references || py_info->vertex_source || py_info->fragment_source) {
1359 Py_XDECREF(py_info->vertex_source);
1360 Py_XDECREF(py_info->fragment_source);
1361 Py_XDECREF(py_info->compute_source);
1362 Py_XDECREF(py_info->references);
1363 }
1364
1365#endif
1366
1367 Py_TYPE(self)->tp_free(self);
1368}
1369
1371 /* Wrap. */
1372 pygpu_shader_info__tp_doc,
1373 ".. class:: GPUShaderCreateInfo()\n"
1374 "\n"
1375 " Stores and describes types and variables that are used in shader sources.\n");
1377 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1378 /*tp_name*/ "GPUShaderCreateInfo",
1379 /*tp_basicsize*/ sizeof(BPyGPUShaderCreateInfo),
1380 /*tp_itemsize*/ 0,
1381 /*tp_dealloc*/ pygpu_shader_info__tp_dealloc,
1382 /*tp_vectorcall_offset*/ 0,
1383 /*tp_getattr*/ nullptr,
1384 /*tp_setattr*/ nullptr,
1385 /*tp_compare*/ nullptr,
1386 /*tp_repr*/ nullptr,
1387 /*tp_as_number*/ nullptr,
1388 /*tp_as_sequence*/ nullptr,
1389 /*tp_as_mapping*/ nullptr,
1390 /*tp_hash*/ nullptr,
1391 /*tp_call*/ nullptr,
1392 /*tp_str*/ nullptr,
1393 /*tp_getattro*/ nullptr,
1394 /*tp_setattro*/ nullptr,
1395 /*tp_as_buffer*/ nullptr,
1397 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1398#else
1399 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
1400#endif
1401 /*tp_doc*/ pygpu_shader_info__tp_doc,
1403 /*tp_traverse*/ pygpu_shader_info__tp_traverse,
1404#else
1405 /*tp_traverse*/ nullptr,
1406#endif
1408 /*tp_clear*/ pygpu_shader_info__tp_clear,
1409#else
1410 /*tp_clear*/ nullptr,
1411#endif
1412 /*tp_richcompare*/ nullptr,
1413 /*tp_weaklistoffset*/ 0,
1414 /*tp_iter*/ nullptr,
1415 /*tp_iternext*/ nullptr,
1416 /*tp_methods*/ pygpu_shader_info__tp_methods,
1417 /*tp_members*/ nullptr,
1418 /*tp_getset*/ nullptr,
1419 /*tp_base*/ nullptr,
1420 /*tp_dict*/ nullptr,
1421 /*tp_descr_get*/ nullptr,
1422 /*tp_descr_set*/ nullptr,
1423 /*tp_dictoffset*/ 0,
1424 /*tp_init*/ nullptr,
1425 /*tp_alloc*/ nullptr,
1426 /*tp_new*/ pygpu_shader_info__tp_new,
1427 /*tp_free*/ nullptr,
1428 /*tp_is_gc*/ nullptr,
1429 /*tp_bases*/ nullptr,
1430 /*tp_mro*/ nullptr,
1431 /*tp_cache*/ nullptr,
1432 /*tp_subclasses*/ nullptr,
1433 /*tp_weaklist*/ nullptr,
1434 /*tp_del*/ nullptr,
1435 /*tp_version_tag*/ 0,
1436 /*tp_finalize*/ nullptr,
1437 /*tp_vectorcall*/ nullptr,
1438};
1439
1441
1442/* -------------------------------------------------------------------- */
1445
1447{
1449
1450#ifdef USE_GPU_PY_REFERENCES
1452 self->references = PyList_New(0);
1453#else
1455#endif
1456
1457 self->interface = interface;
1458
1459 return (PyObject *)self;
1460}
1461
1462PyObject *BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info)
1463{
1465
1466#ifdef USE_GPU_PY_REFERENCES
1468 self->vertex_source = nullptr;
1469 self->fragment_source = nullptr;
1470 self->compute_source = nullptr;
1471 self->typedef_source = nullptr;
1472 self->references = PyList_New(0);
1473#else
1475#endif
1476
1477 self->info = info;
1478 self->constants_total_size = 0;
1479
1480 return (PyObject *)self;
1481}
1482
#define BLI_assert(a)
Definition BLI_assert.h:46
KDTree *BLI_kdtree_nd_ new(unsigned int nodes_len_capacity)
Definition kdtree_impl.h:98
#define STRINGIFY(x)
int pad[32 - sizeof(int)]
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
#define USE_GPU_PY_REFERENCES
PyTypeObject BPyGPUStageInterfaceInfo_Type
const struct PyC_StringEnumItems pygpu_attrtype_items[]
PyTypeObject BPyGPUShaderCreateInfo_Type
#define BPyGPUStageInterfaceInfo_Check(v)
PyObject * BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info)
static int pygpu_shader_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
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 pygpu_interface_info__tp_clear(PyObject *self)
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)
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 const PyC_StringEnumItems pygpu_depth_write_items[]
static int pygpu_interface_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
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
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 PyObject * pygpu_shader_info_depth_write(BPyGPUShaderCreateInfo *self, PyObject *args)
static PyMethodDef pygpu_interface_info__tp_methods[]
static int pygpu_shader_info__tp_clear(PyObject *self)
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[]
constexpr int GPU_DEPTH24_STENCIL8_DEPRECATED
constexpr int GPU_DEPTH_COMPONENT24_DEPRECATED
#define interface
#define printf(...)
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)
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
header-only compatibility defines.
Py_DECREF(oname)
#define PY_ARG_PARSER_HEAD_COMPAT()
const char * name
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 & 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 & vertex_out(StageInterfaceInfo &interface)
Self & sampler(int slot, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS, GPUSamplerState sampler=GPUSamplerState::internal_sampler())
Self & image(int slot, TextureFormat format, Qualifier qualifiers, ImageReadWriteType type, StringRefNull name, Frequency freq=Frequency::PASS)
Self & uniform_buf(int slot, StringRefNull type_name, StringRefNull name, Frequency freq=Frequency::PASS)
Self & local_group_size(int local_size_x, int local_size_y=1, int local_size_z=1)
Self & define(StringRefNull name, StringRefNull value="")