summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2022-03-31 19:19:03 +0200
committerGitHub <noreply@github.com>2022-03-31 19:19:03 +0200
commit155a94fabee3ca7305677474d41d497d419b258f (patch)
tree99938d19b9d593609ffd7619458a457581464de0 /drivers
parent44b2962f4fa83449b6dc29768b175290a6f6b801 (diff)
parent36defd1179c3600b824feb1362a3216c353c01aa (diff)
Merge pull request #59385 from BastiaanOlij/extract_shader_storage
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp42
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h7
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp4
-rw-r--r--drivers/gles3/rasterizer_gles3.h3
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp872
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h270
-rw-r--r--drivers/gles3/storage/material_storage.cpp913
-rw-r--r--drivers/gles3/storage/material_storage.h338
8 files changed, 1307 insertions, 1142 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index b47d2e08f1..2b8241cd40 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -40,6 +40,7 @@
#include "servers/rendering/rendering_server_default.h"
#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
+#include "storage/material_storage.h"
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
@@ -212,6 +213,8 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -228,14 +231,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
Item *ci = items[i];
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
- RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.get_or_null(material);
+ GLES3::Material *material_ptr = material_storage->get_material(material);
if (material.is_null() && ci->canvas_group != nullptr) {
material = default_canvas_group_material;
}
if (material != prev_material) {
- RasterizerStorageGLES3::Shader *shader_ptr = nullptr;
+ GLES3::Shader *shader_ptr = nullptr;
if (material_ptr) {
shader_ptr = material_ptr->shader;
@@ -906,6 +909,8 @@ void RasterizerCanvasGLES3::canvas_end() {
}
void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, RID &r_last_texture, Size2 &r_texpixel_size) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
if (p_texture == RID()) {
p_texture = default_canvas_texture;
}
@@ -1251,9 +1256,8 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
}
void RasterizerCanvasGLES3::initialize() {
- // !BAS! shouldn't we be obtaining storage here as well?
- canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
- texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
// quad buffer
{
@@ -1423,10 +1427,10 @@ void RasterizerCanvasGLES3::initialize() {
//state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false));
{
- default_canvas_group_shader = storage->shader_allocate();
- storage->shader_initialize(default_canvas_group_shader);
+ default_canvas_group_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_canvas_group_shader);
- storage->shader_set_code(default_canvas_group_shader, R"(
+ material_storage->shader_set_code(default_canvas_group_shader, R"(
// Default CanvasGroup shader.
shader_type canvas_item;
@@ -1441,10 +1445,10 @@ void fragment() {
COLOR *= c;
}
)");
- default_canvas_group_material = storage->material_allocate();
- storage->material_initialize(default_canvas_group_material);
+ default_canvas_group_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_canvas_group_material);
- storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+ material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
@@ -1456,13 +1460,25 @@ void fragment() {
state.current_shader_version = state.canvas_shader_default_version;
}
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::singleton = nullptr;
+
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
+ return singleton;
+}
+
RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
+ singleton = this;
}
+
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
+ GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
state.canvas_shader.version_free(state.canvas_shader_default_version);
- storage->free(default_canvas_group_material);
- storage->free(default_canvas_group_shader);
+ material_storage->material_free(default_canvas_group_material);
+ material_storage->shader_free(default_canvas_group_shader);
canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+ singleton = nullptr;
}
void RasterizerCanvasGLES3::finalize() {
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 1f57c2b5ea..4e825ab8b2 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -38,6 +38,7 @@
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
#include "storage/canvas_texture_storage.h"
+#include "storage/material_storage.h"
#include "storage/texture_storage.h"
#include "shaders/canvas.glsl.gen.h"
@@ -45,6 +46,8 @@
class RasterizerSceneGLES3;
class RasterizerCanvasGLES3 : public RendererCanvasRender {
+ static RasterizerCanvasGLES3 *singleton;
+
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
@@ -219,8 +222,6 @@ public:
RasterizerSceneGLES3 *scene_render;
- GLES3::CanvasTextureStorage *canvas_texture_storage;
- GLES3::TextureStorage *texture_storage;
RasterizerStorageGLES3 *storage;
void _set_uniforms();
@@ -277,6 +278,8 @@ public:
void initialize();
void finalize();
+
+ static RasterizerCanvasGLES3 *get_singleton();
RasterizerCanvasGLES3();
~RasterizerCanvasGLES3();
};
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index faadb2a4ed..61aefc1192 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -260,9 +260,9 @@ void RasterizerGLES3::initialize() {
RasterizerGLES3::RasterizerGLES3() {
canvas.storage = &storage;
canvas.scene_render = &scene;
- storage.canvas = &canvas;
+ //storage.canvas = &canvas;
//scene.storage = &storage;
- storage.scene = &scene;
+ //storage.scene = &scene;
}
void RasterizerGLES3::prepare_for_blitting_render_targets() {
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 4aa94e5293..55ee54e992 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -40,6 +40,7 @@
#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
#include "storage/decal_atlas_storage.h"
+#include "storage/material_storage.h"
#include "storage/render_target_storage.h"
#include "storage/texture_storage.h"
@@ -55,6 +56,7 @@ protected:
GLES3::CanvasTextureStorage canvas_texture_storage;
GLES3::TextureStorage texture_storage;
GLES3::DecalAtlasStorage decal_atlas_storage;
+ GLES3::MaterialStorage material_storage;
RasterizerStorageGLES3 storage;
RasterizerCanvasGLES3 canvas;
RasterizerSceneGLES3 scene;
@@ -63,6 +65,7 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; }
+ RendererMaterialStorage *get_material_storage() { return &material_storage; }
RendererTextureStorage *get_texture_storage() { return &texture_storage; }
RendererDecalAtlasStorage *get_decal_atlas_storage() { return &decal_atlas_storage; }
RendererStorage *get_storage() { return &storage; }
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 5efbc715ab..c71423a45d 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -34,7 +34,7 @@
#include "core/config/project_settings.h"
#include "core/math/transform_3d.h"
-#include "rasterizer_canvas_gles3.h"
+// #include "rasterizer_canvas_gles3.h"
#include "rasterizer_scene_gles3.h"
#include "servers/rendering/shader_language.h"
@@ -58,755 +58,6 @@ RID RasterizerStorageGLES3::sky_create() {
void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) {
}
-/* SHADER API */
-
-RID RasterizerStorageGLES3::shader_allocate() {
- Shader *shader = memnew(Shader);
- shader->mode = RS::SHADER_CANVAS_ITEM;
- //shader->shader = &scene->state.scene_shader;
- RID rid = shader_owner.make_rid(shader);
- _shader_make_dirty(shader);
- shader->self = rid;
-
- return rid;
-}
-
-void RasterizerStorageGLES3::shader_initialize(RID p_rid) {
- // noop
-}
-
-//RID RasterizerStorageGLES3::shader_create() {
-// Shader *shader = memnew(Shader);
-// shader->mode = RS::SHADER_SPATIAL;
-// shader->shader = &scene->state.scene_shader;
-// RID rid = shader_owner.make_rid(shader);
-// _shader_make_dirty(shader);
-// shader->self = rid;
-
-// return rid;
-//}
-
-void RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) {
- if (p_shader->dirty_list.in_list()) {
- return;
- }
-
- _shader_dirty_list.add(&p_shader->dirty_list);
-}
-
-void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- shader->code = p_code;
-
- String mode_string = ShaderLanguage::get_shader_type(p_code);
- RS::ShaderMode mode;
-
- if (mode_string == "canvas_item") {
- mode = RS::SHADER_CANVAS_ITEM;
- } else if (mode_string == "particles") {
- mode = RS::SHADER_PARTICLES;
- } else if (mode_string == "sky") {
- mode = RS::SHADER_SKY;
- } else if (mode_string == "spatial") {
- mode = RS::SHADER_SPATIAL;
- } else {
- mode = RS::SHADER_MAX;
- ERR_PRINT("shader type " + mode_string + " not supported in OpenGL renderer");
- }
-
- if (shader->version.is_valid() && mode != shader->mode) {
- shader->shader->version_free(shader->version);
- shader->version = RID();
- }
-
- shader->mode = mode;
-
- // TODO handle all shader types
- if (mode == RS::SHADER_CANVAS_ITEM) {
- shader->shader = &canvas->state.canvas_shader;
-
- } else if (mode == RS::SHADER_SPATIAL) {
- //shader->shader = &scene->state.scene_shader;
- } else if (mode == RS::SHADER_PARTICLES) {
- } else if (mode == RS::SHADER_SKY) {
- } else {
- return;
- }
-
- if (shader->version.is_null() && shader->shader) {
- shader->version = shader->shader->version_create();
- }
-
- _shader_make_dirty(shader);
-}
-
-String RasterizerStorageGLES3::shader_get_code(RID p_shader) const {
- const Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, "");
-
- return shader->code;
-}
-
-void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
- _shader_dirty_list.remove(&p_shader->dirty_list);
-
- p_shader->valid = false;
-
- p_shader->uniforms.clear();
-
- if (p_shader->code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions *actions = nullptr;
-
- switch (p_shader->mode) {
- case RS::SHADER_CANVAS_ITEM: {
- p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
- p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
-
- p_shader->canvas_item.uses_screen_texture = false;
- p_shader->canvas_item.uses_screen_uv = false;
- p_shader->canvas_item.uses_time = false;
- p_shader->canvas_item.uses_modulate = false;
- p_shader->canvas_item.uses_color = false;
- p_shader->canvas_item.uses_vertex = false;
-
- p_shader->canvas_item.uses_model_matrix = false;
- p_shader->canvas_item.uses_extra_matrix = false;
- p_shader->canvas_item.uses_projection_matrix = false;
- p_shader->canvas_item.uses_instance_custom = false;
-
- shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
- shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
- shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
- shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
- shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
-
- shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
- shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
-
- shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
- shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
- shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
- shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
- shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate;
- shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color;
-
- shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
-
- shaders.actions_canvas.usage_flag_pointers["MODEL_MATRIX"] = &p_shader->canvas_item.uses_model_matrix;
- shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
- shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
- shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
-
- actions = &shaders.actions_canvas;
- actions->uniforms = &p_shader->uniforms;
- } break;
-
- case RS::SHADER_SPATIAL: {
- // TODO remove once 3D is added back
- return;
- p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
- p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
- p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
- p_shader->spatial.uses_alpha = false;
- p_shader->spatial.uses_alpha_scissor = false;
- p_shader->spatial.uses_discard = false;
- p_shader->spatial.unshaded = false;
- p_shader->spatial.no_depth_test = false;
- p_shader->spatial.uses_sss = false;
- p_shader->spatial.uses_time = false;
- p_shader->spatial.uses_vertex_lighting = false;
- p_shader->spatial.uses_screen_texture = false;
- p_shader->spatial.uses_depth_texture = false;
- p_shader->spatial.uses_vertex = false;
- p_shader->spatial.uses_tangent = false;
- p_shader->spatial.uses_ensure_correct_normals = false;
- p_shader->spatial.writes_modelview_or_projection = false;
- p_shader->spatial.uses_world_coordinates = false;
-
- shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
- shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
- shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
- shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
-
- shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
- shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
- shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
- shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
-
- shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
- shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
- shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
-
- shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
- shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
-
- shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting;
-
- shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;
-
- shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;
-
- shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
- shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;
-
- shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
- shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
- shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
- shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
- shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
-
- // Use of any of these BUILTINS indicate the need for transformed tangents.
- // This is needed to know when to transform tangents in software skinning.
- shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
- shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;
-
- shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
- shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
- shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
-
- actions = &shaders.actions_scene;
- actions->uniforms = &p_shader->uniforms;
- } break;
-
- default: {
- return;
- } break;
- }
-
- Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
- if (err != OK) {
- return;
- }
-
- Vector<StringName> texture_uniform_names;
- for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
- texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
- }
-
- p_shader->shader->version_set_code(p_shader->version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
-
- p_shader->texture_uniforms = gen_code.texture_uniforms;
-
- p_shader->uses_vertex_time = gen_code.uses_vertex_time;
- p_shader->uses_fragment_time = gen_code.uses_fragment_time;
-
- for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) {
- _material_make_dirty(E->self());
- }
-
- p_shader->valid = true;
-}
-
-void RasterizerStorageGLES3::update_dirty_shaders() {
- while (_shader_dirty_list.first()) {
- _update_shader(_shader_dirty_list.first()->self());
- }
-}
-
-void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- if (shader->dirty_list.in_list()) {
- _update_shader(shader);
- }
-
- Map<int, StringName> order;
-
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
- } else {
- order[E->get().order] = E->key();
- }
- }
-
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi;
- ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
-
- pi.name = E->get();
-
- switch (u.type) {
- case ShaderLanguage::TYPE_VOID: {
- pi.type = Variant::NIL;
- } break;
-
- case ShaderLanguage::TYPE_BOOL: {
- pi.type = Variant::BOOL;
- } break;
-
- // bool vectors
- case ShaderLanguage::TYPE_BVEC2: {
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y";
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z";
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z,w";
- } break;
-
- // int stuff
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_INT: {
- pi.type = Variant::INT;
-
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
- }
- } break;
-
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC4: {
- // not sure what this should be in godot 4
- // pi.type = Variant::POOL_INT_ARRAY;
- pi.type = Variant::PACKED_INT32_ARRAY;
- } break;
-
- case ShaderLanguage::TYPE_FLOAT: {
- pi.type = Variant::FLOAT;
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
- }
- } break;
-
- case ShaderLanguage::TYPE_VEC2: {
- pi.type = Variant::VECTOR2;
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- pi.type = Variant::VECTOR3;
- } break;
-
- case ShaderLanguage::TYPE_VEC4: {
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- pi.type = Variant::COLOR;
- } else {
- pi.type = Variant::PLANE;
- }
- } break;
-
- case ShaderLanguage::TYPE_MAT2: {
- pi.type = Variant::TRANSFORM2D;
- } break;
-
- case ShaderLanguage::TYPE_MAT3: {
- pi.type = Variant::BASIS;
- } break;
-
- case ShaderLanguage::TYPE_MAT4: {
- pi.type = Variant::TRANSFORM3D;
- } break;
-
- case ShaderLanguage::TYPE_SAMPLER2D:
- // case ShaderLanguage::TYPE_SAMPLEREXT:
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D: {
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "Texture";
- } break;
-
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "CubeMap";
- } break;
-
- case ShaderLanguage::TYPE_SAMPLER2DARRAY:
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY:
- case ShaderLanguage::TYPE_SAMPLER3D:
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D: {
- // Not implemented in OpenGL
- } break;
- // new for godot 4
- case ShaderLanguage::TYPE_SAMPLERCUBEARRAY:
- case ShaderLanguage::TYPE_STRUCT:
- case ShaderLanguage::TYPE_MAX: {
- } break;
- }
-
- p_param_list->push_back(pi);
- }
-}
-
-void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
- ERR_FAIL_COND(p_texture.is_valid() && !GLES3::TextureStorage::get_singleton()->owns_texture(p_texture));
-
- if (!p_texture.is_valid()) {
- if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
- shader->default_textures[p_name].erase(p_index);
-
- if (shader->default_textures[p_name].is_empty()) {
- shader->default_textures.erase(p_name);
- }
- }
- } else {
- if (!shader->default_textures.has(p_name)) {
- shader->default_textures[p_name] = Map<int, RID>();
- }
- shader->default_textures[p_name][p_index] = p_texture;
- }
-
- _shader_make_dirty(shader);
-}
-
-RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
- const Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RID());
-
- if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
- return shader->default_textures[p_name][p_index];
- }
-
- return RID();
-}
-
-/* COMMON MATERIAL API */
-
-void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const {
- if (p_material->dirty_list.in_list()) {
- return;
- }
-
- _material_dirty_list.add(&p_material->dirty_list);
-}
-
-RID RasterizerStorageGLES3::material_allocate() {
- Material *material = memnew(Material);
- return material_owner.make_rid(material);
-}
-
-void RasterizerStorageGLES3::material_initialize(RID p_rid) {
-}
-
-//RID RasterizerStorageGLES3::material_create() {
-// Material *material = memnew(Material);
-
-// return material_owner.make_rid(material);
-//}
-
-void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- Shader *shader = shader_owner.get_or_null(p_shader);
-
- if (material->shader) {
- // if a shader is present, remove the old shader
- material->shader->materials.remove(&material->list);
- }
-
- material->shader = shader;
-
- if (shader) {
- shader->materials.add(&material->list);
- }
-
- _material_make_dirty(material);
-}
-
-RID RasterizerStorageGLES3::material_get_shader(RID p_material) const {
- const Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, RID());
-
- if (material->shader) {
- return material->shader->self;
- }
-
- return RID();
-}
-
-void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (p_value.get_type() == Variant::NIL) {
- material->params.erase(p_param);
- } else {
- material->params[p_param] = p_value;
- }
-
- _material_make_dirty(material);
-}
-
-Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const {
- const Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, RID());
-
- if (material->params.has(p_param)) {
- return material->params[p_param];
- }
-
- return material_get_param_default(p_material, p_param);
-}
-
-Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const StringName &p_param) const {
- const Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, Variant());
-
- if (material->shader) {
- if (material->shader->uniforms.has(p_param)) {
- ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
- Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
- }
- }
- return Variant();
-}
-
-void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_width) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- material->line_width = p_width;
-}
-
-void RasterizerStorageGLES3::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- material->next_pass = p_next_material;
-}
-
-bool RasterizerStorageGLES3::material_is_animated(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->dirty_list.in_list()) {
- _update_material(material);
- }
-
- bool animated = material->is_animated_cache;
- if (!animated && material->next_pass.is_valid()) {
- animated = material_is_animated(material->next_pass);
- }
- return animated;
-}
-
-bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->dirty_list.in_list()) {
- _update_material(material);
- }
-
- bool casts_shadows = material->can_cast_shadow_cache;
-
- if (!casts_shadows && material->next_pass.is_valid()) {
- casts_shadows = material_casts_shadows(material->next_pass);
- }
-
- return casts_shadows;
-}
-
-bool RasterizerStorageGLES3::material_uses_tangents(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
-
- if (!material->shader) {
- return false;
- }
-
- if (material->shader->dirty_list.in_list()) {
- _update_shader(material->shader);
- }
-
- return material->shader->spatial.uses_tangent;
-}
-
-bool RasterizerStorageGLES3::material_uses_ensure_correct_normals(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
-
- if (!material->shader) {
- return false;
- }
-
- if (material->shader->dirty_list.in_list()) {
- _update_shader(material->shader);
- }
-
- return material->shader->spatial.uses_ensure_correct_normals;
-}
-
-void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, DependencyTracker *p_instance) {
- /*
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
- if (E) {
- E->get()++;
- } else {
- material->instance_owners[p_instance] = 1;
- }
-*/
-}
-
-void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, DependencyTracker *p_instance) {
- /*
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
- ERR_FAIL_COND(!E);
-
- E->get()--;
-
- if (E->get() == 0) {
- material->instance_owners.erase(E);
- }
-*/
-}
-
-void RasterizerStorageGLES3::material_set_render_priority(RID p_material, int priority) {
- ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN);
- ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX);
-
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- material->render_priority = priority;
-}
-
-void RasterizerStorageGLES3::_update_material(Material *p_material) {
- if (p_material->dirty_list.in_list()) {
- _material_dirty_list.remove(&p_material->dirty_list);
- }
-
- if (p_material->shader && p_material->shader->dirty_list.in_list()) {
- _update_shader(p_material->shader);
- }
-
- if (p_material->shader && !p_material->shader->valid) {
- return;
- }
-
- {
- bool can_cast_shadow = false;
- bool is_animated = false;
-
- if (p_material->shader && p_material->shader->mode == RS::SHADER_SPATIAL) {
- if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
- (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
- can_cast_shadow = true;
- }
-
- if (p_material->shader->spatial.uses_discard && p_material->shader->uses_fragment_time) {
- is_animated = true;
- }
-
- if (p_material->shader->spatial.uses_vertex && p_material->shader->uses_vertex_time) {
- is_animated = true;
- }
-
- if (can_cast_shadow != p_material->can_cast_shadow_cache || is_animated != p_material->is_animated_cache) {
- p_material->can_cast_shadow_cache = can_cast_shadow;
- p_material->is_animated_cache = is_animated;
-
- /*
- for (Map<Geometry *, int>::Element *E = p_material->geometry_owners.front(); E; E = E->next()) {
- E->key()->material_changed_notify();
- }
-
- for (Map<InstanceBaseDependency *, int>::Element *E = p_material->instance_owners.front(); E; E = E->next()) {
- E->key()->base_changed(false, true);
- }
- */
- }
- }
- }
-
- // uniforms and other things will be set in the use_material method in ShaderGLES3
-
- if (p_material->shader && p_material->shader->texture_uniforms.size() > 0) {
- p_material->textures.resize(p_material->shader->texture_uniforms.size());
-
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_material->shader->uniforms.front(); E; E = E->next()) {
- if (E->get().texture_order < 0) {
- continue; // not a texture, does not go here
- }
-
- RID texture;
-
- Map<StringName, Variant>::Element *V = p_material->params.find(E->key());
-
- if (V) {
- texture = V->get();
- }
-
- if (!texture.is_valid()) {
- Map<StringName, Map<int, RID>>::Element *W = p_material->shader->default_textures.find(E->key());
-
- // TODO: make texture uniform array properly works with GLES3
- if (W && W->get().has(0)) {
- texture = W->get()[0];
- }
- }
-
- p_material->textures.write[E->get().texture_order] = Pair<StringName, RID>(E->key(), texture);
- }
- } else {
- p_material->textures.clear();
- }
-}
-/*
-void RasterizerStorageGLES3::_material_add_geometry(RID p_material, Geometry *p_geometry) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
-
- if (I) {
- I->get()++;
- } else {
- material->geometry_owners[p_geometry] = 1;
- }
-}
-
-void RasterizerStorageGLES3::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
- ERR_FAIL_COND(!I);
-
- I->get()--;
-
- if (I->get() == 0) {
- material->geometry_owners.erase(I);
- }
-}
-*/
-void RasterizerStorageGLES3::update_dirty_materials() {
- while (_material_dirty_list.first()) {
- Material *material = _material_dirty_list.first()->self();
- _update_material(material);
- }
-}
-
/* MESH API */
RID RasterizerStorageGLES3::mesh_allocate() {
@@ -1489,6 +740,10 @@ void RasterizerStorageGLES3::particles_set_canvas_sdf_collision(RID p_particles,
void RasterizerStorageGLES3::update_particles() {
}
+bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
+ return false;
+}
+
/* PARTICLES COLLISION */
RID RasterizerStorageGLES3::particles_collision_allocate() {
@@ -1595,52 +850,6 @@ AABB RasterizerStorageGLES3::visibility_notifier_get_aabb(RID p_notifier) const
void RasterizerStorageGLES3::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
}
-/* GLOBAL VARIABLES */
-
-void RasterizerStorageGLES3::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
-}
-
-void RasterizerStorageGLES3::global_variable_remove(const StringName &p_name) {
-}
-
-Vector<StringName> RasterizerStorageGLES3::global_variable_get_list() const {
- return Vector<StringName>();
-}
-
-void RasterizerStorageGLES3::global_variable_set(const StringName &p_name, const Variant &p_value) {
-}
-
-void RasterizerStorageGLES3::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
-}
-
-Variant RasterizerStorageGLES3::global_variable_get(const StringName &p_name) const {
- return Variant();
-}
-
-RS::GlobalVariableType RasterizerStorageGLES3::global_variable_get_type(const StringName &p_name) const {
- return RS::GLOBAL_VAR_TYPE_MAX;
-}
-
-void RasterizerStorageGLES3::global_variables_load_settings(bool p_load_textures) {
-}
-
-void RasterizerStorageGLES3::global_variables_clear() {
-}
-
-int32_t RasterizerStorageGLES3::global_variables_instance_allocate(RID p_instance) {
- return 0;
-}
-
-void RasterizerStorageGLES3::global_variables_instance_free(RID p_instance) {
-}
-
-void RasterizerStorageGLES3::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
-}
-
-bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
- return false;
-}
-
/* RENDER TARGET */
void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) {
@@ -2594,63 +1803,12 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
memdelete(sky);
return true;
- } else if (shader_owner.owns(p_rid)) {
- Shader *shader = shader_owner.get_or_null(p_rid);
-
- if (shader->shader && shader->version.is_valid()) {
- shader->shader->version_free(shader->version);
- }
-
- if (shader->dirty_list.in_list()) {
- _shader_dirty_list.remove(&shader->dirty_list);
- }
-
- while (shader->materials.first()) {
- Material *m = shader->materials.first()->self();
-
- m->shader = nullptr;
- _material_make_dirty(m);
-
- shader->materials.remove(shader->materials.first());
- }
-
- shader_owner.free(p_rid);
- memdelete(shader);
-
+ } else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+ GLES3::MaterialStorage::get_singleton()->shader_free(p_rid);
return true;
- } else if (material_owner.owns(p_rid)) {
- Material *m = material_owner.get_or_null(p_rid);
-
- if (m->shader) {
- m->shader->materials.remove(&m->list);
- }
-
- /*
- for (Map<Geometry *, int>::Element *E = m->geometry_owners.front(); E; E = E->next()) {
- Geometry *g = E->key();
- g->material = RID();
- }
-
- for (Map<InstanceBaseDependency *, int>::Element *E = m->instance_owners.front(); E; E = E->next()) {
- InstanceBaseDependency *ins = E->key();
-
- if (ins->material_override == p_rid) {
- ins->material_override = RID();
- }
-
- for (int i = 0; i < ins->materials.size(); i++) {
- if (ins->materials[i] == p_rid) {
- ins->materials.write[i] = RID();
- }
- }
- }
-*/
-
- material_owner.free(p_rid);
- memdelete(m);
-
+ } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+ GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
return true;
-
} else {
return false;
}
@@ -2975,13 +2133,6 @@ void RasterizerStorageGLES3::initialize() {
// OR max_vertex_texture_image_units is zero
config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0);
- shaders.copy.initialize();
- shaders.copy_version = shaders.copy.version_create(); //TODO
- shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
- //shaders.cubemap_filter.init();
- //bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
- //shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
-
{
// quad for copying stuff
@@ -3139,8 +2290,8 @@ uint64_t RasterizerStorageGLES3::get_rendering_info(RS::RenderingInfo p_info) {
}
void RasterizerStorageGLES3::update_dirty_resources() {
- update_dirty_shaders();
- update_dirty_materials();
+ GLES3::MaterialStorage::get_singleton()->update_dirty_shaders();
+ GLES3::MaterialStorage::get_singleton()->update_dirty_materials();
// update_dirty_skeletons();
// update_dirty_multimeshes();
}
@@ -3150,7 +2301,6 @@ RasterizerStorageGLES3::RasterizerStorageGLES3() {
}
RasterizerStorageGLES3::~RasterizerStorageGLES3() {
- shaders.copy.version_free(shaders.copy_version);
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 4e04b918c2..b9022142dd 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -42,18 +42,17 @@
#include "servers/rendering/shader_language.h"
#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
+#include "storage/material_storage.h"
#include "storage/render_target_storage.h"
#include "storage/texture_storage.h"
-#include "shaders/copy.glsl.gen.h"
-
-class RasterizerCanvasGLES3;
-class RasterizerSceneGLES3;
+// class RasterizerCanvasGLES3;
+// class RasterizerSceneGLES3;
class RasterizerStorageGLES3 : public RendererStorage {
public:
- RasterizerCanvasGLES3 *canvas;
- RasterizerSceneGLES3 *scene;
+ // RasterizerCanvasGLES3 *canvas;
+ // RasterizerSceneGLES3 *scene;
static GLuint system_fbo;
@@ -79,19 +78,6 @@ public:
} resources;
- mutable struct Shaders {
- ShaderCompiler compiler;
-
- CopyShaderGLES3 copy;
- RID copy_version;
- //CubemapFilterShaderGLES3 cubemap_filter;
-
- ShaderCompiler::IdentifierActions actions_canvas;
- ShaderCompiler::IdentifierActions actions_scene;
- ShaderCompiler::IdentifierActions actions_particles;
-
- } shaders;
-
struct Info {
uint64_t texture_mem = 0;
uint64_t vertex_mem = 0;
@@ -146,231 +132,6 @@ public:
RID sky_create();
void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
- // SHADER API
-
- struct Material;
-
- struct Shader {
- RID self;
-
- RS::ShaderMode mode;
- ShaderGLES3 *shader;
- String code;
- SelfList<Material>::List materials;
-
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
-
- RID version;
-
- SelfList<Shader> dirty_list;
-
- Map<StringName, Map<int, RID>> default_textures;
-
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- bool valid;
-
- String path;
-
- uint32_t index;
- uint64_t last_pass;
-
- struct CanvasItem {
- enum BlendMode {
- BLEND_MODE_MIX,
- BLEND_MODE_ADD,
- BLEND_MODE_SUB,
- BLEND_MODE_MUL,
- BLEND_MODE_PMALPHA,
- };
-
- int blend_mode;
-
- enum LightMode {
- LIGHT_MODE_NORMAL,
- LIGHT_MODE_UNSHADED,
- LIGHT_MODE_LIGHT_ONLY
- };
-
- int light_mode;
-
- bool uses_screen_texture;
- bool uses_screen_uv;
- bool uses_time;
- bool uses_modulate;
- bool uses_color;
- bool uses_vertex;
-
- // all these should disable item joining if used in a custom shader
- bool uses_model_matrix;
- bool uses_extra_matrix;
- bool uses_projection_matrix;
- bool uses_instance_custom;
-
- } canvas_item;
-
- struct Spatial {
- enum BlendMode {
- BLEND_MODE_MIX,
- BLEND_MODE_ADD,
- BLEND_MODE_SUB,
- BLEND_MODE_MUL,
- };
-
- int blend_mode;
-
- enum DepthDrawMode {
- DEPTH_DRAW_OPAQUE,
- DEPTH_DRAW_ALWAYS,
- DEPTH_DRAW_NEVER,
- DEPTH_DRAW_ALPHA_PREPASS,
- };
-
- int depth_draw_mode;
-
- enum CullMode {
- CULL_MODE_FRONT,
- CULL_MODE_BACK,
- CULL_MODE_DISABLED,
- };
-
- int cull_mode;
-
- bool uses_alpha;
- bool uses_alpha_scissor;
- bool unshaded;
- bool no_depth_test;
- bool uses_vertex;
- bool uses_discard;
- bool uses_sss;
- bool uses_screen_texture;
- bool uses_depth_texture;
- bool uses_time;
- bool uses_tangent;
- bool uses_ensure_correct_normals;
- bool writes_modelview_or_projection;
- bool uses_vertex_lighting;
- bool uses_world_coordinates;
-
- } spatial;
-
- struct Particles {
- } particles;
-
- bool uses_vertex_time;
- bool uses_fragment_time;
-
- Shader() :
- dirty_list(this) {
- shader = nullptr;
- valid = false;
- version = RID();
- last_pass = 0;
- }
- };
-
- mutable RID_PtrOwner<Shader> shader_owner;
- mutable SelfList<Shader>::List _shader_dirty_list;
-
- void _shader_make_dirty(Shader *p_shader);
-
- RID shader_allocate() override;
- void shader_initialize(RID p_rid) override;
-
- //RID shader_create() override;
-
- void shader_set_code(RID p_shader, const String &p_code) override;
- String shader_get_code(RID p_shader) const override;
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
-
- RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
- void _update_shader(Shader *p_shader) const;
- void update_dirty_shaders();
-
- // new
- Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- // COMMON MATERIAL API
-
- struct Material {
- RID self;
- Shader *shader;
- Map<StringName, Variant> params;
- SelfList<Material> list;
- SelfList<Material> dirty_list;
- Vector<Pair<StringName, RID>> textures;
- float line_width;
- int render_priority;
-
- RID next_pass;
-
- uint32_t index;
- uint64_t last_pass;
-
- // Map<Geometry *, int> geometry_owners;
- // Map<InstanceBaseDependency *, int> instance_owners;
-
- bool can_cast_shadow_cache;
- bool is_animated_cache;
-
- Material() :
- list(this),
- dirty_list(this) {
- can_cast_shadow_cache = false;
- is_animated_cache = false;
- shader = nullptr;
- line_width = 1.0;
- last_pass = 0;
- render_priority = 0;
- }
- };
-
- mutable SelfList<Material>::List _material_dirty_list;
- void _material_make_dirty(Material *p_material) const;
-
- // void _material_add_geometry(RID p_material, Geometry *p_geometry);
- // void _material_remove_geometry(RID p_material, Geometry *p_geometry);
-
- void _update_material(Material *p_material);
-
- mutable RID_PtrOwner<Material> material_owner;
-
- // new
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
- void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
-
- // old
- RID material_allocate() override;
- void material_initialize(RID p_rid) override;
-
- //RID material_create() override;
-
- void material_set_shader(RID p_material, RID p_shader) override;
- RID material_get_shader(RID p_material) const;
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
- Variant material_get_param(RID p_material, const StringName &p_param) const override;
- Variant material_get_param_default(RID p_material, const StringName &p_param) const;
-
- void material_set_line_width(RID p_material, float p_width);
- void material_set_next_pass(RID p_material, RID p_next_material) override;
-
- bool material_is_animated(RID p_material) override;
- bool material_casts_shadows(RID p_material) override;
- bool material_uses_tangents(RID p_material);
- bool material_uses_ensure_correct_normals(RID p_material);
-
- void material_add_instance_owner(RID p_material, DependencyTracker *p_instance);
- void material_remove_instance_owner(RID p_material, DependencyTracker *p_instance);
-
- void material_set_render_priority(RID p_material, int priority) override;
-
- void update_dirty_materials();
-
/* MESH API */
RID mesh_allocate() override;
@@ -694,6 +455,7 @@ public:
void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
void update_particles() override;
+ bool particles_is_inactive(RID p_particles) const override;
/* PARTICLES COLLISION */
@@ -737,26 +499,6 @@ public:
AABB visibility_notifier_get_aabb(RID p_notifier) const override;
void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
- /* GLOBAL VARIABLES */
-
- void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- void global_variable_remove(const StringName &p_name) override;
- Vector<StringName> global_variable_get_list() const override;
-
- void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- Variant global_variable_get(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
-
- void global_variables_load_settings(bool p_load_textures = true) override;
- void global_variables_clear() override;
-
- int32_t global_variables_instance_allocate(RID p_instance) override;
- void global_variables_instance_free(RID p_instance) override;
- void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
-
- bool particles_is_inactive(RID p_particles) const override;
-
// RENDER TARGET
mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
new file mode 100644
index 0000000000..f773a6160a
--- /dev/null
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -0,0 +1,913 @@
+/*************************************************************************/
+/* material_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "material_storage.h"
+#include "config.h"
+#include "texture_storage.h"
+
+#include "drivers/gles3/rasterizer_canvas_gles3.h"
+
+using namespace GLES3;
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+ return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+ singleton = this;
+
+ shaders.copy.initialize();
+ shaders.copy_version = shaders.copy.version_create(); //TODO
+ shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
+ //shaders.cubemap_filter.init();
+ //bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
+ //shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
+}
+
+MaterialStorage::~MaterialStorage() {
+ shaders.copy.version_free(shaders.copy_version);
+
+ singleton = nullptr;
+}
+
+/* GLOBAL VARIABLE API */
+
+void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+}
+
+Vector<StringName> MaterialStorage::global_variable_get_list() const {
+ return Vector<StringName>();
+}
+
+void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+}
+
+Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+ return Variant();
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+ return RS::GLOBAL_VAR_TYPE_MAX;
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+}
+
+void MaterialStorage::global_variables_clear() {
+}
+
+int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
+ return 0;
+}
+
+void MaterialStorage::global_variables_instance_free(RID p_instance) {
+}
+
+void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+}
+
+/* SHADER API */
+
+void MaterialStorage::_shader_make_dirty(Shader *p_shader) {
+ if (p_shader->dirty_list.in_list()) {
+ return;
+ }
+
+ _shader_dirty_list.add(&p_shader->dirty_list);
+}
+
+RID MaterialStorage::shader_allocate() {
+ Shader *shader = memnew(Shader);
+ shader->mode = RS::SHADER_CANVAS_ITEM;
+ //shader->shader = &scene->state.scene_shader;
+ RID rid = shader_owner.make_rid(shader);
+ _shader_make_dirty(shader);
+ shader->self = rid;
+
+ return rid;
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+ // noop
+}
+
+//RID MaterialStorage::shader_create() {
+// Shader *shader = memnew(Shader);
+// shader->mode = RS::SHADER_SPATIAL;
+// shader->shader = &scene->state.scene_shader;
+// RID rid = shader_owner.make_rid(shader);
+// _shader_make_dirty(shader);
+// shader->self = rid;
+
+// return rid;
+//}
+
+void MaterialStorage::shader_free(RID p_rid) {
+ Shader *shader = shader_owner.get_or_null(p_rid);
+
+ if (shader->shader && shader->version.is_valid()) {
+ shader->shader->version_free(shader->version);
+ }
+
+ if (shader->dirty_list.in_list()) {
+ _shader_dirty_list.remove(&shader->dirty_list);
+ }
+
+ while (shader->materials.first()) {
+ Material *m = shader->materials.first()->self();
+
+ m->shader = nullptr;
+ _material_make_dirty(m);
+
+ shader->materials.remove(shader->materials.first());
+ }
+
+ shader_owner.free(p_rid);
+ memdelete(shader);
+}
+
+void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->code = p_code;
+
+ String mode_string = ShaderLanguage::get_shader_type(p_code);
+ RS::ShaderMode mode;
+
+ if (mode_string == "canvas_item") {
+ mode = RS::SHADER_CANVAS_ITEM;
+ } else if (mode_string == "particles") {
+ mode = RS::SHADER_PARTICLES;
+ } else if (mode_string == "sky") {
+ mode = RS::SHADER_SKY;
+ } else if (mode_string == "spatial") {
+ mode = RS::SHADER_SPATIAL;
+ } else {
+ mode = RS::SHADER_MAX;
+ ERR_PRINT("shader type " + mode_string + " not supported in OpenGL renderer");
+ }
+
+ if (shader->version.is_valid() && mode != shader->mode) {
+ shader->shader->version_free(shader->version);
+ shader->version = RID();
+ }
+
+ shader->mode = mode;
+
+ // TODO handle all shader types
+ if (mode == RS::SHADER_CANVAS_ITEM) {
+ shader->shader = &RasterizerCanvasGLES3::get_singleton()->state.canvas_shader;
+ } else if (mode == RS::SHADER_SPATIAL) {
+ //shader->shader = &scene->state.scene_shader;
+ } else if (mode == RS::SHADER_PARTICLES) {
+ } else if (mode == RS::SHADER_SKY) {
+ } else {
+ return;
+ }
+
+ if (shader->version.is_null() && shader->shader) {
+ shader->version = shader->shader->version_create();
+ }
+
+ _shader_make_dirty(shader);
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+ const Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, "");
+
+ return shader->code;
+}
+
+void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ if (shader->dirty_list.in_list()) {
+ _update_shader(shader);
+ }
+
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+ PropertyInfo pi;
+ ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
+
+ pi.name = E->get();
+
+ switch (u.type) {
+ case ShaderLanguage::TYPE_VOID: {
+ pi.type = Variant::NIL;
+ } break;
+
+ case ShaderLanguage::TYPE_BOOL: {
+ pi.type = Variant::BOOL;
+ } break;
+
+ // bool vectors
+ case ShaderLanguage::TYPE_BVEC2: {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y";
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z";
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z,w";
+ } break;
+
+ // int stuff
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_INT: {
+ pi.type = Variant::INT;
+
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC4: {
+ // not sure what this should be in godot 4
+ // pi.type = Variant::POOL_INT_ARRAY;
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } break;
+
+ case ShaderLanguage::TYPE_FLOAT: {
+ pi.type = Variant::FLOAT;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_VEC2: {
+ pi.type = Variant::VECTOR2;
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ pi.type = Variant::VECTOR3;
+ } break;
+
+ case ShaderLanguage::TYPE_VEC4: {
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type = Variant::COLOR;
+ } else {
+ pi.type = Variant::PLANE;
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_MAT2: {
+ pi.type = Variant::TRANSFORM2D;
+ } break;
+
+ case ShaderLanguage::TYPE_MAT3: {
+ pi.type = Variant::BASIS;
+ } break;
+
+ case ShaderLanguage::TYPE_MAT4: {
+ pi.type = Variant::TRANSFORM3D;
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLER2D:
+ // case ShaderLanguage::TYPE_SAMPLEREXT:
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D: {
+ pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "Texture";
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "CubeMap";
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D: {
+ // Not implemented in OpenGL
+ } break;
+ // new for godot 4
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY:
+ case ShaderLanguage::TYPE_STRUCT:
+ case ShaderLanguage::TYPE_MAX: {
+ } break;
+ }
+
+ p_param_list->push_back(pi);
+ }
+}
+
+void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+ ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture));
+
+ if (!p_texture.is_valid()) {
+ if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
+ shader->default_textures[p_name].erase(p_index);
+
+ if (shader->default_textures[p_name].is_empty()) {
+ shader->default_textures.erase(p_name);
+ }
+ }
+ } else {
+ if (!shader->default_textures.has(p_name)) {
+ shader->default_textures[p_name] = Map<int, RID>();
+ }
+ shader->default_textures[p_name][p_index] = p_texture;
+ }
+
+ _shader_make_dirty(shader);
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+ const Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RID());
+
+ if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
+ return shader->default_textures[p_name][p_index];
+ }
+
+ return RID();
+}
+
+void MaterialStorage::_update_shader(Shader *p_shader) const {
+ _shader_dirty_list.remove(&p_shader->dirty_list);
+
+ p_shader->valid = false;
+
+ p_shader->uniforms.clear();
+
+ if (p_shader->code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions *actions = nullptr;
+
+ switch (p_shader->mode) {
+ case RS::SHADER_CANVAS_ITEM: {
+ p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
+ p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
+
+ p_shader->canvas_item.uses_screen_texture = false;
+ p_shader->canvas_item.uses_screen_uv = false;
+ p_shader->canvas_item.uses_time = false;
+ p_shader->canvas_item.uses_modulate = false;
+ p_shader->canvas_item.uses_color = false;
+ p_shader->canvas_item.uses_vertex = false;
+
+ p_shader->canvas_item.uses_model_matrix = false;
+ p_shader->canvas_item.uses_extra_matrix = false;
+ p_shader->canvas_item.uses_projection_matrix = false;
+ p_shader->canvas_item.uses_instance_custom = false;
+
+ shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
+ shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
+ shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
+ shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
+ shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
+
+ shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
+ shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
+
+ shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
+ shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
+ shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
+ shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
+ shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate;
+ shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color;
+
+ shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
+
+ shaders.actions_canvas.usage_flag_pointers["MODEL_MATRIX"] = &p_shader->canvas_item.uses_model_matrix;
+ shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
+ shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
+ shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
+
+ actions = &shaders.actions_canvas;
+ actions->uniforms = &p_shader->uniforms;
+ } break;
+
+ case RS::SHADER_SPATIAL: {
+ // TODO remove once 3D is added back
+ return;
+ p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
+ p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
+ p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
+ p_shader->spatial.uses_alpha = false;
+ p_shader->spatial.uses_alpha_scissor = false;
+ p_shader->spatial.uses_discard = false;
+ p_shader->spatial.unshaded = false;
+ p_shader->spatial.no_depth_test = false;
+ p_shader->spatial.uses_sss = false;
+ p_shader->spatial.uses_time = false;
+ p_shader->spatial.uses_vertex_lighting = false;
+ p_shader->spatial.uses_screen_texture = false;
+ p_shader->spatial.uses_depth_texture = false;
+ p_shader->spatial.uses_vertex = false;
+ p_shader->spatial.uses_tangent = false;
+ p_shader->spatial.uses_ensure_correct_normals = false;
+ p_shader->spatial.writes_modelview_or_projection = false;
+ p_shader->spatial.uses_world_coordinates = false;
+
+ shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
+ shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
+ shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
+ shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
+
+ shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
+ shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
+ shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
+ shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
+
+ shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
+ shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
+ shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
+
+ shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
+ shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
+
+ shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting;
+
+ shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;
+
+ shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;
+
+ shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
+ shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;
+
+ shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
+ shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
+ shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
+ shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
+ shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
+
+ // Use of any of these BUILTINS indicate the need for transformed tangents.
+ // This is needed to know when to transform tangents in software skinning.
+ shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
+ shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;
+
+ shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
+ shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
+ shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
+
+ actions = &shaders.actions_scene;
+ actions->uniforms = &p_shader->uniforms;
+ } break;
+
+ default: {
+ return;
+ } break;
+ }
+
+ Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
+ if (err != OK) {
+ return;
+ }
+
+ Vector<StringName> texture_uniform_names;
+ for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+ texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+ }
+
+ p_shader->shader->version_set_code(p_shader->version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+
+ p_shader->texture_uniforms = gen_code.texture_uniforms;
+
+ p_shader->uses_vertex_time = gen_code.uses_vertex_time;
+ p_shader->uses_fragment_time = gen_code.uses_fragment_time;
+
+ for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) {
+ _material_make_dirty(E->self());
+ }
+
+ p_shader->valid = true;
+}
+
+void MaterialStorage::update_dirty_shaders() {
+ while (_shader_dirty_list.first()) {
+ _update_shader(_shader_dirty_list.first()->self());
+ }
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_make_dirty(Material *p_material) const {
+ if (p_material->dirty_list.in_list()) {
+ return;
+ }
+
+ _material_dirty_list.add(&p_material->dirty_list);
+}
+
+void MaterialStorage::_update_material(Material *p_material) {
+ if (p_material->dirty_list.in_list()) {
+ _material_dirty_list.remove(&p_material->dirty_list);
+ }
+
+ if (p_material->shader && p_material->shader->dirty_list.in_list()) {
+ _update_shader(p_material->shader);
+ }
+
+ if (p_material->shader && !p_material->shader->valid) {
+ return;
+ }
+
+ {
+ bool can_cast_shadow = false;
+ bool is_animated = false;
+
+ if (p_material->shader && p_material->shader->mode == RS::SHADER_SPATIAL) {
+ if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
+ (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
+ can_cast_shadow = true;
+ }
+
+ if (p_material->shader->spatial.uses_discard && p_material->shader->uses_fragment_time) {
+ is_animated = true;
+ }
+
+ if (p_material->shader->spatial.uses_vertex && p_material->shader->uses_vertex_time) {
+ is_animated = true;
+ }
+
+ if (can_cast_shadow != p_material->can_cast_shadow_cache || is_animated != p_material->is_animated_cache) {
+ p_material->can_cast_shadow_cache = can_cast_shadow;
+ p_material->is_animated_cache = is_animated;
+
+ /*
+ for (Map<Geometry *, int>::Element *E = p_material->geometry_owners.front(); E; E = E->next()) {
+ E->key()->material_changed_notify();
+ }
+
+ for (Map<InstanceBaseDependency *, int>::Element *E = p_material->instance_owners.front(); E; E = E->next()) {
+ E->key()->base_changed(false, true);
+ }
+ */
+ }
+ }
+ }
+
+ // uniforms and other things will be set in the use_material method in ShaderGLES3
+
+ if (p_material->shader && p_material->shader->texture_uniforms.size() > 0) {
+ p_material->textures.resize(p_material->shader->texture_uniforms.size());
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_material->shader->uniforms.front(); E; E = E->next()) {
+ if (E->get().texture_order < 0) {
+ continue; // not a texture, does not go here
+ }
+
+ RID texture;
+
+ Map<StringName, Variant>::Element *V = p_material->params.find(E->key());
+
+ if (V) {
+ texture = V->get();
+ }
+
+ if (!texture.is_valid()) {
+ Map<StringName, Map<int, RID>>::Element *W = p_material->shader->default_textures.find(E->key());
+
+ // TODO: make texture uniform array properly works with GLES3
+ if (W && W->get().has(0)) {
+ texture = W->get()[0];
+ }
+ }
+
+ p_material->textures.write[E->get().texture_order] = Pair<StringName, RID>(E->key(), texture);
+ }
+ } else {
+ p_material->textures.clear();
+ }
+}
+
+RID MaterialStorage::material_allocate() {
+ Material *material = memnew(Material);
+ return material_owner.make_rid(material);
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+}
+
+//RID MaterialStorage::material_create() {
+// Material *material = memnew(Material);
+
+// return material_owner.make_rid(material);
+//}
+
+void MaterialStorage::material_free(RID p_rid) {
+ Material *m = material_owner.get_or_null(p_rid);
+
+ if (m->shader) {
+ m->shader->materials.remove(&m->list);
+ }
+
+ /*
+ for (Map<Geometry *, int>::Element *E = m->geometry_owners.front(); E; E = E->next()) {
+ Geometry *g = E->key();
+ g->material = RID();
+ }
+
+ for (Map<InstanceBaseDependency *, int>::Element *E = m->instance_owners.front(); E; E = E->next()) {
+ InstanceBaseDependency *ins = E->key();
+
+ if (ins->material_override == p_rid) {
+ ins->material_override = RID();
+ }
+
+ for (int i = 0; i < ins->materials.size(); i++) {
+ if (ins->materials[i] == p_rid) {
+ ins->materials.write[i] = RID();
+ }
+ }
+ }
+*/
+
+ material_owner.free(p_rid);
+ memdelete(m);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ Shader *shader = get_shader(p_shader);
+
+ if (material->shader) {
+ // if a shader is present, remove the old shader
+ material->shader->materials.remove(&material->list);
+ }
+
+ material->shader = shader;
+
+ if (shader) {
+ shader->materials.add(&material->list);
+ }
+
+ _material_make_dirty(material);
+}
+
+void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (p_value.get_type() == Variant::NIL) {
+ material->params.erase(p_param);
+ } else {
+ material->params[p_param] = p_value;
+ }
+
+ _material_make_dirty(material);
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+ const Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, RID());
+
+ if (material->params.has(p_param)) {
+ return material->params[p_param];
+ }
+
+ return material_get_param_default(p_material, p_param);
+}
+
+void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ material->next_pass = p_next_material;
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+ ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN);
+ ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX);
+
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ material->render_priority = priority;
+}
+
+bool MaterialStorage::material_is_animated(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+ if (material->dirty_list.in_list()) {
+ _update_material(material);
+ }
+
+ bool animated = material->is_animated_cache;
+ if (!animated && material->next_pass.is_valid()) {
+ animated = material_is_animated(material->next_pass);
+ }
+ return animated;
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+ if (material->dirty_list.in_list()) {
+ _update_material(material);
+ }
+
+ bool casts_shadows = material->can_cast_shadow_cache;
+
+ if (!casts_shadows && material->next_pass.is_valid()) {
+ casts_shadows = material_casts_shadows(material->next_pass);
+ }
+
+ return casts_shadows;
+}
+
+Variant MaterialStorage::material_get_param_default(RID p_material, const StringName &p_param) const {
+ const Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+
+ if (material->shader) {
+ if (material->shader->uniforms.has(p_param)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ }
+ }
+ return Variant();
+}
+
+void MaterialStorage::update_dirty_materials() {
+ while (_material_dirty_list.first()) {
+ Material *material = _material_dirty_list.first()->self();
+ _update_material(material);
+ }
+}
+
+/* are these still used? */
+RID MaterialStorage::material_get_shader(RID p_material) const {
+ const Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, RID());
+
+ if (material->shader) {
+ return material->shader->self;
+ }
+
+ return RID();
+}
+
+void MaterialStorage::material_set_line_width(RID p_material, float p_width) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ material->line_width = p_width;
+}
+
+bool MaterialStorage::material_uses_tangents(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+
+ if (!material->shader) {
+ return false;
+ }
+
+ if (material->shader->dirty_list.in_list()) {
+ _update_shader(material->shader);
+ }
+
+ return material->shader->spatial.uses_tangent;
+}
+
+bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+
+ if (!material->shader) {
+ return false;
+ }
+
+ if (material->shader->dirty_list.in_list()) {
+ _update_shader(material->shader);
+ }
+
+ return material->shader->spatial.uses_ensure_correct_normals;
+}
+
+void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+ /*
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
+ if (E) {
+ E->get()++;
+ } else {
+ material->instance_owners[p_instance] = 1;
+ }
+*/
+}
+
+void MaterialStorage::material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+ /*
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
+ ERR_FAIL_COND(!E);
+
+ E->get()--;
+
+ if (E->get() == 0) {
+ material->instance_owners.erase(E);
+ }
+*/
+}
+
+/*
+void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometry) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
+
+ if (I) {
+ I->get()++;
+ } else {
+ material->geometry_owners[p_geometry] = 1;
+ }
+}
+
+void MaterialStorage::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
+ ERR_FAIL_COND(!I);
+
+ I->get()--;
+
+ if (I->get() == 0) {
+ material->geometry_owners.erase(I);
+ }
+}
+*/
+
+#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
new file mode 100644
index 0000000000..bf17e66c2f
--- /dev/null
+++ b/drivers/gles3/storage/material_storage.h
@@ -0,0 +1,338 @@
+/*************************************************************************/
+/* material_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MATERIAL_STORAGE_GLES3_H
+#define MATERIAL_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+#include "drivers/gles3/shaders/copy.glsl.gen.h"
+
+namespace GLES3 {
+
+/* SHADER Structs */
+
+struct Shaders {
+ ShaderCompiler compiler;
+
+ CopyShaderGLES3 copy;
+ RID copy_version;
+ //CubemapFilterShaderGLES3 cubemap_filter;
+
+ ShaderCompiler::IdentifierActions actions_canvas;
+ ShaderCompiler::IdentifierActions actions_scene;
+ ShaderCompiler::IdentifierActions actions_particles;
+};
+
+struct Material;
+
+struct Shader {
+ RID self;
+
+ RS::ShaderMode mode;
+ ShaderGLES3 *shader;
+ String code;
+ SelfList<Material>::List materials;
+
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+
+ RID version;
+
+ SelfList<Shader> dirty_list;
+
+ Map<StringName, Map<int, RID>> default_textures;
+
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ bool valid;
+
+ String path;
+
+ uint32_t index;
+ uint64_t last_pass;
+
+ struct CanvasItem {
+ enum BlendMode {
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ BLEND_MODE_PMALPHA,
+ };
+
+ int blend_mode;
+
+ enum LightMode {
+ LIGHT_MODE_NORMAL,
+ LIGHT_MODE_UNSHADED,
+ LIGHT_MODE_LIGHT_ONLY
+ };
+
+ int light_mode;
+
+ bool uses_screen_texture;
+ bool uses_screen_uv;
+ bool uses_time;
+ bool uses_modulate;
+ bool uses_color;
+ bool uses_vertex;
+
+ // all these should disable item joining if used in a custom shader
+ bool uses_model_matrix;
+ bool uses_extra_matrix;
+ bool uses_projection_matrix;
+ bool uses_instance_custom;
+
+ } canvas_item;
+
+ struct Spatial {
+ enum BlendMode {
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ };
+
+ int blend_mode;
+
+ enum DepthDrawMode {
+ DEPTH_DRAW_OPAQUE,
+ DEPTH_DRAW_ALWAYS,
+ DEPTH_DRAW_NEVER,
+ DEPTH_DRAW_ALPHA_PREPASS,
+ };
+
+ int depth_draw_mode;
+
+ enum CullMode {
+ CULL_MODE_FRONT,
+ CULL_MODE_BACK,
+ CULL_MODE_DISABLED,
+ };
+
+ int cull_mode;
+
+ bool uses_alpha;
+ bool uses_alpha_scissor;
+ bool unshaded;
+ bool no_depth_test;
+ bool uses_vertex;
+ bool uses_discard;
+ bool uses_sss;
+ bool uses_screen_texture;
+ bool uses_depth_texture;
+ bool uses_time;
+ bool uses_tangent;
+ bool uses_ensure_correct_normals;
+ bool writes_modelview_or_projection;
+ bool uses_vertex_lighting;
+ bool uses_world_coordinates;
+
+ } spatial;
+
+ struct Particles {
+ } particles;
+
+ bool uses_vertex_time;
+ bool uses_fragment_time;
+
+ Shader() :
+ dirty_list(this) {
+ shader = nullptr;
+ valid = false;
+ version = RID();
+ last_pass = 0;
+ }
+};
+
+/* MATERIAL Structs */
+
+struct Material {
+ RID self;
+ Shader *shader;
+ Map<StringName, Variant> params;
+ SelfList<Material> list;
+ SelfList<Material> dirty_list;
+ Vector<Pair<StringName, RID>> textures;
+ float line_width;
+ int render_priority;
+
+ RID next_pass;
+
+ uint32_t index;
+ uint64_t last_pass;
+
+ // Map<Geometry *, int> geometry_owners;
+ // Map<InstanceBaseDependency *, int> instance_owners;
+
+ bool can_cast_shadow_cache;
+ bool is_animated_cache;
+
+ Material() :
+ list(this),
+ dirty_list(this) {
+ can_cast_shadow_cache = false;
+ is_animated_cache = false;
+ shader = nullptr;
+ line_width = 1.0;
+ last_pass = 0;
+ render_priority = 0;
+ }
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+ static MaterialStorage *singleton;
+
+ /* SHADER API */
+
+ mutable Shaders shaders;
+
+ mutable RID_PtrOwner<Shader> shader_owner;
+ mutable SelfList<Shader>::List _shader_dirty_list;
+
+ /* MATERIAL API */
+
+ mutable SelfList<Material>::List _material_dirty_list;
+ mutable RID_PtrOwner<Material> material_owner;
+
+public:
+ static MaterialStorage *get_singleton();
+
+ MaterialStorage();
+ virtual ~MaterialStorage();
+
+ /* GLOBAL VARIABLE API */
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
+ virtual void global_variable_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_variable_get_list() const override;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_variable_get(const StringName &p_name) const override;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) override;
+ virtual void global_variables_clear() override;
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) override;
+ virtual void global_variables_instance_free(RID p_instance) override;
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+
+ /* SHADER API */
+
+ Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
+ bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
+
+ void _shader_make_dirty(Shader *p_shader);
+
+ virtual RID shader_allocate() override;
+ virtual void shader_initialize(RID p_rid) override;
+ virtual void shader_free(RID p_rid) override;
+
+ //RID shader_create() override;
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual String shader_get_code(RID p_shader) const override;
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+ void _update_shader(Shader *p_shader) const;
+ void update_dirty_shaders();
+
+ // new
+ Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ /* MATERIAL API */
+
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+ bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
+
+ void _material_make_dirty(Material *p_material) const;
+
+ // void _material_add_geometry(RID p_material, Geometry *p_geometry);
+ // void _material_remove_geometry(RID p_material, Geometry *p_geometry);
+
+ void _update_material(Material *p_material);
+
+ // new
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+ virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+
+ // old
+ virtual RID material_allocate() override;
+ virtual void material_initialize(RID p_rid) override;
+
+ virtual void material_free(RID p_rid) override;
+
+ //RID material_create() override;
+
+ virtual void material_set_shader(RID p_material, RID p_shader) override;
+ virtual RID material_get_shader(RID p_material) const;
+
+ virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
+ virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
+ virtual Variant material_get_param_default(RID p_material, const StringName &p_param) const;
+
+ void material_set_line_width(RID p_material, float p_width);
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
+
+ virtual bool material_is_animated(RID p_material) override;
+ virtual bool material_casts_shadows(RID p_material) override;
+ bool material_uses_tangents(RID p_material);
+ bool material_uses_ensure_correct_normals(RID p_material);
+
+ void material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance);
+ void material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance);
+
+ void material_set_render_priority(RID p_material, int priority) override;
+
+ void update_dirty_materials();
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !MATERIAL_STORAGE_GLES3_H