From 8f2bb1b1f055b55f41165b00de58109dab6df8f9 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 7 Jul 2021 12:36:25 +0200 Subject: Use compile time inlining for buitin structs. --- source/blender/gpu/intern/gpu_shader.cc | 2 +- .../gpu/intern/gpu_uniform_buffer_private.hh | 49 ++++- .../gpu/intern/gpu_uniform_buffer_structs.cc | 224 ++++++++++++++++++--- 3 files changed, 248 insertions(+), 27 deletions(-) diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 373162d35f7..b71f46fb3fc 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -211,7 +211,7 @@ void GPU_shader_free(GPUShader *shader) /* -------------------------------------------------------------------- */ /** \name Creation utils * \{ */ - + GPUShader *GPU_shader_create(const char *vertcode, const char *fragcode, const char *geomcode, diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh index b514b312c11..06ec14780a8 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh @@ -29,6 +29,8 @@ #include "GPU_shader.h" #include "GPU_uniform_buffer_types.h" +#include + struct GPUUniformBuf; namespace blender { @@ -88,14 +90,55 @@ static inline const UniformBuf *unwrap(const GPUUniformBuf *vert) class UniformBuiltinStructType { public: - UniformBuiltinStructType(const GPUUniformBuiltinStructType type); + constexpr UniformBuiltinStructType(const GPUUniformBuiltinStructType type); + static const UniformBuiltinStructType &get(const GPUUniformBuiltinStructType type); + + bool has_all_builtin_uniforms(const ShaderInterface &interface) const; GPUUniformBuiltinStructType type; + struct AttributeBinding { + int binding = -1; + size_t offset = -1; - bool has_all_builtin_uniforms(const ShaderInterface &interface) const; + bool has_binding() const; + }; + + const AttributeBinding &attribute_binding(const GPUUniformBuiltin builtin_uniform) const + { + return m_attribute_bindings[builtin_uniform]; + } + + const size_t data_size() const + { + return m_data_size; + } + + private: + const std::array &m_attribute_bindings; + const size_t m_data_size; +}; + +class UniformBuiltinStruct { + public: + struct Flags { + bool is_dirty : 1; + }; + + UniformBuiltinStruct(const GPUUniformBuiltinStructType type); + ~UniformBuiltinStruct(); + + void *data() const + { + return m_data; + }; + + bool uniform_int(int location, int comp_len, int array_size, const int *data); + bool uniform_float(int location, int comp_len, int array_size, const float *data); private: - bool has_attribute(const GPUUniformBuiltin builtin_uniform) const; + Flags m_flags; + const UniformBuiltinStructType &m_type_info; + void *m_data; }; std::optional find_smallest_uniform_builtin_struct( diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_structs.cc b/source/blender/gpu/intern/gpu_uniform_buffer_structs.cc index 897d1088e43..bdb16d2ec54 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer_structs.cc +++ b/source/blender/gpu/intern/gpu_uniform_buffer_structs.cc @@ -23,6 +23,8 @@ #include "gpu_uniform_buffer_private.hh" +#include "MEM_guardedalloc.h" + #include "GPU_shader.h" #include "GPU_uniform_buffer_types.h" #include "gpu_shader_interface.hh" @@ -30,49 +32,168 @@ namespace blender::gpu { /* -------------------------------------------------------------------- */ -/** \name Struct type +/** \name Attribute bindings * \{ */ +const int BUILTIN_BINDING_LOCATION_OFFSET = 1000; -UniformBuiltinStructType::UniformBuiltinStructType(const GPUUniformBuiltinStructType type) - : type(type) +static constexpr int to_binding_location(const GPUUniformBuiltin builtin_uniform) { + return BUILTIN_BINDING_LOCATION_OFFSET + builtin_uniform; } -bool UniformBuiltinStructType::has_attribute(const GPUUniformBuiltin builtin_uniform) const +static GPUUniformBuiltin to_builtin_uniform(int location) { - switch (type) { - case GPU_UNIFORM_STRUCT_NONE: - return false; + return static_cast(location - BUILTIN_BINDING_LOCATION_OFFSET); +} + +static bool is_valid_location(int location) +{ + int builtin_uniform = location - BUILTIN_BINDING_LOCATION_OFFSET; + if (builtin_uniform < 0 || builtin_uniform >= GPU_NUM_UNIFORMS) { + return false; + } + return true; +} + +static constexpr UniformBuiltinStructType::AttributeBinding determine_binding_struct_1( + const GPUUniformBuiltin builtin_uniform) +{ + UniformBuiltinStructType::AttributeBinding result; + switch (builtin_uniform) { + case GPU_UNIFORM_MODEL: + result.binding = to_binding_location(builtin_uniform); + result.offset = offsetof(GPUUniformBuiltinStruct1, ModelMatrix); + break; + case GPU_UNIFORM_MVP: + result.binding = to_binding_location(builtin_uniform); + result.offset = offsetof(GPUUniformBuiltinStruct1, ModelViewProjectionMatrix); + break; + case GPU_UNIFORM_COLOR: + result.binding = to_binding_location(builtin_uniform); + result.offset = offsetof(GPUUniformBuiltinStruct1, color); + break; + case GPU_UNIFORM_CLIPPLANES: + result.binding = to_binding_location(builtin_uniform); + result.offset = offsetof(GPUUniformBuiltinStruct1, WorldClipPlanes); + break; + case GPU_UNIFORM_SRGB_TRANSFORM: + result.binding = to_binding_location(builtin_uniform); + result.offset = offsetof(GPUUniformBuiltinStruct1, SrgbTransform); break; - case GPU_UNIFORM_STRUCT_1: - return ELEM(builtin_uniform, - GPU_UNIFORM_MODEL, - GPU_UNIFORM_MVP, - GPU_UNIFORM_COLOR, - GPU_UNIFORM_CLIPPLANES, - GPU_UNIFORM_SRGB_TRANSFORM); + default: break; + }; + + return result; +} + +static constexpr UniformBuiltinStructType::AttributeBinding determine_binding( + const GPUUniformBuiltinStructType struct_type, const GPUUniformBuiltin builtin_uniform) +{ + switch (struct_type) { + case GPU_UNIFORM_STRUCT_NONE: case GPU_NUM_UNIFORM_STRUCTS: - return false; - break; - } - return false; + return {}; + + case GPU_UNIFORM_STRUCT_1: + return determine_binding_struct_1(builtin_uniform); + }; + return {}; +} + +static constexpr std::array +builtin_uniforms_for_struct_type(const GPUUniformBuiltinStructType struct_type) +{ + return { + determine_binding(struct_type, GPU_UNIFORM_MODEL), + determine_binding(struct_type, GPU_UNIFORM_VIEW), + determine_binding(struct_type, GPU_UNIFORM_MODELVIEW), + determine_binding(struct_type, GPU_UNIFORM_PROJECTION), + determine_binding(struct_type, GPU_UNIFORM_VIEWPROJECTION), + determine_binding(struct_type, GPU_UNIFORM_MVP), + determine_binding(struct_type, GPU_UNIFORM_MODEL_INV), + determine_binding(struct_type, GPU_UNIFORM_VIEW_INV), + determine_binding(struct_type, GPU_UNIFORM_MODELVIEW_INV), + determine_binding(struct_type, GPU_UNIFORM_PROJECTION_INV), + determine_binding(struct_type, GPU_UNIFORM_VIEWPROJECTION_INV), + determine_binding(struct_type, GPU_UNIFORM_NORMAL), + determine_binding(struct_type, GPU_UNIFORM_ORCO), + determine_binding(struct_type, GPU_UNIFORM_CLIPPLANES), + determine_binding(struct_type, GPU_UNIFORM_COLOR), + determine_binding(struct_type, GPU_UNIFORM_BASE_INSTANCE), + determine_binding(struct_type, GPU_UNIFORM_RESOURCE_CHUNK), + determine_binding(struct_type, GPU_UNIFORM_RESOURCE_ID), + determine_binding(struct_type, GPU_UNIFORM_SRGB_TRANSFORM), + }; +} + +static constexpr std::array< + const std::array, + GPU_NUM_UNIFORM_STRUCTS> + ATTRIBUTE_BINDINGS = { + builtin_uniforms_for_struct_type(GPU_UNIFORM_STRUCT_NONE), + builtin_uniforms_for_struct_type(GPU_UNIFORM_STRUCT_1), +}; + +static constexpr size_t data_size_for(const GPUUniformBuiltinStructType struct_type) +{ + + switch (struct_type) { + case GPU_UNIFORM_STRUCT_NONE: + case GPU_NUM_UNIFORM_STRUCTS: + return 0; + + case GPU_UNIFORM_STRUCT_1: + return sizeof(GPUUniformBuiltinStruct1); + }; + return 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Struct type + * \{ */ + +constexpr UniformBuiltinStructType::UniformBuiltinStructType( + const GPUUniformBuiltinStructType type) + : type(type), m_attribute_bindings(ATTRIBUTE_BINDINGS[type]), m_data_size(data_size_for(type)) +{ +} + +bool UniformBuiltinStructType::AttributeBinding::has_binding() const +{ + return binding != -1; } bool UniformBuiltinStructType::has_all_builtin_uniforms(const ShaderInterface &interface) const { for (int i = 0; i < GPU_NUM_UNIFORMS; i++) { const GPUUniformBuiltin builtin_uniform = static_cast(i); + const AttributeBinding &binding = attribute_binding(builtin_uniform); const bool builtin_is_used = interface.builtins_[i] != -1; - if (builtin_is_used && !has_attribute(builtin_uniform)) { + const bool has_attribute = binding.has_binding(); + if (builtin_is_used && !has_attribute) { return false; } } return true; } +static constexpr std::array STRUCT_TYPE_INFOS = + { + UniformBuiltinStructType(GPU_UNIFORM_STRUCT_NONE), + UniformBuiltinStructType(GPU_UNIFORM_STRUCT_1), +}; + +const UniformBuiltinStructType &UniformBuiltinStructType::get( + const GPUUniformBuiltinStructType type) +{ + return STRUCT_TYPE_INFOS[type]; +} + std::optional find_smallest_uniform_builtin_struct( const ShaderInterface &interface) { @@ -80,10 +201,8 @@ std::optional find_smallest_uniform_builtin_s return std::nullopt; } - const UniformBuiltinStructType struct1(GPU_UNIFORM_STRUCT_1); - - if (struct1.has_all_builtin_uniforms(interface)) { - return std::make_optional(struct1.type); + if (UniformBuiltinStructType::get(GPU_UNIFORM_STRUCT_1).has_all_builtin_uniforms(interface)) { + return std::make_optional(GPU_UNIFORM_STRUCT_1); } return std::nullopt; @@ -91,4 +210,63 @@ std::optional find_smallest_uniform_builtin_s /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Struct type + * \{ */ + +UniformBuiltinStruct::UniformBuiltinStruct(const GPUUniformBuiltinStructType type) + : m_type_info(UniformBuiltinStructType::get(type)) +{ + m_data = MEM_mallocN(m_type_info.data_size(), __func__); +} + +UniformBuiltinStruct::~UniformBuiltinStruct() +{ + MEM_freeN(m_data); + m_data = nullptr; +} + +bool UniformBuiltinStruct::uniform_int(int location, int comp_len, int array_size, const int *data) +{ + if (is_valid_location(location)) { + return false; + } + const GPUUniformBuiltin builtin_uniform = to_builtin_uniform(location); + const UniformBuiltinStructType::AttributeBinding &attribute = m_type_info.attribute_binding( + builtin_uniform); + + if (!attribute.has_binding()) { + return false; + } + const size_t attribute_len = comp_len * array_size * sizeof(int); + memcpy(((uint8_t *)m_data) + attribute.offset, data, attribute_len); + m_flags.is_dirty = true; + + return true; +} + +bool UniformBuiltinStruct::uniform_float(int location, + int comp_len, + int array_size, + const float *data) +{ + if (is_valid_location(location)) { + return false; + } + const GPUUniformBuiltin builtin_uniform = to_builtin_uniform(location); + const UniformBuiltinStructType::AttributeBinding &attribute = m_type_info.attribute_binding( + builtin_uniform); + + if (!attribute.has_binding()) { + return false; + } + const size_t attribute_len = comp_len * array_size * sizeof(float); + memcpy(((uint8_t *)m_data) + attribute.offset, data, attribute_len); + m_flags.is_dirty = true; + + return true; +} + +/** \} */ + } // namespace blender::gpu -- cgit v1.2.3