Blender V4.5
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``\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``\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");
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
392 StageInterfaceInfo *interface = new StageInterfaceInfo(name, "");
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 values are:\n"
735 " :type format: str\n"
736 " :arg type: The data type describing how the image is to be read in the shader. "
737 "Possible values are:\n"
739 "\n"
740 " :type type: str\n"
741 " :arg name: The image resource name.\n"
742 " :type name: str\n"
743 " :arg qualifiers: Set containing values that describe how the image resource is to be "
744 "read or written. Possible values are:\n"
746 ""
747 " :type qualifiers: set[str]\n");
749 PyObject *args,
750 PyObject *kwds)
751{
752 int slot;
753 PyC_StringEnum pygpu_texformat = {pygpu_textureformat_items};
754 PyC_StringEnum pygpu_imagetype = {pygpu_imagetype_items};
755 const char *name;
756 PyObject *py_qualifiers = nullptr;
757 Qualifier qualifier = Qualifier::no_restrict;
758
759 static const char *_keywords[] = {"slot", "format", "type", "name", "qualifiers", nullptr};
760 static _PyArg_Parser _parser = {
762 "i" /* `slot` */
763 "O&" /* `format` */
764 "O&" /* `type` */
765 "s" /* `name` */
766 "|$" /* Optional keyword only arguments. */
767 "O" /* `qualifiers` */
768 ":image",
769 _keywords,
770 nullptr,
771 };
772 if (!_PyArg_ParseTupleAndKeywordsFast(args,
773 kwds,
774 &_parser,
775 &slot,
777 &pygpu_texformat,
779 &pygpu_imagetype,
780 &name,
781 &py_qualifiers))
782 {
783 return nullptr;
784 }
785
786 if (py_qualifiers &&
788 pygpu_qualifiers, py_qualifiers, (int *)&qualifier, "shader_info.image") == -1)
789 {
790 return nullptr;
791 }
792
793# ifdef USE_GPU_PY_REFERENCES
794 PyList_Append(self->references, PyTuple_GET_ITEM(args, 3)); /* name */
795# endif
796
797 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
798 info->image(slot,
799 (eGPUTextureFormat)pygpu_texformat.value_found,
800 qualifier,
802 name);
803
804 Py_RETURN_NONE;
805}
806#endif
807
809 /* Wrap. */
810 pygpu_shader_info_sampler_doc,
811 ".. method:: sampler(slot, type, name)\n"
812 "\n"
813 " Specify an image texture sampler.\n"
814 "\n"
815 " :arg slot: The image texture sampler index.\n"
816 " :type slot: int\n"
817 " :arg type: The data type describing the format of each sampler unit. Possible values "
818 "are:\n"
820 "\n"
821 " :type type: str\n"
822 " :arg name: The image texture sampler name.\n"
823 " :type name: str\n");
824static PyObject *pygpu_shader_info_sampler(BPyGPUShaderCreateInfo *self, PyObject *args)
825{
826 int slot;
827 PyC_StringEnum pygpu_samplertype = {pygpu_imagetype_items};
828 const char *name;
829
830 if (!PyArg_ParseTuple(
831 args, "iO&s:sampler", &slot, PyC_ParseStringEnum, &pygpu_samplertype, &name))
832 {
833 return nullptr;
834 }
835
836#ifdef USE_GPU_PY_REFERENCES
837 PyList_Append(self->references, PyTuple_GET_ITEM(args, 2)); /* name */
838#endif
839
840 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
841 info->sampler(slot, (ImageType)pygpu_samplertype.value_found, name);
842
843 Py_RETURN_NONE;
844}
845
846static int constant_type_size(Type type)
847{
848 switch (type) {
849 case Type::bool_t:
850 case Type::float_t:
851 case Type::int_t:
852 case Type::uint_t:
853 case Type::uchar4_t:
854 case Type::char4_t:
855 case Type::float3_10_10_10_2_t:
856 case Type::ushort2_t:
857 case Type::short2_t:
858 return 4;
859 break;
860 case Type::ushort3_t:
861 case Type::short3_t:
862 return 6;
863 break;
864 case Type::float2_t:
865 case Type::uint2_t:
866 case Type::int2_t:
867 case Type::ushort4_t:
868 case Type::short4_t:
869 return 8;
870 break;
871 case Type::float3_t:
872 case Type::uint3_t:
873 case Type::int3_t:
874 return 12;
875 break;
876 case Type::float4_t:
877 case Type::uint4_t:
878 case Type::int4_t:
879 return 16;
880 break;
881 case Type::float3x3_t:
882 return 36 + 3 * 4;
883 case Type::float4x4_t:
884 return 64;
885 break;
886 case Type::uchar_t:
887 case Type::char_t:
888 return 1;
889 break;
890 case Type::uchar2_t:
891 case Type::char2_t:
892 case Type::ushort_t:
893 case Type::short_t:
894 return 2;
895 break;
896 case Type::uchar3_t:
897 case Type::char3_t:
898 return 3;
899 break;
900 }
901 BLI_assert(false);
902 return -1;
903}
904
906{
907 int size_prev = 0;
908 int size_last = 0;
909 for (const ShaderCreateInfo::PushConst &uniform : info->push_constants_) {
910 int pad = 0;
911 int size = constant_type_size(uniform.type);
912 if (size_last && size_last != size) {
913 /* Calc pad. */
914 int pack = (size == 8) ? 8 : 16;
915 if (size_last < size) {
916 pad = pack - (size_last % pack);
917 }
918 else {
919 pad = size_prev % pack;
920 }
921 }
922 else if (size == 12) {
923 /* It is still unclear how Vulkan handles padding for `vec3` constants. For now let's follow
924 * the rules of the `std140` layout. */
925 pad = 4;
926 }
927 size_prev += pad + size * std::max(1, uniform.array_size);
928 size_last = size;
929 }
930 return size_prev + (size_prev % 16);
931}
932
934 /* Wrap. */
935 pygpu_shader_info_push_constant_doc,
936 ".. method:: push_constant(type, name, size=0)\n"
937 "\n"
938 " Specify a global access constant.\n"
939 "\n"
940 " :arg type: One of these types:\n"
941 "\n" PYDOC_TYPE_LIST
942 "\n"
943 " :type type: str\n"
944 " :arg name: Name of the constant.\n"
945 " :type name: str\n"
946 " :arg size: If not zero, indicates that the constant is an array with the specified size.\n"
947 " :type size: int\n");
949 PyObject *args,
950 PyObject *kwds)
951{
953 const char *name = nullptr;
954 int array_size = 0;
955
956 static const char *_keywords[] = {"type", "name", "size", nullptr};
957 static _PyArg_Parser _parser = {
959 "O&" /* `type` */
960 "s" /* `name` */
961 "|" /* Optional arguments. */
962 "I" /* `size` */
963 ":push_constant",
964 _keywords,
965 nullptr,
966 };
967 if (!_PyArg_ParseTupleAndKeywordsFast(
968 args, kwds, &_parser, PyC_ParseStringEnum, &pygpu_type, &name, &array_size))
969 {
970 return nullptr;
971 }
972
973#ifdef USE_GPU_PY_REFERENCES
974 PyObject *py_name = PyTuple_GET_ITEM(args, 1);
975 PyList_Append(self->references, py_name);
976#endif
977
978 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
979 info->push_constant((Type)pygpu_type.value_found, name, array_size);
980
981#define VULKAN_LIMIT 128
982 int size = constants_calc_size(info);
983 if (size > VULKAN_LIMIT) {
984 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);
985 }
986#undef VULKAN_LIMIT
987
988 Py_RETURN_NONE;
989}
990
992 /* Wrap. */
993 pygpu_shader_info_vertex_source_doc,
994 ".. method:: vertex_source(source)\n"
995 "\n"
996 " Vertex shader source code written in GLSL.\n"
997 "\n"
998 " Example:\n"
999 "\n"
1000 " .. code-block:: python\n"
1001 "\n"
1002 " \"void main {gl_Position = vec4(pos, 1.0);}\"\n"
1003 "\n"
1004 " :arg source: The vertex shader source code.\n"
1005 " :type source: str\n"
1006 "\n"
1007 " .. seealso:: `GLSL Cross Compilation "
1008 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1010{
1011 const char *vertex_source = PyUnicode_AsUTF8(o);
1012 if (vertex_source == nullptr) {
1013 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1014 return nullptr;
1015 }
1016
1017#ifdef USE_GPU_PY_REFERENCES
1018 if (self->vertex_source) {
1019 Py_DECREF(self->vertex_source);
1020 }
1021
1022 self->vertex_source = o;
1023 Py_INCREF(o);
1024#endif
1025
1026 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1027 info->vertex_source("draw_colormanagement_lib.glsl");
1028 info->vertex_source_generated = vertex_source;
1029
1030 Py_RETURN_NONE;
1031}
1032
1034 /* Wrap. */
1035 pygpu_shader_info_compute_source_doc,
1036 ".. method:: compute_source(source)\n"
1037 "\n"
1038 " compute shader source code written in GLSL.\n"
1039 "\n"
1040 " Example:\n"
1041 "\n"
1042 " .. code-block:: python\n"
1043 "\n"
1044 " \"\"\"void main() {\n"
1045 " int2 index = int2(gl_GlobalInvocationID.xy);\n"
1046 " vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1047 " imageStore(img_output, index, color);\n"
1048 " }\"\"\"\n"
1049 "\n"
1050 " :arg source: The compute shader source code.\n"
1051 " :type source: str\n"
1052 "\n"
1053 " .. seealso:: `GLSL Cross Compilation "
1054 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1056{
1057 const char *compute_source = PyUnicode_AsUTF8(o);
1058 if (compute_source == nullptr) {
1059 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1060 return nullptr;
1061 }
1062
1063#ifdef USE_GPU_PY_REFERENCES
1064 if (self->compute_source) {
1065 Py_DECREF(self->compute_source);
1066 }
1067
1068 self->compute_source = o;
1069 Py_INCREF(o);
1070#endif
1071
1072 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1073 info->compute_source("draw_colormanagement_lib.glsl");
1074 info->compute_source_generated = compute_source;
1075
1076 Py_RETURN_NONE;
1077}
1078
1080 /* Wrap. */
1081 pygpu_shader_info_fragment_source_doc,
1082 ".. method:: fragment_source(source)\n"
1083 "\n"
1084 " Fragment shader source code written in GLSL.\n"
1085 "\n"
1086 " Example:\n"
1087 "\n"
1088 " .. code-block:: python\n"
1089 "\n"
1090 " \"void main {fragColor = vec4(0.0, 0.0, 0.0, 1.0);}\"\n"
1091 "\n"
1092 " :arg source: The fragment shader source code.\n"
1093 " :type source: str\n"
1094 "\n"
1095 " .. seealso:: `GLSL Cross Compilation "
1096 "<https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__\n");
1098{
1099 const char *fragment_source = PyUnicode_AsUTF8(o);
1100 if (fragment_source == nullptr) {
1101 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1102 return nullptr;
1103 }
1104
1105#ifdef USE_GPU_PY_REFERENCES
1106 if (self->fragment_source) {
1107 Py_DECREF(self->fragment_source);
1108 }
1109
1110 self->fragment_source = o;
1111 Py_INCREF(o);
1112#endif
1113
1114 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1115 info->fragment_source("draw_colormanagement_lib.glsl");
1116 info->fragment_source_generated = fragment_source;
1117
1118 Py_RETURN_NONE;
1119}
1120
1122 /* Wrap. */
1123 pygpu_shader_info_typedef_source_doc,
1124 ".. method:: typedef_source(source)\n"
1125 "\n"
1126 " Source code included before resource declaration. "
1127 "Useful for defining structs used by Uniform Buffers.\n"
1128 "\n"
1129 " Example:\n"
1130 "\n"
1131 " .. code-block:: python\n"
1132 "\n"
1133 " \"struct MyType {int foo; float bar;};\"\n"
1134 "\n"
1135 " :arg source: The source code defining types.\n"
1136 " :type source: str\n");
1138{
1139 const char *typedef_source = PyUnicode_AsUTF8(o);
1140 if (typedef_source == nullptr) {
1141 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
1142 return nullptr;
1143 }
1144
1145#ifdef USE_GPU_PY_REFERENCES
1146 if (self->typedef_source) {
1147 Py_DECREF(self->typedef_source);
1148 }
1149
1150 self->typedef_source = o;
1151 Py_INCREF(o);
1152#endif
1153
1154 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1155#if 0
1156 if (info->typedef_sources_.is_empty()) {
1157 info->typedef_source("GPU_shader_shared_utils.hh");
1158 }
1159#endif
1160 info->typedef_source_generated = typedef_source;
1161
1162 Py_RETURN_NONE;
1163}
1164
1166 /* Wrap. */
1167 pygpu_shader_info_define_doc,
1168 ".. method:: define(name, value)\n"
1169 "\n"
1170 " Add a preprocessing define directive. In GLSL it would be something like:\n"
1171 "\n"
1172 " .. code-block:: glsl\n"
1173 "\n"
1174 " #define name value\n"
1175 "\n"
1176 " :arg name: Token name.\n"
1177 " :type name: str\n"
1178 " :arg value: Text that replaces token occurrences.\n"
1179 " :type value: str\n");
1180static PyObject *pygpu_shader_info_define(BPyGPUShaderCreateInfo *self, PyObject *args)
1181{
1182 const char *name;
1183 const char *value = nullptr;
1184
1185 if (!PyArg_ParseTuple(args, "s|s:define", &name, &value)) {
1186 return nullptr;
1187 }
1188
1189#ifdef USE_GPU_PY_REFERENCES
1190 PyList_Append(self->references, PyTuple_GET_ITEM(args, 0)); /* name */
1191 if (value) {
1192 PyList_Append(self->references, PyTuple_GET_ITEM(args, 1)); /* value */
1193 }
1194#endif
1195
1196 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1197 if (value) {
1198 info->define(name, value);
1199 }
1200 else {
1201 info->define(name);
1202 }
1203
1204 Py_RETURN_NONE;
1205}
1206
1208 /* Wrap. */
1209 pygpu_shader_info_local_group_size_doc,
1210 ".. method:: local_group_size(x, y=1, z=1)\n"
1211 "\n"
1212 " Specify the local group size for compute shaders.\n"
1213 "\n"
1214 " :arg x: The local group size in the x dimension.\n"
1215 " :type x: int\n"
1216 " :arg y: The local group size in the y dimension. Optional. Defaults to 1.\n"
1217 " :type y: int\n"
1218 " :arg z: The local group size in the z dimension. Optional. Defaults to 1.\n"
1219 " :type z: int\n");
1221{
1222 int x = -1, y = 1, z = 1;
1223
1224 if (!PyArg_ParseTuple(args, "i|ii:local_group_size", &x, &y, &z)) {
1225 return nullptr;
1226 }
1227
1228 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(self->info);
1229 info->local_group_size(x, y, z);
1230
1231 Py_RETURN_NONE;
1232}
1233
1234static PyMethodDef pygpu_shader_info__tp_methods[] = {
1235 {"vertex_in",
1236 (PyCFunction)pygpu_shader_info_vertex_in,
1237 METH_VARARGS,
1238 pygpu_shader_info_vertex_in_doc},
1239 {"vertex_out",
1240 (PyCFunction)pygpu_shader_info_vertex_out,
1241 METH_O,
1242 pygpu_shader_info_vertex_out_doc},
1243 {"depth_write",
1244 (PyCFunction)(void *)pygpu_shader_info_depth_write,
1245 METH_O,
1246 pygpu_shader_info_depth_write_doc},
1247 {"fragment_out",
1248 (PyCFunction)(void *)pygpu_shader_info_fragment_out,
1249 METH_VARARGS | METH_KEYWORDS,
1250 pygpu_shader_info_fragment_out_doc},
1251 {"uniform_buf",
1252 (PyCFunction)(void *)pygpu_shader_info_uniform_buf,
1253 METH_VARARGS,
1254 pygpu_shader_info_uniform_buf_doc},
1255#ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
1256 {"image",
1257 (PyCFunction)(void *)pygpu_shader_info_image,
1258 METH_VARARGS | METH_KEYWORDS,
1259 pygpu_shader_info_image_doc},
1260#endif
1261 {"sampler",
1262 (PyCFunction)pygpu_shader_info_sampler,
1263 METH_VARARGS,
1264 pygpu_shader_info_sampler_doc},
1265 {"push_constant",
1266 (PyCFunction)(void *)pygpu_shader_info_push_constant,
1267 METH_VARARGS | METH_KEYWORDS,
1268 pygpu_shader_info_push_constant_doc},
1269 {"vertex_source",
1271 METH_O,
1272 pygpu_shader_info_vertex_source_doc},
1273 {"fragment_source",
1275 METH_O,
1276 pygpu_shader_info_fragment_source_doc},
1277 {"compute_source",
1279 METH_O,
1280 pygpu_shader_info_compute_source_doc},
1281 {"typedef_source",
1283 METH_O,
1284 pygpu_shader_info_typedef_source_doc},
1285 {"define", (PyCFunction)pygpu_shader_info_define, METH_VARARGS, pygpu_shader_info_define_doc},
1286 {"local_group_size",
1288 METH_VARARGS,
1289 pygpu_shader_info_local_group_size_doc},
1290 {nullptr, nullptr, 0, nullptr},
1291};
1292
1294
1295/* -------------------------------------------------------------------- */
1298
1299static PyObject *pygpu_shader_info__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds)
1300{
1301 if (PyTuple_Size(args) || kwds) {
1302 PyErr_SetString(PyExc_TypeError, "no args or keywords are expected");
1303 return nullptr;
1304 }
1305
1306 ShaderCreateInfo *info = new ShaderCreateInfo("pyGPU_Shader");
1307 GPUShaderCreateInfo *shader_info = reinterpret_cast<GPUShaderCreateInfo *>(info);
1308
1309 return BPyGPUShaderCreateInfo_CreatePyObject(shader_info);
1310}
1311
1312#ifdef USE_GPU_PY_REFERENCES
1313
1314static int pygpu_shader_info__tp_traverse(PyObject *self, visitproc visit, void *arg)
1315{
1316 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1317 Py_VISIT(py_info->vertex_source);
1318 Py_VISIT(py_info->fragment_source);
1319 Py_VISIT(py_info->compute_source);
1320 Py_VISIT(py_info->references);
1321 return 0;
1322}
1323
1325{
1326 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1327 Py_CLEAR(py_info->vertex_source);
1328 Py_CLEAR(py_info->fragment_source);
1329 Py_CLEAR(py_info->compute_source);
1330 Py_CLEAR(py_info->references);
1331 return 0;
1332}
1333
1334#endif
1335
1337{
1338 BPyGPUShaderCreateInfo *py_info = reinterpret_cast<BPyGPUShaderCreateInfo *>(self);
1339 ShaderCreateInfo *info = reinterpret_cast<ShaderCreateInfo *>(py_info->info);
1340 delete info;
1341
1342#ifdef USE_GPU_PY_REFERENCES
1343 PyObject_GC_UnTrack(self);
1344 if (py_info->references || py_info->vertex_source || py_info->fragment_source) {
1346 Py_XDECREF(py_info->vertex_source);
1347 Py_XDECREF(py_info->fragment_source);
1348 Py_XDECREF(py_info->compute_source);
1349 Py_XDECREF(py_info->references);
1350 }
1351
1352#endif
1353
1354 Py_TYPE(self)->tp_free(self);
1355}
1356
1358 /* Wrap. */
1359 pygpu_shader_info__tp_doc,
1360 ".. class:: GPUShaderCreateInfo()\n"
1361 "\n"
1362 " Stores and describes types and variables that are used in shader sources.\n");
1363
1365 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1366 /*tp_name*/ "GPUShaderCreateInfo",
1367 /*tp_basicsize*/ sizeof(BPyGPUShaderCreateInfo),
1368 /*tp_itemsize*/ 0,
1369 /*tp_dealloc*/ pygpu_shader_info__tp_dealloc,
1370 /*tp_vectorcall_offset*/ 0,
1371 /*tp_getattr*/ nullptr,
1372 /*tp_setattr*/ nullptr,
1373 /*tp_compare*/ nullptr,
1374 /*tp_repr*/ nullptr,
1375 /*tp_as_number*/ nullptr,
1376 /*tp_as_sequence*/ nullptr,
1377 /*tp_as_mapping*/ nullptr,
1378 /*tp_hash*/ nullptr,
1379 /*tp_call*/ nullptr,
1380 /*tp_str*/ nullptr,
1381 /*tp_getattro*/ nullptr,
1382 /*tp_setattro*/ nullptr,
1383 /*tp_as_buffer*/ nullptr,
1385 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1386#else
1387 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
1388#endif
1389 /*tp_doc*/ pygpu_shader_info__tp_doc,
1391 /*tp_traverse*/ pygpu_shader_info__tp_traverse,
1392#else
1393 /*tp_traverse*/ nullptr,
1394#endif
1396 /*tp_clear*/ pygpu_shader_info__tp_clear,
1397#else
1398 /*tp_clear*/ nullptr,
1399#endif
1400 /*tp_richcompare*/ nullptr,
1401 /*tp_weaklistoffset*/ 0,
1402 /*tp_iter*/ nullptr,
1403 /*tp_iternext*/ nullptr,
1404 /*tp_methods*/ pygpu_shader_info__tp_methods,
1405 /*tp_members*/ nullptr,
1406 /*tp_getset*/ nullptr,
1407 /*tp_base*/ nullptr,
1408 /*tp_dict*/ nullptr,
1409 /*tp_descr_get*/ nullptr,
1410 /*tp_descr_set*/ nullptr,
1411 /*tp_dictoffset*/ 0,
1412 /*tp_init*/ nullptr,
1413 /*tp_alloc*/ nullptr,
1414 /*tp_new*/ pygpu_shader_info__tp_new,
1415 /*tp_free*/ nullptr,
1416 /*tp_is_gc*/ nullptr,
1417 /*tp_bases*/ nullptr,
1418 /*tp_mro*/ nullptr,
1419 /*tp_cache*/ nullptr,
1420 /*tp_subclasses*/ nullptr,
1421 /*tp_weaklist*/ nullptr,
1422 /*tp_del*/ nullptr,
1423 /*tp_version_tag*/ 0,
1424 /*tp_finalize*/ nullptr,
1425 /*tp_vectorcall*/ nullptr,
1426};
1427
1429
1430/* -------------------------------------------------------------------- */
1433
1435{
1437
1438#ifdef USE_GPU_PY_REFERENCES
1440 self->references = PyList_New(0);
1441#else
1443#endif
1444
1445 self->interface = interface;
1446
1447 return (PyObject *)self;
1448}
1449
1450PyObject *BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info)
1451{
1453
1454#ifdef USE_GPU_PY_REFERENCES
1456 self->vertex_source = nullptr;
1457 self->fragment_source = nullptr;
1458 self->compute_source = nullptr;
1459 self->typedef_source = nullptr;
1460 self->references = PyList_New(0);
1461#else
1463#endif
1464
1465 self->info = info;
1466 self->constants_total_size = 0;
1467
1468 return (PyObject *)self;
1469}
1470
#define BLI_assert(a)
Definition BLI_assert.h:46
KDTree *BLI_kdtree_nd_ new(unsigned int nodes_len_capacity)
Definition kdtree_impl.h:97
#define STRINGIFY(x)
eGPUTextureFormat
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 interface
#define printf(...)
#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[]
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.
#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 & compute_source(StringRefNull filename)
Self & fragment_source(StringRefNull filename)
Self & vertex_in(int slot, Type type, StringRefNull name)
Self & image(int slot, eGPUTextureFormat format, Qualifier qualifiers, ImageReadWriteType type, StringRefNull name, Frequency freq=Frequency::PASS)
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 & 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="")