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:
committed by
Germano Cavalcante
parent
93e3da136f
commit
19fee82b72
@@ -206,12 +206,14 @@ void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, cons
|
||||
* Used to create #GPUVertexFormat from the shader's vertex input layout.
|
||||
* \{ */
|
||||
|
||||
unsigned int GPU_shader_get_attribute_len(const GPUShader *shader);
|
||||
uint GPU_shader_get_attribute_len(const GPUShader *shader);
|
||||
uint GPU_shader_get_ssbo_input_len(const GPUShader *shader);
|
||||
int GPU_shader_get_attribute(const GPUShader *shader, const char *name);
|
||||
bool GPU_shader_get_attribute_info(const GPUShader *shader,
|
||||
int attr_location,
|
||||
char r_name[256],
|
||||
int *r_type);
|
||||
bool GPU_shader_get_ssbo_input_info(const GPUShader *shader, int ssbo_location, char r_name[256]);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
@@ -664,6 +664,12 @@ uint GPU_shader_get_attribute_len(const GPUShader *shader)
|
||||
return interface->attr_len_;
|
||||
}
|
||||
|
||||
uint GPU_shader_get_ssbo_input_len(const GPUShader *shader)
|
||||
{
|
||||
const ShaderInterface *interface = unwrap(shader)->interface;
|
||||
return interface->ssbo_len_;
|
||||
}
|
||||
|
||||
int GPU_shader_get_attribute(const GPUShader *shader, const char *name)
|
||||
{
|
||||
const ShaderInterface *interface = unwrap(shader)->interface;
|
||||
@@ -688,6 +694,19 @@ bool GPU_shader_get_attribute_info(const GPUShader *shader,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPU_shader_get_ssbo_input_info(const GPUShader *shader, int ssbo_location, char r_name[256])
|
||||
{
|
||||
const ShaderInterface *interface = unwrap(shader)->interface;
|
||||
|
||||
const ShaderInput *ssbo_input = interface->ssbo_get(ssbo_location);
|
||||
if (!ssbo_input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_strncpy(r_name, interface->input_name_get(ssbo_input), 256);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -68,3 +68,4 @@ struct BPyGPUShaderCreateInfo {
|
||||
|
||||
PyObject *BPyGPUStageInterfaceInfo_CreatePyObject(GPUStageInterfaceInfo *interface);
|
||||
PyObject *BPyGPUShaderCreateInfo_CreatePyObject(GPUShaderCreateInfo *info);
|
||||
bool bpygpu_shader_is_polyline(GPUShader *shader);
|
||||
|
||||
Reference in New Issue
Block a user