Python GPU: GPUBatch and GPUShader refactor.
The changes are: - The shader now is passed as a parameter of the batch `draw` method (batch.draw(shader)). Since the batch always has to set a shader before drawing; - The batch methods to specify a value to a uniform have been removed. Uniforms are parameters of the program (here called shader). If you change a uniform, it changes in all batchs that use the same program; - New methods were added to set uniforms by the shader; - The `batch.program_set_builtin` was removed. It is a duplicate of `program_set` but without a shader object. We need the shader object to configure the uniform; Differential Revision: https://developer.blender.org/D3752
This commit is contained in:
		@@ -75,6 +75,18 @@ static int bpygpu_pyLong_as_shader_enum(PyObject *o)
 | 
			
		||||
	return (int)id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bpygpu_uniform_location_get(const GPUShaderInterface *shaderface, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shaderface, name);
 | 
			
		||||
 | 
			
		||||
	if (uniform == NULL) {
 | 
			
		||||
		PyErr_SetString(PyExc_ValueError, "uniform not found");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return uniform->location;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -324,57 +336,200 @@ static PyObject *bpygpu_shader_uniform_vector_int(
 | 
			
		||||
	Py_RETURN_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_uniform_float_doc,
 | 
			
		||||
	".. method:: uniform_float(location, value)\n"
 | 
			
		||||
	"\n"
 | 
			
		||||
	"   Set uniform value.\n"
 | 
			
		||||
	"\n"
 | 
			
		||||
	"   :param location: builtin identifier.\n"
 | 
			
		||||
	"   :type location: `int`\n"
 | 
			
		||||
	"   :param value: uniform value.\n"
 | 
			
		||||
	"   :type value: `float`\n"
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_uniform_bool_doc,
 | 
			
		||||
".. method:: uniform_bool(name, seq)\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   Specify the value of a uniform variable for the current program object.\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   :param name: name of the uniform variable whose location is to be queried.\n"
 | 
			
		||||
"   :type name: `str`\n"
 | 
			
		||||
"   :param seq: values that will be used to update the specified uniform variable.\n"
 | 
			
		||||
"   :type seq: sequence of bools\n"
 | 
			
		||||
);
 | 
			
		||||
static PyObject *bpygpu_shader_uniform_float(
 | 
			
		||||
	BPyGPUShader *self, PyObject *args)
 | 
			
		||||
static PyObject *bpygpu_shader_uniform_bool(
 | 
			
		||||
        BPyGPUShader *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
	int location;
 | 
			
		||||
	float value;
 | 
			
		||||
	const char *error_prefix = "GPUShader.uniform_bool";
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		const char *id;
 | 
			
		||||
		PyObject *seq;
 | 
			
		||||
	} params;
 | 
			
		||||
 | 
			
		||||
	if (!PyArg_ParseTuple(
 | 
			
		||||
	            args, "if:GPUShader.uniform_float",
 | 
			
		||||
	            &location, &value))
 | 
			
		||||
	        args, "sO:GPUShader.uniform_bool",
 | 
			
		||||
	        ¶ms.id, ¶ms.seq))
 | 
			
		||||
	{
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GPU_shader_uniform_float(self->shader, location, value);
 | 
			
		||||
	int values[4];
 | 
			
		||||
	int length;
 | 
			
		||||
	int ret;
 | 
			
		||||
	{
 | 
			
		||||
		PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
 | 
			
		||||
		if (seq_fast == NULL) {
 | 
			
		||||
			ret = -1;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			length = PySequence_Fast_GET_SIZE(params.seq);
 | 
			
		||||
			if (length == 0 || length > 4) {
 | 
			
		||||
				PyErr_Format(PyExc_TypeError,
 | 
			
		||||
				             "%s: invalid sequence length. expected 1..4, got %d",
 | 
			
		||||
				             error_prefix, length);
 | 
			
		||||
				ret = -1;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ret = PyC_AsArray_FAST(
 | 
			
		||||
				        values, seq_fast, length, &PyLong_Type,
 | 
			
		||||
				        false, error_prefix);
 | 
			
		||||
			}
 | 
			
		||||
			Py_DECREF(seq_fast);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (ret == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const int location = bpygpu_uniform_location_get(GPU_shader_get_interface(self->shader), params.id);
 | 
			
		||||
	if (location == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
 | 
			
		||||
 | 
			
		||||
	Py_RETURN_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_uniform_float_doc,
 | 
			
		||||
".. method:: uniform_float(name, seq)\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   Specify the value of a uniform variable for the current program object.\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   :param name: name of the uniform variable whose location is to be queried.\n"
 | 
			
		||||
"   :type name: `str`\n"
 | 
			
		||||
"   :param seq: values that will be used to update the specified uniform variable.\n"
 | 
			
		||||
"   :type seq: sequence of numbers\n"
 | 
			
		||||
);
 | 
			
		||||
static PyObject *bpygpu_shader_uniform_float(
 | 
			
		||||
        BPyGPUShader *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
	const char *error_prefix = "GPUShader.uniform_float";
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		const char *id;
 | 
			
		||||
		PyObject *seq;
 | 
			
		||||
	} params;
 | 
			
		||||
 | 
			
		||||
	if (!PyArg_ParseTuple(
 | 
			
		||||
	        args, "sO:GPUShader.uniform_float",
 | 
			
		||||
	        ¶ms.id, ¶ms.seq))
 | 
			
		||||
	{
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	float values[16];
 | 
			
		||||
	int length;
 | 
			
		||||
	int ret;
 | 
			
		||||
	{
 | 
			
		||||
		PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
 | 
			
		||||
		if (seq_fast == NULL) {
 | 
			
		||||
			ret = -1;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			length = PySequence_Fast_GET_SIZE(params.seq);
 | 
			
		||||
			if ((length == 0) || (length > 16) ||
 | 
			
		||||
			    (4 < length && length < 9) ||
 | 
			
		||||
			    (9 < length && length < 16))
 | 
			
		||||
			{
 | 
			
		||||
				PyErr_Format(PyExc_TypeError,
 | 
			
		||||
				             "%s: invalid sequence length. expected 1..4, 9 or 16, got %d",
 | 
			
		||||
				             error_prefix, length);
 | 
			
		||||
				ret = -1;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ret = PyC_AsArray_FAST(
 | 
			
		||||
				        values, seq_fast, length, &PyFloat_Type,
 | 
			
		||||
				        false, error_prefix);
 | 
			
		||||
			}
 | 
			
		||||
			Py_DECREF(seq_fast);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (ret == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const int location = bpygpu_uniform_location_get(GPU_shader_get_interface(self->shader), params.id);
 | 
			
		||||
	if (location == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GPU_shader_uniform_vector(self->shader, location, length, 1, values);
 | 
			
		||||
 | 
			
		||||
	Py_RETURN_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_uniform_int_doc,
 | 
			
		||||
".. method:: uniform_int(location, value)\n"
 | 
			
		||||
".. method:: uniform_int(name, seq)\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   Set uniform value.\n"
 | 
			
		||||
"   Specify the value of a uniform variable for the current program object.\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"   :param location: builtin identifier.\n"
 | 
			
		||||
"   :type location: `int`\n"
 | 
			
		||||
"   :param value: uniform value.\n"
 | 
			
		||||
"   :type value: `int`\n"
 | 
			
		||||
"   :param name: name of the uniform variable whose location is to be queried.\n"
 | 
			
		||||
"   :type name: `str`\n"
 | 
			
		||||
"   :param seq: values that will be used to update the specified uniform variable.\n"
 | 
			
		||||
"   :type seq: sequence of numbers\n"
 | 
			
		||||
);
 | 
			
		||||
static PyObject *bpygpu_shader_uniform_int(
 | 
			
		||||
        BPyGPUShader *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
	int location, value;
 | 
			
		||||
	const char *error_prefix = "GPUShader.uniform_int";
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		const char *id;
 | 
			
		||||
		PyObject *seq;
 | 
			
		||||
	} params;
 | 
			
		||||
 | 
			
		||||
	if (!PyArg_ParseTuple(
 | 
			
		||||
	        args, "ii:GPUShader.uniform_int",
 | 
			
		||||
	        &location, &value))
 | 
			
		||||
	        args, "sO:GPUShader.uniform_int",
 | 
			
		||||
	        ¶ms.id, ¶ms.seq))
 | 
			
		||||
	{
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GPU_shader_uniform_int(self->shader, location, value);
 | 
			
		||||
	int values[4];
 | 
			
		||||
	int length;
 | 
			
		||||
	int ret;
 | 
			
		||||
	{
 | 
			
		||||
		PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
 | 
			
		||||
		if (seq_fast == NULL) {
 | 
			
		||||
			ret = -1;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			length = PySequence_Fast_GET_SIZE(params.seq);
 | 
			
		||||
			if (length == 0 || length > 4) {
 | 
			
		||||
				PyErr_Format(PyExc_TypeError,
 | 
			
		||||
				             "%s: invalid sequence length. expected 1..4, got %d",
 | 
			
		||||
				             error_prefix, length);
 | 
			
		||||
				ret = -1;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ret = PyC_AsArray_FAST(
 | 
			
		||||
				        values, seq_fast, length, &PyLong_Type,
 | 
			
		||||
				        false, error_prefix);
 | 
			
		||||
			}
 | 
			
		||||
			Py_DECREF(seq_fast);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (ret == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const int location = bpygpu_uniform_location_get(GPU_shader_get_interface(self->shader), params.id);
 | 
			
		||||
	if (location == -1) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
 | 
			
		||||
 | 
			
		||||
	Py_RETURN_NONE;
 | 
			
		||||
}
 | 
			
		||||
@@ -408,14 +563,6 @@ static PyObject *bpygpu_shader_attr_from_name(
 | 
			
		||||
	return PyLong_FromLong(attrib);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_program_doc,
 | 
			
		||||
"The name of the program object for use by the OpenGL API (read-only).\n\n:type: int"
 | 
			
		||||
);
 | 
			
		||||
static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
 | 
			
		||||
{
 | 
			
		||||
	return PyLong_FromLong(GPU_shader_get_program(self->shader));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct PyMethodDef bpygpu_shader_methods[] = {
 | 
			
		||||
	{"bind", (PyCFunction)bpygpu_shader_bind,
 | 
			
		||||
	 METH_NOARGS, bpygpu_shader_bind_doc},
 | 
			
		||||
@@ -437,6 +584,9 @@ static struct PyMethodDef bpygpu_shader_methods[] = {
 | 
			
		||||
	{"uniform_vector_int",
 | 
			
		||||
	 (PyCFunction)bpygpu_shader_uniform_vector_int,
 | 
			
		||||
	 METH_VARARGS, bpygpu_shader_uniform_vector_int_doc},
 | 
			
		||||
	{"uniform_bool",
 | 
			
		||||
	 (PyCFunction)bpygpu_shader_uniform_bool,
 | 
			
		||||
	 METH_VARARGS, bpygpu_shader_uniform_bool_doc},
 | 
			
		||||
	{"uniform_float",
 | 
			
		||||
	 (PyCFunction)bpygpu_shader_uniform_float,
 | 
			
		||||
	 METH_VARARGS, bpygpu_shader_uniform_float_doc},
 | 
			
		||||
@@ -449,6 +599,14 @@ static struct PyMethodDef bpygpu_shader_methods[] = {
 | 
			
		||||
	{NULL, NULL, 0, NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(bpygpu_shader_program_doc,
 | 
			
		||||
"The name of the program object for use by the OpenGL API (read-only).\n\n:type: int"
 | 
			
		||||
);
 | 
			
		||||
static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
 | 
			
		||||
{
 | 
			
		||||
	return PyLong_FromLong(GPU_shader_get_program(self->shader));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyGetSetDef bpygpu_shader_getseters[] = {
 | 
			
		||||
	{"program",
 | 
			
		||||
	 (getter)bpygpu_shader_program_get, (setter)NULL,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user