Python API: new GPUShader.format_calc() method

Reviewers: mano-wii, fclem, campbellbarton

Differential Revision: https://developer.blender.org/D3772
This commit is contained in:
2018-10-09 11:17:29 +02:00
parent 1b910082a0
commit 9560fe60e4
3 changed files with 133 additions and 0 deletions

View File

@@ -80,8 +80,11 @@ typedef struct GPUVertFormat {
GPUVertAttr attribs[GPU_VERT_ATTR_MAX_LEN]; /* TODO: variable-size attribs array */
} GPUVertFormat;
struct GPUShaderInterface;
void GPU_vertformat_clear(GPUVertFormat *);
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src);
void GPU_vertformat_from_interface(GPUVertFormat *format, const struct GPUShaderInterface *shaderface);
uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name,

View File

@@ -29,6 +29,8 @@
* GPU vertex format
*/
#include "GPU_shader_interface.h"
#include "GPU_vertex_format.h"
#include "gpu_vertex_format_private.h"
#include <stddef.h>
@@ -278,6 +280,115 @@ void VertexFormat_pack(GPUVertFormat *format)
format->packed = true;
}
static uint calc_input_component_size(const GPUShaderInput *input)
{
int size = input->size;
switch (input->gl_type) {
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_UNSIGNED_INT_VEC2:
return size * 2;
case GL_FLOAT_VEC3:
case GL_INT_VEC3:
case GL_UNSIGNED_INT_VEC3:
return size * 3;
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_INT_VEC4:
case GL_UNSIGNED_INT_VEC4:
return size * 4;
case GL_FLOAT_MAT3:
return size * 9;
case GL_FLOAT_MAT4:
return size * 16;
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT3x2:
return size * 6;
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT4x2:
return size * 8;
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4x3:
return size * 12;
default:
return size;
}
}
static void get_fetch_mode_and_comp_type(
int gl_type,
GPUVertCompType *r_comp_type,
uint *r_gl_comp_type,
GPUVertFetchMode *r_fetch_mode)
{
switch (gl_type) {
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT3x2:
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4x2:
case GL_FLOAT_MAT4x3:
*r_comp_type = GPU_COMP_F32;
*r_gl_comp_type = GL_FLOAT;
*r_fetch_mode = GPU_FETCH_FLOAT;
break;
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
*r_comp_type = GPU_COMP_I32;
*r_gl_comp_type = GL_INT;
*r_fetch_mode = GPU_FETCH_INT;
break;
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2:
case GL_UNSIGNED_INT_VEC3:
case GL_UNSIGNED_INT_VEC4:
*r_comp_type = GPU_COMP_U32;
*r_gl_comp_type = GL_UNSIGNED_INT;
*r_fetch_mode = GPU_FETCH_INT;
break;
default:
BLI_assert(0);
}
}
void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface)
{
const char *name_buffer = shaderface->name_buffer;
for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) {
const GPUShaderInput *input = shaderface->attrib_buckets[i];
if (input == NULL) {
continue;
}
const GPUShaderInput *next = input;
while (next != NULL) {
input = next;
next = input->next;
format->name_len++; /* multiname support */
format->attr_len++;
GPUVertAttr *attrib = format->attribs + input->location;
attrib->name[attrib->name_len++] = copy_attrib_name(format, name_buffer + input->name_offset);
attrib->offset = 0; /* offsets & stride are calculated later (during pack) */
attrib->comp_len = calc_input_component_size(input);
attrib->sz = attrib->comp_len * 4;
get_fetch_mode_and_comp_type(input->gl_type, &attrib->comp_type, &attrib->gl_comp_type, &attrib->fetch_mode);
}
}
}
/* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
* Of the code here, only struct GPUPackedNormal needs to change. */

View File

@@ -36,6 +36,7 @@
#include "../generic/python_utildefines.h"
#include "gpu_py_shader.h" /* own include */
#include "gpu_py_vertex_format.h"
/* -------------------------------------------------------------------- */
@@ -569,6 +570,21 @@ static PyObject *bpygpu_shader_attr_from_name(
return PyLong_FromLong(attrib);
}
PyDoc_STRVAR(bpygpu_shader_calc_format_doc,
".. method:: calc_format()\n"
"\n"
" Build a new format based on the attributes of the shader.\n"
"\n"
" :return: vertex attribute format for the shader\n"
" :rtype: GPUVertFormat\n"
);
static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
{
BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader));
return (PyObject *)ret;
}
static struct PyMethodDef bpygpu_shader_methods[] = {
{"bind", (PyCFunction)bpygpu_shader_bind,
METH_NOARGS, bpygpu_shader_bind_doc},
@@ -602,6 +618,9 @@ static struct PyMethodDef bpygpu_shader_methods[] = {
{"attr_from_name",
(PyCFunction)bpygpu_shader_attr_from_name,
METH_O, bpygpu_shader_attr_from_name_doc},
{"format_calc",
(PyCFunction)bpygpu_shader_calc_format,
METH_NOARGS, bpygpu_shader_calc_format_doc},
{NULL, NULL, 0, NULL}
};