summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h6
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h132
-rw-r--r--servers/rendering/dummy/storage/material_storage.h95
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h129
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp10
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.h41
-rw-r--r--servers/rendering/renderer_compositor.h4
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp302
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h21
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp187
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h57
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp94
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp52
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h18
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp137
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h32
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h16
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h10
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp77
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h40
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp97
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h24
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp4264
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h862
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp2392
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h315
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp1921
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h694
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.cpp2
-rw-r--r--servers/rendering/renderer_scene_cull.cpp96
-rw-r--r--servers/rendering/renderer_scene_cull.h32
-rw-r--r--servers/rendering/renderer_scene_render.h2
-rw-r--r--servers/rendering/renderer_storage.h149
-rw-r--r--servers/rendering/renderer_viewport.h2
-rw-r--r--servers/rendering/rendering_device.h3
-rw-r--r--servers/rendering/rendering_server_default.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h39
-rw-r--r--servers/rendering/rendering_server_globals.cpp2
-rw-r--r--servers/rendering/rendering_server_globals.h4
-rw-r--r--servers/rendering/shader_language.cpp60
-rw-r--r--servers/rendering/shader_language.h14
-rw-r--r--servers/rendering/storage/material_storage.h101
-rw-r--r--servers/rendering/storage/mesh_storage.h136
51 files changed, 6682 insertions, 6017 deletions
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 219f468b2f..f7bd7d0d18 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -39,6 +39,8 @@
#include "servers/rendering/dummy/rasterizer_storage_dummy.h"
#include "servers/rendering/dummy/storage/canvas_texture_storage.h"
#include "servers/rendering/dummy/storage/decal_atlas_storage.h"
+#include "servers/rendering/dummy/storage/material_storage.h"
+#include "servers/rendering/dummy/storage/mesh_storage.h"
#include "servers/rendering/dummy/storage/texture_storage.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
@@ -51,6 +53,8 @@ private:
protected:
RasterizerCanvasDummy canvas;
RendererDummy::CanvasTextureStorage canvas_texture_storage;
+ RendererDummy::MaterialStorage material_storage;
+ RendererDummy::MeshStorage mesh_storage;
RendererDummy::TextureStorage texture_storage;
RendererDummy::DecalAtlasStorage decal_atlas_storage;
RasterizerStorageDummy storage;
@@ -58,6 +62,8 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
+ RendererMaterialStorage *get_material_storage() override { return &material_storage; };
+ RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; };
RendererStorage *get_storage() override { return &storage; }
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
index 1e753f8b6b..ea69d2f9a6 100644
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ b/servers/rendering/dummy/rasterizer_storage_dummy.h
@@ -36,113 +36,6 @@
class RasterizerStorageDummy : public RendererStorage {
public:
- /* SHADER API */
-
- RID shader_allocate() override { return RID(); }
- void shader_initialize(RID p_rid) override {}
- void shader_set_code(RID p_shader, const String &p_code) override {}
- String shader_get_code(RID p_shader) const override { return ""; }
- 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 { return RID(); }
- Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
- /* COMMON MATERIAL API */
-
- RID material_allocate() override { return RID(); }
- void material_initialize(RID p_rid) override {}
- void material_set_render_priority(RID p_material, int priority) override {}
- void material_set_shader(RID p_shader_material, RID p_shader) override {}
-
- 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 { return Variant(); }
-
- void material_set_next_pass(RID p_material, RID p_next_material) override {}
-
- bool material_is_animated(RID p_material) override { return false; }
- bool material_casts_shadows(RID p_material) override { return false; }
- 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 {}
-
- /* MESH API */
-
- RID mesh_allocate() override { return RID(); }
- void mesh_initialize(RID p_rid) override {}
- void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
- bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- RID mesh_instance_create(RID p_base) override { return RID(); }
- void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
- void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
- void mesh_instance_check_for_update(RID p_mesh_instance) override {}
- void update_mesh_instances() override {}
- void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
- float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
-
- void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
-
- int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
-
- void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
-
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
-
- RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- int mesh_get_surface_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
- AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
-
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
- void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- void mesh_clear(RID p_mesh) override {}
-
- /* MULTIMESH API */
-
- RID multimesh_allocate() override { return RID(); }
- void multimesh_initialize(RID p_rid) override {}
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
- int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
-
- RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
- AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
- Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
- int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
-
- /* SKELETON API */
-
- RID skeleton_allocate() override { return RID(); }
- void skeleton_initialize(RID p_rid) override {}
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
- int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
-
/* Light API */
RID directional_light_allocate() override { return RID(); }
@@ -202,6 +95,8 @@ public:
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+ void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+ float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
@@ -212,7 +107,6 @@ public:
bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
- void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
/* VOXEL GI API */
@@ -352,6 +246,8 @@ public:
void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+ bool particles_is_inactive(RID p_particles) const override { return false; }
+
/* FOG VOLUMES */
RID fog_volume_allocate() override { return RID(); }
@@ -372,26 +268,6 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
virtual 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 { return Vector<StringName>(); }
-
- 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 { return Variant(); }
- RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
-
- 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 { return 0; }
- 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 { return false; }
-
/* RENDER TARGET */
RID render_target_create() override { return RID(); }
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
new file mode 100644
index 0000000000..8890be8ea9
--- /dev/null
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -0,0 +1,95 @@
+/*************************************************************************/
+/* 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_DUMMY_H
+#define MATERIAL_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererDummy {
+
+class MaterialStorage : public RendererMaterialStorage {
+public:
+ /* 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 { return Vector<StringName>(); }
+
+ 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 { return Variant(); }
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+
+ 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 { return 0; }
+ 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 */
+
+ virtual RID shader_allocate() override { return RID(); }
+ virtual void shader_initialize(RID p_rid) override {}
+ virtual void shader_free(RID p_rid) override{};
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) override {}
+ virtual String shader_get_code(RID p_shader) const override { return ""; }
+ 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 { return RID(); }
+ virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+ /* MATERIAL API */
+ virtual RID material_allocate() override { return RID(); }
+ virtual void material_initialize(RID p_rid) override {}
+ virtual void material_free(RID p_rid) override{};
+
+ virtual void material_set_render_priority(RID p_material, int priority) override {}
+ virtual void material_set_shader(RID p_shader_material, RID p_shader) override {}
+
+ 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 { return Variant(); }
+
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) override {}
+
+ virtual bool material_is_animated(RID p_material) override { return false; }
+ virtual bool material_casts_shadows(RID p_material) override { return false; }
+ 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 {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MATERIAL_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
new file mode 100644
index 0000000000..dfbd265bba
--- /dev/null
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* mesh_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 MESH_STORAGE_DUMMY_H
+#define MESH_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererDummy {
+
+class MeshStorage : public RendererMeshStorage {
+public:
+ /* MESH API */
+
+ virtual RID mesh_allocate() override { return RID(); }
+ virtual void mesh_initialize(RID p_rid) override {}
+ virtual void mesh_free(RID p_rid) override {}
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
+
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
+ virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
+ virtual void mesh_clear(RID p_mesh) override {}
+
+ /* MESH INSTANCE */
+
+ virtual RID mesh_instance_create(RID p_base) override { return RID(); }
+ virtual void mesh_instance_free(RID p_rid) override {}
+
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {}
+ virtual void update_mesh_instances() override {}
+
+ /* MULTIMESH API */
+
+ virtual RID multimesh_allocate() override { return RID(); }
+ virtual void multimesh_initialize(RID p_rid) override {}
+ virtual void multimesh_free(RID p_rid) override {}
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() override { return RID(); }
+ virtual void skeleton_initialize(RID p_rid) override {}
+ virtual void skeleton_free(RID p_rid) override {}
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 22149c9e43..f38d800aa7 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -997,8 +997,8 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con
ERR_FAIL_COND(!m);
m->mesh = p_mesh;
if (canvas_item->skeleton.is_valid()) {
- m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh);
- RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
+ m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh);
+ RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
}
m->texture = p_texture;
@@ -1093,12 +1093,12 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton)
Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c);
if (canvas_item->skeleton.is_valid()) {
if (cm->mesh_instance.is_null()) {
- cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh);
+ cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh);
}
- RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
} else {
if (cm->mesh_instance.is_valid()) {
- RSG::storage->free(cm->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(cm->mesh_instance);
cm->mesh_instance = RID();
}
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index fc53ce2327..94bae30ae0 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -124,7 +124,7 @@ public:
Set<RID> viewports;
struct ChildItem {
Point2 mirror;
- Item *item;
+ Item *item = nullptr;
bool operator<(const ChildItem &p_item) const {
return item->index < p_item.item->index;
}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1840925f78..46ca3b0da8 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -31,6 +31,7 @@
#ifndef RENDERINGSERVERCANVASRENDER_H
#define RENDERINGSERVERCANVASRENDER_H
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_storage.h"
class RendererCanvasRender {
@@ -82,10 +83,10 @@ public:
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
- Light *shadows_next_ptr;
- Light *filter_next_ptr;
- Light *next_ptr;
- Light *directional_next_ptr;
+ Light *shadows_next_ptr = nullptr;
+ Light *filter_next_ptr = nullptr;
+ Light *next_ptr = nullptr;
+ Light *directional_next_ptr = nullptr;
RID light_internal;
uint64_t version;
@@ -167,7 +168,7 @@ public:
MAX_SIZE = 4096
};
uint32_t usage;
- uint8_t *memory;
+ uint8_t *memory = nullptr;
};
struct Command {
@@ -184,7 +185,7 @@ public:
TYPE_ANIMATION_SLICE,
};
- Command *next;
+ Command *next = nullptr;
Type type;
virtual ~Command() {}
};
@@ -304,8 +305,8 @@ public:
};
struct ViewportRender {
- RenderingServer *owner;
- void *udata;
+ RenderingServer *owner = nullptr;
+ void *udata = nullptr;
Rect2 rect;
};
@@ -333,22 +334,22 @@ public:
RID material;
RID skeleton;
- Item *next;
+ Item *next = nullptr;
struct CopyBackBuffer {
Rect2 rect;
Rect2 screen_rect;
bool full;
};
- CopyBackBuffer *copy_back_buffer;
+ CopyBackBuffer *copy_back_buffer = nullptr;
Color final_modulate;
Transform2D final_transform;
Rect2 final_clip_rect;
- Item *final_clip_owner;
- Item *material_owner;
- Item *canvas_group_owner;
- ViewportRender *vp_render;
+ Item *final_clip_owner = nullptr;
+ Item *material_owner = nullptr;
+ Item *canvas_group_owner = nullptr;
+ ViewportRender *vp_render = nullptr;
bool distance_field;
bool light_masked;
@@ -403,14 +404,14 @@ public:
} break;
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- AABB aabb = RendererStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID());
+ AABB aabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(mesh->mesh, RID());
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
} break;
case Item::Command::TYPE_MULTIMESH: {
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
- AABB aabb = RendererStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh);
+ AABB aabb = RendererRD::MeshStorage::get_singleton()->multimesh_get_aabb(multimesh->multimesh);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
@@ -452,14 +453,14 @@ public:
return rect;
}
- Command *commands;
- Command *last_command;
+ Command *commands = nullptr;
+ Command *last_command = nullptr;
Vector<CommandBlock> blocks;
uint32_t current_block;
template <class T>
T *alloc_command() {
- T *command;
+ T *command = nullptr;
if (commands == nullptr) {
// As the most common use case of canvas items is to
// use only one command, the first is done with it's
@@ -589,7 +590,7 @@ public:
bool sdf_collision;
RS::CanvasOccluderPolygonCullMode cull_cache;
- LightOccluderInstance *next;
+ LightOccluderInstance *next = nullptr;
LightOccluderInstance() {
enabled = true;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 8d8fcee5a4..74eff4bb40 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -36,6 +36,8 @@
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/canvas_texture_storage.h"
#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering_server.h"
@@ -74,6 +76,8 @@ public:
static RendererCompositor *create();
virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
+ virtual RendererMaterialStorage *get_material_storage() = 0;
+ virtual RendererMeshStorage *get_mesh_storage() = 0;
virtual RendererTextureStorage *get_texture_storage() = 0;
virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0;
virtual RendererStorage *get_storage() = 0;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 24108b3a59..0b36fe3964 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -269,7 +269,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
- render_elements = (RenderElementData *)memalloc(sizeof(RenderElementData *) * render_element_max);
+ render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData *) * render_element_max));
render_element_count = 0;
element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 0ae51ed876..e24d020a14 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -31,6 +31,7 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -59,14 +60,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -79,14 +72,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
{
Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(specular_msaa);
- fb.push_back(depth_msaa);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular_msaa);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -165,11 +150,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
color = RID();
depth = RID();
- color_specular_fb = RID();
- specular_only_fb = RID();
- color_fb = RID();
depth_fb = RID();
+ color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
+
if (normal_roughness_buffer.is_valid()) {
RD::get_singleton()->free(normal_roughness_buffer);
if (normal_roughness_buffer_msaa.is_valid()) {
@@ -203,7 +187,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -246,7 +230,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -257,6 +241,31 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
}
}
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) {
+ if (color_framebuffers.has(p_color_pass_flags)) {
+ return color_framebuffers[p_color_pass_flags];
+ }
+
+ bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
+
+ Vector<RID> fb;
+ fb.push_back(use_msaa ? color_msaa : color);
+
+ if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ ensure_specular();
+ fb.push_back(use_msaa ? specular_msaa : specular);
+ } else {
+ fb.push_back(RID());
+ }
+
+ fb.push_back(use_msaa ? depth_msaa : depth);
+
+ int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
+ RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
+ color_framebuffers[p_color_pass_flags] = framebuffer;
+ return framebuffer;
+}
+
void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) {
if (rb->normal_roughness_buffer.is_valid()) {
return;
@@ -306,8 +315,9 @@ bool RenderForwardClustered::free(RID p_rid) {
/// RENDERING ///
-template <RenderForwardClustered::PassMode p_pass_mode>
+template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags>
void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -340,7 +350,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
- if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
}
@@ -403,10 +413,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
-
+ uint32_t pipeline_color_pass_flags = 0;
uint32_t pipeline_specialization = 0;
- if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
+ if (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
}
@@ -422,28 +432,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
switch (p_pass_mode) {
case PASS_MODE_COLOR: {
if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
- } else {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
- }
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for specular pass");
- if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
- } else {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS;
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
@@ -473,7 +481,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ if constexpr (p_pass_mode == PASS_MODE_COLOR) {
+ pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags];
+ } else {
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ }
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -481,12 +493,12 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
//skeleton and blend shape
if (surf->owner->mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -544,14 +556,23 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
//use template for faster performance (pass mode comparisons are inlined)
switch (p_params->pass_mode) {
+#define VALID_FLAG_COMBINATION(f) \
+ case f: { \
+ _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \
+ } break;
+
case PASS_MODE_COLOR: {
- _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ switch (p_params->color_pass_flags) {
+ VALID_FLAG_COMBINATION(0);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW);
+ default: {
+ ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
+ }
+ }
+
} break;
case PASS_MODE_SHADOW: {
_render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
@@ -663,7 +684,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_enabled = false;
if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
@@ -944,6 +965,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -1080,7 +1103,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1104,7 +1127,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t indices;
- surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1116,13 +1139,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
} else {
surf->sort.lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1219,7 +1242,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RenderBufferDataForwardClustered *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
- render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
@@ -1238,12 +1261,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
- RID opaque_framebuffer;
- RID opaque_specular_framebuffer;
+ RID color_framebuffer;
+ RID color_only_framebuffer;
RID depth_framebuffer;
- RID alpha_framebuffer;
PassMode depth_pass_mode = PASS_MODE_DEPTH;
+ uint32_t color_pass_flags = 0;
Vector<Color> depth_pass_clear;
bool using_separate_specular = false;
bool using_ssr = false;
@@ -1256,15 +1279,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- opaque_framebuffer = render_buffer->color_fb;
-
if (p_render_data->voxel_gi_instances->size() > 0) {
using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->view_count > 1) {
+ depth_pass_mode = PASS_MODE_DEPTH;
+ } else if (!p_render_data->environment.is_valid() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
if (environment_is_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
@@ -1272,14 +1294,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
-
if (environment_is_ssr_enabled(p_render_data->environment)) {
- render_buffer->ensure_specular();
using_separate_specular = true;
using_ssr = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1304,15 +1323,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
};
}
- alpha_framebuffer = opaque_framebuffer;
+ if (p_render_data->view_count > 1) {
+ color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
+ color_only_framebuffer = render_buffer->color_only_fb;
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_only_framebuffer = color_framebuffer;
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- alpha_framebuffer = opaque_framebuffer;
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
@@ -1342,11 +1366,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
- if (using_sss) {
- using_separate_specular = true;
- render_buffer->ensure_specular();
+ if (using_sss && !using_separate_specular) {
using_separate_specular = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
}
RID radiance_texture;
bool draw_sky = false;
@@ -1368,7 +1391,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
@@ -1378,7 +1401,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
@@ -1449,7 +1472,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1495,20 +1518,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
- //regular forward for now
Vector<Color> c;
- if (using_separate_specular) {
+ {
Color cc = clear_color.to_linear();
- cc.a = 0; //subsurf scatter must be 0
+ if (using_separate_specular) {
+ cc.a = 0; //subsurf scatter must be 0
+ }
c.push_back(cc);
- c.push_back(Color(0, 0, 0, 0));
- } else {
- c.push_back(clear_color.to_linear());
+
+ if (render_buffer) {
+ c.push_back(Color(0, 0, 0, 0));
+ }
}
- RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
- _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
@@ -1526,10 +1550,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
- gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
+ gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
@@ -1543,9 +1567,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
- _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm);
+ _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm);
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1559,9 +1583,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
} else {
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1588,12 +1612,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -1616,7 +1640,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1738,7 +1764,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1781,7 +1807,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
@@ -1818,7 +1844,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1864,7 +1890,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1918,7 +1944,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
_update_render_base_uniform_set();
- RenderBufferDataForwardClustered *render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
+ RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
ERR_FAIL_COND(!render_buffer);
PassMode pass_mode = PASS_MODE_SDF;
@@ -1984,7 +2010,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false);
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
@@ -2165,7 +2191,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2182,9 +2208,11 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
RenderBufferDataForwardClustered *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
}
//default render buffer and scene state uniform set
@@ -2429,6 +2457,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
}
RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
Vector<RD::Uniform> uniforms;
{
@@ -2557,7 +2586,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
}
RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
- RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
+ RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
return rb->normal_roughness_buffer;
}
@@ -2585,6 +2614,8 @@ void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_g
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha;
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -2633,12 +2664,12 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2651,8 +2682,8 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->shader = p_material->shader_data;
sdcache->material_uniform_set = p_material->uniform_set;
- sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
- sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2688,23 +2719,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardClustered::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2712,7 +2745,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
SceneShaderForwardClustered::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2720,10 +2753,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2734,10 +2767,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
@@ -2746,6 +2779,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2759,7 +2793,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
//if no materials, no surfaces.
const RID *inst_materials = ginstance->data->surface_materials.ptr();
@@ -2776,19 +2810,19 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base);
if (mesh.is_valid()) {
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t j = 0; j < surface_count; j++) {
_geometry_instance_add_surface(ginstance, j, materials[j], mesh);
}
}
- ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2813,7 +2847,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t k = 0; k < surface_count; k++) {
_geometry_instance_add_surface(ginstance, k, materials[k], mesh);
@@ -2837,17 +2871,17 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2864,10 +2898,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2907,7 +2941,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index b770cc8f0e..37366d3e14 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -103,10 +103,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID depth_fb;
RID depth_normal_roughness_fb;
RID depth_normal_roughness_voxelgi_fb;
- RID color_fb;
- RID color_specular_fb;
+ RID color_only_fb;
RID specular_only_fb;
int width, height;
+ Map<uint32_t, RID> color_framebuffers;
uint32_t view_count;
RID render_sdfgi_uniform_set;
@@ -114,6 +114,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void ensure_voxelgi();
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
};
@@ -135,8 +136,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
enum PassMode {
PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
@@ -146,6 +145,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PASS_MODE_SDF,
};
+ enum ColorPassFlags {
+ COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ COLOR_PASS_FLAG_MULTIVIEW = 1 << 2
+ };
+
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -155,6 +160,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
int element_count = 0;
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
+ uint32_t color_pass_flags = 0;
bool no_gi = false;
uint32_t view_count = 1;
RID render_pass_uniform_set;
@@ -168,12 +174,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
+ color_pass_flags = p_color_pass_flags;
no_gi = p_no_gi;
view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
@@ -325,7 +332,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 };
LocalVector<InstanceData> instance_data[RENDER_LIST_MAX];
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
@@ -374,7 +381,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t lod_index : 8;
};
- template <PassMode p_pass_mode>
+ template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 5a0ed7ebad..2acce8bab7 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "render_forward_clustered.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -233,10 +234,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
}
- RD::PipelineColorBlendState blend_state_blend;
- blend_state_blend.attachments.push_back(blend_attachment);
- RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
- RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+ // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular
+ RD::PipelineColorBlendState blend_state_color_blend;
+ blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() };
+ RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2);
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
@@ -279,18 +280,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_COLOR_PASS,
};
shader_version = shader_version_table[k];
@@ -306,38 +297,62 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
- if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS || k == PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW) {
- if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
- multisample_state.enable_alpha_to_coverage = true;
- } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
- multisample_state.enable_alpha_to_coverage = true;
- multisample_state.enable_alpha_to_one = true;
- }
-
- blend_state = blend_state_blend;
-
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ if (k == PIPELINE_VERSION_COLOR_PASS) {
+ for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
+ if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
+ continue;
+ }
+
+ int shader_flags = 0;
+ if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
+ if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ multisample_state.enable_alpha_to_one = true;
+ }
+
+ blend_state = blend_state_color_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ }
+ } else {
+ blend_state = blend_state_color_opaque;
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ int variant = shader_version + shader_flags;
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
+ color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
- } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS || k == PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW) {
- blend_state = blend_state_opaque;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
+ }
- RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ }
}
}
}
@@ -384,13 +399,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
-void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -445,7 +460,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -469,7 +484,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -484,17 +499,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() {
}
SceneShaderForwardClustered::~SceneShaderForwardClustered() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -505,27 +523,40 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
- shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
- shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
-
- // multiview versions of our shaders
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
+
+ Vector<String> color_pass_flags = {
+ "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
+ "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP
+ "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW
+ };
+
+ for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
+ String version = "";
+ for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) {
+ if ((1 << j) & i) {
+ version += color_pass_flags[j];
+ }
+ }
+ shader_versions.push_back(version);
+ }
shader.initialize(shader_versions, p_defines);
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
+ // TODO Add a way to enable/disable color pass flags
}
}
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+ valid_color_pass_pipelines.insert(0);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -710,9 +741,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (clustered).
shader_type spatial;
@@ -727,11 +758,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
@@ -740,10 +771,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (clustered).
shader_type spatial;
@@ -755,11 +786,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 4398517259..1b7709bedb 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -42,7 +42,7 @@ private:
static SceneShaderForwardClustered *singleton;
public:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
@@ -51,18 +51,18 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
-
+ SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_MAX
};
+ enum ShaderColorPassFlags {
+ SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0,
+ SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1,
+ SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
+ SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3
+ };
+
enum PipelineVersion {
PIPELINE_VERSION_DEPTH_PASS,
PIPELINE_VERSION_DEPTH_PASS_DP,
@@ -70,22 +70,19 @@ public:
PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
- PIPELINE_VERSION_OPAQUE_PASS,
- PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_TRANSPARENT_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
-
PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW,
- PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW,
-
+ PIPELINE_VERSION_COLOR_PASS,
PIPELINE_VERSION_MAX
};
+ enum PipelineColorPassFlags {
+ PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
+ PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
+ PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4,
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -93,7 +90,7 @@ public:
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -137,6 +134,7 @@ public:
RID version;
uint32_t vertex_input_mask;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
+ PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
String path;
@@ -180,7 +178,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -195,13 +193,13 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct MaterialData : public RendererRD::MaterialData {
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -213,8 +211,8 @@ public:
virtual ~MaterialData();
};
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -240,6 +238,7 @@ public:
ShaderData *overdraw_material_shader_ptr = nullptr;
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
+ Set<uint32_t> valid_color_pass_pipelines;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index a09a604e49..156d535447 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -31,6 +31,7 @@
#include "render_forward_mobile.h"
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -290,12 +291,14 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() {
}
RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
RenderBufferDataForwardMobile *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
}
// default render buffer and scene state uniform set
@@ -474,7 +477,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RenderBufferDataForwardMobile *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
- render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
@@ -593,7 +596,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
*/
} break;
@@ -605,7 +608,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
*/
} break;
@@ -1300,7 +1303,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1323,6 +1326,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
}
void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -1412,7 +1417,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1436,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t indices;
- surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1448,13 +1453,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
} else {
surf->lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1564,7 +1569,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_enabled = false;
if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardMobile *render_buffers = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
@@ -1812,6 +1817,8 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -1954,12 +1961,12 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
//skeleton and blend shape
if (surf->owner->mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -2278,6 +2285,8 @@ void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geom
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha);
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -2326,12 +2335,12 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2344,8 +2353,8 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->shader = p_material->shader_data;
sdcache->material_uniform_set = p_material->uniform_set;
- sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
- sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2379,23 +2388,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardMobile::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2403,7 +2414,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
SceneShaderForwardMobile::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2411,10 +2422,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2425,10 +2436,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
@@ -2437,6 +2448,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2450,7 +2462,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
//if no materials, no surfaces.
const RID *inst_materials = ginstance->data->surface_materials.ptr();
@@ -2467,19 +2479,19 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base);
if (mesh.is_valid()) {
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t j = 0; j < surface_count; j++) {
_geometry_instance_add_surface(ginstance, j, materials[j], mesh);
}
}
- ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2504,7 +2516,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t k = 0; k < surface_count; k++) {
_geometry_instance_add_surface(ginstance, k, materials[k], mesh);
@@ -2527,17 +2539,17 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2557,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2593,7 +2605,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardMobile *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 6162ca55af..0ddfe89eea 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -328,7 +328,7 @@ protected:
uint32_t max_lightmaps;
RID lightmap_buffer;
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 9452c7e6df..60badbdfee 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "render_forward_mobile.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -366,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
-void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -427,7 +428,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -451,7 +452,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -469,6 +470,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
storage = p_storage;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
/* SCENE SHADER */
@@ -494,8 +496,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -677,9 +679,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (mobile).
shader_type spatial;
@@ -694,11 +696,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
@@ -706,10 +708,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (mobile).
shader_type spatial;
@@ -721,11 +723,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
@@ -765,12 +767,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector
}
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 92db15e3b0..b89fe908d3 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -40,7 +40,7 @@ namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
public:
enum ShaderVersion {
@@ -57,7 +57,7 @@ public:
SHADER_VERSION_MAX
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -143,7 +143,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -157,13 +157,13 @@ public:
virtual ~ShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct MaterialData : public RendererRD::MaterialData {
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -177,8 +177,8 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index e812a48d3d..9151c53823 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -58,7 +58,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants);
ERR_FAIL_COND_V(pipeline.is_null(), RID());
- versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
+ versions = static_cast<Version *>(memrealloc(versions, sizeof(Version) * (version_count + 1)));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
versions[version_count].vertex_id = p_vertex_format_id;
versions[version_count].wireframe = wireframe;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 8d82480b38..1e80381d88 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -57,7 +57,7 @@ class PipelineCacheRD {
RID pipeline;
};
- Version *versions;
+ Version *versions = nullptr;
uint32_t version_count;
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index e56e263540..5b5a39c215 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -35,7 +35,10 @@
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -106,6 +109,8 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
// This dramatically reduces the amount of pipeline objects
// that need to be created for these formats.
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
uint32_t vertex_count = p_points.size();
uint32_t stride = 2; //vertices always repeat
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
@@ -188,7 +193,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR);
+ buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -216,7 +221,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV);
+ buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -249,7 +254,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES);
}
//weights
@@ -282,7 +287,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS);
+ buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -359,7 +364,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
bool use_normal;
bool use_specular;
- bool success = canvas_texture_storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -396,6 +401,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
//create an empty push constant
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RS::CanvasItemTextureFilter current_filter = default_filter;
RS::CanvasItemTextureRepeat current_repeat = default_repeat;
@@ -750,26 +756,26 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
RID multimesh = mm->multimesh;
- mesh = storage->multimesh_get_mesh(multimesh);
+ mesh = mesh_storage->multimesh_get_mesh(multimesh);
texture = mm->texture;
- if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
break;
}
- instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
if (instance_count == 0) {
break;
}
- RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+ RID uniform_set = mesh_storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
- if (storage->multimesh_uses_colors(multimesh)) {
+ if (mesh_storage->multimesh_uses_colors(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
}
- if (storage->multimesh_uses_custom_data(multimesh)) {
+ if (mesh_storage->multimesh_uses_custom_data(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
}
} else if (c->type == Item::Command::TYPE_PARTICLES) {
@@ -834,7 +840,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
- uint32_t surf_count = storage->mesh_get_surface_count(mesh);
+ uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
push_constant.modulation[0] = base_color.r * modulate.r;
@@ -849,9 +855,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
for (uint32_t j = 0; j < surf_count; j++) {
- void *surface = storage->mesh_get_surface(mesh, j);
+ void *surface = mesh_storage->mesh_get_surface(mesh, j);
- RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface);
+ RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask();
@@ -860,15 +866,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID;
if (mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
}
RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- RID index_array = storage->mesh_surface_get_index_array(surface, 0);
+ RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0);
if (index_array.is_valid()) {
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array);
@@ -978,7 +984,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
} else {
screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
- screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
}
u.append_id(screen);
@@ -1021,7 +1027,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1036,6 +1042,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
}
void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1100,9 +1107,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
if (material != prev_material) {
- MaterialData *material_data = nullptr;
+ CanvasMaterialData *material_data = nullptr;
if (material.is_valid()) {
- material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
}
if (material_data) {
@@ -1129,6 +1136,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
r_sdf_used = false;
int item_count = 0;
@@ -1364,7 +1374,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_valid()) {
- MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
@@ -1389,7 +1399,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
if (cm->mesh_instance.is_valid()) {
- storage->mesh_instance_check_for_update(cm->mesh_instance);
+ mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
update_skeletons = true;
}
}
@@ -1401,7 +1411,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (canvas_group_owner == nullptr) {
//Canvas group begins here, render until before this item
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
@@ -1424,7 +1434,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (ci == canvas_group_owner) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -1441,7 +1451,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (backbuffer_copy) {
//render anything pending, including clearing if no items
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
@@ -1457,7 +1467,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -1938,7 +1948,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
-void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
+void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -1976,7 +1986,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
@@ -2120,7 +2130,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -2137,7 +2147,7 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN
}
}
-void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -2158,13 +2168,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa
}
}
-void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -2173,7 +2183,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt
}
}
-bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -2181,15 +2191,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa
return uniforms[p_param].texture_order >= 0;
}
-bool RendererCanvasRenderRD::ShaderData::is_animated() const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
return false;
}
-bool RendererCanvasRenderRD::ShaderData::casts_shadows() const {
+bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
return false;
}
-Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -2198,19 +2208,19 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
return Variant();
}
-RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
}
-RendererCanvasRenderRD::ShaderData::ShaderData() {
+RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
valid = false;
uses_screen_texture = false;
uses_sdf = false;
}
-RendererCanvasRenderRD::ShaderData::~ShaderData() {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
ERR_FAIL_COND(!canvas_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -2218,23 +2228,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
- ShaderData *shader_data = memnew(ShaderData);
+RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+ CanvasShaderData *shader_data = memnew(CanvasShaderData);
return shader_data;
}
-bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
-RendererCanvasRenderRD::MaterialData::~MaterialData() {
+RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
- MaterialData *material_data = memnew(MaterialData);
+RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+ CanvasMaterialData *material_data = memnew(CanvasMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
@@ -2248,8 +2258,8 @@ void RendererCanvasRenderRD::update() {
}
RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
- canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
- texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{ //create default samplers
@@ -2573,7 +2583,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.append_id(storage->get_default_rd_storage_buffer());
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
uniforms.push_back(u);
}
@@ -2586,16 +2596,16 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
{
- 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;
@@ -2610,10 +2620,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);
}
static_assert(sizeof(PushConstant) == 128);
@@ -2661,10 +2671,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
}
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//canvas state
- 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);
{
if (state.canvas_state_buffer.is_valid()) {
@@ -2701,6 +2712,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
}
RD::get_singleton()->free(state.shadow_texture);
- canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+ RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index c0138c4fe0..6448e1a664 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -37,15 +37,11 @@
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererRD::CanvasTextureStorage *canvas_texture_storage;
- RendererRD::TextureStorage *texture_storage;
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum {
BASE_UNIFORM_SET = 0,
@@ -155,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
ShaderCompiler compiler;
} shader;
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct CanvasShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -186,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -194,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- ShaderData();
- virtual ~ShaderData();
+ CanvasShaderData();
+ virtual ~CanvasShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct CanvasMaterialData : public RendererRD::MaterialData {
+ CanvasShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~MaterialData();
+ virtual ~CanvasMaterialData();
};
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
- return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+ RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
}
/**************************/
@@ -365,7 +361,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t pad2;
};
- LightUniform *light_uniforms;
+ LightUniform *light_uniforms = nullptr;
RID lights_uniform_buffer;
RID canvas_state_buffer;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 6d6cf0ce73..5b7c63b508 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -156,6 +156,8 @@ void RendererCompositorRD::finalize() {
memdelete(canvas);
memdelete(storage);
memdelete(decal_atlas_storage);
+ memdelete(mesh_storage);
+ memdelete(material_storage);
memdelete(texture_storage);
memdelete(canvas_texture_storage);
@@ -289,6 +291,8 @@ RendererCompositorRD::RendererCompositorRD() {
canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
texture_storage = memnew(RendererRD::TextureStorage);
decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
+ material_storage = memnew(RendererRD::MaterialStorage);
+ mesh_storage = memnew(RendererRD::MeshStorage);
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index a860093bb1..542cff0159 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -41,18 +41,22 @@
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
- UniformSetCacheRD *uniform_set_cache;
- RendererCanvasRenderRD *canvas;
+ UniformSetCacheRD *uniform_set_cache = nullptr;
+ RendererCanvasRenderRD *canvas = nullptr;
RendererRD::CanvasTextureStorage *canvas_texture_storage;
+ RendererRD::MaterialStorage *material_storage;
+ RendererRD::MeshStorage *mesh_storage;
RendererRD::TextureStorage *texture_storage;
RendererRD::DecalAtlasStorage *decal_atlas_storage;
- RendererStorageRD *storage;
- RendererSceneRenderRD *scene;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneRenderRD *scene = nullptr;
enum BlitMode {
BLIT_MODE_NORMAL,
@@ -95,8 +99,10 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
- RendererTextureStorage *get_texture_storage() { return texture_storage; }
RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
+ RendererMaterialStorage *get_material_storage() { return material_storage; };
+ RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
+ RendererTextureStorage *get_texture_storage() { return texture_storage; };
RendererStorage *get_storage() { return storage; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index d51b1bf691..ed60bc4362 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -55,7 +55,7 @@ class RendererSceneRenderRD;
class RendererSceneGIRD {
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
/* VOXEL_GI INSTANCE */
@@ -331,8 +331,8 @@ public:
struct VoxelGIInstance {
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
RID probe;
RID texture;
@@ -455,8 +455,8 @@ public:
};
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
// used for rendering (voxelization)
RID render_albedo;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 4a6dbc137c..ac7ac692ce 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -34,6 +34,8 @@
#include "core/os/os.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
@@ -2359,6 +2361,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -2571,6 +2574,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -2647,6 +2651,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
}
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
EffectsRD *effects = storage->get_effects();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -3860,7 +3865,7 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
@@ -3920,13 +3925,13 @@ void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_
}
}
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E->get());
p.info.name = E->key(); //supply name
p.index = E->get().instance_index;
@@ -3961,7 +3966,7 @@ Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const String
}
RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
}
@@ -3971,7 +3976,7 @@ RendererSceneRenderRD::FogShaderData::FogShaderData() {
}
RendererSceneRenderRD::FogShaderData::~FogShaderData() {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -3983,7 +3988,7 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() {
// Fog material
bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -3994,23 +3999,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
FogShaderData *shader_data = memnew(FogShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
FogMaterialData *material_data = memnew(FogMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
};
@@ -4068,6 +4073,9 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto
}
void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -4268,7 +4276,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
FogMaterialData *material = nullptr;
if (fog_material.is_valid()) {
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -4276,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (!material) {
fog_material = volumetric_fog.default_material;
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
}
ERR_FAIL_COND(!material);
@@ -5493,7 +5501,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
GeometryInstance *gi = geometry_instance_create(p_base);
- uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+ uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
materials.resize(sc);
@@ -5605,12 +5613,13 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
}
RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
- texture_storage = RendererRD::TextureStorage::get_singleton();
storage = p_storage;
singleton = this;
}
void RendererSceneRenderRD::init() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5667,8 +5676,8 @@ void RendererSceneRenderRD::init() {
volumetric_fog_modes.push_back("");
volumetric_fog.shader.initialize(volumetric_fog_modes);
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
}
@@ -5707,9 +5716,9 @@ void RendererSceneRenderRD::init() {
{
// default material and shader for fog shader
- volumetric_fog.default_shader = storage->shader_allocate();
- storage->shader_initialize(volumetric_fog.default_shader);
- storage->shader_set_code(volumetric_fog.default_shader, R"(
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
// Default fog shader.
shader_type fog;
@@ -5719,11 +5728,11 @@ void fog() {
ALBEDO = vec3(1.0);
}
)");
- volumetric_fog.default_material = storage->material_allocate();
- storage->material_initialize(volumetric_fog.default_material);
- storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
- FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+ FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -5753,7 +5762,7 @@ void fog() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -5822,6 +5831,8 @@ void fog() {
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
}
@@ -5838,20 +5849,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
- storage->free(volumetric_fog.default_shader);
- storage->free(volumetric_fog.default_material);
- }
-
- RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
- sky.sky_shader.shader.version_free(md->shader_data->version);
- RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer);
- RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer);
- memdelete_arr(sky.sky_scene_state.directional_lights);
- memdelete_arr(sky.sky_scene_state.last_frame_directional_lights);
- storage->free(sky.sky_shader.default_shader);
- storage->free(sky.sky_shader.default_material);
- storage->free(sky.sky_scene_state.fog_shader);
- storage->free(sky.sky_scene_state.fog_material);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+ }
+
memdelete_arr(directional_penumbra_shadow_kernel);
memdelete_arr(directional_soft_shadow_kernel);
memdelete_arr(penumbra_shadow_kernel);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index e302db2631..b2c8daffb1 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -41,7 +41,6 @@
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -93,8 +92,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
friend RendererSceneGIRD;
protected:
- RendererRD::TextureStorage *texture_storage;
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
double time;
double time_step = 0;
@@ -316,10 +314,10 @@ private:
float shadows_quality_radius = 1.0;
float directional_shadow_quality_radius = 1.0;
- float *directional_penumbra_shadow_kernel;
- float *directional_soft_shadow_kernel;
- float *penumbra_shadow_kernel;
- float *soft_shadow_kernel;
+ float *directional_penumbra_shadow_kernel = nullptr;
+ float *directional_soft_shadow_kernel = nullptr;
+ float *penumbra_shadow_kernel = nullptr;
+ float *soft_shadow_kernel = nullptr;
int directional_penumbra_shadow_samples = 0;
int directional_soft_shadow_samples = 0;
int penumbra_shadow_samples = 0;
@@ -707,27 +705,27 @@ private:
template <class T>
struct InstanceSort {
float depth;
- T *instance;
+ T *instance = nullptr;
bool operator<(const InstanceSort &p_sort) const {
return depth < p_sort.depth;
}
};
- ReflectionData *reflections;
+ ReflectionData *reflections = nullptr;
InstanceSort<ReflectionProbeInstance> *reflection_sort;
uint32_t max_reflections;
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
uint32_t reflection_count = 0;
- DecalData *decals;
+ DecalData *decals = nullptr;
InstanceSort<DecalInstance> *decal_sort;
uint32_t max_decals;
RID decal_buffer;
uint32_t decal_count;
- LightData *omni_lights;
- LightData *spot_lights;
+ LightData *omni_lights = nullptr;
+ LightData *spot_lights = nullptr;
InstanceSort<LightInstance> *omni_light_sort;
InstanceSort<LightInstance> *spot_light_sort;
@@ -737,7 +735,7 @@ private:
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
- DirectionalLightData *directional_lights;
+ DirectionalLightData *directional_lights = nullptr;
uint32_t max_directional_lights;
RID directional_light_buffer;
@@ -909,7 +907,7 @@ private:
void _volumetric_fog_erase(RenderBuffers *rb);
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
- struct FogShaderData : public RendererStorageRD::ShaderData {
+ struct FogShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
@@ -929,7 +927,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -939,8 +937,8 @@ private:
virtual ~FogShaderData();
};
- struct FogMaterialData : public RendererStorageRD::MaterialData {
- FogShaderData *shader_data;
+ struct FogMaterialData : public RendererRD::MaterialData {
+ FogShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
@@ -950,11 +948,11 @@ private:
virtual ~FogMaterialData();
};
- RendererStorageRD::ShaderData *_create_fog_shader_func();
- static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+ RendererRD::ShaderData *_create_fog_shader_func();
+ static RendererRD::ShaderData *_create_fog_shader_funcs();
- RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
RID shadow_sampler;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 44da9e40f8..061aa8b4aa 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@@ -90,7 +91,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
// !BAS! Contemplate making `SkyShader sky` accessible from this struct or even part of this struct.
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
@@ -177,13 +178,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -218,7 +219,7 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
}
RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
@@ -228,7 +229,7 @@ RendererSceneSkyRD::SkyShaderData::SkyShaderData() {
}
RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -240,7 +241,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
// Sky material
bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -767,24 +768,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
////////////////////////////////////////////////////////////////////////////////
// RendererSceneSkyRD
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
@@ -797,6 +798,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -833,8 +835,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
// register our shader funds
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -896,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
{
// default material and shader for sky shader
- sky_shader.default_shader = storage->shader_allocate();
- storage->shader_initialize(sky_shader.default_shader);
+ sky_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_shader.default_shader);
- storage->shader_set_code(sky_shader.default_shader, R"(
+ material_storage->shader_set_code(sky_shader.default_shader, R"(
// Default sky shader.
shader_type sky;
@@ -909,12 +911,12 @@ void sky() {
}
)");
- sky_shader.default_material = storage->material_allocate();
- storage->material_initialize(sky_shader.default_material);
+ sky_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_shader.default_material);
- storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+ material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
- SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
@@ -947,7 +949,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -986,10 +988,10 @@ void sky() {
{
// Need defaults for using fog with clear color
- sky_scene_state.fog_shader = storage->shader_allocate();
- storage->shader_initialize(sky_scene_state.fog_shader);
+ sky_scene_state.fog_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_scene_state.fog_shader);
- storage->shader_set_code(sky_scene_state.fog_shader, R"(
+ material_storage->shader_set_code(sky_scene_state.fog_shader, R"(
// Default clear color sky shader.
shader_type sky;
@@ -1000,10 +1002,10 @@ void sky() {
COLOR = clear_color.rgb;
}
)");
- sky_scene_state.fog_material = storage->material_allocate();
- storage->material_initialize(sky_scene_state.fog_material);
+ sky_scene_state.fog_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_scene_state.fog_material);
- storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
+ material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
Vector<RD::Uniform> uniforms;
{
@@ -1054,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
}
RendererSceneSkyRD::~RendererSceneSkyRD() {
- // TODO cleanup anything created in init...
+ // cleanup anything created in init...
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
+ sky_shader.shader.version_free(md->shader_data->version);
+ RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
+ RD::get_singleton()->free(sky_scene_state.uniform_buffer);
+ memdelete_arr(sky_scene_state.directional_lights);
+ memdelete_arr(sky_scene_state.last_frame_directional_lights);
+ material_storage->shader_free(sky_shader.default_shader);
+ material_storage->material_free(sky_shader.default_material);
+ material_storage->shader_free(sky_scene_state.fog_shader);
+ material_storage->material_free(sky_scene_state.fog_material);
if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
RD::get_singleton()->free(sky_scene_state.uniform_set);
@@ -1072,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
SkyMaterialData *material = nullptr;
@@ -1085,7 +1100,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1093,7 +1108,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1282,6 +1297,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
}
void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1292,7 +1308,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1300,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1450,6 +1466,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1467,7 +1484,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1475,13 +1492,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1556,6 +1573,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1570,7 +1588,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1578,7 +1596,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1640,6 +1658,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
}
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1657,7 +1676,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1665,13 +1684,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 13d24e2508..010e2178a9 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -63,7 +63,7 @@ public:
};
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -105,7 +105,7 @@ private:
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
- struct SkyShaderData : public RendererStorageRD::ShaderData {
+ struct SkyShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
@@ -129,7 +129,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -162,8 +162,8 @@ public:
UBO ubo;
- SkyDirectionalLightData *directional_lights;
- SkyDirectionalLightData *last_frame_directional_lights;
+ SkyDirectionalLightData *directional_lights = nullptr;
+ SkyDirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t max_directional_lights;
uint32_t last_frame_directional_light_count;
RID directional_light_buffer;
@@ -227,8 +227,8 @@ public:
RID default_shader_rd;
} sky_shader;
- struct SkyMaterialData : public RendererStorageRD::MaterialData {
- SkyShaderData *shader_data;
+ struct SkyMaterialData : public RendererRD::MaterialData {
+ SkyShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
@@ -262,7 +262,7 @@ public:
Sky *dirty_list = nullptr;
//State to track when radiance cubemap needs updating
- SkyMaterialData *prev_material;
+ SkyMaterialData *prev_material = nullptr;
Vector3 prev_position;
float prev_time;
@@ -281,11 +281,11 @@ public:
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
- RendererStorageRD::ShaderData *_create_sky_shader_func();
- static RendererStorageRD::ShaderData *_create_sky_shader_funcs();
+ RendererRD::ShaderData *_create_sky_shader_func();
+ static RendererRD::ShaderData *_create_sky_shader_funcs();
- RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
RendererSceneSkyRD();
void init(RendererStorageRD *p_storage);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 5b6dfbe19f..72f98a4690 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -37,6 +37,7 @@
#include "renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
@@ -137,3105 +138,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* SHADER API */
-
-RID RendererStorageRD::shader_allocate() {
- return shader_owner.allocate_rid();
-}
-void RendererStorageRD::shader_initialize(RID p_rid) {
- Shader shader;
- shader.data = nullptr;
- shader.type = SHADER_TYPE_MAX;
-
- shader_owner.initialize_rid(p_rid, shader);
-}
-
-void RendererStorageRD::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);
-
- ShaderType new_type;
- if (mode_string == "canvas_item") {
- new_type = SHADER_TYPE_2D;
- } else if (mode_string == "particles") {
- new_type = SHADER_TYPE_PARTICLES;
- } else if (mode_string == "spatial") {
- new_type = SHADER_TYPE_3D;
- } else if (mode_string == "sky") {
- new_type = SHADER_TYPE_SKY;
- } else if (mode_string == "fog") {
- new_type = SHADER_TYPE_FOG;
- } else {
- new_type = SHADER_TYPE_MAX;
- }
-
- if (new_type != shader->type) {
- if (shader->data) {
- memdelete(shader->data);
- shader->data = nullptr;
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->shader_type = new_type;
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
- }
-
- shader->type = new_type;
-
- if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
- shader->data = shader_data_request_func[new_type]();
- } else {
- shader->type = SHADER_TYPE_MAX; //invalid
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- if (shader->data) {
- material->data = material_data_request_func[new_type](shader->data);
- material->data->self = material->self;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- }
- material->shader_type = new_type;
- }
-
- if (shader->data) {
- for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
- for (const KeyValue<int, RID> &E2 : E.value) {
- shader->data->set_default_texture_param(E.key, E2.value, E2.key);
- }
- }
- }
- }
-
- if (shader->data) {
- shader->data->set_code(p_code);
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
- }
-}
-
-String RendererStorageRD::shader_get_code(RID p_shader) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, String());
- return shader->code;
-}
-
-void RendererStorageRD::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->data) {
- return shader->data->get_param_list(p_param_list);
- }
-}
-
-void RendererStorageRD::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);
-
- if (p_texture.is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)) {
- if (!shader->default_texture_parameter.has(p_name)) {
- shader->default_texture_parameter[p_name] = Map<int, RID>();
- }
- shader->default_texture_parameter[p_name][p_index] = p_texture;
- } else {
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- shader->default_texture_parameter[p_name].erase(p_index);
-
- if (shader->default_texture_parameter[p_name].is_empty()) {
- shader->default_texture_parameter.erase(p_name);
- }
- }
- }
- if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture, p_index);
- }
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- _material_queue_update(material, false, true);
- }
-}
-
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- return shader->default_texture_parameter[p_name][p_index];
- }
-
- return RID();
-}
-
-Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, Variant());
- if (shader->data) {
- return shader->data->get_default_parameter(p_param);
- }
- return Variant();
-}
-
-void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
- ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
- shader_data_request_func[p_shader_type] = p_function;
-}
-
-RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
- if (shader->data) {
- return shader->data->get_native_source_code();
- }
- return RS::ShaderNativeSourceCode();
-}
-
-/* COMMON MATERIAL API */
-
-RID RendererStorageRD::material_allocate() {
- return material_owner.allocate_rid();
-}
-void RendererStorageRD::material_initialize(RID p_rid) {
- material_owner.initialize_rid(p_rid);
- Material *material = material_owner.get_or_null(p_rid);
- material->self = p_rid;
-}
-
-void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
- material->uniform_dirty = material->uniform_dirty || p_uniform;
- material->texture_dirty = material->texture_dirty || p_texture;
-
- if (material->update_element.in_list()) {
- return;
- }
-
- material_update_list.add(&material->update_element);
-}
-
-void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
-
- if (material->shader) {
- material->shader->owners.erase(material);
- material->shader = nullptr;
- material->shader_type = SHADER_TYPE_MAX;
- }
-
- if (p_shader.is_null()) {
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- material->shader_id = 0;
- return;
- }
-
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
- material->shader = shader;
- material->shader_type = shader->type;
- material->shader_id = p_shader.get_local_index();
- shader->owners.insert(material);
-
- if (shader->type == SHADER_TYPE_MAX) {
- return;
- }
-
- ERR_FAIL_COND(shader->data == nullptr);
-
- material->data = material_data_request_func[shader->type](shader->data);
- material->data->self = p_material;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- //updating happens later
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
-}
-
-void RendererStorageRD::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 {
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
- material->params[p_param] = p_value;
- }
-
- if (material->shader && material->shader->data) { //shader is valid
- bool is_texture = material->shader->data->is_param_texture(p_param);
- _material_queue_update(material, !is_texture, is_texture);
- } else {
- _material_queue_update(material, true, true);
- }
-}
-
-Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, Variant());
- if (material->params.has(p_param)) {
- return material->params[p_param];
- } else {
- return Variant();
- }
-}
-
-void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->next_pass == p_next_material) {
- return;
- }
-
- material->next_pass = p_next_material;
- if (material->data) {
- material->data->set_next_pass(p_next_material);
- }
-
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
-}
-
-void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- material->priority = priority;
- if (material->data) {
- material->data->set_render_priority(priority);
- }
-}
-
-bool RendererStorageRD::material_is_animated(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->shader && material->shader->data) {
- if (material->shader->data->is_animated()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_is_animated(material->next_pass);
- }
- }
- return false; //by default nothing is animated
-}
-
-bool RendererStorageRD::material_casts_shadows(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, true);
- if (material->shader && material->shader->data) {
- if (material->shader->data->casts_shadows()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_casts_shadows(material->next_pass);
- }
- }
- return true; //by default everything casts shadows
-}
-
-void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- if (material->shader && material->shader->data) {
- material->shader->data->get_instance_param_list(r_parameters);
-
- if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
- }
- }
-}
-
-void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- p_instance->update_dependency(&material->dependency);
- if (material->next_pass.is_valid()) {
- material_update_dependency(material->next_pass, p_instance);
- }
-}
-
-void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
- ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
- material_data_request_func[p_shader_type] = p_function;
-}
-
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = (r[i] != 0) ? 1 : 0;
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- bool v = value;
- gui[0] = v ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 2 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v & 1 ? 1 : 0;
- gui[1] = v & 2 ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 3 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- gui[j + 2] = r[i + 2] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i] ? 1 : 0;
- gui[i + 1] = r[i + 1] ? 1 : 0;
- gui[i + 2] = r[i + 2] ? 1 : 0;
- gui[i + 3] = r[i + 3] ? 1 : 0;
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- gui[3] = (v & 8) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- float v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector2Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector2 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- }
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector3Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- gui[j + 2] = a[i].z;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector3 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- }
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
- const PackedColorArray &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- Color color = a[i];
- if (p_linear_color) {
- color = color.to_linear();
- }
- gui[j] = color.r;
- gui[j + 1] = color.g;
- gui[j + 2] = color.b;
- gui[j + 3] = color.a;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- gui[j + 3] = 0;
- }
- }
- } else {
- const PackedFloat32Array &a = value;
- int s = a.size();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i + 3 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- }
- } else {
- if (value.get_type() == Variant::COLOR) {
- Color v = value;
-
- if (p_linear_color) {
- v = v.to_linear();
- }
-
- gui[0] = v.r;
- gui[1] = v.g;
- gui[2] = v.b;
- gui[3] = v.a;
- } else if (value.get_type() == Variant::RECT2) {
- Rect2 v = value;
-
- gui[0] = v.position.x;
- gui[1] = v.position.y;
- gui[2] = v.size.x;
- gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUATERNION) {
- Quaternion v = value;
-
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- gui[3] = v.w;
- } else {
- Plane v = value;
-
- gui[0] = v.normal.x;
- gui[1] = v.normal.y;
- gui[2] = v.normal.z;
- gui[3] = v.d;
- }
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
- if (i + 3 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
-
- gui[j + 4] = a[i + 2];
- gui[j + 5] = a[i + 3];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- gui[j + 6] = 0; // ignored
- gui[j + 7] = 0; // ignored
- }
- } else {
- Transform2D v = value;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
- gui[2] = 0; // ignored
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
- gui[6] = 0; // ignored
- gui[7] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
- if (i + 8 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
- gui[j + 2] = a[i + 2];
-
- gui[j + 4] = a[i + 3];
- gui[j + 5] = a[i + 4];
- gui[j + 6] = a[i + 5];
-
- gui[j + 8] = a[i + 6];
- gui[j + 9] = a[i + 7];
- gui[j + 10] = a[i + 8];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- gui[j + 6] = 0;
-
- gui[j + 8] = 0;
- gui[j + 9] = 0;
- gui[j + 10] = 1;
- }
- gui[j + 3] = 0; // ignored
- gui[j + 7] = 0; // ignored
- gui[j + 11] = 0; // ignored
- }
- } else {
- Basis v = value;
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
- gui[7] = 0; // ignored
-
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
- gui[11] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0; i < p_array_size * 16; i += 16) {
- if (i + 15 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
-
- gui[i + 4] = a[i + 4];
- gui[i + 5] = a[i + 5];
- gui[i + 6] = a[i + 6];
- gui[i + 7] = a[i + 7];
-
- gui[i + 8] = a[i + 8];
- gui[i + 9] = a[i + 9];
- gui[i + 10] = a[i + 10];
- gui[i + 11] = a[i + 11];
-
- gui[i + 12] = a[i + 12];
- gui[i + 13] = a[i + 13];
- gui[i + 14] = a[i + 14];
- gui[i + 15] = a[i + 15];
- } else {
- gui[i] = 1;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
-
- gui[i + 4] = 0;
- gui[i + 5] = 1;
- gui[i + 6] = 0;
- gui[i + 7] = 0;
-
- gui[i + 8] = 0;
- gui[i + 9] = 0;
- gui[i + 10] = 1;
- gui[i + 11] = 0;
-
- gui[i + 12] = 0;
- gui[i + 13] = 0;
- gui[i + 14] = 0;
- gui[i + 15] = 1;
- }
- }
- } else {
- Transform3D v = value;
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
- gui[3] = 0;
-
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
- gui[7] = 0;
-
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
- gui[11] = 0;
-
- gui[12] = v.origin.x;
- gui[13] = v.origin.y;
- gui[14] = v.origin.z;
- gui[15] = 1;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
- *gui = value[0].boolean ? 1 : 0;
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
- gui[3] = value[3].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
- gui[0] = value[0].sint;
-
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].uint;
-
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].uint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
- gui[0] = value[0].real;
-
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].real;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = value[2].real;
- gui[5] = value[3].real;
- gui[6] = 0;
- gui[7] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = value[2].real;
- gui[3] = 0;
- gui[4] = value[3].real;
- gui[5] = value[4].real;
- gui[6] = value[5].real;
- gui[7] = 0;
- gui[8] = value[6].real;
- gui[9] = value[7].real;
- gui[10] = value[8].real;
- gui[11] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 16; i++) {
- gui[i] = value[i].real;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
-
- switch (type) {
- case ShaderLanguage::TYPE_BOOL:
- case ShaderLanguage::TYPE_INT:
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_FLOAT: {
- memset(data, 0, 4 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC2:
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_VEC2: {
- memset(data, 0, 8 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC3:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3:
- case ShaderLanguage::TYPE_BVEC4:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC4:
- case ShaderLanguage::TYPE_VEC4: {
- memset(data, 0, 16 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- memset(data, 0, 32 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- memset(data, 0, 48 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- memset(data, 0, 64 * p_array_size);
- } break;
-
- default: {
- }
- }
-}
-
-void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
- bool uses_global_buffer = false;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
- if (E.value.order < 0) {
- continue; // texture, does not go here
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue; //instance uniforms don't appear in the buffer
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
- //this is a global variable, get the index to it
- RendererStorageRD *rs = base_singleton;
-
- GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key);
- uint32_t index = 0;
- if (gv) {
- index = gv->buffer_index;
- } else {
- WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
- }
-
- uint32_t offset = p_uniform_offsets[E.value.order];
- uint32_t *intptr = (uint32_t *)&p_buffer[offset];
- *intptr = index;
- uses_global_buffer = true;
- continue;
- }
-
- //regular uniform
- uint32_t offset = p_uniform_offsets[E.value.order];
-#ifdef DEBUG_ENABLED
- uint32_t size = 0U;
- // The following code enforces a 16-byte alignment of uniform arrays.
- if (E.value.array_size > 0) {
- size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
- int m = (16 * E.value.array_size);
- if ((size % m) != 0U) {
- size += m - (size % m);
- }
- } else {
- size = ShaderLanguage::get_datatype_size(E.value.type);
- }
- ERR_CONTINUE(offset + size > p_buffer_size);
-#endif
- uint8_t *data = &p_buffer[offset];
- const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
-
- if (V) {
- //user provided
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
-
- } else if (E.value.default_value.size()) {
- //default value
- _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
- //value=E.value.default_value;
- } else {
- //zero because it was not provided
- if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- //colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
- } else {
- //else just zero it out
- _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
- }
- }
- }
-
- if (uses_global_buffer != (global_buffer_E != nullptr)) {
- RendererStorageRD *rs = base_singleton;
- if (uses_global_buffer) {
- global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self);
- } else {
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- global_buffer_E = nullptr;
- }
- }
-}
-
-RendererStorageRD::MaterialData::~MaterialData() {
- if (global_buffer_E) {
- //unregister global buffers
- RendererStorageRD *rs = base_singleton;
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- }
-
- if (global_texture_E) {
- //unregister global textures
- RendererStorageRD *rs = base_singleton;
-
- for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key);
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- //unregister material from those using global textures
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
-}
-
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
-#ifdef TOOLS_ENABLED
- RendererRD::Texture *roughness_detect_texture = nullptr;
- RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
- RendererRD::Texture *normal_detect_texture = nullptr;
-#endif
-
- bool uses_global_textures = false;
- global_textures_pass++;
-
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const StringName &uniform_name = p_texture_uniforms[i].name;
- int uniform_array_size = p_texture_uniforms[i].array_size;
-
- Vector<RID> textures;
-
- if (p_texture_uniforms[i].global) {
- RendererStorageRD *rs = base_singleton;
-
- uses_global_textures = true;
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name);
- if (v) {
- if (v->buffer_index >= 0) {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
-
- } else {
- Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
- if (!E) {
- E = used_global_textures.insert(uniform_name, global_textures_pass);
- v->texture_materials.insert(self);
- } else {
- E->get() = global_textures_pass;
- }
-
- textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
- }
-
- } else {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
- }
- } else {
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
- if (V) {
- if (V->get().is_array()) {
- Array array = (Array)V->get();
- if (uniform_array_size > 0) {
- for (int j = 0; j < array.size(); j++) {
- textures.push_back(array[j]);
- }
- } else {
- if (array.size() > 0) {
- textures.push_back(array[0]);
- }
- }
- } else {
- textures.push_back(V->get());
- }
- }
-
- if (uniform_array_size > 0) {
- if (textures.size() < uniform_array_size) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- for (int j = textures.size(); j < uniform_array_size; j++) {
- if (W && W->get().has(j)) {
- textures.push_back(W->get()[j]);
- } else {
- textures.push_back(RID());
- }
- }
- }
- } else if (textures.is_empty()) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- if (W && W->get().has(0)) {
- textures.push_back(W->get()[0]);
- }
- }
- }
-
- RID rd_texture;
-
- if (textures.is_empty()) {
- //check default usage
- switch (p_texture_uniforms[i].type) {
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D:
- case ShaderLanguage::TYPE_SAMPLER2D: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_ANISO);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- default: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
- } break;
- }
- } break;
-
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- } break;
- default: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
- } break;
- }
- } break;
- case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLER3D: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY:
- case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- } break;
-
- default: {
- }
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- if (uniform_array_size > 0) {
- for (int j = 0; j < uniform_array_size; j++) {
- p_textures[k++] = rd_texture;
- }
- } else {
- p_textures[k++] = rd_texture;
- }
- } else {
- bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
-
- for (int j = 0; j < textures.size(); j++) {
- RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(textures[j]);
-
- if (tex) {
- rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
-#ifdef TOOLS_ENABLED
- if (tex->detect_3d_callback && p_use_linear_color) {
- tex->detect_3d_callback(tex->detect_3d_callback_ud);
- }
- if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
- if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
- normal_detect_texture = tex;
- }
- tex->detect_normal_callback(tex->detect_normal_callback_ud);
- }
- if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
- //find the normal texture
- roughness_detect_texture = tex;
- roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
- }
-#endif
- }
- if (rd_texture.is_null()) {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- p_textures[k++] = rd_texture;
- }
- }
- }
- {
- //for textures no longer used, unregister them
- List<Map<StringName, uint64_t>::Element *> to_delete;
- RendererStorageRD *rs = base_singleton;
-
- for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
- if (E->get() != global_textures_pass) {
- to_delete.push_back(E);
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- }
-
- while (to_delete.front()) {
- used_global_textures.erase(to_delete.front()->get());
- to_delete.pop_front();
- }
- //handle registering/unregistering global textures
- if (uses_global_textures != (global_texture_E != nullptr)) {
- if (uses_global_textures) {
- global_texture_E = rs->global_variables.materials_using_texture.push_back(self);
- } else {
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- global_texture_E = nullptr;
- }
- }
- }
-}
-
-void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
- if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(p_uniform_set);
- }
-}
-
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
- if ((uint32_t)ubo_data.size() != p_ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(p_ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
- }
-
- uint32_t tex_uniform_count = 0U;
- for (int i = 0; i < p_texture_uniforms.size(); i++) {
- tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
- }
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return false;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return false;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (p_ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.append_id(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const int array_size = p_texture_uniforms[i].array_size;
-
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + k;
- if (array_size > 0) {
- for (int j = 0; j < array_size; j++) {
- u.append_id(textures[k++]);
- }
- } else {
- u.append_id(textures[k++]);
- }
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
-
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self);
-
- return true;
-}
-
-void RendererStorageRD::_material_uniform_set_erased(void *p_material) {
- RID rid = *(RID *)p_material;
- Material *material = base_singleton->material_owner.get_or_null(rid);
- if (material) {
- if (material->data) {
- // Uniform set may be gone because a dependency was erased. This happens
- // if a texture is deleted, so re-create it.
- base_singleton->_material_queue_update(material, false, true);
- }
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
-}
-
-void RendererStorageRD::_update_queued_materials() {
- while (material_update_list.first()) {
- Material *material = material_update_list.first()->self();
- bool uniforms_changed = false;
-
- if (material->data) {
- uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
- }
- material->texture_dirty = false;
- material->uniform_dirty = false;
-
- material_update_list.remove(&material->update_element);
-
- if (uniforms_changed) {
- //some implementations such as 3D renderer cache the matreial uniform set, so update is required
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
- }
-}
-
-/* MESH API */
-
-RID RendererStorageRD::mesh_allocate() {
- return mesh_owner.allocate_rid();
-}
-void RendererStorageRD::mesh_initialize(RID p_rid) {
- mesh_owner.initialize_rid(p_rid, Mesh());
-}
-
-void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
- ERR_FAIL_COND(p_blend_shape_count < 0);
-
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
-
- mesh->blend_shape_count = p_blend_shape_count;
-}
-
-/// Returns stride
-void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
-
-#ifdef DEBUG_ENABLED
- //do a validation, to catch errors first
- {
- uint32_t stride = 0;
- uint32_t attrib_stride = 0;
- uint32_t skin_stride = 0;
-
- for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
- if ((p_surface.format & (1 << i))) {
- switch (i) {
- case RS::ARRAY_VERTEX: {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- stride += sizeof(float) * 2;
- } else {
- stride += sizeof(float) * 3;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_TANGENT: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_COLOR: {
- attrib_stride += sizeof(uint32_t);
- } break;
- case RS::ARRAY_TEX_UV: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- int idx = i - RS::ARRAY_CUSTOM0;
- uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
- uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
- uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
- attrib_stride += fmtsize[fmt];
-
- } break;
- case RS::ARRAY_WEIGHTS:
- case RS::ARRAY_BONES: {
- //uses a separate array
- bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
- skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8);
- } break;
- }
- }
- }
-
- int expected_size = stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
-
- int bs_expected_size = expected_size * mesh->blend_shape_count;
-
- ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")");
-
- int expected_attrib_size = attrib_stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
-
- if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
- expected_size = skin_stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
- }
- }
-
-#endif
-
- Mesh::Surface *s = memnew(Mesh::Surface);
-
- s->format = p_surface.format;
- s->primitive = p_surface.primitive;
-
- bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
-
- s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
- s->vertex_buffer_size = p_surface.vertex_data.size();
-
- if (p_surface.attribute_data.size()) {
- s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
- }
- if (p_surface.skin_data.size()) {
- s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage);
- s->skin_buffer_size = p_surface.skin_data.size();
- }
-
- s->vertex_count = p_surface.vertex_count;
-
- if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
- mesh->has_bone_weights = true;
- }
-
- if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
-
- s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
- s->index_count = p_surface.index_count;
- s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
- if (p_surface.lods.size()) {
- s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
- s->lod_count = p_surface.lods.size();
-
- for (int i = 0; i < p_surface.lods.size(); i++) {
- uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
- s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
- s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
- s->lods[i].edge_length = p_surface.lods[i].edge_length;
- s->lods[i].index_count = indices;
- }
- }
- }
-
- s->aabb = p_surface.aabb;
- s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
-
- if (mesh->blend_shape_count > 0) {
- s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
- }
-
- if (use_as_storage) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (s->skin_buffer.is_valid()) {
- u.append_id(s->skin_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (s->blend_shape_buffer.is_valid()) {
- u.append_id(s->blend_shape_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
-
- s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE);
- }
-
- if (mesh->surface_count == 0) {
- mesh->bone_aabbs = p_surface.bone_aabbs;
- mesh->aabb = p_surface.aabb;
- } else {
- if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
- // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
- // Each surface may affect different numbers of bones.
- mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
- }
- for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
- }
- mesh->aabb.merge_with(p_surface.aabb);
- }
-
- s->material = p_surface.material;
-
- mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
- mesh->surfaces[mesh->surface_count] = s;
- mesh->surface_count++;
-
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-
- mesh->material_cache.clear();
-}
-
-int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const {
- const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, -1);
- return mesh->blend_shape_count;
-}
-
-void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX((int)p_mode, 2);
-
- mesh->blend_shape_mode = p_mode;
-}
-
-RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
- return mesh->blend_shape_mode;
-}
-
-void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- mesh->surfaces[p_surface]->material = p_material;
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- mesh->material_cache.clear();
-}
-
-RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
-
- return mesh->surfaces[p_surface]->material;
-}
-
-RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
-
- Mesh::Surface &s = *mesh->surfaces[p_surface];
-
- RS::SurfaceData sd;
- sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
- if (s.attribute_buffer.is_valid()) {
- sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
- }
- if (s.skin_buffer.is_valid()) {
- sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
- }
- sd.vertex_count = s.vertex_count;
- sd.index_count = s.index_count;
- sd.primitive = s.primitive;
-
- if (sd.index_count) {
- sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
- }
- sd.aabb = s.aabb;
- for (uint32_t i = 0; i < s.lod_count; i++) {
- RS::SurfaceData::LOD lod;
- lod.edge_length = s.lods[i].edge_length;
- lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
- sd.lods.push_back(lod);
- }
-
- sd.bone_aabbs = s.bone_aabbs;
-
- if (s.blend_shape_buffer.is_valid()) {
- sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
- }
-
- return sd;
-}
-
-int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- return mesh->surface_count;
-}
-
-void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- mesh->custom_aabb = p_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
- return mesh->custom_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
-
- if (mesh->custom_aabb != AABB()) {
- return mesh->custom_aabb;
- }
-
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- if (!skeleton || skeleton->size == 0) {
- return mesh->aabb;
- }
-
- AABB aabb;
-
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- AABB laabb;
- if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
- int bs = mesh->surfaces[i]->bone_aabbs.size();
- const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
-
- int sbs = skeleton->size;
- ERR_CONTINUE(bs > sbs);
- const float *baseptr = skeleton->data.ptr();
-
- bool first = true;
-
- if (skeleton->use_2d) {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 8;
-
- Transform3D mtx;
-
- mtx.basis.elements[0].x = dataptr[0];
- mtx.basis.elements[1].x = dataptr[1];
- mtx.origin.x = dataptr[3];
-
- mtx.basis.elements[0].y = dataptr[4];
- mtx.basis.elements[1].y = dataptr[5];
- mtx.origin.y = dataptr[7];
-
- AABB baabb = mtx.xform(skbones[j]);
-
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- } else {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 12;
-
- Transform3D mtx;
-
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.basis.elements[0][2] = dataptr[2];
- mtx.origin.x = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.basis.elements[1][2] = dataptr[6];
- mtx.origin.y = dataptr[7];
- mtx.basis.elements[2][0] = dataptr[8];
- mtx.basis.elements[2][1] = dataptr[9];
- mtx.basis.elements[2][2] = dataptr[10];
- mtx.origin.z = dataptr[11];
-
- AABB baabb = mtx.xform(skbones[j]);
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- }
-
- if (laabb.size == Vector3()) {
- laabb = mesh->surfaces[i]->aabb;
- }
- } else {
- laabb = mesh->surfaces[i]->aabb;
- }
-
- if (i == 0) {
- aabb = laabb;
- } else {
- aabb.merge_with(laabb);
- }
- }
-
- return aabb;
-}
-
-void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.erase(mesh);
- }
- mesh->shadow_mesh = p_shadow_mesh;
-
- shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
-
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.insert(mesh);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-void RendererStorageRD::mesh_clear(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- Mesh::Surface &s = *mesh->surfaces[i];
- RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
- if (s.attribute_buffer.is_valid()) {
- RD::get_singleton()->free(s.attribute_buffer);
- }
- if (s.skin_buffer.is_valid()) {
- RD::get_singleton()->free(s.skin_buffer);
- }
- if (s.versions) {
- memfree(s.versions); //reallocs, so free with memfree.
- }
-
- if (s.index_buffer.is_valid()) {
- RD::get_singleton()->free(s.index_buffer);
- }
-
- if (s.lod_count) {
- for (uint32_t j = 0; j < s.lod_count; j++) {
- RD::get_singleton()->free(s.lods[j].index_buffer);
- }
- memdelete_arr(s.lods);
- }
-
- if (s.blend_shape_buffer.is_valid()) {
- RD::get_singleton()->free(s.blend_shape_buffer);
- }
-
- memdelete(mesh->surfaces[i]);
- }
- if (mesh->surfaces) {
- memfree(mesh->surfaces);
- }
-
- mesh->surfaces = nullptr;
- mesh->surface_count = 0;
- mesh->material_cache.clear();
- //clear instance data
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_clear(mi);
- }
- mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-}
-
-bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, false);
-
- return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
-}
-
-/* MESH INSTANCE */
-
-RID RendererStorageRD::mesh_instance_create(RID p_base) {
- Mesh *mesh = mesh_owner.get_or_null(p_base);
- ERR_FAIL_COND_V(!mesh, RID());
-
- RID rid = mesh_instance_owner.make_rid();
- MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
-
- mi->mesh = mesh;
-
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- _mesh_instance_add_surface(mi, mesh, i);
- }
-
- mi->I = mesh->instances.push_back(mi);
-
- mi->dirty = true;
-
- return rid;
-}
-void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- if (mi->skeleton == p_skeleton) {
- return;
- }
- mi->skeleton = p_skeleton;
- mi->skeleton_version = 0;
- mi->dirty = true;
-}
-
-void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- ERR_FAIL_COND(!mi);
- ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
- mi->blend_weights[p_shape] = p_weight;
- mi->weights_dirty = true;
- //will be eventually updated
-}
-
-void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) {
- for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].versions) {
- for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
- RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array);
- }
- memfree(mi->surfaces[i].versions);
- }
- if (mi->surfaces[i].vertex_buffer.is_valid()) {
- RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
- }
- }
- mi->surfaces.clear();
-
- if (mi->blend_weights_buffer.is_valid()) {
- RD::get_singleton()->free(mi->blend_weights_buffer);
- }
- mi->blend_weights.clear();
- mi->weights_dirty = false;
- mi->skeleton_version = 0;
-}
-
-void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
- if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) {
- mi->blend_weights.resize(mesh->blend_shape_count);
- for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
- mi->blend_weights[i] = 0;
- }
- mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
- mi->weights_dirty = true;
- }
-
- MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
- //surface warrants transform
- s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s.vertex_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (mi->blend_weights_buffer.is_valid()) {
- u.append_id(mi->blend_weights_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
- }
-
- mi->surfaces.push_back(s);
- mi->dirty = true;
-}
-
-void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
-
- bool needs_update = mi->dirty;
-
- if (mi->weights_dirty && !mi->weight_update_list.in_list()) {
- dirty_mesh_instance_weights.add(&mi->weight_update_list);
- needs_update = true;
- }
-
- if (mi->array_update_list.in_list()) {
- return;
- }
-
- if (!needs_update && mi->skeleton.is_valid()) {
- Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
- if (sk && sk->version != mi->skeleton_version) {
- needs_update = true;
- }
- }
-
- if (needs_update) {
- dirty_mesh_instance_arrays.add(&mi->array_update_list);
- }
-}
-
-void RendererStorageRD::update_mesh_instances() {
- while (dirty_mesh_instance_weights.first()) {
- MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
-
- if (mi->blend_weights_buffer.is_valid()) {
- RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr());
- }
- dirty_mesh_instance_weights.remove(&mi->weight_update_list);
- mi->weights_dirty = false;
- }
- if (dirty_mesh_instance_arrays.first() == nullptr) {
- return; //nothing to do
- }
-
- //process skeletons and blend shapes
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- while (dirty_mesh_instance_arrays.first()) {
- MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
-
- Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
-
- for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
- continue;
- }
-
- bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE);
- if (sk && sk->uniform_set_mi.is_valid()) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON);
- }
-
- SkeletonShader::PushConstant push_constant;
-
- push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL;
- push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT;
- push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES);
- push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0;
-
- push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count;
- push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
- push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
- push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
-
- push_constant.blend_shape_count = mi->mesh->blend_shape_count;
- push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
- push_constant.pad0 = 0;
- push_constant.pad1 = 0;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant));
-
- //dispatch without barrier, so all is done at the same time
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1);
- }
-
- mi->dirty = false;
- if (sk) {
- mi->skeleton_version = sk->version;
- }
- dirty_mesh_instance_arrays.remove(&mi->array_update_list);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
- Vector<RD::VertexAttribute> attributes;
- Vector<RID> buffers;
-
- uint32_t stride = 0;
- uint32_t attribute_stride = 0;
- uint32_t skin_stride = 0;
-
- for (int i = 0; i < RS::ARRAY_INDEX; i++) {
- RD::VertexAttribute vd;
- RID buffer;
- vd.location = i;
-
- if (!(s->format & (1 << i))) {
- // Not supplied by surface, use default value
- buffer = mesh_default_rd_buffers[i];
- vd.stride = 0;
- switch (i) {
- case RS::ARRAY_VERTEX: {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- } break;
- case RS::ARRAY_TANGENT: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- case RS::ARRAY_COLOR: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
-
- } break;
- case RS::ARRAY_TEX_UV: {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- case RS::ARRAY_BONES: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
- } break;
- case RS::ARRAY_WEIGHTS: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- }
- } else {
- //Supplied, use it
-
- vd.stride = 1; //mark that it needs a stride set (default uses 0)
-
- switch (i) {
- case RS::ARRAY_VERTEX: {
- vd.offset = stride;
-
- if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- stride += sizeof(float) * 2;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- stride += sizeof(float) * 3;
- }
-
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_TANGENT: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_COLOR: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- attribute_stride += sizeof(int8_t) * 4;
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_TEX_UV: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- attribute_stride += sizeof(float) * 2;
- buffer = s->attribute_buffer;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- attribute_stride += sizeof(float) * 2;
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- vd.offset = attribute_stride;
-
- int idx = i - RS::ARRAY_CUSTOM0;
- uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
- uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
- uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
- RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
- vd.format = fmtrd[fmt];
- attribute_stride += fmtsize[fmt];
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_BONES: {
- vd.offset = skin_stride;
-
- vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
- skin_stride += sizeof(int16_t) * 4;
- buffer = s->skin_buffer;
- } break;
- case RS::ARRAY_WEIGHTS: {
- vd.offset = skin_stride;
-
- vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
- skin_stride += sizeof(int16_t) * 4;
- buffer = s->skin_buffer;
- } break;
- }
- }
-
- if (!(p_input_mask & (1 << i))) {
- continue; // Shader does not need this, skip it (but computing stride was important anyway)
- }
-
- attributes.push_back(vd);
- buffers.push_back(buffer);
- }
-
- //update final stride
- for (int i = 0; i < attributes.size(); i++) {
- if (attributes[i].stride == 0) {
- continue; //default location
- }
- int loc = attributes[i].location;
-
- if (loc < RS::ARRAY_COLOR) {
- attributes.write[i].stride = stride;
- } else if (loc < RS::ARRAY_BONES) {
- attributes.write[i].stride = attribute_stride;
- } else {
- attributes.write[i].stride = skin_stride;
- }
- }
-
- v.input_mask = p_input_mask;
- v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
- v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
-}
-
-////////////////// MULTIMESH
-
-RID RendererStorageRD::multimesh_allocate() {
- return multimesh_owner.allocate_rid();
-}
-void RendererStorageRD::multimesh_initialize(RID p_rid) {
- multimesh_owner.initialize_rid(p_rid, MultiMesh());
-}
-
-void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
- return;
- }
-
- if (multimesh->buffer.is_valid()) {
- RD::get_singleton()->free(multimesh->buffer);
- multimesh->buffer = RID();
- multimesh->uniform_set_2d = RID(); //cleared by dependency
- multimesh->uniform_set_3d = RID(); //cleared by dependency
- }
-
- if (multimesh->data_cache_dirty_regions) {
- memdelete_arr(multimesh->data_cache_dirty_regions);
- multimesh->data_cache_dirty_regions = nullptr;
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- multimesh->instances = p_instances;
- multimesh->xform_format = p_transform_format;
- multimesh->uses_colors = p_use_colors;
- multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
- multimesh->uses_custom_data = p_use_custom_data;
- multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
- multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
- multimesh->buffer_set = false;
-
- //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
- multimesh->data_cache = Vector<float>();
- multimesh->aabb = AABB();
- multimesh->aabb_dirty = false;
- multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
-
- if (multimesh->instances) {
- multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
- }
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH);
-}
-
-int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->instances;
-}
-
-void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- if (multimesh->mesh == p_mesh) {
- return;
- }
- multimesh->mesh = p_mesh;
-
- if (multimesh->instances == 0) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //we have a data cache, just mark it dirt
- _multimesh_mark_all_dirty(multimesh, false, true);
- } else if (multimesh->instances) {
- //need to re-create AABB unfortunately, calling this has a penalty
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- const uint8_t *r = buffer.ptr();
- const float *data = (const float *)r;
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- }
- }
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-#define MULTIMESH_DIRTY_REGION_SIZE 512
-
-void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
- if (multimesh->data_cache.size() > 0) {
- return; //already local
- }
- ERR_FAIL_COND(multimesh->data_cache.size() > 0);
- // this means that the user wants to load/save individual elements,
- // for this, the data must reside on CPU, so just copy it there.
- multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = multimesh->data_cache.ptrw();
-
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- {
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
- } else {
- memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
- }
- }
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
-}
-
-void RendererStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
- uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
-#ifdef DEBUG_ENABLED
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
-#endif
- if (!multimesh->data_cache_dirty_regions[region_index]) {
- multimesh->data_cache_dirty_regions[region_index] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-void RendererStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
- if (p_data) {
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- if (!multimesh->data_cache_dirty_regions[i]) {
- multimesh->data_cache_dirty_regions[i] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
- }
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
- ERR_FAIL_COND(multimesh->mesh.is_null());
- AABB aabb;
- AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
- for (int i = 0; i < p_instances; i++) {
- const float *data = p_data + multimesh->stride_cache * i;
- Transform3D t;
-
- if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
- t.basis.elements[0][0] = data[0];
- t.basis.elements[0][1] = data[1];
- t.basis.elements[0][2] = data[2];
- t.origin.x = data[3];
- t.basis.elements[1][0] = data[4];
- t.basis.elements[1][1] = data[5];
- t.basis.elements[1][2] = data[6];
- t.origin.y = data[7];
- t.basis.elements[2][0] = data[8];
- t.basis.elements[2][1] = data[9];
- t.basis.elements[2][2] = data[10];
- t.origin.z = data[11];
-
- } else {
- t.basis.elements[0].x = data[0];
- t.basis.elements[1].x = data[1];
- t.origin.x = data[3];
-
- t.basis.elements[0].y = data[4];
- t.basis.elements[1].y = data[5];
- t.origin.y = data[7];
- }
-
- if (i == 0) {
- aabb = t.xform(mesh_aabb);
- } else {
- aabb.merge_with(t.xform(mesh_aabb));
- }
- }
-
- multimesh->aabb = aabb;
-}
-
-void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_colors);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_custom_data);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, RID());
-
- return multimesh->mesh;
-}
-
-Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform3D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
-
- _multimesh_make_local(multimesh);
-
- Transform3D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
- }
-
- return t;
-}
-
-Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform2D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
-
- _multimesh_make_local(multimesh);
-
- Transform2D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
- }
-
- return t;
-}
-
-Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
-
- {
- const float *r = p_buffer.ptr();
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
- multimesh->buffer_set = true;
- }
-
- if (multimesh->data_cache.size()) {
- //if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
- {
- //clear dirty since nothing will be dirty anymore
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
- } else if (multimesh->mesh.is_valid()) {
- //if we have a mesh set, we need to re-generate the AABB from the new data
- const float *data = p_buffer.ptr();
-
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
-}
-
-Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Vector<float>());
- if (multimesh->buffer.is_null()) {
- return Vector<float>();
- } else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
- } else {
- //get from memory
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- Vector<float> ret;
- ret.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = ret.ptrw();
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
-
- return ret;
- }
-}
-
-void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
- if (multimesh->visible_instances == p_visible) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //there is a data cache..
- _multimesh_mark_all_dirty(multimesh, false, true);
- }
-
- multimesh->visible_instances = p_visible;
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
-}
-
-int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->visible_instances;
-}
-
-AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, AABB());
- if (multimesh->aabb_dirty) {
- const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes();
- }
- return multimesh->aabb;
-}
-
-void RendererStorageRD::_update_dirty_multimeshes() {
- while (multimesh_dirty_list) {
- MultiMesh *multimesh = multimesh_dirty_list;
-
- if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
- const float *data = multimesh->data_cache.ptr();
-
- uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
-
- if (multimesh->data_cache_used_dirty_regions) {
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
-
- uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
-
- if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
- //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
- } else {
- //not that many regions? update them all
- for (uint32_t i = 0; i < visible_region_count; i++) {
- if (multimesh->data_cache_dirty_regions[i]) {
- uint32_t offset = i * region_size;
- uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
- }
- }
- }
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
-
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- if (multimesh->aabb_dirty) {
- //aabb is dirty..
- _multimesh_re_create_aabb(multimesh, data, visible_instances);
- multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
- }
-
- multimesh_dirty_list = multimesh->dirty_list;
-
- multimesh->dirty_list = nullptr;
- multimesh->dirty = false;
- }
-
- multimesh_dirty_list = nullptr;
-}
-
/* PARTICLES */
RID RendererStorageRD::particles_allocate() {
@@ -3519,7 +421,7 @@ void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles
particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4);
memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
- particles->emission_buffer = (ParticleEmissionBuffer *)particles->emission_buffer_data.ptrw();
+ particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw());
particles->emission_buffer->particle_max = particles->amount;
particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
@@ -3643,7 +545,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
float longest_axis_size = 0;
for (int i = 0; i < particles->draw_passes.size(); i++) {
if (particles->draw_passes[i].is_valid()) {
- AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID());
+ AABB maabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
}
}
@@ -3705,6 +607,7 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool
void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -3731,7 +634,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
if (p_particles->emission_storage_buffer.is_valid()) {
u.append_id(p_particles->emission_storage_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -3746,7 +649,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
}
u.append_id(sub_emitter->emission_storage_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -4094,9 +997,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
- ParticlesMaterialData *m = (ParticlesMaterialData *)material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES);
+ ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES));
if (!m) {
- m = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES);
+ m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES));
}
ERR_FAIL_COND(!m);
@@ -4249,7 +1152,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
void RendererStorageRD::_particles_update_buffers(Particles *particles) {
uint32_t userdata_count = 0;
- const Material *material = material_owner.get_or_null(particles->process_material);
+ const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material);
if (material && material->shader && material->shader->data) {
const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
userdata_count = shader_data->userdata_count;
@@ -4389,7 +1292,7 @@ void RendererStorageRD::update_particles() {
if (particles->trail_bind_pose_buffer.is_valid()) {
u.append_id(particles->trail_bind_pose_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -4636,13 +1539,13 @@ void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *
}
}
-void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -4691,7 +1594,7 @@ RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
+RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
return shader_data;
}
@@ -4704,7 +1607,7 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
+RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -5025,195 +1928,6 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b
}
}
-/* SKELETON API */
-
-RID RendererStorageRD::skeleton_allocate() {
- return skeleton_owner.allocate_rid();
-}
-void RendererStorageRD::skeleton_initialize(RID p_rid) {
- skeleton_owner.initialize_rid(p_rid, Skeleton());
-}
-
-void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
- if (!skeleton->dirty) {
- skeleton->dirty = true;
- skeleton->dirty_list = skeleton_dirty_list;
- skeleton_dirty_list = skeleton;
- }
-}
-
-void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_COND(p_bones < 0);
-
- if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
- return;
- }
-
- skeleton->size = p_bones;
- skeleton->use_2d = p_2d_skeleton;
- skeleton->uniform_set_3d = RID();
-
- if (skeleton->buffer.is_valid()) {
- RD::get_singleton()->free(skeleton->buffer);
- skeleton->buffer = RID();
- skeleton->data.clear();
- skeleton->uniform_set_mi = RID();
- }
-
- if (skeleton->size) {
- skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
- skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
- memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
-
- _skeleton_make_dirty(skeleton);
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(skeleton->buffer);
- uniforms.push_back(u);
- }
- skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
- }
- }
-
- skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA);
-}
-
-int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, 0);
-
- return skeleton->size;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 12;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform3D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
- ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 12;
-
- Transform3D t;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(!skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 8;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform2D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
- ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 8;
-
- Transform2D t;
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton->use_2d);
-
- skeleton->base_transform_2d = p_base_transform;
-}
-
-void RendererStorageRD::_update_dirty_skeletons() {
- while (skeleton_dirty_list) {
- Skeleton *skeleton = skeleton_dirty_list;
-
- if (skeleton->size) {
- RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
- }
-
- skeleton_dirty_list = skeleton->dirty_list;
-
- skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
-
- skeleton->version++;
-
- skeleton->dirty = false;
- skeleton->dirty_list = nullptr;
- }
-
- skeleton_dirty_list = nullptr;
-}
-
/* LIGHT */
void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
@@ -6929,11 +3643,11 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta
}
void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (mesh_owner.owns(p_base)) {
- Mesh *mesh = mesh_owner.get_or_null(p_base);
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base);
p_instance->update_dependency(&mesh->dependency);
- } else if (multimesh_owner.owns(p_base)) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_base);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base);
p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
@@ -6968,18 +3682,11 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
}
}
-void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
-
- p_instance->update_dependency(&skeleton->dependency);
-}
-
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
- if (mesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
return RS::INSTANCE_MESH;
}
- if (multimesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
if (reflection_probe_owner.owns(p_rid)) {
@@ -7013,675 +3720,11 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
return RS::INSTANCE_NONE;
}
-int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) {
- int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
- bool valid = true;
- for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
- valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
- break;
- }
- }
-
- if (!valid) {
- continue; //if not valid, idx is in new position
- }
-
- return idx;
- } else {
- idx += global_variables.buffer_usage[idx].elements;
- }
- }
-
- return -1;
-}
-
-void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
- switch (p_type) {
- case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- bool b = p_value;
- bv.x = b ? 1.0 : 0.0;
- bv.y = 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = (bvec & 8) ? 1.0 : 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- int32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Rect2i v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- uint32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- float v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector2 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector3 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Plane v = p_value;
- bv.x = v.normal.x;
- bv.y = v.normal.y;
- bv.z = v.normal.z;
- bv.w = v.d;
- } break;
- case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Color v = p_value;
- bv.x = v.r;
- bv.y = v.g;
- bv.z = v.b;
- bv.w = v.a;
-
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.to_linear();
- bv_linear.x = v.r;
- bv_linear.y = v.g;
- bv_linear.z = v.b;
- bv_linear.w = v.a;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Rect2 v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Vector<float> m2 = p_value;
- if (m2.size() < 4) {
- m2.resize(4);
- }
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = m2[2];
- bv[1].y = m2[3];
- bv[1].z = 0;
- bv[1].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Basis v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[1][0];
- bv[0].z = v.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.elements[0][1];
- bv[1].y = v.elements[1][1];
- bv[1].z = v.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.elements[0][2];
- bv[2].y = v.elements[1][2];
- bv[2].z = v.elements[2][2];
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
-
- Vector<float> m2 = p_value;
- if (m2.size() < 16) {
- m2.resize(16);
- }
-
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = m2[2];
- bv[0].w = m2[3];
-
- bv[1].x = m2[4];
- bv[1].y = m2[5];
- bv[1].z = m2[6];
- bv[1].w = m2[7];
-
- bv[2].x = m2[8];
- bv[2].y = m2[9];
- bv[2].z = m2[10];
- bv[2].w = m2[11];
-
- bv[3].x = m2[12];
- bv[3].y = m2[13];
- bv[3].z = m2[14];
- bv[3].w = m2[15];
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform2D v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[0][1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = v.elements[1][0];
- bv[1].y = v.elements[1][1];
- bv[1].z = 0;
- bv[1].w = 0;
-
- bv[2].x = v.elements[2][0];
- bv[2].y = v.elements[2][1];
- bv[2].z = 1;
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform3D v = p_value;
- bv[0].x = v.basis.elements[0][0];
- bv[0].y = v.basis.elements[1][0];
- bv[0].z = v.basis.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.basis.elements[0][1];
- bv[1].y = v.basis.elements[1][1];
- bv[1].z = v.basis.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.basis.elements[0][2];
- bv[2].y = v.basis.elements[1][2];
- bv[2].z = v.basis.elements[2][2];
- bv[2].w = 0;
-
- bv[3].x = v.origin.x;
- bv[3].y = v.origin.y;
- bv[3].z = v.origin.z;
- bv[3].w = 1;
-
- } break;
- default: {
- ERR_FAIL();
- }
- }
-}
-
-void RendererStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
- int32_t prev_chunk = -1;
-
- for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
- }
- }
-
- prev_chunk = chunk;
- }
-}
-
-void RendererStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
- gv.type = p_type;
- gv.value = p_value;
- gv.buffer_index = -1;
-
- if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //is texture
- global_variables.must_update_texture_materials = true; //normally there are none
- } else {
- gv.buffer_elements = 1;
- if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 2;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 3;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 4;
- }
-
- //is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
- ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
-
- global_variables.must_update_buffer_materials = true; //normally there are none
- }
-
- global_variables.variables[p_name] = gv;
-}
-
-void RendererStorageRD::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
- return;
- }
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
- } else {
- global_variables.must_update_texture_materials = true;
- }
-
- global_variables.variables.erase(p_name);
-}
-
-Vector<StringName> RendererStorageRD::global_variable_get_list() const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- const StringName *K = nullptr;
- Vector<StringName> names;
- while ((K = global_variables.variables.next(K))) {
- names.push_back(*K);
- }
- names.sort_custom<StringName::AlphCompare>();
- return names;
-}
-
-void RendererStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
- gv.value = p_value;
- if (gv.override.get_type() == Variant::NIL) {
- if (gv.buffer_index >= 0) {
- //buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
- }
-}
-
-void RendererStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
- return; //variable may not exist
- }
-
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
-
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- gv.override = p_value;
-
- if (gv.buffer_index >= 0) {
- //buffer
- if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- } else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
- }
-
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
-}
-
-Variant RendererStorageRD::global_variable_get(const StringName &p_name) const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- if (!global_variables.variables.has(p_name)) {
- return Variant();
- }
-
- return global_variables.variables[p_name].value;
-}
-
-RS::GlobalVariableType RendererStorageRD::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
- return RS::GLOBAL_VAR_TYPE_MAX;
- }
-
- return global_variables.variables[p_name].type;
-}
-
-RS::GlobalVariableType RendererStorageRD::global_variable_get_type(const StringName &p_name) const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- return global_variable_get_type_internal(p_name);
-}
-
-void RendererStorageRD::global_variables_load_settings(bool p_load_textures) {
- List<PropertyInfo> settings;
- ProjectSettings::get_singleton()->get_property_list(&settings);
-
- for (const PropertyInfo &E : settings) {
- if (E.name.begins_with("shader_globals/")) {
- StringName name = E.name.get_slice("/", 1);
- Dictionary d = ProjectSettings::get_singleton()->get(E.name);
-
- ERR_CONTINUE(!d.has("type"));
- ERR_CONTINUE(!d.has("value"));
-
- String type = d["type"];
-
- static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
- "bool",
- "bvec2",
- "bvec3",
- "bvec4",
- "int",
- "ivec2",
- "ivec3",
- "ivec4",
- "rect2i",
- "uint",
- "uvec2",
- "uvec3",
- "uvec4",
- "float",
- "vec2",
- "vec3",
- "vec4",
- "color",
- "rect2",
- "mat2",
- "mat3",
- "mat4",
- "transform_2d",
- "transform",
- "sampler2D",
- "sampler2DArray",
- "sampler3D",
- "samplerCube",
- };
-
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
-
- for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
- if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
- break;
- }
- }
-
- ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
-
- Variant value = d["value"];
-
- if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //textire
- if (!p_load_textures) {
- value = RID();
- continue;
- }
-
- String path = value;
- RES resource = ResourceLoader::load(path);
- ERR_CONTINUE(resource.is_null());
- value = resource;
- }
-
- if (global_variables.variables.has(name)) {
- //has it, update it
- global_variable_set(name, value);
- } else {
- global_variable_add(name, gvtype, value);
- }
- }
- }
-}
-
-void RendererStorageRD::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
-}
-
-RID RendererStorageRD::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
-}
-
-int32_t RendererStorageRD::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
- ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
- return pos;
-}
-
-void RendererStorageRD::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
- if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
- }
- global_variables.instance_buffer_pos.erase(p_instance);
-}
-
-void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
- return; //just not allocated, ignore
- }
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
-
- if (pos < 0) {
- return; //again, not allocated, ignore
- }
- ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
- ShaderLanguage::TYPE_MAX, //nil
- ShaderLanguage::TYPE_BOOL, //bool
- ShaderLanguage::TYPE_INT, //int
- ShaderLanguage::TYPE_FLOAT, //float
- ShaderLanguage::TYPE_MAX, //string
- ShaderLanguage::TYPE_VEC2, //vec2
- ShaderLanguage::TYPE_IVEC2, //vec2i
- ShaderLanguage::TYPE_VEC4, //rect2
- ShaderLanguage::TYPE_IVEC4, //rect2i
- ShaderLanguage::TYPE_VEC3, // vec3
- ShaderLanguage::TYPE_IVEC3, //vec3i
- ShaderLanguage::TYPE_MAX, //xform2d not supported here
- ShaderLanguage::TYPE_VEC4, //plane
- ShaderLanguage::TYPE_VEC4, //quat
- ShaderLanguage::TYPE_MAX, //aabb not supported here
- ShaderLanguage::TYPE_MAX, //basis not supported here
- ShaderLanguage::TYPE_MAX, //xform not supported here
- ShaderLanguage::TYPE_VEC4 //color
- };
-
- ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
-
- ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- pos += p_index;
-
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
-}
-
-void RendererStorageRD::_update_global_variables() {
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
- // 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
- } else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
-
- for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
-
- global_variables.buffer_dirty_regions[i] = false;
- }
- }
- }
-
- global_variables.buffer_dirty_region_count = 0;
- }
-
- if (global_variables.must_update_buffer_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, true, false);
- }
-
- global_variables.must_update_buffer_materials = false;
- }
-
- if (global_variables.must_update_texture_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_texture) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, false, true);
- }
-
- global_variables.must_update_texture_materials = false;
- }
-}
-
void RendererStorageRD::update_dirty_resources() {
- _update_global_variables(); //must do before materials, so it can queue them for update
- _update_queued_materials();
- _update_dirty_multimeshes();
- _update_dirty_skeletons();
+ RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
+ RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas();
}
@@ -7710,60 +3753,18 @@ bool RendererStorageRD::free(RID p_rid) {
RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
} else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid);
- } else if (shader_owner.owns(p_rid)) {
- Shader *shader = shader_owner.get_or_null(p_rid);
- //make material unreference this
- while (shader->owners.size()) {
- material_set_shader(shader->owners.front()->get()->self, RID());
- }
- //clear data if exists
- if (shader->data) {
- memdelete(shader->data);
- }
- shader_owner.free(p_rid);
-
- } else if (material_owner.owns(p_rid)) {
- Material *material = material_owner.get_or_null(p_rid);
- material_set_shader(p_rid, RID()); //clean up shader
- material->dependency.deleted_notify(p_rid);
-
- material_owner.free(p_rid);
- } else if (mesh_owner.owns(p_rid)) {
- mesh_clear(p_rid);
- mesh_set_shadow_mesh(p_rid, RID());
- Mesh *mesh = mesh_owner.get_or_null(p_rid);
- mesh->dependency.deleted_notify(p_rid);
- if (mesh->instances.size()) {
- ERR_PRINT("deleting mesh with active instances");
- }
- if (mesh->shadow_owners.size()) {
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
- }
- mesh_owner.free(p_rid);
- } else if (mesh_instance_owner.owns(p_rid)) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
- _mesh_instance_clear(mi);
- mi->mesh->instances.erase(mi->I);
- mi->I = nullptr;
-
- mesh_instance_owner.free(p_rid);
-
- } else if (multimesh_owner.owns(p_rid)) {
- _update_dirty_multimeshes();
- multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
- multimesh->dependency.deleted_notify(p_rid);
- multimesh_owner.free(p_rid);
- } else if (skeleton_owner.owns(p_rid)) {
- _update_dirty_skeletons();
- skeleton_allocate_data(p_rid, 0);
- Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
- skeleton->dependency.deleted_notify(p_rid);
- skeleton_owner.free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->material_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
reflection_probe->dependency.deleted_notify(p_rid);
@@ -7902,20 +3903,7 @@ RendererStorageRD::RendererStorageRD() {
base_singleton = this;
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
- for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- shader_data_request_func[i] = nullptr;
- }
-
- static_assert(sizeof(GlobalVariables::Value) == 16);
-
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//default samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
@@ -8005,120 +3993,6 @@ RendererStorageRD::RendererStorageRD() {
//custom sampler
sampler_rd_configure_custom(0.0f);
- //default rd buffers
- {
- Vector<uint8_t> buffer;
- {
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //normal
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tangent
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //color
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 1.0;
- fptr[2] = 1.0;
- fptr[3] = 1.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tex uv 1
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- { //tex uv 2
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //bones
- buffer.resize(sizeof(uint32_t) * 4);
- {
- uint8_t *w = buffer.ptrw();
- uint32_t *fptr = (uint32_t *)w;
- fptr[0] = 0;
- fptr[1] = 0;
- fptr[2] = 0;
- fptr[3] = 0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //weights
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- }
-
using_lightmap_array = true; // high end
if (using_lightmap_array) {
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
@@ -8144,8 +4018,8 @@ RendererStorageRD::RendererStorageRD() {
particles_modes.push_back("");
particles_shader.shader.initialize(particles_modes, String());
}
- shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
- material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+ RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -8209,9 +4083,9 @@ RendererStorageRD::RendererStorageRD() {
{
// default material and shader for particles shader
- particles_shader.default_shader = shader_allocate();
- shader_initialize(particles_shader.default_shader);
- shader_set_code(particles_shader.default_shader, R"(
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
// Default particles shader.
shader_type particles;
@@ -8220,11 +4094,11 @@ void process() {
COLOR = vec4(1.0);
}
)");
- particles_shader.default_material = material_allocate();
- material_initialize(particles_shader.default_material);
- material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
- ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES);
+ ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES));
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -8254,15 +4128,13 @@ void process() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(global_variables_get_storage_buffer());
+ u.append_id(material_storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
}
- default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
-
{
Vector<String> copy_modes;
for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
@@ -8305,37 +4177,10 @@ void process() {
rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
}
}
- {
- Vector<String> skeleton_modes;
- skeleton_modes.push_back("\n#define MODE_2D\n");
- skeleton_modes.push_back("");
-
- skeleton_shader.shader.initialize(skeleton_modes);
- skeleton_shader.version = skeleton_shader.shader.version_create();
- for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) {
- skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i);
- skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]);
- }
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(default_rd_storage_buffer);
- uniforms.push_back(u);
- }
- skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
- }
- }
}
RendererStorageRD::~RendererStorageRD() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//def samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
@@ -8353,20 +4198,11 @@ RendererStorageRD::~RendererStorageRD() {
}
}
- //def buffers
- for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
- RD::get_singleton()->free(mesh_default_rd_buffers[i]);
- }
-
particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
rt_sdf.shader.version_free(rt_sdf.shader_version);
- skeleton_shader.shader.version_free(skeleton_shader.version);
-
- RenderingServer::get_singleton()->free(particles_shader.default_material);
- RenderingServer::get_singleton()->free(particles_shader.default_shader);
-
- RD::get_singleton()->free(default_rd_storage_buffer);
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
if (effects) {
memdelete(effects);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 3aa475b34d..4c45dd4295 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -39,10 +39,8 @@
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
@@ -127,331 +125,11 @@ public:
}
}
- enum ShaderType {
- SHADER_TYPE_2D,
- SHADER_TYPE_3D,
- SHADER_TYPE_PARTICLES,
- SHADER_TYPE_SKY,
- SHADER_TYPE_FOG,
- SHADER_TYPE_MAX
- };
-
- struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_param_texture(const StringName &p_param) const = 0;
- virtual bool is_animated() const = 0;
- virtual bool casts_shadows() const = 0;
- virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
-
- virtual ~ShaderData() {}
- };
-
- typedef ShaderData *(*ShaderDataRequestFunction)();
-
- struct MaterialData {
- void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
- virtual void set_render_priority(int p_priority) = 0;
- virtual void set_next_pass(RID p_pass) = 0;
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData();
-
- //to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void free_parameters_uniform_set(RID p_uniform_set);
-
- private:
- friend class RendererStorageRD;
- RID self;
- List<RID>::Element *global_buffer_E = nullptr;
- List<RID>::Element *global_texture_E = nullptr;
- uint64_t global_textures_pass = 0;
- Map<StringName, uint64_t> used_global_textures;
-
- //internally by update_parameters_uniform_set
- Vector<uint8_t> ubo_data;
- RID uniform_buffer;
- Vector<RID> texture_cache;
- };
- typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
- static void _material_uniform_set_erased(void *p_material);
-
- enum DefaultRDBuffer {
- DEFAULT_RD_BUFFER_VERTEX,
- DEFAULT_RD_BUFFER_NORMAL,
- DEFAULT_RD_BUFFER_TANGENT,
- DEFAULT_RD_BUFFER_COLOR,
- DEFAULT_RD_BUFFER_TEX_UV,
- DEFAULT_RD_BUFFER_TEX_UV2,
- DEFAULT_RD_BUFFER_CUSTOM0,
- DEFAULT_RD_BUFFER_CUSTOM1,
- DEFAULT_RD_BUFFER_CUSTOM2,
- DEFAULT_RD_BUFFER_CUSTOM3,
- DEFAULT_RD_BUFFER_BONES,
- DEFAULT_RD_BUFFER_WEIGHTS,
- DEFAULT_RD_BUFFER_MAX,
- };
-
private:
/* TEXTURE API */
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
- RID default_rd_storage_buffer;
-
- /* SHADER */
-
- struct Material;
-
- struct Shader {
- ShaderData *data;
- String code;
- ShaderType type;
- Map<StringName, Map<int, RID>> default_texture_parameter;
- Set<Material *> owners;
- };
-
- ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Shader, true> shader_owner;
-
- /* Material */
-
- struct Material {
- RID self;
- MaterialData *data = nullptr;
- Shader *shader = nullptr;
- //shortcut to shader data and type
- ShaderType shader_type = SHADER_TYPE_MAX;
- uint32_t shader_id = 0;
- bool uniform_dirty = false;
- bool texture_dirty = false;
- Map<StringName, Variant> params;
- int32_t priority = 0;
- RID next_pass;
- SelfList<Material> update_element;
-
- Dependency dependency;
-
- Material() :
- update_element(this) {}
- };
-
- MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Material, true> material_owner;
-
- SelfList<Material>::List material_update_list;
- void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
- void _update_queued_materials();
-
- /* Mesh */
-
- struct MeshInstance;
-
- struct Mesh {
- struct Surface {
- RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
- uint32_t format = 0;
-
- RID vertex_buffer;
- RID attribute_buffer;
- RID skin_buffer;
- uint32_t vertex_count = 0;
- uint32_t vertex_buffer_size = 0;
- uint32_t skin_buffer_size = 0;
-
- // A different pipeline needs to be allocated
- // depending on the inputs available in the
- // material.
- // There are never that many geometry/material
- // combinations, so a simple array is the most
- // cache-efficient structure.
-
- struct Version {
- uint32_t input_mask = 0;
- RD::VertexFormatID vertex_format = 0;
- RID vertex_array;
- };
-
- SpinLock version_lock; //needed to access versions
- Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
-
- RID index_buffer;
- RID index_array;
- uint32_t index_count = 0;
-
- struct LOD {
- float edge_length = 0.0;
- uint32_t index_count = 0;
- RID index_buffer;
- RID index_array;
- };
-
- LOD *lods = nullptr;
- uint32_t lod_count = 0;
-
- AABB aabb;
-
- Vector<AABB> bone_aabbs;
-
- RID blend_shape_buffer;
-
- RID material;
-
- uint32_t render_index = 0;
- uint64_t render_pass = 0;
-
- uint32_t multimesh_render_index = 0;
- uint64_t multimesh_render_pass = 0;
-
- uint32_t particles_render_index = 0;
- uint64_t particles_render_pass = 0;
-
- RID uniform_set;
- };
-
- uint32_t blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
-
- Surface **surfaces = nullptr;
- uint32_t surface_count = 0;
-
- Vector<AABB> bone_aabbs;
-
- bool has_bone_weights = false;
-
- AABB aabb;
- AABB custom_aabb;
-
- Vector<RID> material_cache;
-
- List<MeshInstance *> instances;
-
- RID shadow_mesh;
- Set<Mesh *> shadow_owners;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Mesh, true> mesh_owner;
-
- struct MeshInstance {
- Mesh *mesh;
- RID skeleton;
- struct Surface {
- RID vertex_buffer;
- RID uniform_set;
-
- Mesh::Surface::Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
- };
- LocalVector<Surface> surfaces;
- LocalVector<float> blend_weights;
-
- RID blend_weights_buffer;
- List<MeshInstance *>::Element *I = nullptr; //used to erase itself
- uint64_t skeleton_version = 0;
- bool dirty = false;
- bool weights_dirty = false;
- SelfList<MeshInstance> weight_update_list;
- SelfList<MeshInstance> array_update_list;
- MeshInstance() :
- weight_update_list(this), array_update_list(this) {}
- };
-
- void _mesh_instance_clear(MeshInstance *mi);
- void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
-
- mutable RID_Owner<MeshInstance> mesh_instance_owner;
-
- SelfList<MeshInstance>::List dirty_mesh_instance_weights;
- SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
-
- struct SkeletonShader {
- struct PushConstant {
- uint32_t has_normal;
- uint32_t has_tangent;
- uint32_t has_skeleton;
- uint32_t has_blend_shape;
-
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t skin_stride;
- uint32_t skin_weight_offset;
-
- uint32_t blend_shape_count;
- uint32_t normalized_blend_shapes;
- uint32_t pad0;
- uint32_t pad1;
- };
-
- enum {
- UNIFORM_SET_INSTANCE = 0,
- UNIFORM_SET_SURFACE = 1,
- UNIFORM_SET_SKELETON = 2,
- };
- enum {
- SHADER_MODE_2D,
- SHADER_MODE_3D,
- SHADER_MODE_MAX
- };
-
- SkeletonShaderRD shader;
- RID version;
- RID version_shader[SHADER_MODE_MAX];
- RID pipeline[SHADER_MODE_MAX];
-
- RID default_skeleton_uniform_set;
- } skeleton_shader;
-
- void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
-
- RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
-
- /* MultiMesh */
- struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<MultiMesh, true> multimesh_owner;
-
- MultiMesh *multimesh_dirty_list = nullptr;
-
- _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
- _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
- void _update_dirty_multimeshes();
/* PARTICLES */
@@ -714,7 +392,7 @@ private:
Particles *particle_update_list = nullptr;
- struct ParticlesShaderData : public ShaderData {
+ struct ParticlesShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
bool uses_collision = false;
@@ -740,7 +418,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -751,12 +429,12 @@ private:
virtual ~ParticlesShaderData();
};
- ShaderData *_create_particles_shader_func();
- static RendererStorageRD::ShaderData *_create_particles_shader_funcs() {
+ RendererRD::ShaderData *_create_particles_shader_func();
+ static RendererRD::ShaderData *_create_particles_shader_funcs() {
return base_singleton->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialData {
+ struct ParticlesMaterialData : public RendererRD::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
@@ -766,8 +444,8 @@ private:
virtual ~ParticlesMaterialData();
};
- MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) {
return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
}
@@ -829,34 +507,6 @@ private:
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
- /* Skeleton */
-
- struct Skeleton {
- bool use_2d = false;
- int size = 0;
- Vector<float> data;
- RID buffer;
-
- bool dirty = false;
- Skeleton *dirty_list = nullptr;
- Transform2D base_transform_2d;
-
- RID uniform_set_3d;
- RID uniform_set_mi;
-
- uint64_t version = 1;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Skeleton, true> skeleton_owner;
-
- _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
-
- Skeleton *skeleton_dirty_list = nullptr;
-
- void _update_dirty_skeletons();
-
/* LIGHT */
struct Light {
@@ -1054,72 +704,6 @@ private:
RID pipelines[SHADER_MAX];
} rt_sdf;
- /* GLOBAL SHADER VARIABLES */
-
- struct GlobalVariables {
- enum {
- BUFFER_DIRTY_REGION_SIZE = 1024
- };
- struct Variable {
- Set<RID> texture_materials; // materials using this
-
- RS::GlobalVariableType type;
- Variant value;
- Variant override;
- int32_t buffer_index; //for vectors
- int32_t buffer_elements; //for vectors
- };
-
- HashMap<StringName, Variable> variables;
-
- struct Value {
- float x;
- float y;
- float z;
- float w;
- };
-
- struct ValueInt {
- int32_t x;
- int32_t y;
- int32_t z;
- int32_t w;
- };
-
- struct ValueUInt {
- uint32_t x;
- uint32_t y;
- uint32_t z;
- uint32_t w;
- };
-
- struct ValueUsage {
- uint32_t elements = 0;
- };
-
- List<RID> materials_using_buffer;
- List<RID> materials_using_texture;
-
- RID buffer;
- Value *buffer_values;
- ValueUsage *buffer_usage;
- bool *buffer_dirty_regions;
- uint32_t buffer_dirty_region_count = 0;
-
- uint32_t buffer_size;
-
- bool must_update_texture_materials = false;
- bool must_update_buffer_materials = false;
-
- HashMap<RID, int32_t> instance_buffer_pos;
-
- } global_variables;
-
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
-
- void _update_global_variables();
/* EFFECTS */
EffectsRD *effects = nullptr;
@@ -1138,412 +722,6 @@ public:
void sampler_rd_set_default(float p_mipmap_bias);
- /* SHADER API */
-
- RID shader_allocate();
- void shader_initialize(RID p_shader);
-
- void shader_set_code(RID p_shader, const String &p_code);
- String shader_get_code(RID p_shader) const;
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
- Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
- void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
-
- virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
-
- /* COMMON MATERIAL API */
-
- RID material_allocate();
- void material_initialize(RID p_material);
-
- void material_set_shader(RID p_material, RID p_shader);
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
- Variant material_get_param(RID p_material, const StringName &p_param) const;
-
- void material_set_next_pass(RID p_material, RID p_next_material);
- void material_set_render_priority(RID p_material, int priority);
-
- bool material_is_animated(RID p_material);
- bool material_casts_shadows(RID p_material);
-
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
-
- void material_update_dependency(RID p_material, DependencyTracker *p_instance);
-
- void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
-
- _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- return material->shader_id;
- }
-
- _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.get_or_null(p_material);
- if (!material || material->shader_type != p_shader_type) {
- return nullptr;
- } else {
- return material->data;
- }
- }
-
- /* MESH API */
-
- RID mesh_allocate();
- void mesh_initialize(RID p_mesh);
-
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count);
-
- /// Return stride
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface);
-
- virtual int mesh_get_blend_shape_count(RID p_mesh) const;
-
- virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode);
- virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
-
- virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
-
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const;
-
- virtual int mesh_get_surface_count(RID p_mesh) const;
-
- virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
-
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
- virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh);
-
- virtual void mesh_clear(RID p_mesh);
-
- virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton);
-
- /* MESH INSTANCE */
-
- virtual RID mesh_instance_create(RID p_base);
- virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton);
- virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight);
- virtual void mesh_instance_check_for_update(RID p_mesh_instance);
- virtual void update_mesh_instances();
-
- _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- r_surface_count = mesh->surface_count;
- if (r_surface_count == 0) {
- return nullptr;
- }
- if (mesh->material_cache.is_empty()) {
- mesh->material_cache.resize(mesh->surface_count);
- for (uint32_t i = 0; i < r_surface_count; i++) {
- mesh->material_cache.write[i] = mesh->surfaces[i]->material;
- }
- }
-
- return mesh->material_cache.ptr();
- }
-
- _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
-
- return mesh->surfaces[p_surface_index];
- }
-
- _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
-
- return mesh->shadow_mesh;
- }
-
- _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
- Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
- return surface->primitive;
- }
-
- _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->lod_count > 0;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->index_count ? s->index_count : s->vertex_count;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- int32_t current_lod = -1;
- if (r_index_count) {
- *r_index_count = s->index_count;
- }
- for (uint32_t i = 0; i < s->lod_count; i++) {
- float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
- if (screen_size > p_mesh_lod_threshold) {
- break;
- }
- current_lod = i;
- }
- if (current_lod == -1) {
- return 0;
- } else {
- if (r_index_count) {
- *r_index_count = s->lods[current_lod].index_count;
- }
- return current_lod + 1;
- }
- }
-
- _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- if (p_lod == 0) {
- return s->index_array;
- } else {
- return s->lods[p_lod - 1].index_array;
- }
- }
-
- _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- s->version_lock.lock();
-
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
-
- for (uint32_t i = 0; i < s->version_count; i++) {
- if (s->versions[i].input_mask != p_input_mask) {
- continue;
- }
- //we have this version, hooray
- r_vertex_format = s->versions[i].vertex_format;
- r_vertex_array_rd = s->versions[i].vertex_array;
- s->version_lock.unlock();
- return;
- }
-
- uint32_t version = s->version_count;
- s->version_count++;
- s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
-
- _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask);
-
- r_vertex_format = s->versions[version].vertex_format;
- r_vertex_array_rd = s->versions[version].vertex_array;
-
- s->version_lock.unlock();
- }
-
- _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- ERR_FAIL_COND(!mi);
- Mesh *mesh = mi->mesh;
- ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
-
- MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- s->version_lock.lock();
-
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
-
- for (uint32_t i = 0; i < mis->version_count; i++) {
- if (mis->versions[i].input_mask != p_input_mask) {
- continue;
- }
- //we have this version, hooray
- r_vertex_format = mis->versions[i].vertex_format;
- r_vertex_array_rd = mis->versions[i].vertex_array;
- s->version_lock.unlock();
- return;
- }
-
- uint32_t version = mis->version_count;
- mis->version_count++;
- mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
-
- _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis);
-
- r_vertex_format = mis->versions[version].vertex_format;
- r_vertex_array_rd = mis->versions[version].vertex_array;
-
- s->version_lock.unlock();
- }
-
- _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
- ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
- return mesh_default_rd_buffers[p_buffer];
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->render_pass != p_render_pass) {
- (*r_index)++;
- s->render_pass = p_render_pass;
- s->render_index = *r_index;
- }
-
- return s->render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->multimesh_render_pass != p_render_pass) {
- (*r_index)++;
- s->multimesh_render_pass = p_render_pass;
- s->multimesh_render_index = *r_index;
- }
-
- return s->multimesh_render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->particles_render_pass != p_render_pass) {
- (*r_index)++;
- s->particles_render_pass = p_render_pass;
- s->particles_render_index = *r_index;
- }
-
- return s->particles_render_index;
- }
-
- /* MULTIMESH API */
-
- RID multimesh_allocate();
- void multimesh_initialize(RID p_multimesh);
-
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
- int multimesh_get_instance_count(RID p_multimesh) const;
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform);
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
-
- RID multimesh_get_mesh(RID p_multimesh) const;
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
-
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer);
- Vector<float> multimesh_get_buffer(RID p_multimesh) const;
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
- int multimesh_get_visible_instances(RID p_multimesh) const;
-
- AABB multimesh_get_aabb(RID p_multimesh) const;
-
- _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->xform_format;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_colors;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_custom_data;
- }
-
- _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (multimesh->visible_instances >= 0) {
- return multimesh->visible_instances;
- }
- return multimesh->instances;
- }
-
- _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_3d;
- }
-
- _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_2d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_2d;
- }
-
- /* SKELETON API */
-
- RID skeleton_allocate();
- void skeleton_initialize(RID p_skeleton);
-
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
- int skeleton_get_bone_count(RID p_skeleton) const;
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform);
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
-
- _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
- return skeleton_owner.get_or_null(p_skeleton) != nullptr;
- }
-
- _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, RID());
- ERR_FAIL_COND_V(skeleton->size == 0, RID());
- if (skeleton->use_2d) {
- return RID();
- }
- if (!skeleton->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(skeleton->buffer);
- uniforms.push_back(u);
- skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return skeleton->uniform_set_3d;
- }
/* Light API */
void _light_initialize(RID p_rid, RS::LightType p_type);
@@ -1713,7 +891,6 @@ public:
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
void base_update_dependency(RID p_base, DependencyTracker *p_instance);
- void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
/* VOXEL GI API */
@@ -1972,27 +1149,6 @@ public:
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
- /* GLOBAL VARIABLES API */
-
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
- virtual void global_variable_remove(const StringName &p_name);
- virtual Vector<StringName> global_variable_get_list() const;
-
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
- virtual Variant global_variable_get(const StringName &p_name) const;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
-
- virtual void global_variables_load_settings(bool p_load_textures = true);
- virtual void global_variables_clear();
-
- virtual int32_t global_variables_instance_allocate(RID p_instance);
- virtual void global_variables_instance_free(RID p_instance);
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
-
- RID global_variables_get_storage_buffer() const;
-
/* RENDER TARGET API */
RID render_target_create();
@@ -2065,8 +1221,6 @@ public:
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
virtual String get_captured_timestamp_name(uint32_t p_index) const;
- RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
-
static RendererStorageRD *base_singleton;
void init_effects(bool p_prefer_raster_effects);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 4e6e50bc44..abe1a09b06 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -499,14 +499,14 @@ layout(location = 1) out uvec2 voxel_gi_buffer;
#endif //MODE_RENDER_NORMAL
#else // RENDER DEPTH
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
layout(location = 0) out vec4 frag_color;
-#endif // MODE_MULTIPLE_RENDER_TARGETS
+#endif // MODE_SEPARATE_SPECULAR
#endif // RENDER DEPTH
@@ -1966,7 +1966,7 @@ void main() {
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
diffuse_buffer = vec4(albedo.rgb, 0.0);
@@ -1984,7 +1984,7 @@ void main() {
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
-#else //MODE_MULTIPLE_RENDER_TARGETS
+#else //MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha);
@@ -1996,7 +1996,7 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
-#endif //MODE_MULTIPLE_RENDER_TARGETS
+#endif //MODE_SEPARATE_SPECULAR
#endif //MODE_RENDER_DEPTH
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
new file mode 100644
index 0000000000..9e3d124bbb
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -0,0 +1,2392 @@
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
+#include "material_storage.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/io/resource_loader.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// UBI helper functions
+
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = (r[i] != 0) ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ bool v = value;
+ gui[0] = v ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 2 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v & 1 ? 1 : 0;
+ gui[1] = v & 2 ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 3 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ gui[j + 2] = r[i + 2] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i] ? 1 : 0;
+ gui[i + 1] = r[i + 1] ? 1 : 0;
+ gui[i + 2] = r[i + 2] ? 1 : 0;
+ gui[i + 3] = r[i + 3] ? 1 : 0;
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ gui[3] = (v & 8) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ float v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedVector2Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector2 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedVector3Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ gui[j + 2] = a[i].z;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector3 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+ const PackedColorArray &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ Color color = a[i];
+ if (p_linear_color) {
+ color = color.to_linear();
+ }
+ gui[j] = color.r;
+ gui[j + 1] = color.g;
+ gui[j + 2] = color.b;
+ gui[j + 3] = color.a;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ gui[j + 3] = 0;
+ }
+ }
+ } else {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i + 3 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ }
+ } else {
+ if (value.get_type() == Variant::COLOR) {
+ Color v = value;
+
+ if (p_linear_color) {
+ v = v.to_linear();
+ }
+
+ gui[0] = v.r;
+ gui[1] = v.g;
+ gui[2] = v.b;
+ gui[3] = v.a;
+ } else if (value.get_type() == Variant::RECT2) {
+ Rect2 v = value;
+
+ gui[0] = v.position.x;
+ gui[1] = v.position.y;
+ gui[2] = v.size.x;
+ gui[3] = v.size.y;
+ } else if (value.get_type() == Variant::QUATERNION) {
+ Quaternion v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
+ } else {
+ Plane v = value;
+
+ gui[0] = v.normal.x;
+ gui[1] = v.normal.y;
+ gui[2] = v.normal.z;
+ gui[3] = v.d;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
+ if (i + 3 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+
+ gui[j + 4] = a[i + 2];
+ gui[j + 5] = a[i + 3];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ gui[j + 6] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ }
+ } else {
+ Transform2D v = value;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[0][1];
+ gui[2] = 0; // ignored
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[1][0];
+ gui[5] = v.elements[1][1];
+ gui[6] = 0; // ignored
+ gui[7] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
+ if (i + 8 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+ gui[j + 2] = a[i + 2];
+
+ gui[j + 4] = a[i + 3];
+ gui[j + 5] = a[i + 4];
+ gui[j + 6] = a[i + 5];
+
+ gui[j + 8] = a[i + 6];
+ gui[j + 9] = a[i + 7];
+ gui[j + 10] = a[i + 8];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ gui[j + 6] = 0;
+
+ gui[j + 8] = 0;
+ gui[j + 9] = 0;
+ gui[j + 10] = 1;
+ }
+ gui[j + 3] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ gui[j + 11] = 0; // ignored
+ }
+ } else {
+ Basis v = value;
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[1][0];
+ gui[2] = v.elements[2][0];
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[0][1];
+ gui[5] = v.elements[1][1];
+ gui[6] = v.elements[2][1];
+ gui[7] = 0; // ignored
+
+ gui[8] = v.elements[0][2];
+ gui[9] = v.elements[1][2];
+ gui[10] = v.elements[2][2];
+ gui[11] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0; i < p_array_size * 16; i += 16) {
+ if (i + 15 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+
+ gui[i + 4] = a[i + 4];
+ gui[i + 5] = a[i + 5];
+ gui[i + 6] = a[i + 6];
+ gui[i + 7] = a[i + 7];
+
+ gui[i + 8] = a[i + 8];
+ gui[i + 9] = a[i + 9];
+ gui[i + 10] = a[i + 10];
+ gui[i + 11] = a[i + 11];
+
+ gui[i + 12] = a[i + 12];
+ gui[i + 13] = a[i + 13];
+ gui[i + 14] = a[i + 14];
+ gui[i + 15] = a[i + 15];
+ } else {
+ gui[i] = 1;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+
+ gui[i + 4] = 0;
+ gui[i + 5] = 1;
+ gui[i + 6] = 0;
+ gui[i + 7] = 0;
+
+ gui[i + 8] = 0;
+ gui[i + 9] = 0;
+ gui[i + 10] = 1;
+ gui[i + 11] = 0;
+
+ gui[i + 12] = 0;
+ gui[i + 13] = 0;
+ gui[i + 14] = 0;
+ gui[i + 15] = 1;
+ }
+ }
+ } else {
+ Transform3D v = value;
+ gui[0] = v.basis.elements[0][0];
+ gui[1] = v.basis.elements[1][0];
+ gui[2] = v.basis.elements[2][0];
+ gui[3] = 0;
+
+ gui[4] = v.basis.elements[0][1];
+ gui[5] = v.basis.elements[1][1];
+ gui[6] = v.basis.elements[2][1];
+ gui[7] = 0;
+
+ gui[8] = v.basis.elements[0][2];
+ gui[9] = v.basis.elements[1][2];
+ gui[10] = v.basis.elements[2][2];
+ gui[11] = 0;
+
+ gui[12] = v.origin.x;
+ gui[13] = v.origin.y;
+ gui[14] = v.origin.z;
+ gui[15] = 1;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+ *gui = value[0].boolean ? 1 : 0;
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+ gui[3] = value[3].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+ gui[0] = value[0].sint;
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].uint;
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].uint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = (float *)data;
+ gui[0] = value[0].real;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = (float *)data;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = 0;
+ gui[3] = 0;
+ gui[4] = value[2].real;
+ gui[5] = value[3].real;
+ gui[6] = 0;
+ gui[7] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = (float *)data;
+
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = value[2].real;
+ gui[3] = 0;
+ gui[4] = value[3].real;
+ gui[5] = value[4].real;
+ gui[6] = value[5].real;
+ gui[7] = 0;
+ gui[8] = value[6].real;
+ gui[9] = value[7].real;
+ gui[10] = value[8].real;
+ gui[11] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 16; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL:
+ case ShaderLanguage::TYPE_INT:
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_FLOAT: {
+ memset(data, 0, 4 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC2:
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_VEC2: {
+ memset(data, 0, 8 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC3:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_BVEC4:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_VEC4: {
+ memset(data, 0, 16 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ memset(data, 0, 32 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ memset(data, 0, 48 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ memset(data, 0, 64 * p_array_size);
+ } break;
+
+ default: {
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialData
+
+void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ bool uses_global_buffer = false;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
+ if (E.value.order < 0) {
+ continue; // texture, does not go here
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue; //instance uniforms don't appear in the buffer
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ //this is a global variable, get the index to it
+ GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ uint32_t index = 0;
+ if (gv) {
+ index = gv->buffer_index;
+ } else {
+ WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
+ }
+
+ uint32_t offset = p_uniform_offsets[E.value.order];
+ uint32_t *intptr = (uint32_t *)&p_buffer[offset];
+ *intptr = index;
+ uses_global_buffer = true;
+ continue;
+ }
+
+ //regular uniform
+ uint32_t offset = p_uniform_offsets[E.value.order];
+#ifdef DEBUG_ENABLED
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_datatype_size(E.value.type);
+ }
+ ERR_CONTINUE(offset + size > p_buffer_size);
+#endif
+ uint8_t *data = &p_buffer[offset];
+ const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
+
+ if (V) {
+ //user provided
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
+
+ } else if (E.value.default_value.size()) {
+ //default value
+ _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
+ //value=E.value.default_value;
+ } else {
+ //zero because it was not provided
+ if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ //colors must be set as black, with alpha as 1.0
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+ } else {
+ //else just zero it out
+ _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
+ }
+ }
+ }
+
+ if (uses_global_buffer != (global_buffer_E != nullptr)) {
+ if (uses_global_buffer) {
+ global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ global_buffer_E = nullptr;
+ }
+ }
+}
+
+MaterialData::~MaterialData() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ if (global_buffer_E) {
+ //unregister global buffers
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ }
+
+ if (global_texture_E) {
+ //unregister global textures
+
+ for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ //unregister material from those using global textures
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+#ifdef TOOLS_ENABLED
+ Texture *roughness_detect_texture = nullptr;
+ RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
+ Texture *normal_detect_texture = nullptr;
+#endif
+
+ bool uses_global_textures = false;
+ global_textures_pass++;
+
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const StringName &uniform_name = p_texture_uniforms[i].name;
+ int uniform_array_size = p_texture_uniforms[i].array_size;
+
+ Vector<RID> textures;
+
+ if (p_texture_uniforms[i].global) {
+ uses_global_textures = true;
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ if (v) {
+ if (v->buffer_index >= 0) {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+
+ } else {
+ Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
+ if (!E) {
+ E = used_global_textures.insert(uniform_name, global_textures_pass);
+ v->texture_materials.insert(self);
+ } else {
+ E->get() = global_textures_pass;
+ }
+
+ textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
+ }
+
+ } else {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+ }
+ } else {
+ const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+ if (V) {
+ if (V->get().is_array()) {
+ Array array = (Array)V->get();
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < array.size(); j++) {
+ textures.push_back(array[j]);
+ }
+ } else {
+ if (array.size() > 0) {
+ textures.push_back(array[0]);
+ }
+ }
+ } else {
+ textures.push_back(V->get());
+ }
+ }
+
+ if (uniform_array_size > 0) {
+ if (textures.size() < uniform_array_size) {
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W && W->get().has(j)) {
+ textures.push_back(W->get()[j]);
+ } else {
+ textures.push_back(RID());
+ }
+ }
+ }
+ } else if (textures.is_empty()) {
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ if (W && W->get().has(0)) {
+ textures.push_back(W->get()[0]);
+ }
+ }
+ }
+
+ RID rd_texture;
+
+ if (textures.is_empty()) {
+ //check default usage
+ switch (p_texture_uniforms[i].type) {
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ } break;
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ } break;
+ }
+ } break;
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER3D: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ } break;
+
+ default: {
+ }
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < uniform_array_size; j++) {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
+
+ for (int j = 0; j < textures.size(); j++) {
+ Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+
+ if (tex) {
+ rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+#ifdef TOOLS_ENABLED
+ if (tex->detect_3d_callback && p_use_linear_color) {
+ tex->detect_3d_callback(tex->detect_3d_callback_ud);
+ }
+ if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
+ normal_detect_texture = tex;
+ }
+ tex->detect_normal_callback(tex->detect_normal_callback_ud);
+ }
+ if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
+ //find the normal texture
+ roughness_detect_texture = tex;
+ roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+ }
+#endif
+ }
+ if (rd_texture.is_null()) {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ p_textures[k++] = rd_texture;
+ }
+ }
+ }
+ {
+ //for textures no longer used, unregister them
+ List<Map<StringName, uint64_t>::Element *> to_delete;
+ for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
+ if (E->get() != global_textures_pass) {
+ to_delete.push_back(E);
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key());
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ }
+
+ while (to_delete.front()) {
+ used_global_textures.erase(to_delete.front()->get());
+ to_delete.pop_front();
+ }
+ //handle registering/unregistering global textures
+ if (uses_global_textures != (global_texture_E != nullptr)) {
+ if (uses_global_textures) {
+ global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ global_texture_E = nullptr;
+ }
+ }
+ }
+}
+
+void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+ if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(p_uniform_set);
+ }
+}
+
+bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+ if ((uint32_t)ubo_data.size() != p_ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(p_ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
+ }
+
+ uint32_t tex_uniform_count = 0U;
+ for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
+ }
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+ update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return false;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return false;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ if (p_ubo_size) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const int array_size = p_texture_uniforms[i].array_size;
+
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + k;
+ if (array_size > 0) {
+ for (int j = 0; j < array_size; j++) {
+ u.append_id(textures[k++]);
+ }
+ } else {
+ u.append_id(textures[k++]);
+ }
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
+
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialStorage
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+ return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+ singleton = this;
+
+ for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+ shader_data_request_func[i] = nullptr;
+ }
+
+ static_assert(sizeof(GlobalVariables::Value) == 16);
+
+ global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
+ memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
+ global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+}
+
+MaterialStorage::~MaterialStorage() {
+ memdelete_arr(global_variables.buffer_values);
+ memdelete_arr(global_variables.buffer_usage);
+ memdelete_arr(global_variables.buffer_dirty_regions);
+ RD::get_singleton()->free(global_variables.buffer);
+
+ singleton = nullptr;
+}
+
+/* GLOBAL VARIABLE API */
+
+int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+ int32_t idx = 0;
+ while (idx + p_elements <= global_variables.buffer_size) {
+ if (global_variables.buffer_usage[idx].elements == 0) {
+ bool valid = true;
+ for (uint32_t i = 1; i < p_elements; i++) {
+ if (global_variables.buffer_usage[idx + i].elements > 0) {
+ valid = false;
+ idx += i + global_variables.buffer_usage[idx + i].elements;
+ break;
+ }
+ }
+
+ if (!valid) {
+ continue; //if not valid, idx is in new position
+ }
+
+ return idx;
+ } else {
+ idx += global_variables.buffer_usage[idx].elements;
+ }
+ }
+
+ return -1;
+}
+
+void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+ switch (p_type) {
+ case RS::GLOBAL_VAR_TYPE_BOOL: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ bool b = p_value;
+ bv.x = b ? 1.0 : 0.0;
+ bv.y = 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = (bvec & 8) ? 1.0 : 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_INT: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ int32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC2: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC3: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC4: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2I: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Rect2i v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UINT: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ uint32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC2: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC3: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC4: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_FLOAT: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ float v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector2 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector3 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Plane v = p_value;
+ bv.x = v.normal.x;
+ bv.y = v.normal.y;
+ bv.z = v.normal.z;
+ bv.w = v.d;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_COLOR: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Color v = p_value;
+ bv.x = v.r;
+ bv.y = v.g;
+ bv.z = v.b;
+ bv.w = v.a;
+
+ GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ v = v.to_linear();
+ bv_linear.x = v.r;
+ bv_linear.y = v.g;
+ bv_linear.z = v.b;
+ bv_linear.w = v.a;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Rect2 v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT2: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Vector<float> m2 = p_value;
+ if (m2.size() < 4) {
+ m2.resize(4);
+ }
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = m2[2];
+ bv[1].y = m2[3];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT3: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Basis v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[1][0];
+ bv[0].z = v.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[0][1];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = v.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[0][2];
+ bv[2].y = v.elements[1][2];
+ bv[2].z = v.elements[2][2];
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT4: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+
+ Vector<float> m2 = p_value;
+ if (m2.size() < 16) {
+ m2.resize(16);
+ }
+
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = m2[2];
+ bv[0].w = m2[3];
+
+ bv[1].x = m2[4];
+ bv[1].y = m2[5];
+ bv[1].z = m2[6];
+ bv[1].w = m2[7];
+
+ bv[2].x = m2[8];
+ bv[2].y = m2[9];
+ bv[2].z = m2[10];
+ bv[2].w = m2[11];
+
+ bv[3].x = m2[12];
+ bv[3].y = m2[13];
+ bv[3].z = m2[14];
+ bv[3].w = m2[15];
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform2D v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[0][1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[1][0];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[2][0];
+ bv[2].y = v.elements[2][1];
+ bv[2].z = 1;
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform3D v = p_value;
+ bv[0].x = v.basis.elements[0][0];
+ bv[0].y = v.basis.elements[1][0];
+ bv[0].z = v.basis.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.basis.elements[0][1];
+ bv[1].y = v.basis.elements[1][1];
+ bv[1].z = v.basis.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.basis.elements[0][2];
+ bv[2].y = v.basis.elements[1][2];
+ bv[2].z = v.basis.elements[2][2];
+ bv[2].w = 0;
+
+ bv[3].x = v.origin.x;
+ bv[3].y = v.origin.y;
+ bv[3].z = v.origin.z;
+ bv[3].w = 1;
+
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+}
+
+void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+ int32_t prev_chunk = -1;
+
+ for (int32_t i = 0; i < p_elements; i++) {
+ int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (chunk != prev_chunk) {
+ if (!global_variables.buffer_dirty_regions[chunk]) {
+ global_variables.buffer_dirty_regions[chunk] = true;
+ global_variables.buffer_dirty_region_count++;
+ }
+ }
+
+ prev_chunk = chunk;
+ }
+}
+
+void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_variables.variables.has(p_name));
+ GlobalVariables::Variable gv;
+ gv.type = p_type;
+ gv.value = p_value;
+ gv.buffer_index = -1;
+
+ if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //is texture
+ global_variables.must_update_texture_materials = true; //normally there are none
+ } else {
+ gv.buffer_elements = 1;
+ if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 2;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 3;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 4;
+ }
+
+ //is vector, allocate in buffer and update index
+ gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
+ global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+
+ global_variables.must_update_buffer_materials = true; //normally there are none
+ }
+
+ global_variables.variables[p_name] = gv;
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+ if (!global_variables.variables.has(p_name)) {
+ return;
+ }
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ if (gv.buffer_index >= 0) {
+ global_variables.buffer_usage[gv.buffer_index].elements = 0;
+ global_variables.must_update_buffer_materials = true;
+ } else {
+ global_variables.must_update_texture_materials = true;
+ }
+
+ global_variables.variables.erase(p_name);
+}
+
+Vector<StringName> MaterialStorage::global_variable_get_list() const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ const StringName *K = nullptr;
+ Vector<StringName> names;
+ while ((K = global_variables.variables.next(K))) {
+ names.push_back(*K);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+ return names;
+}
+
+void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_variables.variables.has(p_name));
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ gv.value = p_value;
+ if (gv.override.get_type() == Variant::NIL) {
+ if (gv.buffer_index >= 0) {
+ //buffer
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_storage->get_material(E->get());
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_variables.variables.has(p_name)) {
+ return; //variable may not exist
+ }
+
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ gv.override = p_value;
+
+ if (gv.buffer_index >= 0) {
+ //buffer
+ if (gv.override.get_type() == Variant::NIL) {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ } else {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ }
+
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_storage->get_material(E->get());
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+}
+
+Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ if (!global_variables.variables.has(p_name)) {
+ return Variant();
+ }
+
+ return global_variables.variables[p_name].value;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
+ if (!global_variables.variables.has(p_name)) {
+ return RS::GLOBAL_VAR_TYPE_MAX;
+ }
+
+ return global_variables.variables[p_name].type;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ return global_variable_get_type_internal(p_name);
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+ List<PropertyInfo> settings;
+ ProjectSettings::get_singleton()->get_property_list(&settings);
+
+ for (const PropertyInfo &E : settings) {
+ if (E.name.begins_with("shader_globals/")) {
+ StringName name = E.name.get_slice("/", 1);
+ Dictionary d = ProjectSettings::get_singleton()->get(E.name);
+
+ ERR_CONTINUE(!d.has("type"));
+ ERR_CONTINUE(!d.has("value"));
+
+ String type = d["type"];
+
+ static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
+ "bool",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "int",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "rect2i",
+ "uint",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "float",
+ "vec2",
+ "vec3",
+ "vec4",
+ "color",
+ "rect2",
+ "mat2",
+ "mat3",
+ "mat4",
+ "transform_2d",
+ "transform",
+ "sampler2D",
+ "sampler2DArray",
+ "sampler3D",
+ "samplerCube",
+ };
+
+ RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+
+ for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
+ if (global_var_type_names[i] == type) {
+ gvtype = RS::GlobalVariableType(i);
+ break;
+ }
+ }
+
+ ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
+
+ Variant value = d["value"];
+
+ if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //textire
+ if (!p_load_textures) {
+ value = RID();
+ continue;
+ }
+
+ String path = value;
+ RES resource = ResourceLoader::load(path);
+ ERR_CONTINUE(resource.is_null());
+ value = resource;
+ }
+
+ if (global_variables.variables.has(name)) {
+ //has it, update it
+ global_variable_set(name, value);
+ } else {
+ global_variable_add(name, gvtype, value);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variables_clear() {
+ global_variables.variables.clear(); //not right but for now enough
+}
+
+RID MaterialStorage::global_variables_get_storage_buffer() const {
+ return global_variables.buffer;
+}
+
+int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+ ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
+ global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ return pos;
+}
+
+void MaterialStorage::global_variables_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ if (pos >= 0) {
+ global_variables.buffer_usage[pos].elements = 0;
+ }
+ global_variables.instance_buffer_pos.erase(p_instance);
+}
+
+void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_variables.instance_buffer_pos.has(p_instance)) {
+ return; //just not allocated, ignore
+ }
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+
+ if (pos < 0) {
+ return; //again, not allocated, ignore
+ }
+ ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
+ ShaderLanguage::TYPE_MAX, //nil
+ ShaderLanguage::TYPE_BOOL, //bool
+ ShaderLanguage::TYPE_INT, //int
+ ShaderLanguage::TYPE_FLOAT, //float
+ ShaderLanguage::TYPE_MAX, //string
+ ShaderLanguage::TYPE_VEC2, //vec2
+ ShaderLanguage::TYPE_IVEC2, //vec2i
+ ShaderLanguage::TYPE_VEC4, //rect2
+ ShaderLanguage::TYPE_IVEC4, //rect2i
+ ShaderLanguage::TYPE_VEC3, // vec3
+ ShaderLanguage::TYPE_IVEC3, //vec3i
+ ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //plane
+ ShaderLanguage::TYPE_VEC4, //quat
+ ShaderLanguage::TYPE_MAX, //aabb not supported here
+ ShaderLanguage::TYPE_MAX, //basis not supported here
+ ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_VEC4 //color
+ };
+
+ ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
+
+ ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ pos += p_index;
+
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_variable_mark_buffer_dirty(pos, 1);
+}
+
+void MaterialStorage::_update_global_variables() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ if (global_variables.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ // 25% of regions dirty, just update all buffer
+ RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ } else {
+ uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+
+ for (uint32_t i = 0; i < total_regions; i++) {
+ if (global_variables.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+
+ global_variables.buffer_dirty_regions[i] = false;
+ }
+ }
+ }
+
+ global_variables.buffer_dirty_region_count = 0;
+ }
+
+ if (global_variables.must_update_buffer_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_buffer) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, true, false);
+ }
+
+ global_variables.must_update_buffer_materials = false;
+ }
+
+ if (global_variables.must_update_texture_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_texture) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, false, true);
+ }
+
+ global_variables.must_update_texture_materials = false;
+ }
+}
+
+/* SHADER API */
+
+RID MaterialStorage::shader_allocate() {
+ return shader_owner.allocate_rid();
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+ Shader shader;
+ shader.data = nullptr;
+ shader.type = SHADER_TYPE_MAX;
+
+ shader_owner.initialize_rid(p_rid, shader);
+}
+
+void MaterialStorage::shader_free(RID p_rid) {
+ Shader *shader = shader_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!shader);
+
+ //make material unreference this
+ while (shader->owners.size()) {
+ material_set_shader(shader->owners.front()->get()->self, RID());
+ }
+
+ //clear data if exists
+ if (shader->data) {
+ memdelete(shader->data);
+ }
+ shader_owner.free(p_rid);
+}
+
+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);
+
+ ShaderType new_type;
+ if (mode_string == "canvas_item") {
+ new_type = SHADER_TYPE_2D;
+ } else if (mode_string == "particles") {
+ new_type = SHADER_TYPE_PARTICLES;
+ } else if (mode_string == "spatial") {
+ new_type = SHADER_TYPE_3D;
+ } else if (mode_string == "sky") {
+ new_type = SHADER_TYPE_SKY;
+ } else if (mode_string == "fog") {
+ new_type = SHADER_TYPE_FOG;
+ } else {
+ new_type = SHADER_TYPE_MAX;
+ }
+
+ if (new_type != shader->type) {
+ if (shader->data) {
+ memdelete(shader->data);
+ shader->data = nullptr;
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ material->shader_type = new_type;
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+ }
+
+ shader->type = new_type;
+
+ if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
+ shader->data = shader_data_request_func[new_type]();
+ } else {
+ shader->type = SHADER_TYPE_MAX; //invalid
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ if (shader->data) {
+ material->data = material_get_data_request_function(new_type)(shader->data);
+ material->data->self = material->self;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ }
+ material->shader_type = new_type;
+ }
+
+ if (shader->data) {
+ for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
+ }
+ }
+ }
+
+ if (shader->data) {
+ shader->data->set_code(p_code);
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+ }
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, String());
+ 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->data) {
+ return shader->data->get_param_list(p_param_list);
+ }
+}
+
+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);
+
+ if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = Map<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
+ } else {
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
+ }
+ if (shader->data) {
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
+ }
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ _material_queue_update(material, false, true);
+ }
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RID());
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
+ }
+
+ return RID();
+}
+
+Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, Variant());
+ if (shader->data) {
+ return shader->data->get_default_parameter(p_param);
+ }
+ return Variant();
+}
+
+void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
+ ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+ shader_data_request_func[p_shader_type] = p_function;
+}
+
+RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+ if (shader->data) {
+ return shader->data->get_native_source_code();
+ }
+ return RS::ShaderNativeSourceCode();
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_uniform_set_erased(void *p_material) {
+ RID rid = *(RID *)p_material;
+ Material *material = MaterialStorage::get_singleton()->get_material(rid);
+ if (material) {
+ if (material->data) {
+ // Uniform set may be gone because a dependency was erased. This happens
+ // if a texture is deleted, so re-create it.
+ MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
+ }
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+}
+
+void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+ material->uniform_dirty = material->uniform_dirty || p_uniform;
+ material->texture_dirty = material->texture_dirty || p_texture;
+
+ if (material->update_element.in_list()) {
+ return;
+ }
+
+ material_update_list.add(&material->update_element);
+}
+
+void MaterialStorage::_update_queued_materials() {
+ while (material_update_list.first()) {
+ Material *material = material_update_list.first()->self();
+ bool uniforms_changed = false;
+
+ if (material->data) {
+ uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
+ }
+ material->texture_dirty = false;
+ material->uniform_dirty = false;
+
+ material_update_list.remove(&material->update_element);
+
+ if (uniforms_changed) {
+ //some implementations such as 3D renderer cache the matreial uniform set, so update is required
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+ }
+}
+
+RID MaterialStorage::material_allocate() {
+ return material_owner.allocate_rid();
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+ material_owner.initialize_rid(p_rid);
+ Material *material = material_owner.get_or_null(p_rid);
+ material->self = p_rid;
+}
+
+void MaterialStorage::material_free(RID p_rid) {
+ Material *material = material_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!material);
+
+ material_set_shader(p_rid, RID()); //clean up shader
+ material->dependency.deleted_notify(p_rid);
+
+ material_owner.free(p_rid);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+
+ if (material->shader) {
+ material->shader->owners.erase(material);
+ material->shader = nullptr;
+ material->shader_type = SHADER_TYPE_MAX;
+ }
+
+ if (p_shader.is_null()) {
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->shader_id = 0;
+ return;
+ }
+
+ Shader *shader = get_shader(p_shader);
+ ERR_FAIL_COND(!shader);
+ material->shader = shader;
+ material->shader_type = shader->type;
+ material->shader_id = p_shader.get_local_index();
+ shader->owners.insert(material);
+
+ if (shader->type == SHADER_TYPE_MAX) {
+ return;
+ }
+
+ ERR_FAIL_COND(shader->data == nullptr);
+
+ material->data = material_data_request_func[shader->type](shader->data);
+ material->data->self = p_material;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ //updating happens later
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+}
+
+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 {
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
+ material->params[p_param] = p_value;
+ }
+
+ if (material->shader && material->shader->data) { //shader is valid
+ bool is_texture = material->shader->data->is_param_texture(p_param);
+ _material_queue_update(material, !is_texture, is_texture);
+ } else {
+ _material_queue_update(material, true, true);
+ }
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+ if (material->params.has(p_param)) {
+ return material->params[p_param];
+ } else {
+ return Variant();
+ }
+}
+
+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);
+
+ if (material->next_pass == p_next_material) {
+ return;
+ }
+
+ material->next_pass = p_next_material;
+ if (material->data) {
+ material->data->set_next_pass(p_next_material);
+ }
+
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ material->priority = priority;
+ if (material->data) {
+ material->data->set_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->shader && material->shader->data) {
+ if (material->shader->data->is_animated()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_is_animated(material->next_pass);
+ }
+ }
+ return false; //by default nothing is animated
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, true);
+ if (material->shader && material->shader->data) {
+ if (material->shader->data->casts_shadows()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_casts_shadows(material->next_pass);
+ }
+ }
+ return true; //by default everything casts shadows
+}
+
+void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ if (material->shader && material->shader->data) {
+ material->shader->data->get_instance_param_list(r_parameters);
+
+ if (material->next_pass.is_valid()) {
+ material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ }
+ }
+}
+
+void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ p_instance->update_dependency(&material->dependency);
+ if (material->next_pass.is_valid()) {
+ material_update_dependency(material->next_pass, p_instance);
+ }
+}
+
+void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
+ ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+ material_data_request_func[p_shader_type] = p_function;
+}
+
+MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+ ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
+ return material_data_request_func[p_shader_type];
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
new file mode 100644
index 0000000000..270d9f0982
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -0,0 +1,315 @@
+/*************************************************************************/
+/* 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_RD_H
+#define MATERIAL_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererRD {
+
+class MaterialStorage;
+
+/* SHADER Structs */
+
+enum ShaderType {
+ SHADER_TYPE_2D,
+ SHADER_TYPE_3D,
+ SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
+ SHADER_TYPE_MAX
+};
+
+struct ShaderData {
+ virtual void set_code(const String &p_Code) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+ virtual bool is_param_texture(const StringName &p_param) const = 0;
+ virtual bool is_animated() const = 0;
+ virtual bool casts_shadows() const = 0;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
+
+ virtual ~ShaderData() {}
+};
+
+typedef ShaderData *(*ShaderDataRequestFunction)();
+
+struct Material;
+
+struct Shader {
+ ShaderData *data = nullptr;
+ String code;
+ ShaderType type;
+ Map<StringName, Map<int, RID>> default_texture_parameter;
+ Set<Material *> owners;
+};
+
+/* Material structs */
+
+struct MaterialData {
+ void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+
+ virtual void set_render_priority(int p_priority) = 0;
+ virtual void set_next_pass(RID p_pass) = 0;
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual ~MaterialData();
+
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
+
+private:
+ friend class MaterialStorage;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ Map<StringName, uint64_t> used_global_textures;
+
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
+};
+
+typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+struct Material {
+ RID self;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
+ //shortcut to shader data and type
+ ShaderType shader_type = SHADER_TYPE_MAX;
+ uint32_t shader_id = 0;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
+ Map<StringName, Variant> params;
+ int32_t priority = 0;
+ RID next_pass;
+ SelfList<Material> update_element;
+
+ RendererStorage::Dependency dependency;
+
+ Material() :
+ update_element(this) {}
+};
+
+/* Global variable structs */
+struct GlobalVariables {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ Set<RID> texture_materials; // materials using this
+
+ RS::GlobalVariableType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values = nullptr;
+ ValueUsage *buffer_usage = nullptr;
+ bool *buffer_dirty_regions = nullptr;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+ friend struct MaterialData;
+ static MaterialStorage *singleton;
+
+ /* GLOBAL VARIABLE API */
+
+ GlobalVariables global_variables;
+
+ int32_t _global_variable_allocate(uint32_t p_elements);
+ void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
+ void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+
+ /* SHADER API */
+
+ ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Shader, true> shader_owner;
+
+ /* MATERIAL API */
+ MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Material, true> material_owner;
+
+ SelfList<Material>::List material_update_list;
+
+ static void _material_uniform_set_erased(void *p_material);
+
+public:
+ static MaterialStorage *get_singleton();
+
+ MaterialStorage();
+ virtual ~MaterialStorage();
+
+ /* GLOBAL VARIABLE API */
+
+ void _update_global_variables();
+
+ 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;
+ RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+
+ 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;
+
+ RID global_variables_get_storage_buffer() const;
+
+ /* 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); };
+
+ virtual RID shader_allocate() override;
+ virtual void shader_initialize(RID p_shader) override;
+ virtual void shader_free(RID p_rid) 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 Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override;
+ void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
+
+ /* 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_queue_update(Material *material, bool p_uniform, bool p_texture);
+ void _update_queued_materials();
+
+ virtual RID material_allocate() override;
+ virtual void material_initialize(RID p_material) override;
+ virtual void material_free(RID p_rid) override;
+
+ virtual void material_set_shader(RID p_material, RID p_shader) override;
+
+ 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 void material_set_next_pass(RID p_material, RID p_next_material) override;
+ virtual void material_set_render_priority(RID p_material, int priority) override;
+
+ virtual bool material_is_animated(RID p_material) override;
+ virtual bool material_casts_shadows(RID p_material) override;
+
+ 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;
+
+ void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+ MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
+
+ _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ return material->shader_id;
+ }
+
+ _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
+ Material *material = material_owner.get_or_null(p_material);
+ if (!material || material->shader_type != p_shader_type) {
+ return nullptr;
+ } else {
+ return material->data;
+ }
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
new file mode 100644
index 0000000000..8c60264ce3
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -0,0 +1,1921 @@
+/*************************************************************************/
+/* mesh_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. */
+/*************************************************************************/
+
+#include "mesh_storage.h"
+
+using namespace RendererRD;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage *MeshStorage::get_singleton() {
+ return singleton;
+}
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+
+ default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
+
+ //default rd buffers
+ {
+ Vector<uint8_t> buffer;
+ {
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //normal
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tangent
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //color
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 1.0;
+ fptr[2] = 1.0;
+ fptr[3] = 1.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tex uv 1
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ { //tex uv 2
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //bones
+ buffer.resize(sizeof(uint32_t) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ uint32_t *fptr = (uint32_t *)w;
+ fptr[0] = 0;
+ fptr[1] = 0;
+ fptr[2] = 0;
+ fptr[3] = 0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //weights
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ }
+
+ {
+ Vector<String> skeleton_modes;
+ skeleton_modes.push_back("\n#define MODE_2D\n");
+ skeleton_modes.push_back("");
+
+ skeleton_shader.shader.initialize(skeleton_modes);
+ skeleton_shader.version = skeleton_shader.shader.version_create();
+ for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) {
+ skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i);
+ skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(default_rd_storage_buffer);
+ uniforms.push_back(u);
+ }
+ skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+ }
+}
+
+MeshStorage::~MeshStorage() {
+ //def buffers
+ for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
+ RD::get_singleton()->free(mesh_default_rd_buffers[i]);
+ }
+
+ skeleton_shader.shader.version_free(skeleton_shader.version);
+
+ RD::get_singleton()->free(default_rd_storage_buffer);
+
+ singleton = nullptr;
+}
+
+/* MESH API */
+
+RID MeshStorage::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, Mesh());
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+ mesh_clear(p_rid);
+ mesh_set_shadow_mesh(p_rid, RID());
+ Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ mesh->dependency.deleted_notify(p_rid);
+ if (mesh->instances.size()) {
+ ERR_PRINT("deleting mesh with active instances");
+ }
+ if (mesh->shadow_owners.size()) {
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+ }
+ mesh_owner.free(p_rid);
+}
+
+void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
+ ERR_FAIL_COND(p_blend_shape_count < 0);
+
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
+
+ mesh->blend_shape_count = p_blend_shape_count;
+}
+
+/// Returns stride
+void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
+
+#ifdef DEBUG_ENABLED
+ //do a validation, to catch errors first
+ {
+ uint32_t stride = 0;
+ uint32_t attrib_stride = 0;
+ uint32_t skin_stride = 0;
+
+ for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
+ if ((p_surface.format & (1 << i))) {
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ stride += sizeof(float) * 2;
+ } else {
+ stride += sizeof(float) * 3;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_TANGENT: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_COLOR: {
+ attrib_stride += sizeof(uint32_t);
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ attrib_stride += fmtsize[fmt];
+
+ } break;
+ case RS::ARRAY_WEIGHTS:
+ case RS::ARRAY_BONES: {
+ //uses a separate array
+ bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8);
+ } break;
+ }
+ }
+ }
+
+ int expected_size = stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+
+ int bs_expected_size = expected_size * mesh->blend_shape_count;
+
+ ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")");
+
+ int expected_attrib_size = attrib_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
+
+ if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
+ expected_size = skin_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+ }
+ }
+
+#endif
+
+ Mesh::Surface *s = memnew(Mesh::Surface);
+
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+
+ bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
+
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+
+ if (p_surface.attribute_data.size()) {
+ s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
+ }
+ if (p_surface.skin_data.size()) {
+ s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage);
+ s->skin_buffer_size = p_surface.skin_data.size();
+ }
+
+ s->vertex_count = p_surface.vertex_count;
+
+ if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
+ mesh->has_bone_weights = true;
+ }
+
+ if (p_surface.index_count) {
+ bool is_index_16 = p_surface.vertex_count <= 65536;
+
+ s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
+ s->index_count = p_surface.index_count;
+ s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
+ if (p_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
+ s->lod_count = p_surface.lods.size();
+
+ for (int i = 0; i < p_surface.lods.size(); i++) {
+ uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
+ s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
+ s->lods[i].edge_length = p_surface.lods[i].edge_length;
+ s->lods[i].index_count = indices;
+ }
+ }
+ }
+
+ s->aabb = p_surface.aabb;
+ s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+
+ if (mesh->blend_shape_count > 0) {
+ s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
+ }
+
+ if (use_as_storage) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(s->vertex_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (s->skin_buffer.is_valid()) {
+ u.append_id(s->skin_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (s->blend_shape_buffer.is_valid()) {
+ u.append_id(s->blend_shape_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+
+ s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE);
+ }
+
+ if (mesh->surface_count == 0) {
+ mesh->bone_aabbs = p_surface.bone_aabbs;
+ mesh->aabb = p_surface.aabb;
+ } else {
+ if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
+ // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
+ // Each surface may affect different numbers of bones.
+ mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
+ }
+ for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
+ mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ }
+ mesh->aabb.merge_with(p_surface.aabb);
+ }
+
+ s->material = p_surface.material;
+
+ mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
+ mesh->surfaces[mesh->surface_count] = s;
+ mesh->surface_count++;
+
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+
+ mesh->material_cache.clear();
+}
+
+int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
+ const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, -1);
+ return mesh->blend_shape_count;
+}
+
+void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX((int)p_mode, 2);
+
+ mesh->blend_shape_mode = p_mode;
+}
+
+RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
+ return mesh->blend_shape_mode;
+}
+
+void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ mesh->surfaces[p_surface]->material = p_material;
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->material_cache.clear();
+}
+
+RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
+
+ return mesh->surfaces[p_surface]->material;
+}
+
+RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[p_surface];
+
+ RS::SurfaceData sd;
+ sd.format = s.format;
+ sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.attribute_buffer.is_valid()) {
+ sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
+ }
+ sd.vertex_count = s.vertex_count;
+ sd.index_count = s.index_count;
+ sd.primitive = s.primitive;
+
+ if (sd.index_count) {
+ sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
+ }
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ RS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+
+ if (s.blend_shape_buffer.is_valid()) {
+ sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
+ }
+
+ return sd;
+}
+
+int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, 0);
+ return mesh->surface_count;
+}
+
+void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ mesh->custom_aabb = p_aabb;
+}
+
+AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+ return mesh->custom_aabb;
+}
+
+AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+
+ if (mesh->custom_aabb != AABB()) {
+ return mesh->custom_aabb;
+ }
+
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ if (!skeleton || skeleton->size == 0) {
+ return mesh->aabb;
+ }
+
+ AABB aabb;
+
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ AABB laabb;
+ if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
+ int bs = mesh->surfaces[i]->bone_aabbs.size();
+ const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
+
+ int sbs = skeleton->size;
+ ERR_CONTINUE(bs > sbs);
+ const float *baseptr = skeleton->data.ptr();
+
+ bool first = true;
+
+ if (skeleton->use_2d) {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 8;
+
+ Transform3D mtx;
+
+ mtx.basis.elements[0].x = dataptr[0];
+ mtx.basis.elements[1].x = dataptr[1];
+ mtx.origin.x = dataptr[3];
+
+ mtx.basis.elements[0].y = dataptr[4];
+ mtx.basis.elements[1].y = dataptr[5];
+ mtx.origin.y = dataptr[7];
+
+ AABB baabb = mtx.xform(skbones[j]);
+
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ } else {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 12;
+
+ Transform3D mtx;
+
+ mtx.basis.elements[0][0] = dataptr[0];
+ mtx.basis.elements[0][1] = dataptr[1];
+ mtx.basis.elements[0][2] = dataptr[2];
+ mtx.origin.x = dataptr[3];
+ mtx.basis.elements[1][0] = dataptr[4];
+ mtx.basis.elements[1][1] = dataptr[5];
+ mtx.basis.elements[1][2] = dataptr[6];
+ mtx.origin.y = dataptr[7];
+ mtx.basis.elements[2][0] = dataptr[8];
+ mtx.basis.elements[2][1] = dataptr[9];
+ mtx.basis.elements[2][2] = dataptr[10];
+ mtx.origin.z = dataptr[11];
+
+ AABB baabb = mtx.xform(skbones[j]);
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ }
+
+ if (laabb.size == Vector3()) {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+ } else {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+
+ if (i == 0) {
+ aabb = laabb;
+ } else {
+ aabb.merge_with(laabb);
+ }
+ }
+
+ return aabb;
+}
+
+void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.erase(mesh);
+ }
+ mesh->shadow_mesh = p_shadow_mesh;
+
+ shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.insert(mesh);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ Mesh::Surface &s = *mesh->surfaces[i];
+ RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.attribute_buffer.is_valid()) {
+ RD::get_singleton()->free(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ RD::get_singleton()->free(s.skin_buffer);
+ }
+ if (s.versions) {
+ memfree(s.versions); //reallocs, so free with memfree.
+ }
+
+ if (s.index_buffer.is_valid()) {
+ RD::get_singleton()->free(s.index_buffer);
+ }
+
+ if (s.lod_count) {
+ for (uint32_t j = 0; j < s.lod_count; j++) {
+ RD::get_singleton()->free(s.lods[j].index_buffer);
+ }
+ memdelete_arr(s.lods);
+ }
+
+ if (s.blend_shape_buffer.is_valid()) {
+ RD::get_singleton()->free(s.blend_shape_buffer);
+ }
+
+ memdelete(mesh->surfaces[i]);
+ }
+ if (mesh->surfaces) {
+ memfree(mesh->surfaces);
+ }
+
+ mesh->surfaces = nullptr;
+ mesh->surface_count = 0;
+ mesh->material_cache.clear();
+ //clear instance data
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_clear(mi);
+ }
+ mesh->has_bone_weights = false;
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+}
+
+bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, false);
+
+ return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
+}
+
+/* MESH INSTANCE */
+
+RID MeshStorage::mesh_instance_create(RID p_base) {
+ Mesh *mesh = mesh_owner.get_or_null(p_base);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ RID rid = mesh_instance_owner.make_rid();
+ MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
+
+ mi->mesh = mesh;
+
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ _mesh_instance_add_surface(mi, mesh, i);
+ }
+
+ mi->I = mesh->instances.push_back(mi);
+
+ mi->dirty = true;
+
+ return rid;
+}
+
+void MeshStorage::mesh_instance_free(RID p_rid) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
+ _mesh_instance_clear(mi);
+ mi->mesh->instances.erase(mi->I);
+ mi->I = nullptr;
+
+ mesh_instance_owner.free(p_rid);
+}
+
+void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ if (mi->skeleton == p_skeleton) {
+ return;
+ }
+ mi->skeleton = p_skeleton;
+ mi->skeleton_version = 0;
+ mi->dirty = true;
+}
+
+void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ ERR_FAIL_COND(!mi);
+ ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
+ mi->blend_weights[p_shape] = p_weight;
+ mi->weights_dirty = true;
+ //will be eventually updated
+}
+
+void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ if (mi->surfaces[i].versions) {
+ for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
+ RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array);
+ }
+ memfree(mi->surfaces[i].versions);
+ }
+ if (mi->surfaces[i].vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
+ }
+ }
+ mi->surfaces.clear();
+
+ if (mi->blend_weights_buffer.is_valid()) {
+ RD::get_singleton()->free(mi->blend_weights_buffer);
+ }
+ mi->blend_weights.clear();
+ mi->weights_dirty = false;
+ mi->skeleton_version = 0;
+}
+
+void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
+ if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) {
+ mi->blend_weights.resize(mesh->blend_shape_count);
+ for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
+ mi->blend_weights[i] = 0;
+ }
+ mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
+ mi->weights_dirty = true;
+ }
+
+ MeshInstance::Surface s;
+ if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ //surface warrants transform
+ s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(s.vertex_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (mi->blend_weights_buffer.is_valid()) {
+ u.append_id(mi->blend_weights_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+ s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
+ }
+
+ mi->surfaces.push_back(s);
+ mi->dirty = true;
+}
+
+void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+
+ bool needs_update = mi->dirty;
+
+ if (mi->weights_dirty && !mi->weight_update_list.in_list()) {
+ dirty_mesh_instance_weights.add(&mi->weight_update_list);
+ needs_update = true;
+ }
+
+ if (mi->array_update_list.in_list()) {
+ return;
+ }
+
+ if (!needs_update && mi->skeleton.is_valid()) {
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
+ if (sk && sk->version != mi->skeleton_version) {
+ needs_update = true;
+ }
+ }
+
+ if (needs_update) {
+ dirty_mesh_instance_arrays.add(&mi->array_update_list);
+ }
+}
+
+void MeshStorage::update_mesh_instances() {
+ while (dirty_mesh_instance_weights.first()) {
+ MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
+
+ if (mi->blend_weights_buffer.is_valid()) {
+ RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr());
+ }
+ dirty_mesh_instance_weights.remove(&mi->weight_update_list);
+ mi->weights_dirty = false;
+ }
+ if (dirty_mesh_instance_arrays.first() == nullptr) {
+ return; //nothing to do
+ }
+
+ //process skeletons and blend shapes
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ while (dirty_mesh_instance_arrays.first()) {
+ MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
+
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
+
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
+ continue;
+ }
+
+ bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE);
+ if (sk && sk->uniform_set_mi.is_valid()) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+
+ SkeletonShader::PushConstant push_constant;
+
+ push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL;
+ push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT;
+ push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES);
+ push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0;
+
+ push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count;
+ push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
+ push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
+ push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
+
+ push_constant.blend_shape_count = mi->mesh->blend_shape_count;
+ push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
+ push_constant.pad0 = 0;
+ push_constant.pad1 = 0;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant));
+
+ //dispatch without barrier, so all is done at the same time
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1);
+ }
+
+ mi->dirty = false;
+ if (sk) {
+ mi->skeleton_version = sk->version;
+ }
+ dirty_mesh_instance_arrays.remove(&mi->array_update_list);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
+ Vector<RD::VertexAttribute> attributes;
+ Vector<RID> buffers;
+
+ uint32_t stride = 0;
+ uint32_t attribute_stride = 0;
+ uint32_t skin_stride = 0;
+
+ for (int i = 0; i < RS::ARRAY_INDEX; i++) {
+ RD::VertexAttribute vd;
+ RID buffer;
+ vd.location = i;
+
+ if (!(s->format & (1 << i))) {
+ // Not supplied by surface, use default value
+ buffer = mesh_default_rd_buffers[i];
+ vd.stride = 0;
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case RS::ARRAY_BONES: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ } break;
+ case RS::ARRAY_WEIGHTS: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ }
+ } else {
+ //Supplied, use it
+
+ vd.stride = 1; //mark that it needs a stride set (default uses 0)
+
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ vd.offset = stride;
+
+ if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ stride += sizeof(float) * 2;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ stride += sizeof(float) * 3;
+ }
+
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ attribute_stride += sizeof(int8_t) * 4;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ vd.offset = attribute_stride;
+
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
+ vd.format = fmtrd[fmt];
+ attribute_stride += fmtsize[fmt];
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_BONES: {
+ vd.offset = skin_stride;
+
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
+ } break;
+ case RS::ARRAY_WEIGHTS: {
+ vd.offset = skin_stride;
+
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
+ } break;
+ }
+ }
+
+ if (!(p_input_mask & (1 << i))) {
+ continue; // Shader does not need this, skip it (but computing stride was important anyway)
+ }
+
+ attributes.push_back(vd);
+ buffers.push_back(buffer);
+ }
+
+ //update final stride
+ for (int i = 0; i < attributes.size(); i++) {
+ if (attributes[i].stride == 0) {
+ continue; //default location
+ }
+ int loc = attributes[i].location;
+
+ if (loc < RS::ARRAY_COLOR) {
+ attributes.write[i].stride = stride;
+ } else if (loc < RS::ARRAY_BONES) {
+ attributes.write[i].stride = attribute_stride;
+ } else {
+ attributes.write[i].stride = skin_stride;
+ }
+ }
+
+ v.input_mask = p_input_mask;
+ v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
+ v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
+}
+
+////////////////// MULTIMESH
+
+RID MeshStorage::multimesh_allocate() {
+ return multimesh_owner.allocate_rid();
+}
+void MeshStorage::multimesh_initialize(RID p_rid) {
+ multimesh_owner.initialize_rid(p_rid, MultiMesh());
+}
+
+void MeshStorage::multimesh_free(RID p_rid) {
+ _update_dirty_multimeshes();
+ multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
+ multimesh->dependency.deleted_notify(p_rid);
+ multimesh_owner.free(p_rid);
+}
+
+void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+
+ if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
+ return;
+ }
+
+ if (multimesh->buffer.is_valid()) {
+ RD::get_singleton()->free(multimesh->buffer);
+ multimesh->buffer = RID();
+ multimesh->uniform_set_2d = RID(); //cleared by dependency
+ multimesh->uniform_set_3d = RID(); //cleared by dependency
+ }
+
+ if (multimesh->data_cache_dirty_regions) {
+ memdelete_arr(multimesh->data_cache_dirty_regions);
+ multimesh->data_cache_dirty_regions = nullptr;
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ multimesh->instances = p_instances;
+ multimesh->xform_format = p_transform_format;
+ multimesh->uses_colors = p_use_colors;
+ multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ multimesh->uses_custom_data = p_use_custom_data;
+ multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
+ multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
+ multimesh->buffer_set = false;
+
+ //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
+ multimesh->data_cache = Vector<float>();
+ multimesh->aabb = AABB();
+ multimesh->aabb_dirty = false;
+ multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
+
+ if (multimesh->instances) {
+ multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+}
+
+int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->instances;
+}
+
+void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ if (multimesh->mesh == p_mesh) {
+ return;
+ }
+ multimesh->mesh = p_mesh;
+
+ if (multimesh->instances == 0) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //we have a data cache, just mark it dirt
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ } else if (multimesh->instances) {
+ //need to re-create AABB unfortunately, calling this has a penalty
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ const uint8_t *r = buffer.ptr();
+ const float *data = (const float *)r;
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ }
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+#define MULTIMESH_DIRTY_REGION_SIZE 512
+
+void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
+ if (multimesh->data_cache.size() > 0) {
+ return; //already local
+ }
+ ERR_FAIL_COND(multimesh->data_cache.size() > 0);
+ // this means that the user wants to load/save individual elements,
+ // for this, the data must reside on CPU, so just copy it there.
+ multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ {
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+ } else {
+ memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
+ }
+ }
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+}
+
+void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
+ uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
+#ifdef DEBUG_ENABLED
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
+#endif
+ if (!multimesh->data_cache_dirty_regions[region_index]) {
+ multimesh->data_cache_dirty_regions[region_index] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
+ if (p_data) {
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ if (!multimesh->data_cache_dirty_regions[i]) {
+ multimesh->data_cache_dirty_regions[i] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+ }
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
+ ERR_FAIL_COND(multimesh->mesh.is_null());
+ AABB aabb;
+ AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
+ for (int i = 0; i < p_instances; i++) {
+ const float *data = p_data + multimesh->stride_cache * i;
+ Transform3D t;
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ t.basis.elements[0][0] = data[0];
+ t.basis.elements[0][1] = data[1];
+ t.basis.elements[0][2] = data[2];
+ t.origin.x = data[3];
+ t.basis.elements[1][0] = data[4];
+ t.basis.elements[1][1] = data[5];
+ t.basis.elements[1][2] = data[6];
+ t.origin.y = data[7];
+ t.basis.elements[2][0] = data[8];
+ t.basis.elements[2][1] = data[9];
+ t.basis.elements[2][2] = data[10];
+ t.origin.z = data[11];
+
+ } else {
+ t.basis.elements[0].x = data[0];
+ t.basis.elements[1].x = data[1];
+ t.origin.x = data[3];
+
+ t.basis.elements[0].y = data[4];
+ t.basis.elements[1].y = data[5];
+ t.origin.y = data[7];
+ }
+
+ if (i == 0) {
+ aabb = t.xform(mesh_aabb);
+ } else {
+ aabb.merge_with(t.xform(mesh_aabb));
+ }
+ }
+
+ multimesh->aabb = aabb;
+}
+
+void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.basis.elements[0][0];
+ dataptr[1] = p_transform.basis.elements[0][1];
+ dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.elements[1][0];
+ dataptr[5] = p_transform.basis.elements[1][1];
+ dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.elements[2][0];
+ dataptr[9] = p_transform.basis.elements[2][1];
+ dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[11] = p_transform.origin.z;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.elements[0][0];
+ dataptr[1] = p_transform.elements[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.elements[2][0];
+ dataptr[4] = p_transform.elements[0][1];
+ dataptr[5] = p_transform.elements[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.elements[2][1];
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_colors);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_custom_data);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, RID());
+
+ return multimesh->mesh;
+}
+
+Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform3D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform3D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.basis.elements[0][0] = dataptr[0];
+ t.basis.elements[0][1] = dataptr[1];
+ t.basis.elements[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.elements[1][0] = dataptr[4];
+ t.basis.elements[1][1] = dataptr[5];
+ t.basis.elements[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.elements[2][0] = dataptr[8];
+ t.basis.elements[2][1] = dataptr[9];
+ t.basis.elements[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+ }
+
+ return t;
+}
+
+Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform2D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform2D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.elements[0][0] = dataptr[0];
+ t.elements[1][0] = dataptr[1];
+ t.elements[2][0] = dataptr[3];
+ t.elements[0][1] = dataptr[4];
+ t.elements[1][1] = dataptr[5];
+ t.elements[2][1] = dataptr[7];
+ }
+
+ return t;
+}
+
+Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
+
+ {
+ const float *r = p_buffer.ptr();
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
+ multimesh->buffer_set = true;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //if we have a data cache, just update it
+ multimesh->data_cache = p_buffer;
+ {
+ //clear dirty since nothing will be dirty anymore
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
+ } else if (multimesh->mesh.is_valid()) {
+ //if we have a mesh set, we need to re-generate the AABB from the new data
+ const float *data = p_buffer.ptr();
+
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+}
+
+Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Vector<float>());
+ if (multimesh->buffer.is_null()) {
+ return Vector<float>();
+ } else if (multimesh->data_cache.size()) {
+ return multimesh->data_cache;
+ } else {
+ //get from memory
+
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ Vector<float> ret;
+ ret.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = ret.ptrw();
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+
+ return ret;
+ }
+}
+
+void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
+ if (multimesh->visible_instances == p_visible) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //there is a data cache..
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ }
+
+ multimesh->visible_instances = p_visible;
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+}
+
+int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->visible_instances;
+}
+
+AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, AABB());
+ if (multimesh->aabb_dirty) {
+ const_cast<MeshStorage *>(this)->_update_dirty_multimeshes();
+ }
+ return multimesh->aabb;
+}
+
+void MeshStorage::_update_dirty_multimeshes() {
+ while (multimesh_dirty_list) {
+ MultiMesh *multimesh = multimesh_dirty_list;
+
+ if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
+ const float *data = multimesh->data_cache.ptr();
+
+ uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+
+ if (multimesh->data_cache_used_dirty_regions) {
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+
+ uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
+
+ if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
+ //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
+ } else {
+ //not that many regions? update them all
+ for (uint32_t i = 0; i < visible_region_count; i++) {
+ if (multimesh->data_cache_dirty_regions[i]) {
+ uint32_t offset = i * region_size;
+ uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ if (multimesh->aabb_dirty) {
+ //aabb is dirty..
+ _multimesh_re_create_aabb(multimesh, data, visible_instances);
+ multimesh->aabb_dirty = false;
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+ }
+
+ multimesh_dirty_list = multimesh->dirty_list;
+
+ multimesh->dirty_list = nullptr;
+ multimesh->dirty = false;
+ }
+
+ multimesh_dirty_list = nullptr;
+}
+
+/* SKELETON API */
+
+RID MeshStorage::skeleton_allocate() {
+ return skeleton_owner.allocate_rid();
+}
+void MeshStorage::skeleton_initialize(RID p_rid) {
+ skeleton_owner.initialize_rid(p_rid, Skeleton());
+}
+
+void MeshStorage::skeleton_free(RID p_rid) {
+ _update_dirty_skeletons();
+ skeleton_allocate_data(p_rid, 0);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
+ skeleton_owner.free(p_rid);
+}
+
+void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) {
+ if (!skeleton->dirty) {
+ skeleton->dirty = true;
+ skeleton->dirty_list = skeleton_dirty_list;
+ skeleton_dirty_list = skeleton;
+ }
+}
+
+void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_COND(p_bones < 0);
+
+ if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
+ return;
+ }
+
+ skeleton->size = p_bones;
+ skeleton->use_2d = p_2d_skeleton;
+ skeleton->uniform_set_3d = RID();
+
+ if (skeleton->buffer.is_valid()) {
+ RD::get_singleton()->free(skeleton->buffer);
+ skeleton->buffer = RID();
+ skeleton->data.clear();
+ skeleton->uniform_set_mi = RID();
+ }
+
+ if (skeleton->size) {
+ skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
+ skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
+ memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
+
+ _skeleton_make_dirty(skeleton);
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(skeleton->buffer);
+ uniforms.push_back(u);
+ }
+ skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+ }
+
+ skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA);
+}
+
+int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, 0);
+
+ return skeleton->size;
+}
+
+void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+
+ dataptr[0] = p_transform.basis.elements[0][0];
+ dataptr[1] = p_transform.basis.elements[0][1];
+ dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.elements[1][0];
+ dataptr[5] = p_transform.basis.elements[1][1];
+ dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.elements[2][0];
+ dataptr[9] = p_transform.basis.elements[2][1];
+ dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[11] = p_transform.origin.z;
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform3D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
+ ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 12;
+
+ Transform3D t;
+
+ t.basis.elements[0][0] = dataptr[0];
+ t.basis.elements[0][1] = dataptr[1];
+ t.basis.elements[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.elements[1][0] = dataptr[4];
+ t.basis.elements[1][1] = dataptr[5];
+ t.basis.elements[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.elements[2][0] = dataptr[8];
+ t.basis.elements[2][1] = dataptr[9];
+ t.basis.elements[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+
+ return t;
+}
+
+void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+
+ dataptr[0] = p_transform.elements[0][0];
+ dataptr[1] = p_transform.elements[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.elements[2][0];
+ dataptr[4] = p_transform.elements[0][1];
+ dataptr[5] = p_transform.elements[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.elements[2][1];
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform2D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
+ ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 8;
+
+ Transform2D t;
+ t.elements[0][0] = dataptr[0];
+ t.elements[1][0] = dataptr[1];
+ t.elements[2][0] = dataptr[3];
+ t.elements[0][1] = dataptr[4];
+ t.elements[1][1] = dataptr[5];
+ t.elements[2][1] = dataptr[7];
+
+ return t;
+}
+
+void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ skeleton->base_transform_2d = p_base_transform;
+}
+
+void MeshStorage::_update_dirty_skeletons() {
+ while (skeleton_dirty_list) {
+ Skeleton *skeleton = skeleton_dirty_list;
+
+ if (skeleton->size) {
+ RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
+ }
+
+ skeleton_dirty_list = skeleton->dirty_list;
+
+ skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES);
+
+ skeleton->version++;
+
+ skeleton->dirty = false;
+ skeleton->dirty_list = nullptr;
+ }
+
+ skeleton_dirty_list = nullptr;
+}
+
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+
+ p_instance->update_dependency(&skeleton->dependency);
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
new file mode 100644
index 0000000000..e8da8ad563
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -0,0 +1,694 @@
+/*************************************************************************/
+/* mesh_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 MESH_STORAGE_RD_H
+#define MESH_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererRD {
+
+/* Mesh */
+
+enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ DEFAULT_RD_BUFFER_COLOR,
+ DEFAULT_RD_BUFFER_TEX_UV,
+ DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_CUSTOM0,
+ DEFAULT_RD_BUFFER_CUSTOM1,
+ DEFAULT_RD_BUFFER_CUSTOM2,
+ DEFAULT_RD_BUFFER_CUSTOM3,
+ DEFAULT_RD_BUFFER_BONES,
+ DEFAULT_RD_BUFFER_WEIGHTS,
+ DEFAULT_RD_BUFFER_MAX,
+};
+
+struct MeshInstance;
+
+struct Mesh {
+ struct Surface {
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
+ uint32_t format = 0;
+
+ RID vertex_buffer;
+ RID attribute_buffer;
+ RID skin_buffer;
+ uint32_t vertex_count = 0;
+ uint32_t vertex_buffer_size = 0;
+ uint32_t skin_buffer_size = 0;
+
+ // A different pipeline needs to be allocated
+ // depending on the inputs available in the
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
+
+ struct LOD {
+ float edge_length = 0.0;
+ uint32_t index_count = 0;
+ RID index_buffer;
+ RID index_array;
+ };
+
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
+
+ AABB aabb;
+
+ Vector<AABB> bone_aabbs;
+
+ RID blend_shape_buffer;
+
+ RID material;
+
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
+
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
+
+ uint32_t particles_render_index = 0;
+ uint64_t particles_render_pass = 0;
+
+ RID uniform_set;
+ };
+
+ uint32_t blend_shape_count = 0;
+ RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
+
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
+
+ Vector<AABB> bone_aabbs;
+
+ bool has_bone_weights = false;
+
+ AABB aabb;
+ AABB custom_aabb;
+
+ Vector<RID> material_cache;
+
+ List<MeshInstance *> instances;
+
+ RID shadow_mesh;
+ Set<Mesh *> shadow_owners;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Mesh Instance */
+
+struct MeshInstance {
+ Mesh *mesh = nullptr;
+ RID skeleton;
+ struct Surface {
+ RID vertex_buffer;
+ RID uniform_set;
+
+ Mesh::Surface::Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+ };
+ LocalVector<Surface> surfaces;
+ LocalVector<float> blend_weights;
+
+ RID blend_weights_buffer;
+ List<MeshInstance *>::Element *I = nullptr; //used to erase itself
+ uint64_t skeleton_version = 0;
+ bool dirty = false;
+ bool weights_dirty = false;
+ SelfList<MeshInstance> weight_update_list;
+ SelfList<MeshInstance> array_update_list;
+ MeshInstance() :
+ weight_update_list(this), array_update_list(this) {}
+};
+
+/* MultiMesh */
+
+struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_used_dirty_regions = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Skeleton */
+
+struct SkeletonShader {
+ struct PushConstant {
+ uint32_t has_normal;
+ uint32_t has_tangent;
+ uint32_t has_skeleton;
+ uint32_t has_blend_shape;
+
+ uint32_t vertex_count;
+ uint32_t vertex_stride;
+ uint32_t skin_stride;
+ uint32_t skin_weight_offset;
+
+ uint32_t blend_shape_count;
+ uint32_t normalized_blend_shapes;
+ uint32_t pad0;
+ uint32_t pad1;
+ };
+
+ enum {
+ UNIFORM_SET_INSTANCE = 0,
+ UNIFORM_SET_SURFACE = 1,
+ UNIFORM_SET_SKELETON = 2,
+ };
+ enum {
+ SHADER_MODE_2D,
+ SHADER_MODE_3D,
+ SHADER_MODE_MAX
+ };
+
+ SkeletonShaderRD shader;
+ RID version;
+ RID version_shader[SHADER_MODE_MAX];
+ RID pipeline[SHADER_MODE_MAX];
+
+ RID default_skeleton_uniform_set;
+};
+
+struct Skeleton {
+ bool use_2d = false;
+ int size = 0;
+ Vector<float> data;
+ RID buffer;
+
+ bool dirty = false;
+ Skeleton *dirty_list = nullptr;
+ Transform2D base_transform_2d;
+
+ RID uniform_set_3d;
+ RID uniform_set_mi;
+
+ uint64_t version = 1;
+
+ RendererStorage::Dependency dependency;
+};
+
+class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
+ RID default_rd_storage_buffer;
+
+ /* Mesh */
+
+ mutable RID_Owner<Mesh, true> mesh_owner;
+
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
+
+ /* Mesh Instance API */
+
+ void _mesh_instance_clear(MeshInstance *mi);
+ void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
+
+ mutable RID_Owner<MeshInstance> mesh_instance_owner;
+
+ SelfList<MeshInstance>::List dirty_mesh_instance_weights;
+ SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
+
+ /* MultiMesh */
+
+ mutable RID_Owner<MultiMesh, true> multimesh_owner;
+
+ MultiMesh *multimesh_dirty_list = nullptr;
+
+ _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
+
+ /* Skeleton */
+
+ SkeletonShader skeleton_shader;
+
+ mutable RID_Owner<Skeleton, true> skeleton_owner;
+
+ _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
+
+ Skeleton *skeleton_dirty_list = nullptr;
+
+public:
+ static MeshStorage *get_singleton();
+
+ MeshStorage();
+ virtual ~MeshStorage();
+
+ RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
+
+ /* MESH API */
+
+ Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+
+ virtual RID mesh_allocate() override;
+ virtual void mesh_initialize(RID p_mesh) override;
+ virtual void mesh_free(RID p_rid) override;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
+
+ /// Return stride
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
+
+ virtual void mesh_clear(RID p_mesh) override;
+
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
+
+ _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ r_surface_count = mesh->surface_count;
+ if (r_surface_count == 0) {
+ return nullptr;
+ }
+ if (mesh->material_cache.is_empty()) {
+ mesh->material_cache.resize(mesh->surface_count);
+ for (uint32_t i = 0; i < r_surface_count; i++) {
+ mesh->material_cache.write[i] = mesh->surfaces[i]->material;
+ }
+ }
+
+ return mesh->material_cache.ptr();
+ }
+
+ _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
+
+ return mesh->surfaces[p_surface_index];
+ }
+
+ _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ return mesh->shadow_mesh;
+ }
+
+ _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
+ Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return surface->primitive;
+ }
+
+ _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->lod_count > 0;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->index_count ? s->index_count : s->vertex_count;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ int32_t current_lod = -1;
+ if (r_index_count) {
+ *r_index_count = s->index_count;
+ }
+ for (uint32_t i = 0; i < s->lod_count; i++) {
+ float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
+ if (screen_size > p_mesh_lod_threshold) {
+ break;
+ }
+ current_lod = i;
+ }
+ if (current_lod == -1) {
+ return 0;
+ } else {
+ if (r_index_count) {
+ *r_index_count = s->lods[current_lod].index_count;
+ }
+ return current_lod + 1;
+ }
+ }
+
+ _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ if (p_lod == 0) {
+ return s->index_array;
+ } else {
+ return s->lods[p_lod - 1].index_array;
+ }
+ }
+
+ _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ s->version_lock.lock();
+
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+
+ for (uint32_t i = 0; i < s->version_count; i++) {
+ if (s->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = s->versions[i].vertex_format;
+ r_vertex_array_rd = s->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
+
+ uint32_t version = s->version_count;
+ s->version_count++;
+ s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
+
+ _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask);
+
+ r_vertex_format = s->versions[version].vertex_format;
+ r_vertex_array_rd = s->versions[version].vertex_array;
+
+ s->version_lock.unlock();
+ }
+
+ _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ ERR_FAIL_COND(!mi);
+ Mesh *mesh = mi->mesh;
+ ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
+
+ MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ s->version_lock.lock();
+
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+
+ for (uint32_t i = 0; i < mis->version_count; i++) {
+ if (mis->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = mis->versions[i].vertex_format;
+ r_vertex_array_rd = mis->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
+
+ uint32_t version = mis->version_count;
+ mis->version_count++;
+ mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
+
+ _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis);
+
+ r_vertex_format = mis->versions[version].vertex_format;
+ r_vertex_array_rd = mis->versions[version].vertex_array;
+
+ s->version_lock.unlock();
+ }
+
+ _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
+ ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
+ return mesh_default_rd_buffers[p_buffer];
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->render_pass != p_render_pass) {
+ (*r_index)++;
+ s->render_pass = p_render_pass;
+ s->render_index = *r_index;
+ }
+
+ return s->render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->multimesh_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->multimesh_render_pass = p_render_pass;
+ s->multimesh_render_index = *r_index;
+ }
+
+ return s->multimesh_render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->particles_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->particles_render_pass = p_render_pass;
+ s->particles_render_index = *r_index;
+ }
+
+ return s->particles_render_index;
+ }
+
+ /* MESH INSTANCE API */
+
+ MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
+ bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+
+ virtual RID mesh_instance_create(RID p_base) override;
+ virtual void mesh_instance_free(RID p_rid) override;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void update_mesh_instances() override;
+
+ /* MULTIMESH API */
+
+ MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
+ bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
+
+ virtual RID multimesh_allocate() override;
+ virtual void multimesh_initialize(RID p_multimesh) override;
+ virtual void multimesh_free(RID p_rid) override;
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
+
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
+
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
+
+ void _update_dirty_multimeshes();
+
+ _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->xform_format;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_colors;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_custom_data;
+ }
+
+ _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh->visible_instances >= 0) {
+ return multimesh->visible_instances;
+ }
+ return multimesh->instances;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (!multimesh->uniform_set_3d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_3d;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (!multimesh->uniform_set_2d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_2d;
+ }
+
+ /* SKELETON API */
+
+ Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
+ bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+
+ virtual RID skeleton_allocate() override;
+ virtual void skeleton_initialize(RID p_skeleton) override;
+ virtual void skeleton_free(RID p_rid) override;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
+ void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
+
+ virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override;
+
+ void _update_dirty_skeletons();
+
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.get_or_null(p_skeleton) != nullptr;
+ }
+
+ _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, RID());
+ ERR_FAIL_COND_V(skeleton->size == 0, RID());
+ if (skeleton->use_2d) {
+ return RID();
+ }
+ if (!skeleton->uniform_set_3d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(skeleton->buffer);
+ uniforms.push_back(u);
+ skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return skeleton->uniform_set_3d;
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index f1a5383295..a3ca7d3720 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -949,7 +949,7 @@ void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
}
String TextureStorage::texture_get_path(RID p_texture) const {
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, String());
return tex->path;
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
index 5843b9db24..84529ca400 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
@@ -36,7 +36,7 @@ void UniformSetCacheRD::_invalidate(Cache *p_cache) {
if (p_cache->prev) {
p_cache->prev->next = p_cache->next;
} else {
- // At begining of table
+ // At beginning of table
uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
hash_table[table_idx] = p_cache->next;
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 0d5b98f1cb..1304c811f7 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -464,10 +464,10 @@ void RendererSceneCull::instance_initialize(RID p_rid) {
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
- bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());
+ bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());
if (needs_instance != p_instance->mesh_instance.is_valid()) {
if (needs_instance) {
- p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base);
+ p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);
} else {
RSG::storage->free(p_instance->mesh_instance);
@@ -488,7 +488,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
}
if (p_instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
}
}
@@ -890,7 +890,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
+ RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
}
@@ -900,7 +900,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i
if (instance->base_type == RS::INSTANCE_MESH) {
//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case
- instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base)));
+ instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base)));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -997,7 +997,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
if (p_skeleton.is_valid()) {
//update the dependency now, so if cleared, we remove it
- RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
+ RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -1438,7 +1438,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
E->get().value = p_value;
if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
//update directly
- RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
+ RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value);
}
}
}
@@ -1847,7 +1847,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+ new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
}
} break;
@@ -1856,7 +1856,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
+ new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base);
}
} break;
@@ -2271,14 +2271,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2348,14 +2348,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
animated_material_found = true;
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2412,13 +2412,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
shadow_data.light = light->instance;
@@ -3037,9 +3037,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (scene_cull_result.mesh_instances.size()) {
for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
+ RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
}
}
@@ -3627,9 +3627,9 @@ void RendererSceneCull::render_particle_colliders() {
}
void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
- List<RendererStorage::InstanceShaderParam> plist;
- RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
- for (const RendererStorage::InstanceShaderParam &E : plist) {
+ List<RendererMaterialStorage::InstanceShaderParam> plist;
+ RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist);
+ for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
StringName name = E.info.name;
if (isparams.has(name)) {
if (isparams[name].info.type != E.info.type) {
@@ -3667,17 +3667,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_override.is_valid()) {
- RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
}
if (p_instance->material_overlay.is_valid()) {
- RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
}
if (p_instance->base_type == RS::INSTANCE_MESH) {
//remove materials no longer used and un-own them
- int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base);
+ int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base);
p_instance->materials.resize(new_mat_count);
_instance_update_mesh_instance(p_instance);
@@ -3688,7 +3688,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
RID particle_material = RSG::storage->particles_get_process_material(p_instance->base);
if (particle_material.is_valid()) {
- RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
}
}
@@ -3704,10 +3704,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_override.is_valid()) {
- if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
+ if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) {
can_cast_shadows = false;
}
- is_animated = RSG::storage->material_is_animated(p_instance->material_override);
+ is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
} else {
if (p_instance->base_type == RS::INSTANCE_MESH) {
@@ -3717,22 +3717,22 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
bool cast_shadows = false;
for (int i = 0; i < p_instance->materials.size(); i++) {
- RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
+ RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_storage->material_is_animated(mat)) {
is_animated = true;
}
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3742,28 +3742,28 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
- RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
+ RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base);
if (mesh.is_valid()) {
bool cast_shadows = false;
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int i = 0; i < sc; i++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_storage->material_is_animated(mat)) {
is_animated = true;
}
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3784,24 +3784,24 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
continue;
}
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int j = 0; j < sc; j++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_storage->material_is_animated(mat)) {
is_animated = true;
}
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
}
@@ -3813,8 +3813,8 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_overlay.is_valid()) {
- can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
- is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
+ can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
+ is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
}
@@ -3834,16 +3834,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
if (p_instance->instance_allocated_shader_parameters) {
- p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
+ p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self);
scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
if (E.value.value.get_type() != Variant::NIL) {
- RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+ RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
- RSG::storage->global_variables_instance_free(p_instance->self);
+ RSG::material_storage->global_variables_instance_free(p_instance->self);
p_instance->instance_allocated_shader_parameters_offset = -1;
scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
}
@@ -3851,7 +3851,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->skeleton.is_valid()) {
- RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
+ RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
}
p_instance->dependency_tracker.update_end();
@@ -3939,7 +3939,7 @@ bool RendererSceneCull::free(RID p_rid) {
if (instance->instance_allocated_shader_parameters) {
//free the used shader parameters
- RSG::storage->global_variables_instance_free(instance->self);
+ RSG::material_storage->global_variables_instance_free(instance->self);
}
update_dirty_instances(); //in case something changed this
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 2112118673..5f71250ced 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -47,7 +47,7 @@
class RendererSceneCull : public RendererScene {
public:
- RendererSceneRender *scene_render;
+ RendererSceneRender *scene_render = nullptr;
enum {
SDFGI_MAX_CASCADES = 8,
@@ -115,7 +115,7 @@ public:
/* VISIBILITY NOTIFIER API */
- RendererSceneOcclusionCull *dummy_occlusion_culling;
+ RendererSceneOcclusionCull *dummy_occlusion_culling = nullptr;
/* SCENARIO API */
@@ -273,7 +273,7 @@ public:
union {
uint64_t instance_data_rid;
RendererSceneRender::GeometryInstance *instance_geometry;
- InstanceVisibilityNotifierData *visibility_notifier;
+ InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
int32_t parent_array_index = -1;
@@ -365,8 +365,8 @@ public:
/* INSTANCING API */
struct InstancePair {
- Instance *a;
- Instance *b;
+ Instance *a = nullptr;
+ Instance *b = nullptr;
SelfList<InstancePair> list_a;
SelfList<InstancePair> list_b;
InstancePair() :
@@ -409,7 +409,7 @@ public:
bool dynamic_gi : 2; //same above for dynamic objects
bool redraw_if_visible : 4;
- Instance *lightmap;
+ Instance *lightmap = nullptr;
Rect2 lightmap_uv_scale;
int lightmap_slice_index;
uint32_t lightmap_cull_index;
@@ -455,7 +455,7 @@ public:
SelfList<Instance> update_item;
- AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
+ AABB *custom_aabb = nullptr; // <Zylann> would using aabb directly with a bool be better?
float extra_margin;
ObjectID object_id;
@@ -465,7 +465,7 @@ public:
uint64_t version; // changes to this, and changes to base increase version
- InstanceBaseData *base_data;
+ InstanceBaseData *base_data = nullptr;
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
@@ -597,7 +597,7 @@ public:
};
struct InstanceReflectionProbeData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
Set<Instance *> geometries;
@@ -613,7 +613,7 @@ public:
};
struct InstanceDecalData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
RID instance;
Set<Instance *> geometries;
@@ -656,7 +656,7 @@ public:
Set<Instance *> geometries;
- Instance *baked_light;
+ Instance *baked_light = nullptr;
RS::LightBakeMode bake_mode;
uint32_t max_sdfgi_cascade = 2;
@@ -671,7 +671,7 @@ public:
};
struct InstanceVoxelGIData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
Set<Instance *> geometries;
Set<Instance *> dynamic_geometries;
@@ -1023,7 +1023,7 @@ public:
struct VisibilityCullData {
uint64_t viewport_mask;
- Scenario *scenario;
+ Scenario *scenario = nullptr;
Vector3 camera_position;
uint32_t cull_offset;
uint32_t cull_count;
@@ -1035,12 +1035,12 @@ public:
_FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
struct CullData {
- Cull *cull;
- Scenario *scenario;
+ Cull *cull = nullptr;
+ Scenario *scenario = nullptr;
RID shadow_atlas;
Transform3D cam_transform;
uint32_t visible_layers;
- Instance *render_reflection_probe;
+ Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
const CameraMatrix *camera_matrix;
uint64_t visibility_viewport_mask;
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 5f9c4bb816..0b8734e68c 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -223,7 +223,7 @@ public:
struct RenderSDFGIUpdateData {
bool update_static = false;
uint32_t static_cascade_count;
- uint32_t *static_cascade_indices;
+ uint32_t *static_cascade_indices = nullptr;
PagedArray<RID> *static_positional_lights;
const Vector<RID> *directional_lights;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 69659aa62c..7bbd414465 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -65,7 +65,6 @@ public:
Map<DependencyTracker *, uint32_t> instances;
};
-public:
struct DependencyTracker {
void *userdata = nullptr;
typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
@@ -120,135 +119,6 @@ public:
Set<Dependency *> dependencies;
};
- /* SHADER API */
-
- virtual RID shader_allocate() = 0;
- virtual void shader_initialize(RID p_rid) = 0;
-
- virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
- virtual String shader_get_code(RID p_shader) const = 0;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
- virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
-
- virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
-
- /* COMMON MATERIAL API */
-
- virtual RID material_allocate() = 0;
- virtual void material_initialize(RID p_rid) = 0;
-
- virtual void material_set_render_priority(RID p_material, int priority) = 0;
- virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
-
- virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
- virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
-
- virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0;
-
- virtual bool material_is_animated(RID p_material) = 0;
- virtual bool material_casts_shadows(RID p_material) = 0;
-
- struct InstanceShaderParam {
- PropertyInfo info;
- int index;
- Variant default_value;
- };
-
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
-
- virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
-
- /* MESH API */
-
- virtual RID mesh_allocate() = 0;
- virtual void mesh_initialize(RID p_rid) = 0;
-
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
-
- /// Returns stride
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0;
-
- virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
-
- virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
- virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
-
- virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
-
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
-
- virtual int mesh_get_surface_count(RID p_mesh) const = 0;
-
- virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
-
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
-
- virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
-
- virtual void mesh_clear(RID p_mesh) = 0;
-
- virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
-
- /* MESH INSTANCE */
-
- virtual RID mesh_instance_create(RID p_base) = 0;
- virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
- virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
- virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
- virtual void update_mesh_instances() = 0;
-
- /* MULTIMESH API */
-
- virtual RID multimesh_allocate() = 0;
- virtual void multimesh_initialize(RID p_rid) = 0;
-
- virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
-
- virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
-
- virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
- virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
- virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
- virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
- virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
-
- virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
-
- virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
- virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
- virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
- virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
-
- virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0;
- virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
-
- virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
- virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
-
- virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
-
- /* SKELETON API */
-
- virtual RID skeleton_allocate() = 0;
- virtual void skeleton_initialize(RID p_rid) = 0;
-
- virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
- virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
- virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
- virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
- virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
- virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
- virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
-
/* Light API */
virtual RID directional_light_allocate() = 0;
@@ -324,7 +194,6 @@ public:
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
- virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* VOXEL GI API */
@@ -491,24 +360,6 @@ public:
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
- /* GLOBAL VARIABLES */
-
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
-
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
-
- virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
- virtual void global_variables_clear() = 0;
-
- virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
- virtual void global_variables_instance_free(RID p_instance) = 0;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
-
/* RENDER TARGET */
enum RenderTargetFlags {
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 2245d9a216..b6e44e8436 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -129,7 +129,7 @@ public:
};
struct CanvasData {
- CanvasBase *canvas;
+ CanvasBase *canvas = nullptr;
Transform2D transform;
int layer;
int sublayer;
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 6ed4448638..1902b5f74a 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -528,6 +528,7 @@ public:
/*********************/
struct AttachmentFormat {
+ enum { UNUSED_ATTACHMENT = 0xFFFFFFFF };
DataFormat format;
TextureSamples samples;
uint32_t usage_flags;
@@ -729,7 +730,7 @@ public:
int binding; // Binding index as specified in shader.
private:
- // In most cases only one ID is provided per binding, so avoid allocating memory unnecesarily for performance.
+ // In most cases only one ID is provided per binding, so avoid allocating memory unnecessarily for performance.
RID id; // If only one is provided, this is used.
Vector<RID> ids; // If multiple ones are provided, this is used instead.
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index d5a55c28f5..2dab7cb84c 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -400,6 +400,8 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RSG::rasterizer = RendererCompositor::create();
RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage();
RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage();
+ RSG::material_storage = RSG::rasterizer->get_material_storage();
+ RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
RSG::texture_storage = RSG::rasterizer->get_texture_storage();
RSG::storage = RSG::rasterizer->get_storage();
RSG::canvas_render = RSG::rasterizer->get_canvas();
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index ea8e8aa056..cc1edc728a 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -213,14 +213,13 @@ public:
FUNC2(texture_set_force_redraw_if_visible, RID, bool)
-//from now on, calls forwarded to this singleton
+ /* SHADER API */
+
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
-
- /* SHADER API */
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
FUNCRIDSPLIT(shader)
@@ -249,8 +248,15 @@ public:
/* MESH API */
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererMeshStorage
+#define server_name RSG::mesh_storage
+
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
- RID mesh = RSG::storage->mesh_allocate();
+ RID mesh = RSG::mesh_storage->mesh_allocate();
// TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!!
@@ -258,16 +264,16 @@ public:
if (Thread::get_caller_id() == server_thread) {
command_queue.flush_if_pending();
}
- RSG::storage->mesh_initialize(mesh);
- RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
+ RSG::mesh_storage->mesh_initialize(mesh);
+ RSG::mesh_storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+ RSG::mesh_storage->mesh_add_surface(mesh, p_surfaces[i]);
}
} else {
- command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh);
- command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_initialize, mesh);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_add_surface, mesh, p_surfaces[i]);
}
}
@@ -342,6 +348,11 @@ public:
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
/* Light API */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
FUNCRIDSPLIT(directional_light)
FUNCRIDSPLIT(omni_light)
@@ -870,8 +881,8 @@ public:
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
FUNC1(global_variable_remove, const StringName &)
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index fb93ae7383..2be87c27b1 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -34,6 +34,8 @@ bool RenderingServerGlobals::threaded = false;
RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr;
+RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
+RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
RendererStorage *RenderingServerGlobals::storage = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 7d00318d8f..40fd638425 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -36,6 +36,8 @@
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/storage/canvas_texture_storage.h"
#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/texture_storage.h"
class RendererCanvasCull;
@@ -47,6 +49,8 @@ public:
static bool threaded;
static RendererCanvasTextureStorage *canvas_texture_storage;
+ static RendererMaterialStorage *material_storage;
+ static RendererMeshStorage *mesh_storage;
static RendererTextureStorage *texture_storage;
static RendererDecalAtlasStorage *decal_atlas_storage;
static RendererStorage *storage;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index a6f3a48398..a0769ef106 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -2813,7 +2813,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool error = false;
if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
- const VariableNode *vn = (VariableNode *)p_func->arguments[arg];
+ const VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg]);
bool is_const = false;
ConstantNode::Value value;
@@ -2825,7 +2825,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
} else {
if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
- ConstantNode *cn = (ConstantNode *)p_func->arguments[arg];
+ const ConstantNode *cn = static_cast<ConstantNode *>(p_func->arguments[arg]);
if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
int value = cn->values[0].sint;
@@ -4132,7 +4132,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
- OperatorNode *op_node = (OperatorNode *)p_node;
+ const OperatorNode *op_node = static_cast<const OperatorNode *>(p_node);
for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) {
if (!_check_node_constness(op_node->arguments[i])) {
return false;
@@ -4142,13 +4142,13 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
case Node::TYPE_CONSTANT:
break;
case Node::TYPE_VARIABLE: {
- VariableNode *varn = (VariableNode *)p_node;
+ const VariableNode *varn = static_cast<const VariableNode *>(p_node);
if (!varn->is_const) {
return false;
}
} break;
case Node::TYPE_ARRAY: {
- ArrayNode *arrn = (ArrayNode *)p_node;
+ const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node);
if (!arrn->is_const) {
return false;
}
@@ -5134,9 +5134,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5153,7 +5157,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
+ ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
@@ -5287,9 +5291,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!expr->is_indexed() && expr->get_array_size() > 0) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5587,9 +5595,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->assign_expression = assign_expression;
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5607,7 +5619,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
+ ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
@@ -6690,7 +6702,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected a constant expression."));
return ERR_PARSE_ERROR;
}
@@ -6746,8 +6758,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- OperatorNode *op = ((OperatorNode *)n);
+ if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
+ OperatorNode *op = static_cast<OperatorNode *>(n);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
_set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
@@ -6791,7 +6803,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
} while (tk.type == TK_COMMA); //another variable
- p_block->statements.push_back((Node *)vdnode);
+ p_block->statements.push_back(static_cast<Node *>(vdnode));
} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
//a sub block, just because..
BlockNode *block = alloc_node<BlockNode>();
@@ -6913,7 +6925,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else {
Set<int> constants;
for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates.
- ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]);
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
@@ -8455,7 +8467,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected constant expression."));
return ERR_PARSE_ERROR;
}
@@ -8511,8 +8523,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (!expr) {
return ERR_PARSE_ERROR;
}
- if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) {
- OperatorNode *op = ((OperatorNode *)expr);
+ if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) {
+ OperatorNode *op = static_cast<OperatorNode *>(expr);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
_set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
@@ -8849,7 +8861,7 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
- BlockNode *last_block = (BlockNode *)p_flow->blocks[i];
+ BlockNode *last_block = static_cast<BlockNode *>(p_flow->blocks[i]);
if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
found = true;
break;
@@ -8867,7 +8879,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
- ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]);
if (flow->flow_op == p_op) {
found = true;
break;
@@ -8878,7 +8890,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
}
}
} else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
- BlockNode *block = (BlockNode *)p_block->statements[i];
+ BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]);
if (_find_last_flow_op_in_block(block, p_op) == OK) {
found = true;
break;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index e5ac14a7db..25ec8760af 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -386,7 +386,7 @@ public:
return node;
}
- Node *nodes;
+ Node *nodes = nullptr;
struct OperatorNode : public Node {
DataType return_cache = TYPE_VOID;
@@ -615,20 +615,20 @@ public:
DataType type;
StringName type_str;
DataPrecision precision;
- ConstantNode *initializer;
+ ConstantNode *initializer = nullptr;
int array_size;
};
struct Function {
StringName name;
- FunctionNode *function;
+ FunctionNode *function = nullptr;
Set<StringName> uses_function;
bool callable;
};
struct Struct {
StringName name;
- StructNode *shader_struct;
+ StructNode *shader_struct = nullptr;
};
struct Varying {
@@ -715,7 +715,7 @@ public:
bool is_op;
union {
Operator op;
- Node *node;
+ Node *node = nullptr;
};
};
@@ -973,7 +973,7 @@ private:
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
Token _get_token();
- ShaderNode *shader;
+ ShaderNode *shader = nullptr;
enum IdentifierType {
IDENTIFIER_FUNCTION,
@@ -1021,7 +1021,7 @@ private:
CompletionType completion_type;
int completion_line;
- BlockNode *completion_block;
+ BlockNode *completion_block = nullptr;
DataType completion_base;
bool completion_base_array;
SubClassTag completion_class;
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
new file mode 100644
index 0000000000..f0363f129a
--- /dev/null
+++ b/servers/rendering/storage/material_storage.h
@@ -0,0 +1,101 @@
+/*************************************************************************/
+/* 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_H
+#define MATERIAL_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMaterialStorage {
+public:
+ virtual ~RendererMaterialStorage(){};
+
+ /* GLOBAL VARIABLE API */
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
+ virtual void global_variable_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_variable_get_list() const = 0;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual Variant global_variable_get(const StringName &p_name) const = 0;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
+ virtual void global_variables_clear() = 0;
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
+ virtual void global_variables_instance_free(RID p_instance) = 0;
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+
+ /* SHADER API */
+ virtual RID shader_allocate() = 0;
+ virtual void shader_initialize(RID p_rid) = 0;
+ virtual void shader_free(RID p_rid) = 0;
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+ virtual String shader_get_code(RID p_shader) const = 0;
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
+ virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
+
+ /* MATERIAL API */
+
+ virtual RID material_allocate() = 0;
+ virtual void material_initialize(RID p_rid) = 0;
+ virtual void material_free(RID p_rid) = 0;
+
+ virtual void material_set_render_priority(RID p_material, int priority) = 0;
+ virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
+
+ virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
+ virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
+
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0;
+
+ virtual bool material_is_animated(RID p_material) = 0;
+ virtual bool material_casts_shadows(RID p_material) = 0;
+
+ struct InstanceShaderParam {
+ PropertyInfo info;
+ int index;
+ Variant default_value;
+ };
+
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
+
+ virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
new file mode 100644
index 0000000000..1dac51319c
--- /dev/null
+++ b/servers/rendering/storage/mesh_storage.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* mesh_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 MESH_STORAGE_H
+#define MESH_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMeshStorage {
+public:
+ virtual ~RendererMeshStorage() {}
+
+ /* MESH API */
+
+ virtual RID mesh_allocate() = 0;
+ virtual void mesh_initialize(RID p_rid) = 0;
+ virtual void mesh_free(RID p_rid) = 0;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
+
+ /// Returns stride
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
+
+ virtual int mesh_get_surface_count(RID p_mesh) const = 0;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
+
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
+
+ virtual void mesh_clear(RID p_mesh) = 0;
+
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
+
+ /* MESH INSTANCE */
+
+ virtual RID mesh_instance_create(RID p_base) = 0;
+ virtual void mesh_instance_free(RID p_rid) = 0;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
+ virtual void update_mesh_instances() = 0;
+
+ /* MULTIMESH API */
+
+ virtual RID multimesh_allocate() = 0;
+ virtual void multimesh_initialize(RID p_rid) = 0;
+ virtual void multimesh_free(RID p_rid) = 0;
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+
+ virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
+
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
+
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() = 0;
+ virtual void skeleton_initialize(RID p_rid) = 0;
+ virtual void skeleton_free(RID p_rid) = 0;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+ virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MESH_STORAGE_H