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:
parent
98a10fd7de
commit
ffa15f4b4a
|
@ -166,124 +166,32 @@ static PyObject *bpygpu_VertBatch_program_set(BPyGPUBatch *self, BPyGPUShader *p
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpygpu_VertBatch_program_set_builtin_doc,
|
||||
"TODO"
|
||||
);
|
||||
static PyObject *bpygpu_VertBatch_program_set_builtin(BPyGPUBatch *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
struct {
|
||||
const char *shader;
|
||||
} params;
|
||||
|
||||
static const char *_keywords[] = {"id", NULL};
|
||||
static _PyArg_Parser _parser = {"s:program_set_builtin", _keywords, 0};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kwds, &_parser,
|
||||
¶ms.shader))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GPUBuiltinShader shader;
|
||||
|
||||
#define MATCH_ID(id) \
|
||||
if (STREQ(params.shader, STRINGIFY(id))) { \
|
||||
shader = GPU_SHADER_##id; \
|
||||
goto success; \
|
||||
} ((void)0)
|
||||
|
||||
MATCH_ID(2D_FLAT_COLOR);
|
||||
MATCH_ID(2D_SMOOTH_COLOR);
|
||||
MATCH_ID(2D_UNIFORM_COLOR);
|
||||
|
||||
MATCH_ID(3D_FLAT_COLOR);
|
||||
MATCH_ID(3D_SMOOTH_COLOR);
|
||||
MATCH_ID(3D_UNIFORM_COLOR);
|
||||
|
||||
#undef MATCH_ID
|
||||
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"shader name not known");
|
||||
return NULL;
|
||||
|
||||
success:
|
||||
GPU_batch_program_set_builtin(self->batch, shader);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *bpygpu_VertBatch_uniform_bool(BPyGPUBatch *self, PyObject *args)
|
||||
{
|
||||
struct {
|
||||
const char *id;
|
||||
bool values[1];
|
||||
} params;
|
||||
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "sO&:uniform_bool",
|
||||
¶ms.id,
|
||||
PyC_ParseBool, ¶ms.values[0]))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GPU_batch_uniform_1b(self->batch, params.id, params.values[0]);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *bpygpu_VertBatch_uniform_i32(BPyGPUBatch *self, PyObject *args)
|
||||
{
|
||||
struct {
|
||||
const char *id;
|
||||
int values[1];
|
||||
} params;
|
||||
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "si:uniform_i32",
|
||||
¶ms.id,
|
||||
¶ms.values[0]))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GPU_batch_uniform_1i(self->batch, params.id, params.values[0]);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *bpygpu_VertBatch_uniform_f32(BPyGPUBatch *self, PyObject *args)
|
||||
{
|
||||
struct {
|
||||
const char *id;
|
||||
float values[4];
|
||||
} params;
|
||||
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "sf|fff:uniform_f32",
|
||||
¶ms.id,
|
||||
¶ms.values[0], ¶ms.values[1], ¶ms.values[2], ¶ms.values[3]))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (PyTuple_GET_SIZE(args)) {
|
||||
case 2: GPU_batch_uniform_1f(self->batch, params.id, params.values[0]); break;
|
||||
case 3: GPU_batch_uniform_2f(self->batch, params.id, UNPACK2(params.values)); break;
|
||||
case 4: GPU_batch_uniform_3f(self->batch, params.id, UNPACK3(params.values)); break;
|
||||
case 5: GPU_batch_uniform_4f(self->batch, params.id, UNPACK4(params.values)); break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpygpu_VertBatch_draw_doc,
|
||||
"TODO"
|
||||
".. method:: draw(program=None)\n"
|
||||
"\n"
|
||||
" Run the drawing program with the parameters assigned to the batch.\n"
|
||||
"\n"
|
||||
" :param program: program that performs the drawing operations. \n"
|
||||
" If `None` is passed, the last program setted to this batch will run.\n"
|
||||
" :type program: :class:`gpu.types.GPUShader`\n"
|
||||
);
|
||||
static PyObject *bpygpu_VertBatch_draw(BPyGPUBatch *self)
|
||||
static PyObject *bpygpu_VertBatch_draw(BPyGPUBatch *self, PyObject *args)
|
||||
{
|
||||
if (!glIsProgram(self->batch->program)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"batch program has not not set");
|
||||
BPyGPUShader *py_program = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "|O!:GPUShader.__exit__",
|
||||
&BPyGPUShader_Type, &py_program))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
else if (self->batch->program != GPU_shader_get_program(py_program->shader)) {
|
||||
GPU_batch_program_set(self->batch,
|
||||
GPU_shader_get_program(py_program->shader),
|
||||
GPU_shader_get_interface(py_program->shader));
|
||||
}
|
||||
|
||||
GPU_batch_draw(self->batch);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -313,16 +221,8 @@ static struct PyMethodDef bpygpu_VertBatch_methods[] = {
|
|||
METH_O, bpygpu_VertBatch_vertbuf_add_doc},
|
||||
{"program_set", (PyCFunction)bpygpu_VertBatch_program_set,
|
||||
METH_O, bpygpu_VertBatch_program_set_doc},
|
||||
{"program_set_builtin", (PyCFunction)bpygpu_VertBatch_program_set_builtin,
|
||||
METH_VARARGS | METH_KEYWORDS, bpygpu_VertBatch_program_set_builtin_doc},
|
||||
{"uniform_bool", (PyCFunction)bpygpu_VertBatch_uniform_bool,
|
||||
METH_VARARGS, NULL},
|
||||
{"uniform_i32", (PyCFunction)bpygpu_VertBatch_uniform_i32,
|
||||
METH_VARARGS, NULL},
|
||||
{"uniform_f32", (PyCFunction)bpygpu_VertBatch_uniform_f32,
|
||||
METH_VARARGS, NULL},
|
||||
{"draw", (PyCFunction) bpygpu_VertBatch_draw,
|
||||
METH_NOARGS, bpygpu_VertBatch_draw_doc},
|
||||
METH_VARARGS, bpygpu_VertBatch_draw_doc},
|
||||
{"__program_use_begin", (PyCFunction)bpygpu_VertBatch_program_use_begin,
|
||||
METH_NOARGS, ""},
|
||||
{"__program_use_end", (PyCFunction)bpygpu_VertBatch_program_use_end,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue