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/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 ++++++++++++++++++++++- 4 files changed, 114 insertions(+), 4 deletions(-) (limited to 'source/blender/gpu/intern') 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++; + } } -- cgit v1.2.3