From 6269d66da29ae000f214e775ee54dfc71623e642 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Thu, 1 Sep 2022 08:21:10 -0300 Subject: PyGPU: GPUShader: implementation of 'attrs_info_get' method With the new `attrs_info_get` method, we can get information about the attributes used in a `GPUShader` and thus have more freedom in the automatic creation of `GPUVertFormat`s Reviewed By: fclem, campbellbarton Differential Revision: https://developer.blender.org/D15764 --- source/blender/gpu/GPU_shader.h | 5 ++ source/blender/gpu/intern/gpu_shader.cc | 23 +++++ source/blender/gpu/intern/gpu_shader_interface.hh | 12 +++ source/blender/gpu/intern/gpu_shader_private.hh | 2 - source/blender/gpu/intern/gpu_vertex_format.cc | 81 ++++++++++++++++- source/blender/gpu/opengl/gl_shader.cc | 102 ---------------------- source/blender/gpu/opengl/gl_shader.hh | 2 - source/blender/gpu/opengl/gl_shader_interface.cc | 54 ++++++++++++ 8 files changed, 173 insertions(+), 108 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 529a3da3ab9..e1f9d1663f6 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -191,7 +191,12 @@ void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const floa void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]); void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]); +unsigned int GPU_shader_get_attribute_len(const GPUShader *shader); int GPU_shader_get_attribute(GPUShader *shader, const char *name); +bool GPU_shader_get_attribute_info(const GPUShader *shader, + int attr_location, + char r_name[256], + int *r_type); void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear); diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 08c768b28ba..2d1b3dc2dca 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -612,6 +612,12 @@ int GPU_shader_get_texture_binding(GPUShader *shader, const char *name) return tex ? tex->binding : -1; } +uint GPU_shader_get_attribute_len(const GPUShader *shader) +{ + ShaderInterface *interface = unwrap(shader)->interface; + return interface->attr_len_; +} + int GPU_shader_get_attribute(GPUShader *shader, const char *name) { ShaderInterface *interface = unwrap(shader)->interface; @@ -619,6 +625,23 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name) return attr ? attr->location : -1; } +bool GPU_shader_get_attribute_info(const GPUShader *shader, + int attr_location, + char r_name[256], + int *r_type) +{ + ShaderInterface *interface = unwrap(shader)->interface; + + const ShaderInput *attr = interface->attr_get(attr_location); + if (!attr) { + return false; + } + + BLI_strncpy(r_name, interface->input_name_get(attr), 256); + *r_type = attr->location != -1 ? interface->attr_types_[attr->location] : -1; + return true; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh index 812244c9b3a..41e06569bdc 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.hh +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -18,6 +18,7 @@ #include "BLI_utildefines.h" #include "GPU_shader.h" +#include "GPU_vertex_format.h" /* GPU_VERT_ATTR_MAX_LEN */ #include "gpu_shader_create_info.hh" namespace blender::gpu { @@ -58,6 +59,13 @@ class ShaderInterface { int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS]; int32_t builtin_buffers_[GPU_NUM_STORAGE_BUFFERS]; + /** + * Currently only used for `GPU_shader_get_attribute_info`. + * This utility is useful for automatic creation of `GPUVertFormat` in Python. + * Use `ShaderInput::location` to identify the `Type`. + */ + uint8_t attr_types_[GPU_VERT_ATTR_MAX_LEN]; + public: ShaderInterface(); ShaderInterface(const shader::ShaderCreateInfo &info); @@ -69,6 +77,10 @@ class ShaderInterface { { return input_lookup(inputs_, attr_len_, name); } + inline const ShaderInput *attr_get(const int binding) const + { + return input_lookup(inputs_, attr_len_, binding); + } inline const ShaderInput *ubo_get(const char *name) const { diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index 4d318093c98..a822cd8aa38 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -55,8 +55,6 @@ class Shader { virtual void uniform_float(int location, int comp_len, int array_size, const float *data) = 0; virtual void uniform_int(int location, int comp_len, int array_size, const int *data) = 0; - virtual void vertformat_from_shader(GPUVertFormat *) const = 0; - std::string defines_declare(const shader::ShaderCreateInfo &info) const; virtual std::string resources_declare(const shader::ShaderCreateInfo &info) const = 0; virtual std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const = 0; diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index 59ae862aa51..2463dc2ae06 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -8,6 +8,7 @@ */ #include "GPU_vertex_format.h" +#include "gpu_shader_create_info.hh" #include "gpu_shader_private.hh" #include "gpu_vertex_format_private.h" @@ -25,6 +26,7 @@ #endif using namespace blender::gpu; +using namespace blender::gpu::shader; void GPU_vertformat_clear(GPUVertFormat *format) { @@ -338,8 +340,83 @@ void VertexFormat_pack(GPUVertFormat *format) format->packed = true; } +static uint component_size_get(const Type gpu_type) +{ + switch (gpu_type) { + case Type::VEC2: + case Type::IVEC2: + case Type::UVEC2: + return 2; + case Type::VEC3: + case Type::IVEC3: + case Type::UVEC3: + return 3; + case Type::VEC4: + case Type::IVEC4: + case Type::UVEC4: + return 4; + case Type::MAT3: + return 12; + case Type::MAT4: + return 16; + default: + return 1; + } +} + +static void recommended_fetch_mode_and_comp_type(Type gpu_type, + GPUVertCompType *r_comp_type, + GPUVertFetchMode *r_fetch_mode) +{ + switch (gpu_type) { + case Type::FLOAT: + case Type::VEC2: + case Type::VEC3: + case Type::VEC4: + case Type::MAT3: + case Type::MAT4: + *r_comp_type = GPU_COMP_F32; + *r_fetch_mode = GPU_FETCH_FLOAT; + break; + case Type::INT: + case Type::IVEC2: + case Type::IVEC3: + case Type::IVEC4: + *r_comp_type = GPU_COMP_I32; + *r_fetch_mode = GPU_FETCH_INT; + break; + case Type::UINT: + case Type::UVEC2: + case Type::UVEC3: + case Type::UVEC4: + *r_comp_type = GPU_COMP_U32; + *r_fetch_mode = GPU_FETCH_INT; + break; + default: + BLI_assert(0); + } +} + void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *gpushader) { - const Shader *shader = reinterpret_cast(gpushader); - shader->vertformat_from_shader(format); + GPU_vertformat_clear(format); + + uint attr_len = GPU_shader_get_attribute_len(gpushader); + int location_test = 0, attrs_added = 0;; + while (attrs_added < attr_len) { + char name[256]; + Type gpu_type; + if (!GPU_shader_get_attribute_info(gpushader, location_test++, name, (int *)&gpu_type)) { + continue; + } + + GPUVertCompType comp_type; + GPUVertFetchMode fetch_mode; + recommended_fetch_mode_and_comp_type(gpu_type, &comp_type, &fetch_mode); + + int comp_len = component_size_get(gpu_type); + + GPU_vertformat_attr_add(format, name, comp_type, comp_len, fetch_mode); + attrs_added++; + } } diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index a08019cc707..1f2ef36716e 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1136,108 +1136,6 @@ void GLShader::uniform_int(int location, int comp_len, int array_size, const int /** \name GPUVertFormat from Shader * \{ */ -static uint calc_component_size(const GLenum gl_type) -{ - switch (gl_type) { - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 2; - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 3; - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - return 4; - case GL_FLOAT_MAT3: - return 9; - case GL_FLOAT_MAT4: - return 16; - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 6; - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT4x2: - return 8; - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - return 12; - default: - return 1; - } -} - -static void get_fetch_mode_and_comp_type(int gl_type, - GPUVertCompType *r_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_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_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_fetch_mode = GPU_FETCH_INT; - break; - default: - BLI_assert(0); - } -} - -void GLShader::vertformat_from_shader(GPUVertFormat *format) const -{ - GPU_vertformat_clear(format); - - GLint attr_len; - glGetProgramiv(shader_program_, GL_ACTIVE_ATTRIBUTES, &attr_len); - - for (int i = 0; i < attr_len; i++) { - char name[256]; - GLenum gl_type; - GLint size; - glGetActiveAttrib(shader_program_, i, sizeof(name), nullptr, &size, &gl_type, name); - - /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ - if (glGetAttribLocation(shader_program_, name) == -1) { - continue; - } - - GPUVertCompType comp_type; - GPUVertFetchMode fetch_mode; - get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode); - - int comp_len = calc_component_size(gl_type) * size; - - GPU_vertformat_attr_add(format, name, comp_type, comp_len, fetch_mode); - } -} - int GLShader::program_handle_get() const { return (int)this->shader_program_; diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh index 2774b24cdbe..bebbb2fa82e 100644 --- a/source/blender/gpu/opengl/gl_shader.hh +++ b/source/blender/gpu/opengl/gl_shader.hh @@ -67,8 +67,6 @@ class GLShader : public Shader { void uniform_float(int location, int comp_len, int array_size, const float *data) override; void uniform_int(int location, int comp_len, int array_size, const int *data) override; - void vertformat_from_shader(GPUVertFormat *format) const override; - /** DEPRECATED: Kept only because of BGL API. */ int program_handle_get() const override; diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 4623a14dab3..b230706b020 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -16,6 +16,7 @@ #include "GPU_capabilities.h" +using namespace blender::gpu::shader; namespace blender::gpu { /* -------------------------------------------------------------------- */ @@ -151,6 +152,52 @@ static inline int ssbo_binding(int32_t program, uint32_t ssbo_index) /** \name Creation / Destruction * \{ */ +static Type gpu_type_from_gl_type(int gl_type) +{ + switch (gl_type) { + case GL_FLOAT: + return Type::FLOAT; + case GL_FLOAT_VEC2: + return Type::VEC2; + case GL_FLOAT_VEC3: + return Type::VEC3; + case GL_FLOAT_VEC4: + return Type::VEC4; + case GL_FLOAT_MAT3: + return Type::MAT3; + case GL_FLOAT_MAT4: + return Type::MAT4; + case GL_UNSIGNED_INT: + return Type::UINT; + case GL_UNSIGNED_INT_VEC2: + return Type::UVEC2; + case GL_UNSIGNED_INT_VEC3: + return Type::UVEC3; + case GL_UNSIGNED_INT_VEC4: + return Type::UVEC4; + case GL_INT: + return Type::INT; + case GL_INT_VEC2: + return Type::IVEC2; + case GL_INT_VEC3: + return Type::IVEC3; + case GL_INT_VEC4: + return Type::IVEC4; + case GL_BOOL: + return Type::BOOL; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + default: + BLI_assert(0); + } + return Type::FLOAT; +} + GLShaderInterface::GLShaderInterface(GLuint program) { /* Necessary to make #glUniform works. */ @@ -246,6 +293,9 @@ GLShaderInterface::GLShaderInterface(GLuint program) name_buffer_offset += set_input_name(input, name, name_len); enabled_attr_mask_ |= (1 << input->location); + + /* Used in `GPU_shader_get_attribute_info`. */ + attr_types_[input->location] = (uint8_t)gpu_type_from_gl_type(type); } /* Uniform Blocks */ @@ -405,7 +455,11 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI } if (input->location != -1) { enabled_attr_mask_ |= (1 << input->location); + + /* Used in `GPU_shader_get_attribute_info`. */ + attr_types_[input->location] = (uint8_t)attr.type; } + input++; } -- cgit v1.2.3