Fix #131236: 'batch_for_shader' not working with POLYLINE shaders

In Blender 4.4 (since commit 00a8d006fe), polyline shaders stopped
using geometry shaders and now rely on SSBOs.

In C++, workarounds allow these shaders to function as before, albeit
with some limitations.

However, this change broke the `batch_for_shader` function in Python,
as `GPUShader.attrs_info_get()` only reads attributes and does not
support SSBOs.

To address this, the method now treats polyline shaders differently,
accessing SSBO inputs instead of attributes.

fix
This commit is contained in:
Germano Cavalcante
2024-12-11 12:30:16 -03:00
committed by Germano Cavalcante
parent 93e3da136f
commit 19fee82b72
4 changed files with 89 additions and 22 deletions

View File

@@ -700,30 +700,67 @@ PyDoc_STRVAR(
" :rtype: tuple[tuple[str, str | None], ...]\n");
static PyObject *pygpu_shader_attrs_info_get(BPyGPUShader *self, PyObject * /*arg*/)
{
uint attr_len = GPU_shader_get_attribute_len(self->shader);
using namespace blender::gpu::shader;
PyObject *ret;
int type;
int location_test = 0, attrs_added = 0;
char name[256];
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);
}
if (bpygpu_shader_is_polyline(self->shader)) {
/* WORKAROUND: Special case for POLYLINE shader. Check the SSBO inputs as attributes. */
uint input_len = GPU_shader_get_ssbo_input_len(self->shader);
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++;
/* Skip "gpu_index_buf". */
input_len -= 1;
ret = PyTuple_New(input_len);
while (attrs_added < input_len) {
if (!GPU_shader_get_ssbo_input_info(self->shader, location_test++, name)) {
continue;
}
if (STREQ(name, "gpu_index_buf")) {
continue;
}
type = STREQ(name, "pos") ? int(Type::VEC3) : STREQ(name, "color") ? int(Type::VEC4) : -1;
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++;
}
}
else {
uint attr_len = GPU_shader_get_attribute_len(self->shader);
ret = PyTuple_New(attr_len);
while (attrs_added < attr_len) {
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;
}
@@ -1099,4 +1136,12 @@ PyObject *bpygpu_shader_init()
return submodule;
}
bool bpygpu_shader_is_polyline(GPUShader *shader)
{
return ELEM(shader,
GPU_shader_get_builtin_shader(GPU_SHADER_3D_POLYLINE_FLAT_COLOR),
GPU_shader_get_builtin_shader(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR),
GPU_shader_get_builtin_shader(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR));
}
/** \} */

View File

@@ -68,3 +68,4 @@ struct BPyGPUShaderCreateInfo {
PyObject *BPyGPUStageInterfaceInfo_CreatePyObject(GPUStageInterfaceInfo *interface);
PyObject *BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info);
bool bpygpu_shader_is_polyline(GPUShader *shader);