Path: blob/master/drivers/gles3/storage/material_storage.h
10000 views
/**************************************************************************/1/* material_storage.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#ifdef GLES3_ENABLED3334#include "core/templates/rid_owner.h"35#include "core/templates/self_list.h"36#include "servers/rendering/shader_compiler.h"37#include "servers/rendering/shader_language.h"38#include "servers/rendering/storage/material_storage.h"39#include "servers/rendering/storage/utilities.h"4041#include "drivers/gles3/shaders/canvas.glsl.gen.h"42#include "drivers/gles3/shaders/particles.glsl.gen.h"43#include "drivers/gles3/shaders/scene.glsl.gen.h"44#include "drivers/gles3/shaders/sky.glsl.gen.h"4546namespace GLES3 {4748/* Shader Structs */4950struct ShaderData {51String path;52HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;53HashMap<StringName, HashMap<int, RID>> default_texture_params;5455virtual void set_path_hint(const String &p_hint);56virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);57virtual Variant get_default_parameter(const StringName &p_parameter) const;58virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;59virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;60virtual bool is_parameter_texture(const StringName &p_param) const;6162virtual void set_code(const String &p_Code) = 0;63virtual bool is_animated() const = 0;64virtual bool casts_shadows() const = 0;65virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }6667virtual ~ShaderData() {}68};6970typedef ShaderData *(*ShaderDataRequestFunction)();7172struct Material;7374struct Shader {75ShaderData *data = nullptr;76String code;77String path_hint;78RS::ShaderMode mode;79HashMap<StringName, HashMap<int, RID>> default_texture_parameter;80HashSet<Material *> owners;81};8283/* Material structs */8485struct MaterialData {86void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size);87void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);8889virtual void set_render_priority(int p_priority) = 0;90virtual void set_next_pass(RID p_pass) = 0;91virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;92virtual void bind_uniforms() = 0;93virtual ~MaterialData();9495// Used internally by all Materials96void update_parameters_internal(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, bool p_is_3d_shader_type);9798protected:99Vector<uint8_t> ubo_data;100GLuint uniform_buffer = GLuint(0);101Vector<RID> texture_cache;102103private:104friend class MaterialStorage;105RID self;106List<RID>::Element *global_buffer_E = nullptr;107List<RID>::Element *global_texture_E = nullptr;108uint64_t global_textures_pass = 0;109HashMap<StringName, uint64_t> used_global_textures;110};111112typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);113114struct Material {115RID self;116MaterialData *data = nullptr;117Shader *shader = nullptr;118//shortcut to shader data and type119RS::ShaderMode shader_mode = RS::SHADER_MAX;120uint32_t shader_id = 0;121bool uniform_dirty = false;122bool texture_dirty = false;123HashMap<StringName, Variant> params;124int32_t priority = 0;125RID next_pass;126SelfList<Material> update_element;127128Dependency dependency;129130Material() :131update_element(this) {}132};133134/* CanvasItem Materials */135136struct CanvasShaderData : public ShaderData {137enum BlendMode { // Used internally.138BLEND_MODE_MIX,139BLEND_MODE_ADD,140BLEND_MODE_SUB,141BLEND_MODE_MUL,142BLEND_MODE_PMALPHA,143BLEND_MODE_DISABLED,144BLEND_MODE_LCD,145};146147// All these members are (re)initialized in `set_code`.148// Make sure to add the init to `set_code` whenever adding new members.149150bool valid;151RID version;152153Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;154155Vector<uint32_t> ubo_offsets;156uint32_t ubo_size;157158String code;159160BlendMode blend_mode;161162bool uses_screen_texture;163bool uses_screen_texture_mipmaps;164bool uses_sdf;165bool uses_time;166bool uses_custom0;167bool uses_custom1;168169uint64_t vertex_input_mask;170171virtual void set_code(const String &p_Code);172virtual bool is_animated() const;173virtual bool casts_shadows() const;174virtual RS::ShaderNativeSourceCode get_native_source_code() const;175176CanvasShaderData();177virtual ~CanvasShaderData();178};179180ShaderData *_create_canvas_shader_func();181182struct CanvasMaterialData : public MaterialData {183CanvasShaderData *shader_data = nullptr;184185virtual void set_render_priority(int p_priority) {}186virtual void set_next_pass(RID p_pass) {}187virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);188virtual void bind_uniforms();189virtual ~CanvasMaterialData();190};191192MaterialData *_create_canvas_material_func(ShaderData *p_shader);193194/* Sky Materials */195196struct SkyShaderData : public ShaderData {197// All these members are (re)initialized in `set_code`.198// Make sure to add the init to `set_code` whenever adding new members.199200bool valid;201RID version;202203Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;204205Vector<uint32_t> ubo_offsets;206uint32_t ubo_size;207208String code;209210bool uses_time;211bool uses_position;212bool uses_half_res;213bool uses_quarter_res;214bool uses_light;215216virtual void set_code(const String &p_Code);217virtual bool is_animated() const;218virtual bool casts_shadows() const;219virtual RS::ShaderNativeSourceCode get_native_source_code() const;220SkyShaderData();221virtual ~SkyShaderData();222};223224ShaderData *_create_sky_shader_func();225226struct SkyMaterialData : public MaterialData {227SkyShaderData *shader_data = nullptr;228bool uniform_set_updated = false;229230virtual void set_render_priority(int p_priority) {}231virtual void set_next_pass(RID p_pass) {}232virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);233virtual void bind_uniforms();234virtual ~SkyMaterialData();235};236237MaterialData *_create_sky_material_func(ShaderData *p_shader);238239/* Scene Materials */240241struct SceneShaderData : public ShaderData {242enum BlendMode { // Used internally.243BLEND_MODE_MIX,244BLEND_MODE_ADD,245BLEND_MODE_SUB,246BLEND_MODE_MUL,247BLEND_MODE_PREMULT_ALPHA,248BLEND_MODE_ALPHA_TO_COVERAGE249};250251enum DepthDraw {252DEPTH_DRAW_DISABLED,253DEPTH_DRAW_OPAQUE,254DEPTH_DRAW_ALWAYS255};256257enum DepthTest {258DEPTH_TEST_DISABLED,259DEPTH_TEST_ENABLED,260DEPTH_TEST_ENABLED_INVERTED,261};262263enum StencilCompare {264STENCIL_COMPARE_LESS,265STENCIL_COMPARE_EQUAL,266STENCIL_COMPARE_LESS_OR_EQUAL,267STENCIL_COMPARE_GREATER,268STENCIL_COMPARE_NOT_EQUAL,269STENCIL_COMPARE_GREATER_OR_EQUAL,270STENCIL_COMPARE_ALWAYS,271STENCIL_COMPARE_MAX // not an actual operator, just the amount of operators272};273274enum StencilFlags {275STENCIL_FLAG_READ = 1,276STENCIL_FLAG_WRITE = 2,277STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,278};279280enum AlphaAntiAliasing {281ALPHA_ANTIALIASING_OFF,282ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,283ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE284};285286// All these members are (re)initialized in `set_code`.287// Make sure to add the init to `set_code` whenever adding new members.288289bool valid;290RID version;291292Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;293294Vector<uint32_t> ubo_offsets;295uint32_t ubo_size;296297String code;298299BlendMode blend_mode;300AlphaAntiAliasing alpha_antialiasing_mode;301DepthDraw depth_draw;302DepthTest depth_test;303RS::CullMode cull_mode;304305StencilCompare stencil_compare;306uint32_t stencil_flags;307int32_t stencil_reference;308bool stencil_enabled;309310bool uses_point_size;311bool uses_alpha;312bool uses_alpha_clip;313bool uses_blend_alpha;314bool uses_depth_prepass_alpha;315bool uses_discard;316bool uses_roughness;317bool uses_normal;318bool uses_particle_trails;319bool wireframe;320321bool unshaded;322bool uses_vertex;323bool uses_position;324bool uses_sss;325bool uses_transmittance;326bool uses_screen_texture;327bool uses_screen_texture_mipmaps;328bool uses_depth_texture;329bool uses_normal_texture;330bool uses_bent_normal_texture;331bool uses_time;332bool uses_vertex_time;333bool uses_fragment_time;334bool writes_modelview_or_projection;335bool uses_world_coordinates;336bool uses_tangent;337bool uses_color;338bool uses_uv;339bool uses_uv2;340bool uses_custom0;341bool uses_custom1;342bool uses_custom2;343bool uses_custom3;344bool uses_bones;345bool uses_weights;346347uint64_t vertex_input_mask;348349virtual void set_code(const String &p_Code);350virtual bool is_animated() const;351virtual bool casts_shadows() const;352virtual RS::ShaderNativeSourceCode get_native_source_code() const;353354SceneShaderData();355virtual ~SceneShaderData();356};357358ShaderData *_create_scene_shader_func();359360struct SceneMaterialData : public MaterialData {361SceneShaderData *shader_data = nullptr;362uint64_t last_pass = 0;363uint32_t index = 0;364RID next_pass;365uint8_t priority = 0;366virtual void set_render_priority(int p_priority);367virtual void set_next_pass(RID p_pass);368virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);369virtual void bind_uniforms();370virtual ~SceneMaterialData();371};372373MaterialData *_create_scene_material_func(ShaderData *p_shader);374375/* Particle Shader */376377enum {378PARTICLES_MAX_USERDATAS = 6379};380381struct ParticlesShaderData : public ShaderData {382// All these members are (re)initialized in `set_code`.383// Make sure to add the init to `set_code` whenever adding new members.384385bool valid;386RID version;387388Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;389390Vector<uint32_t> ubo_offsets;391uint32_t ubo_size;392393String code;394395bool uses_collision;396bool uses_time;397398bool userdatas_used[PARTICLES_MAX_USERDATAS] = {};399uint32_t userdata_count;400401virtual void set_code(const String &p_Code);402virtual bool is_animated() const;403virtual bool casts_shadows() const;404virtual RS::ShaderNativeSourceCode get_native_source_code() const;405406ParticlesShaderData() {}407virtual ~ParticlesShaderData();408};409410ShaderData *_create_particles_shader_func();411412struct ParticleProcessMaterialData : public MaterialData {413ParticlesShaderData *shader_data = nullptr;414RID uniform_set;415416virtual void set_render_priority(int p_priority) {}417virtual void set_next_pass(RID p_pass) {}418virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);419virtual void bind_uniforms();420virtual ~ParticleProcessMaterialData();421};422423MaterialData *_create_particles_material_func(ShaderData *p_shader);424425/* Global shader uniform structs */426struct GlobalShaderUniforms {427enum {428BUFFER_DIRTY_REGION_SIZE = 1024429};430struct Variable {431HashSet<RID> texture_materials; // materials using this432433RS::GlobalShaderParameterType type;434Variant value;435Variant override;436int32_t buffer_index; //for vectors437int32_t buffer_elements; //for vectors438};439440HashMap<StringName, Variable> variables;441442struct Value {443float x;444float y;445float z;446float w;447};448449struct ValueInt {450int32_t x;451int32_t y;452int32_t z;453int32_t w;454};455456struct ValueUInt {457uint32_t x;458uint32_t y;459uint32_t z;460uint32_t w;461};462463struct ValueUsage {464uint32_t elements = 0;465};466467List<RID> materials_using_buffer;468List<RID> materials_using_texture;469470GLuint buffer = GLuint(0);471Value *buffer_values = nullptr;472ValueUsage *buffer_usage = nullptr;473bool *buffer_dirty_regions = nullptr;474uint32_t buffer_dirty_region_count = 0;475476uint32_t buffer_size;477478bool must_update_texture_materials = false;479bool must_update_buffer_materials = false;480481HashMap<RID, int32_t> instance_buffer_pos;482};483484class MaterialStorage : public RendererMaterialStorage {485private:486friend struct MaterialData;487static MaterialStorage *singleton;488489/* GLOBAL SHADER UNIFORM API */490491GlobalShaderUniforms global_shader_uniforms;492493int32_t _global_shader_uniform_allocate(uint32_t p_elements);494void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value);495void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);496497/* SHADER API */498499ShaderDataRequestFunction shader_data_request_func[RS::SHADER_MAX];500mutable RID_Owner<Shader, true> shader_owner;501502/* MATERIAL API */503MaterialDataRequestFunction material_data_request_func[RS::SHADER_MAX];504mutable RID_Owner<Material, true> material_owner;505506SelfList<Material>::List material_update_list;507HashSet<RID> dummy_embedded_set;508509public:510static MaterialStorage *get_singleton();511512MaterialStorage();513virtual ~MaterialStorage();514515static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {516p_array[0] = p_mtx.basis.rows[0][0];517p_array[1] = p_mtx.basis.rows[1][0];518p_array[2] = p_mtx.basis.rows[2][0];519p_array[3] = 0;520p_array[4] = p_mtx.basis.rows[0][1];521p_array[5] = p_mtx.basis.rows[1][1];522p_array[6] = p_mtx.basis.rows[2][1];523p_array[7] = 0;524p_array[8] = p_mtx.basis.rows[0][2];525p_array[9] = p_mtx.basis.rows[1][2];526p_array[10] = p_mtx.basis.rows[2][2];527p_array[11] = 0;528p_array[12] = p_mtx.origin.x;529p_array[13] = p_mtx.origin.y;530p_array[14] = p_mtx.origin.z;531p_array[15] = 1;532}533534static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {535p_array[0] = p_mtx.rows[0][0];536p_array[1] = p_mtx.rows[1][0];537p_array[2] = p_mtx.rows[2][0];538p_array[3] = 0;539p_array[4] = p_mtx.rows[0][1];540p_array[5] = p_mtx.rows[1][1];541p_array[6] = p_mtx.rows[2][1];542p_array[7] = 0;543p_array[8] = p_mtx.rows[0][2];544p_array[9] = p_mtx.rows[1][2];545p_array[10] = p_mtx.rows[2][2];546p_array[11] = 0;547}548549static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {550for (int i = 0; i < 4; i++) {551for (int j = 0; j < 4; j++) {552p_array[i * 4 + j] = p_mtx.columns[i][j];553}554}555}556557struct Shaders {558CanvasShaderGLES3 canvas_shader;559SkyShaderGLES3 sky_shader;560SceneShaderGLES3 scene_shader;561ParticlesShaderGLES3 particles_process_shader;562563ShaderCompiler compiler_canvas;564ShaderCompiler compiler_scene;565ShaderCompiler compiler_particles;566ShaderCompiler compiler_sky;567} shaders;568569/* GLOBAL SHADER UNIFORM API */570571void _update_global_shader_uniforms();572573virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override;574virtual void global_shader_parameter_remove(const StringName &p_name) override;575virtual Vector<StringName> global_shader_parameter_get_list() const override;576577virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override;578virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override;579virtual Variant global_shader_parameter_get(const StringName &p_name) const override;580virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override;581RS::GlobalShaderParameterType global_shader_parameter_get_type_internal(const StringName &p_name) const;582583virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override;584virtual void global_shader_parameters_clear() override;585586virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override;587virtual void global_shader_parameters_instance_free(RID p_instance) override;588virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override;589590GLuint global_shader_parameters_get_uniform_buffer() const;591592/* SHADER API */593594Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }595bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }596597void _shader_make_dirty(Shader *p_shader);598599virtual RID shader_allocate() override;600virtual void shader_initialize(RID p_rid, bool p_embedded = true) override;601virtual void shader_free(RID p_rid) override;602603virtual void shader_set_code(RID p_shader, const String &p_code) override;604virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;605virtual String shader_get_code(RID p_shader) const override;606virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;607608virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;609virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override;610virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_name) const override;611612virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;613virtual void shader_embedded_set_lock() override {}614virtual const HashSet<RID> &shader_embedded_set_get() const override { return dummy_embedded_set; }615virtual void shader_embedded_set_unlock() override {}616617/* MATERIAL API */618619Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }620bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }621622void _material_queue_update(Material *material, bool p_uniform, bool p_texture);623void _update_queued_materials();624625virtual RID material_allocate() override;626virtual void material_initialize(RID p_rid) override;627virtual void material_free(RID p_rid) override;628629virtual void material_set_shader(RID p_material, RID p_shader) override;630631virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;632virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;633634virtual void material_set_next_pass(RID p_material, RID p_next_material) override;635virtual void material_set_render_priority(RID p_material, int priority) override;636637virtual bool material_is_animated(RID p_material) override;638virtual bool material_casts_shadows(RID p_material) override;639virtual RS::CullMode material_get_cull_mode(RID p_material) const override;640641virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;642643virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;644645_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {646Material *material = material_owner.get_or_null(p_material);647return material->shader_id;648}649650_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, RS::ShaderMode p_shader_mode) {651Material *material = material_owner.get_or_null(p_material);652if (!material || material->shader_mode != p_shader_mode) {653return nullptr;654} else {655return material->data;656}657}658};659660} // namespace GLES3661662#endif // GLES3_ENABLED663664665