diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_shader_create_info.hh')
-rw-r--r-- | source/blender/gpu/intern/gpu_shader_create_info.hh | 248 |
1 files changed, 243 insertions, 5 deletions
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index 63c6e94f4c8..dafa741977c 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -30,8 +30,11 @@ #include "BLI_string_ref.hh" #include "BLI_vector.hh" +#include "GPU_material.h" #include "GPU_texture.h" +#include <iostream> + namespace blender::gpu::shader { #ifndef GPU_SHADER_CREATE_INFO @@ -62,7 +65,61 @@ enum class Type { BOOL, }; +/* All of these functions is a bit out of place */ +static inline Type to_type(const eGPUType type) +{ + switch (type) { + case GPU_FLOAT: + return Type::FLOAT; + case GPU_VEC2: + return Type::VEC2; + case GPU_VEC3: + return Type::VEC3; + case GPU_VEC4: + return Type::VEC4; + case GPU_MAT3: + return Type::MAT3; + case GPU_MAT4: + return Type::MAT4; + default: + BLI_assert_msg(0, "Error: Cannot convert eGPUType to shader::Type."); + return Type::FLOAT; + } +} + +static inline std::ostream &operator<<(std::ostream &stream, const Type type) +{ + switch (type) { + case Type::FLOAT: + return stream << "float"; + case Type::VEC2: + return stream << "vec2"; + case Type::VEC3: + return stream << "vec3"; + case Type::VEC4: + return stream << "vec4"; + case Type::MAT3: + return stream << "mat3"; + case Type::MAT4: + return stream << "mat4"; + default: + BLI_assert(0); + return stream; + } +} + +static inline std::ostream &operator<<(std::ostream &stream, const eGPUType type) +{ + switch (type) { + case GPU_CLOSURE: + return stream << "Closure"; + default: + return stream << to_type(type); + } +} + enum class BuiltinBits { + NONE = 0, /** * Allow getting barycentric coordinates inside the fragment shader. * \note Emulated on OpenGL. @@ -72,6 +129,10 @@ enum class BuiltinBits { FRONT_FACING = (1 << 4), GLOBAL_INVOCATION_ID = (1 << 5), INSTANCE_ID = (1 << 6), + /** + * Allow setting the target layer when the output is a layered frame-buffer. + * \note Emulated through geometry shader on older hardware. + */ LAYER = (1 << 7), LOCAL_INVOCATION_ID = (1 << 8), LOCAL_INVOCATION_INDEX = (1 << 9), @@ -125,10 +186,13 @@ enum class ImageType { /* Storage qualifiers. */ enum class Qualifier { - RESTRICT = (1 << 0), - READ_ONLY = (1 << 1), - WRITE_ONLY = (1 << 2), - QUALIFIER_MAX = (WRITE_ONLY << 1) - 1, + /** Restrict flag is set by default. Unless specified otherwise. */ + NO_RESTRICT = (1 << 0), + READ = (1 << 1), + WRITE = (1 << 2), + /** Shorthand version of combined flags. */ + READ_WRITE = READ | WRITE, + QUALIFIER_MAX = (WRITE << 1) - 1, }; ENUM_OPERATORS(Qualifier, Qualifier::QUALIFIER_MAX); @@ -221,16 +285,45 @@ struct ShaderCreateInfo { bool do_static_compilation_ = false; /** If true, all additionally linked create info will be merged into this one. */ bool finalized_ = false; + /** If true, all resources will have an automatic location assigned. */ + bool auto_resource_location_ = false; /** * Maximum length of all the resource names including each null terminator. * Only for names used by gpu::ShaderInterface. */ size_t interface_names_size_ = 0; + /** Manually set builtins. */ + BuiltinBits builtins_ = BuiltinBits::NONE; + /** Manually set generated code. */ + std::string vertex_source_generated = ""; + std::string fragment_source_generated = ""; + std::string typedef_source_generated = ""; + /** Manually set generated dependencies. */ + Vector<const char *, 0> dependencies_generated; + +#define TEST_EQUAL(a, b, _member) \ + if (!((a)._member == (b)._member)) { \ + return false; \ + } + +#define TEST_VECTOR_EQUAL(a, b, _vector) \ + TEST_EQUAL(a, b, _vector.size()); \ + for (auto i : _vector.index_range()) { \ + TEST_EQUAL(a, b, _vector[i]); \ + } struct VertIn { int index; Type type; StringRefNull name; + + bool operator==(const VertIn &b) + { + TEST_EQUAL(*this, b, index); + TEST_EQUAL(*this, b, type); + TEST_EQUAL(*this, b, name); + return true; + } }; Vector<VertIn> vertex_inputs_; @@ -240,6 +333,15 @@ struct ShaderCreateInfo { PrimitiveOut primitive_out; /** Set to -1 by default to check if used. */ int max_vertices = -1; + + bool operator==(const GeometryStageLayout &b) + { + TEST_EQUAL(*this, b, primitive_in); + TEST_EQUAL(*this, b, invocations); + TEST_EQUAL(*this, b, primitive_out); + TEST_EQUAL(*this, b, max_vertices); + return true; + } }; GeometryStageLayout geometry_layout_; @@ -247,8 +349,15 @@ struct ShaderCreateInfo { int local_size_x = -1; int local_size_y = -1; int local_size_z = -1; - }; + bool operator==(const ComputeStageLayout &b) + { + TEST_EQUAL(*this, b, local_size_x); + TEST_EQUAL(*this, b, local_size_y); + TEST_EQUAL(*this, b, local_size_z); + return true; + } + }; ComputeStageLayout compute_layout_; struct FragOut { @@ -256,6 +365,15 @@ struct ShaderCreateInfo { Type type; DualBlend blend; StringRefNull name; + + bool operator==(const FragOut &b) + { + TEST_EQUAL(*this, b, index); + TEST_EQUAL(*this, b, type); + TEST_EQUAL(*this, b, blend); + TEST_EQUAL(*this, b, name); + return true; + } }; Vector<FragOut> fragment_outputs_; @@ -301,6 +419,35 @@ struct ShaderCreateInfo { }; Resource(BindType type, int _slot) : bind_type(type), slot(_slot){}; + + bool operator==(const Resource &b) + { + TEST_EQUAL(*this, b, bind_type); + TEST_EQUAL(*this, b, slot); + switch (bind_type) { + case UNIFORM_BUFFER: + TEST_EQUAL(*this, b, uniformbuf.type_name); + TEST_EQUAL(*this, b, uniformbuf.name); + break; + case STORAGE_BUFFER: + TEST_EQUAL(*this, b, storagebuf.qualifiers); + TEST_EQUAL(*this, b, storagebuf.type_name); + TEST_EQUAL(*this, b, storagebuf.name); + break; + case SAMPLER: + TEST_EQUAL(*this, b, sampler.type); + TEST_EQUAL(*this, b, sampler.sampler); + TEST_EQUAL(*this, b, sampler.name); + break; + case IMAGE: + TEST_EQUAL(*this, b, image.format); + TEST_EQUAL(*this, b, image.type); + TEST_EQUAL(*this, b, image.qualifiers); + TEST_EQUAL(*this, b, image.name); + break; + } + return true; + } }; /** * Resources are grouped by frequency of change. @@ -317,6 +464,14 @@ struct ShaderCreateInfo { Type type; StringRefNull name; int array_size; + + bool operator==(const PushConst &b) + { + TEST_EQUAL(*this, b, type); + TEST_EQUAL(*this, b, name); + TEST_EQUAL(*this, b, array_size); + return true; + } }; Vector<PushConst> push_constants_; @@ -538,6 +693,18 @@ struct ShaderCreateInfo { return *(Self *)this; } + Self &builtins(BuiltinBits builtin) + { + builtins_ |= builtin; + return *(Self *)this; + } + + Self &auto_resource_location(bool value) + { + auto_resource_location_ = value; + return *(Self *)this; + } + /** \} */ /* -------------------------------------------------------------------- */ @@ -608,6 +775,77 @@ struct ShaderCreateInfo { void validate(const ShaderCreateInfo &other_info); /** \} */ + + /* -------------------------------------------------------------------- */ + /** \name Operators. + * + * \{ */ + + /* Comparison operator for GPUPass cache. We only compare if it will create the same shader code. + * So we do not compare name and some other internal stuff. */ + bool operator==(const ShaderCreateInfo &b) + { + TEST_EQUAL(*this, b, builtins_); + TEST_EQUAL(*this, b, vertex_source_generated); + TEST_EQUAL(*this, b, fragment_source_generated); + TEST_EQUAL(*this, b, typedef_source_generated); + TEST_VECTOR_EQUAL(*this, b, vertex_inputs_); + TEST_EQUAL(*this, b, geometry_layout_); + TEST_EQUAL(*this, b, compute_layout_); + TEST_VECTOR_EQUAL(*this, b, fragment_outputs_); + TEST_VECTOR_EQUAL(*this, b, pass_resources_); + TEST_VECTOR_EQUAL(*this, b, batch_resources_); + TEST_VECTOR_EQUAL(*this, b, vertex_out_interfaces_); + TEST_VECTOR_EQUAL(*this, b, geometry_out_interfaces_); + TEST_VECTOR_EQUAL(*this, b, push_constants_); + TEST_VECTOR_EQUAL(*this, b, typedef_sources_); + TEST_EQUAL(*this, b, vertex_source_); + TEST_EQUAL(*this, b, geometry_source_); + TEST_EQUAL(*this, b, fragment_source_); + TEST_EQUAL(*this, b, compute_source_); + TEST_VECTOR_EQUAL(*this, b, additional_infos_); + TEST_VECTOR_EQUAL(*this, b, defines_); + return true; + } + + /** Debug print */ + friend std::ostream &operator<<(std::ostream &stream, const ShaderCreateInfo &info) + { + /* TODO(@fclem): Complete print. */ + + auto print_resource = [&](const Resource &res) { + switch (res.bind_type) { + case Resource::BindType::UNIFORM_BUFFER: + stream << "UNIFORM_BUFFER(" << res.slot << ", " << res.uniformbuf.name << ")" + << std::endl; + break; + case Resource::BindType::STORAGE_BUFFER: + stream << "STORAGE_BUFFER(" << res.slot << ", " << res.storagebuf.name << ")" + << std::endl; + break; + case Resource::BindType::SAMPLER: + stream << "SAMPLER(" << res.slot << ", " << res.sampler.name << ")" << std::endl; + break; + case Resource::BindType::IMAGE: + stream << "IMAGE(" << res.slot << ", " << res.image.name << ")" << std::endl; + break; + } + }; + + /* TODO(@fclem): Order the resources. */ + for (auto &res : info.batch_resources_) { + print_resource(res); + } + for (auto &res : info.pass_resources_) { + print_resource(res); + } + return stream; + } + + /** \} */ + +#undef TEST_EQUAL +#undef TEST_VECTOR_EQUAL }; } // namespace blender::gpu::shader |