Blender V5.0
gpu_py_compute.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 "GPU_capabilities.hh"
15#include "GPU_compute.hh"
16#include "GPU_state.hh"
17
18#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
19
20#include "gpu_py.hh"
21#include "gpu_py_compute.hh" /* own include */
22#include "gpu_py_shader.hh"
23
25 /* Wrap. */
26 pygpu_compute_dispatch_doc,
27 ".. function:: dispatch(shader, groups_x_len, groups_y_len, groups_z_len)\n"
28 "\n"
29 " Dispatches GPU compute.\n"
30 "\n"
31 " :arg shader: The shader that you want to dispatch.\n"
32 " :type shader: :class:`gpu.types.GPUShader`\n"
33 " :arg groups_x_len: Int for group x length:\n"
34 " :type groups_x_len: int\n"
35 " :arg groups_y_len: Int for group y length:\n"
36 " :type groups_y_len: int\n"
37 " :arg groups_z_len: Int for group z length:\n"
38 " :type groups_z_len: int\n"
39 " :return: Shader object.\n"
40 " :rtype: :class:`gpu.types.GPUShader`\n");
41static PyObject *pygpu_compute_dispatch(PyObject * /*self*/, PyObject *args, PyObject *kwds)
42{
44
45 BPyGPUShader *py_shader;
46 int groups_x_len;
47 int groups_y_len;
48 int groups_z_len;
49
50 static const char *_keywords[] = {
51 "shader", "groups_x_len", "groups_y_len", "groups_z_len", nullptr};
52 static _PyArg_Parser _parser = {
54 "O" /* `shader` */
55 "i" /* `groups_x_len` */
56 "i" /* `groups_y_len` */
57 "i" /* `groups_z_len` */
58 ":dispatch",
59 _keywords,
60 nullptr,
61 };
62 if (_PyArg_ParseTupleAndKeywordsFast(
63 args, kwds, &_parser, &py_shader, &groups_x_len, &groups_y_len, &groups_z_len))
64 {
65 if (!BPyGPUShader_Check(py_shader)) {
66 PyErr_Format(PyExc_TypeError, "Expected a GPUShader, got %s", Py_TYPE(py_shader)->tp_name);
67 return nullptr;
68 }
69
70 /* Check that groups do not exceed #GPU_max_work_group_count(). */
71 const int max_work_group_count_x = GPU_max_work_group_count(0);
72 const int max_work_group_count_y = GPU_max_work_group_count(1);
73 const int max_work_group_count_z = GPU_max_work_group_count(2);
74
75 /* Report back to the user both the requested and the maximum supported value. */
76 if (groups_x_len > GPU_max_work_group_count(0)) {
77 PyErr_Format(PyExc_ValueError,
78 "groups_x_len (%d) exceeds maximum supported value (max work group count: %d)",
79 groups_x_len,
80 max_work_group_count_x);
81 return nullptr;
82 }
83 if (groups_y_len > GPU_max_work_group_count(1)) {
84 PyErr_Format(PyExc_ValueError,
85 "groups_y_len (%d) exceeds maximum supported value (max work group count: %d)",
86 groups_y_len,
87 max_work_group_count_y);
88 return nullptr;
89 }
90 if (groups_z_len > GPU_max_work_group_count(2)) {
91 PyErr_Format(PyExc_ValueError,
92 "groups_z_len (%d) exceeds maximum supported value (max work group count: %d)",
93 groups_z_len,
94 max_work_group_count_z);
95 return nullptr;
96 }
97
98 blender::gpu::Shader *shader = py_shader->shader;
99 GPU_compute_dispatch(shader, groups_x_len, groups_y_len, groups_z_len);
101 }
102 Py_RETURN_NONE;
103}
104
105/* -------------------------------------------------------------------- */
108
109#ifdef __GNUC__
110# ifdef __clang__
111# pragma clang diagnostic push
112# pragma clang diagnostic ignored "-Wcast-function-type"
113# else
114# pragma GCC diagnostic push
115# pragma GCC diagnostic ignored "-Wcast-function-type"
116# endif
117#endif
118
119static PyMethodDef pygpu_compute__tp_methods[] = {
120 {"dispatch",
121 (PyCFunction)pygpu_compute_dispatch,
122 METH_VARARGS | METH_KEYWORDS,
123 pygpu_compute_dispatch_doc},
124 {nullptr, nullptr, 0, nullptr},
125};
126
127#ifdef __GNUC__
128# ifdef __clang__
129# pragma clang diagnostic pop
130# else
131# pragma GCC diagnostic pop
132# endif
133#endif
134
136 /* Wrap. */
137 pygpu_compute__tp_doc,
138 "This module provides access to the global GPU compute functions.");
139static PyModuleDef pygpu_compute_module_def = {
140 /*m_base*/ PyModuleDef_HEAD_INIT,
141 /*m_name*/ "gpu.compute",
142 /*m_doc*/ pygpu_compute__tp_doc,
143 /*m_size*/ 0,
144 /*m_methods*/ pygpu_compute__tp_methods,
145 /*m_slots*/ nullptr,
146 /*m_traverse*/ nullptr,
147 /*m_clear*/ nullptr,
148 /*m_free*/ nullptr,
149};
150
152{
153 PyObject *submodule;
154
155 submodule = PyModule_Create(&pygpu_compute_module_def);
156
157 return submodule;
158}
159
int GPU_max_work_group_count(int index)
void GPU_compute_dispatch(blender::gpu::Shader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
@ GPU_BARRIER_TEXTURE_FETCH
Definition GPU_state.hh:37
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
Definition GPU_state.hh:35
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
Definition gpu_py.hh:20
PyDoc_STRVAR(pygpu_compute_dispatch_doc, ".. function:: dispatch(shader, groups_x_len, groups_y_len, groups_z_len)\n" "\n" " Dispatches GPU compute.\n" "\n" " :arg shader: The shader that you want to dispatch.\n" " :type shader: :class:`gpu.types.GPUShader`\n" " :arg groups_x_len: Int for group x length:\n" " :type groups_x_len: int\n" " :arg groups_y_len: Int for group y length:\n" " :type groups_y_len: int\n" " :arg groups_z_len: Int for group z length:\n" " :type groups_z_len: int\n" " :return: Shader object.\n" " :rtype: :class:`gpu.types.GPUShader`\n")
static PyMethodDef pygpu_compute__tp_methods[]
PyObject * bpygpu_compute_init()
static PyObject * pygpu_compute_dispatch(PyObject *, PyObject *args, PyObject *kwds)
static PyModuleDef pygpu_compute_module_def
#define BPyGPUShader_Check(v)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
PyObject_VAR_HEAD blender::gpu::Shader * shader