diff options
Diffstat (limited to 'source/blender/python/gpu/gpu_py_shader.c')
-rw-r--r-- | source/blender/python/gpu/gpu_py_shader.c | 231 |
1 files changed, 146 insertions, 85 deletions
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 101b9f8e4c6..a57b00e671e 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -16,6 +16,7 @@ #include "GPU_uniform_buffer.h" #include "../generic/py_capi_utils.h" +#include "../generic/python_utildefines.h" #include "../mathutils/mathutils.h" #include "gpu_py.h" @@ -30,52 +31,40 @@ * \{ */ #define PYDOC_BUILTIN_SHADER_DESCRIPTION \ - "``2D_FLAT_COLOR``\n" \ + "``FLAT_COLOR``\n" \ " :Attributes: vec3 pos, vec4 color\n" \ " :Uniforms: none\n" \ - "``2D_IMAGE``\n" \ + "``IMAGE``\n" \ " :Attributes: vec3 pos, vec2 texCoord\n" \ " :Uniforms: sampler2D image\n" \ - "``2D_SMOOTH_COLOR``\n" \ - " :Attributes: vec3 pos, vec4 color\n" \ - " :Uniforms: none\n" \ - "``2D_UNIFORM_COLOR``\n" \ - " :Attributes: vec3 pos\n" \ - " :Uniforms: vec4 color\n" \ - "``3D_FLAT_COLOR``\n" \ - " :Attributes: vec3 pos, vec4 color\n" \ - " :Uniforms: none\n" \ - "``3D_IMAGE``\n" \ + "``IMAGE_COLOR``\n" \ " :Attributes: vec3 pos, vec2 texCoord\n" \ - " :Uniforms: sampler2D image\n" \ - "``3D_SMOOTH_COLOR``\n" \ + " :Uniforms: sampler2D image, vec4 color\n" \ + "``SMOOTH_COLOR``\n" \ " :Attributes: vec3 pos, vec4 color\n" \ " :Uniforms: none\n" \ - "``3D_UNIFORM_COLOR``\n" \ + "``UNIFORM_COLOR``\n" \ " :Attributes: vec3 pos\n" \ " :Uniforms: vec4 color\n" \ - "``3D_POLYLINE_FLAT_COLOR``\n" \ + "``POLYLINE_FLAT_COLOR``\n" \ " :Attributes: vec3 pos, vec4 color\n" \ " :Uniforms: vec2 viewportSize, float lineWidth\n" \ - "``3D_POLYLINE_SMOOTH_COLOR``\n" \ + "``POLYLINE_SMOOTH_COLOR``\n" \ " :Attributes: vec3 pos, vec4 color\n" \ " :Uniforms: vec2 viewportSize, float lineWidth\n" \ - "``3D_POLYLINE_UNIFORM_COLOR``\n" \ + "``POLYLINE_UNIFORM_COLOR``\n" \ " :Attributes: vec3 pos\n" \ " :Uniforms: vec2 viewportSize, float lineWidth\n" static const struct PyC_StringEnumItems pygpu_shader_builtin_items[] = { - {GPU_SHADER_2D_FLAT_COLOR, "2D_FLAT_COLOR"}, - {GPU_SHADER_2D_IMAGE, "2D_IMAGE"}, - {GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"}, - {GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"}, - {GPU_SHADER_3D_FLAT_COLOR, "3D_FLAT_COLOR"}, - {GPU_SHADER_3D_IMAGE, "3D_IMAGE"}, - {GPU_SHADER_3D_SMOOTH_COLOR, "3D_SMOOTH_COLOR"}, - {GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"}, - {GPU_SHADER_3D_POLYLINE_FLAT_COLOR, "3D_POLYLINE_FLAT_COLOR"}, - {GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR, "3D_POLYLINE_SMOOTH_COLOR"}, - {GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, "3D_POLYLINE_UNIFORM_COLOR"}, + {GPU_SHADER_3D_FLAT_COLOR, "FLAT_COLOR"}, + {GPU_SHADER_3D_IMAGE, "IMAGE"}, + {GPU_SHADER_3D_IMAGE_COLOR, "IMAGE_COLOR"}, + {GPU_SHADER_3D_SMOOTH_COLOR, "SMOOTH_COLOR"}, + {GPU_SHADER_3D_UNIFORM_COLOR, "UNIFORM_COLOR"}, + {GPU_SHADER_3D_POLYLINE_FLAT_COLOR, "POLYLINE_FLAT_COLOR"}, + {GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR, "POLYLINE_SMOOTH_COLOR"}, + {GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, "POLYLINE_UNIFORM_COLOR"}, {0, NULL}, }; @@ -174,7 +163,7 @@ PyDoc_STRVAR(pygpu_shader_uniform_from_name_doc, "\n" " Get uniform location by name.\n" "\n" - " :param name: Name of the uniform variable whose location is to be queried.\n" + " :arg name: Name of the uniform variable whose location is to be queried.\n" " :type name: str\n" " :return: Location of the uniform variable.\n" " :rtype: int\n"); @@ -195,16 +184,15 @@ static PyObject *pygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *ar return PyLong_FromLong(uniform); } -PyDoc_STRVAR( - pygpu_shader_uniform_block_from_name_doc, - ".. method:: uniform_block_from_name(name)\n" - "\n" - " Get uniform block location by name.\n" - "\n" - " :param name: Name of the uniform block variable whose location is to be queried.\n" - " :type name: str\n" - " :return: The location of the uniform block variable.\n" - " :rtype: int\n"); +PyDoc_STRVAR(pygpu_shader_uniform_block_from_name_doc, + ".. method:: uniform_block_from_name(name)\n" + "\n" + " Get uniform block location by name.\n" + "\n" + " :arg name: Name of the uniform block variable whose location is to be queried.\n" + " :type name: str\n" + " :return: The location of the uniform block variable.\n" + " :rtype: int\n"); static PyObject *pygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg) { const char *name = PyUnicode_AsUTF8(arg); @@ -256,11 +244,11 @@ PyDoc_STRVAR(pygpu_shader_uniform_vector_float_doc, "\n" " Set the buffer to fill the uniform.\n" "\n" - " :param location: Location of the uniform variable to be modified.\n" + " :arg location: Location of the uniform variable to be modified.\n" " :type location: int\n" - " :param buffer: The data that should be set. Can support the buffer protocol.\n" + " :arg buffer: The data that should be set. Can support the buffer protocol.\n" " :type buffer: sequence of floats\n" - " :param length: Size of the uniform data type:\n\n" + " :arg length: Size of the uniform data type:\n\n" " - 1: float\n" " - 2: vec2 or float[2]\n" " - 3: vec3 or float[3]\n" @@ -268,7 +256,7 @@ PyDoc_STRVAR(pygpu_shader_uniform_vector_float_doc, " - 9: mat3\n" " - 16: mat4\n" " :type length: int\n" - " :param count: Specifies the number of elements, vector or matrices that are to " + " :arg count: Specifies the number of elements, vector or matrices that are to " "be modified.\n" " :type count: int\n"); static PyObject *pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args) @@ -282,6 +270,7 @@ static PyObject *pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject return NULL; } + GPU_shader_bind(self->shader); GPU_shader_uniform_vector(self->shader, location, length, count, pybuffer.buf); PyBuffer_Release(&pybuffer); @@ -304,6 +293,7 @@ static PyObject *pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *a return NULL; } + GPU_shader_bind(self->shader); GPU_shader_uniform_vector_int(self->shader, location, length, count, pybuffer.buf); PyBuffer_Release(&pybuffer); @@ -312,14 +302,14 @@ static PyObject *pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *a } PyDoc_STRVAR(pygpu_shader_uniform_bool_doc, - ".. method:: uniform_bool(name, seq)\n" + ".. method:: uniform_bool(name, value)\n" "\n" " Specify the value of a uniform variable for the current program object.\n" "\n" - " :param name: Name of the uniform variable whose value is to be changed.\n" + " :arg name: Name of the uniform variable whose value is to be changed.\n" " :type name: str\n" - " :param seq: Value that will be used to update the specified uniform variable.\n" - " :type seq: sequence of bools\n"); + " :arg value: Value that will be used to update the specified uniform variable.\n" + " :type value: bool or sequence of bools\n"); static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) { const char *error_prefix = "GPUShader.uniform_bool"; @@ -335,15 +325,14 @@ static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) int values[4]; int length; - int ret; - { + int ret = -1; + if (PySequence_Check(params.seq)) { PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix); if (seq_fast == NULL) { PyErr_Format(PyExc_TypeError, "%s: expected a sequence, got %s", error_prefix, Py_TYPE(params.seq)->tp_name); - ret = -1; } else { length = PySequence_Fast_GET_SIZE(seq_fast); @@ -352,7 +341,6 @@ static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) "%s: invalid sequence length. expected 1..4, got %d", error_prefix, length); - ret = -1; } else { ret = PyC_AsArray_FAST( @@ -361,6 +349,15 @@ static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) Py_DECREF(seq_fast); } } + else if (((values[0] = (int)PyLong_AsLong(params.seq)) != -1) && ELEM(values[0], 0, 1)) { + length = 1; + ret = 0; + } + else { + PyErr_Format( + PyExc_ValueError, "expected a bool or sequence, got %s", Py_TYPE(params.seq)->tp_name); + } + if (ret == -1) { return NULL; } @@ -371,6 +368,7 @@ static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) return NULL; } + GPU_shader_bind(self->shader); GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); Py_RETURN_NONE; @@ -381,9 +379,9 @@ PyDoc_STRVAR(pygpu_shader_uniform_float_doc, "\n" " Specify the value of a uniform variable for the current program object.\n" "\n" - " :param name: Name of the uniform variable whose value is to be changed.\n" + " :arg name: Name of the uniform variable whose value is to be changed.\n" " :type name: str\n" - " :param value: Value that will be used to update the specified uniform variable.\n" + " :arg value: Value that will be used to update the specified uniform variable.\n" " :type value: single number or sequence of numbers\n"); static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) { @@ -440,6 +438,7 @@ static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) return NULL; } + GPU_shader_bind(self->shader); GPU_shader_uniform_vector(self->shader, location, length, 1, values); Py_RETURN_NONE; @@ -450,9 +449,9 @@ PyDoc_STRVAR(pygpu_shader_uniform_int_doc, "\n" " Specify the value of a uniform variable for the current program object.\n" "\n" - " :param name: name of the uniform variable whose value is to be changed.\n" + " :arg name: name of the uniform variable whose value is to be changed.\n" " :type name: str\n" - " :param seq: Value that will be used to update the specified uniform variable.\n" + " :arg seq: Value that will be used to update the specified uniform variable.\n" " :type seq: sequence of numbers\n"); static PyObject *pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) { @@ -511,6 +510,7 @@ static PyObject *pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) return NULL; } + GPU_shader_bind(self->shader); GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); Py_RETURN_NONE; @@ -521,9 +521,9 @@ PyDoc_STRVAR(pygpu_shader_uniform_sampler_doc, "\n" " Specify the value of a texture uniform variable for the current GPUShader.\n" "\n" - " :param name: name of the uniform variable whose texture is to be specified.\n" + " :arg name: name of the uniform variable whose texture is to be specified.\n" " :type name: str\n" - " :param texture: Texture to attach.\n" + " :arg texture: Texture to attach.\n" " :type texture: :class:`gpu.types.GPUTexture`\n"); static PyObject *pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args) { @@ -534,6 +534,7 @@ static PyObject *pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args return NULL; } + GPU_shader_bind(self->shader); int slot = GPU_shader_get_texture_binding(self->shader, name); GPU_texture_bind(py_texture->tex, slot); GPU_shader_uniform_1i(self->shader, name, slot); @@ -547,9 +548,9 @@ PyDoc_STRVAR( "\n" " Specify the value of an uniform buffer object variable for the current GPUShader.\n" "\n" - " :param name: name of the uniform variable whose UBO is to be specified.\n" + " :arg name: name of the uniform variable whose UBO is to be specified.\n" " :type name: str\n" - " :param ubo: Uniform Buffer to attach.\n" + " :arg ubo: Uniform Buffer to attach.\n" " :type texture: :class:`gpu.types.GPUUniformBuf`\n"); static PyObject *pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args) { @@ -568,21 +569,21 @@ static PyObject *pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args) return NULL; } + GPU_shader_bind(self->shader); GPU_uniformbuf_bind(py_ubo->ubo, binding); Py_RETURN_NONE; } -PyDoc_STRVAR( - pygpu_shader_attr_from_name_doc, - ".. method:: attr_from_name(name)\n" - "\n" - " Get attribute location by name.\n" - "\n" - " :param name: The name of the attribute variable whose location is to be queried.\n" - " :type name: str\n" - " :return: The location of an attribute variable.\n" - " :rtype: int\n"); +PyDoc_STRVAR(pygpu_shader_attr_from_name_doc, + ".. method:: attr_from_name(name)\n" + "\n" + " Get attribute location by name.\n" + "\n" + " :arg name: The name of the attribute variable whose location is to be queried.\n" + " :type name: str\n" + " :return: The location of an attribute variable.\n" + " :rtype: int\n"); static PyObject *pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) { const char *name = PyUnicode_AsUTF8(arg); @@ -600,20 +601,58 @@ static PyObject *pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) return PyLong_FromLong(attr); } -PyDoc_STRVAR(pygpu_shader_calc_format_doc, - ".. method:: calc_format()\n" +PyDoc_STRVAR(pygpu_shader_format_calc_doc, + ".. method:: format_calc()\n" "\n" " Build a new format based on the attributes of the shader.\n" "\n" " :return: vertex attribute format for the shader\n" " :rtype: :class:`gpu.types.GPUVertFormat`\n"); -static PyObject *pygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg)) +static PyObject *pygpu_shader_format_calc(BPyGPUShader *self, PyObject *UNUSED(arg)) { BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL); GPU_vertformat_from_shader(&ret->fmt, self->shader); return (PyObject *)ret; } +PyDoc_STRVAR( + pygpu_shader_attrs_info_get_doc, + ".. method:: attrs_info_get()\n" + "\n" + " Information about the attributes used in the Shader.\n" + "\n" + " :return: tuples containing information about the attributes in order (name, type)\n" + " :rtype: tuple\n"); +static PyObject *pygpu_shader_attrs_info_get(BPyGPUShader *self, PyObject *UNUSED(arg)) +{ + uint attr_len = GPU_shader_get_attribute_len(self->shader); + int location_test = 0, attrs_added = 0; + ; + PyObject *ret = PyTuple_New(attr_len); + while (attrs_added < attr_len) { + char name[256]; + int type; + if (!GPU_shader_get_attribute_info(self->shader, location_test++, name, &type)) { + continue; + } + PyObject *py_type; + if (type != -1) { + py_type = PyUnicode_InternFromString( + PyC_StringEnum_FindIDFromValue(pygpu_attrtype_items, type)); + } + else { + py_type = Py_None; + Py_INCREF(py_type); + } + + PyObject *attr_info = PyTuple_New(2); + PyTuple_SET_ITEMS(attr_info, PyUnicode_FromString(name), py_type); + PyTuple_SetItem(ret, attrs_added, attr_info); + attrs_added++; + } + return ret; +} + static struct PyMethodDef pygpu_shader__tp_methods[] = { {"bind", (PyCFunction)pygpu_shader_bind, METH_NOARGS, pygpu_shader_bind_doc}, {"uniform_from_name", @@ -657,9 +696,13 @@ static struct PyMethodDef pygpu_shader__tp_methods[] = { METH_O, pygpu_shader_attr_from_name_doc}, {"format_calc", - (PyCFunction)pygpu_shader_calc_format, + (PyCFunction)pygpu_shader_format_calc, METH_NOARGS, - pygpu_shader_calc_format_doc}, + pygpu_shader_format_calc_doc}, + {"attrs_info_get", + (PyCFunction)pygpu_shader_attrs_info_get, + METH_NOARGS, + pygpu_shader_attrs_info_get_doc}, {NULL, NULL, 0, NULL}, }; @@ -712,17 +755,17 @@ PyDoc_STRVAR( " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``\n" " to transform the output sRGB colors to the frame-buffer color-space.\n" "\n" - " :param vertexcode: Vertex shader code.\n" + " :arg vertexcode: Vertex shader code.\n" " :type vertexcode: str\n" - " :param fragcode: Fragment shader code.\n" + " :arg fragcode: Fragment shader code.\n" " :type value: str\n" - " :param geocode: Geometry shader code.\n" + " :arg geocode: Geometry shader code.\n" " :type value: str\n" - " :param libcode: Code with functions and presets to be shared between shaders.\n" + " :arg libcode: Code with functions and presets to be shared between shaders.\n" " :type value: str\n" - " :param defines: Preprocessor directives.\n" + " :arg defines: Preprocessor directives.\n" " :type value: str\n" - " :param name: Name of shader code, for debugging purposes.\n" + " :arg name: Name of shader code, for debugging purposes.\n" " :type value: str\n"); PyTypeObject BPyGPUShader_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUShader", @@ -741,6 +784,24 @@ PyTypeObject BPyGPUShader_Type = { /** \name gpu.shader Module API * \{ */ +static int pyc_parse_buitinshader_w_backward_compatibility(PyObject *o, void *p) +{ + struct PyC_StringEnum *e = p; + const char *value = PyUnicode_AsUTF8(o); + if (value && ELEM(value[0], u'2', u'3')) { + /* Deprecated enums that start with "3D_" or "2D_". */ + value += 3; + for (int i = 0; e->items[i].id; i++) { + if (STREQ(e->items[i].id, value)) { + e->value_found = e->items[i].value; + return 1; + } + } + } + + return PyC_ParseStringEnum(o, p); +} + PyDoc_STRVAR(pygpu_shader_unbind_doc, ".. function:: unbind()\n" "\n" @@ -763,9 +824,9 @@ PyDoc_STRVAR( "``CLIPPED`` value to the config parameter. Note that in this case you also need to " "manually set the value of ``mat4 ModelMatrix``.\n" "\n" - " :param shader_name: One of the builtin shader names.\n" + " :arg shader_name: One of the builtin shader names.\n" " :type shader_name: str\n" - " :param config: One of these types of shader configuration:\n" + " :arg config: One of these types of shader configuration:\n" "\n" " - ``DEFAULT``\n" " - ``CLIPPED``\n" @@ -791,7 +852,7 @@ static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, - PyC_ParseStringEnum, + pyc_parse_buitinshader_w_backward_compatibility, &pygpu_bultinshader, PyC_ParseStringEnum, &pygpu_config)) { @@ -809,7 +870,7 @@ PyDoc_STRVAR(pygpu_shader_create_from_info_doc, "\n" " Create shader from a GPUShaderCreateInfo.\n" "\n" - " :param shader_info: GPUShaderCreateInfo\n" + " :arg shader_info: GPUShaderCreateInfo\n" " :type shader_info: :class:`bpy.types.GPUShaderCreateInfo`\n" " :return: Shader object corresponding to the given name.\n" " :rtype: :class:`bpy.types.GPUShader`\n"); |