Rewrite render code to be more cache and thread friendly.

This commit is contained in:
reduz 2021-01-04 09:33:25 -03:00
parent 9a2f18f8e7
commit 5d2a1d7892
12 changed files with 1167 additions and 919 deletions

View file

@ -61,6 +61,8 @@ public:
_ALWAYS_INLINE_ bool is_valid() const { return _id != 0; } _ALWAYS_INLINE_ bool is_valid() const { return _id != 0; }
_ALWAYS_INLINE_ bool is_null() const { return _id == 0; } _ALWAYS_INLINE_ bool is_null() const { return _id == 0; }
_ALWAYS_INLINE_ uint32_t get_local_index() const { return _id & 0xFFFFFFFF; }
static _ALWAYS_INLINE_ RID from_uint64(uint64_t p_id) { static _ALWAYS_INLINE_ RID from_uint64(uint64_t p_id) {
RID _rid; RID _rid;
_rid._id = p_id; _rid._id = p_id;

File diff suppressed because it is too large Load diff

View file

@ -48,7 +48,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
enum { enum {
SDFGI_MAX_CASCADES = 8, SDFGI_MAX_CASCADES = 8,
MAX_GI_PROBES = 8, MAX_GI_PROBES = 8,
MAX_LIGHTMAPS = 8 MAX_LIGHTMAPS = 8,
MAX_GI_PROBES_PER_INSTANCE = 2,
}; };
/* Scene Shader */ /* Scene Shader */
@ -199,14 +200,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
} }
/* Push Constant */
struct PushConstant {
uint32_t index;
uint32_t pad;
float bake_uv2_offset[2];
};
/* Framebuffer */ /* Framebuffer */
struct RenderBufferDataForward : public RenderBufferData { struct RenderBufferDataForward : public RenderBufferData {
@ -294,16 +287,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_SKELETON = 1 << 19, INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
}; };
struct InstanceData {
float transform[16];
float normal_transform[16];
uint32_t flags;
uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
uint32_t mask;
float lightmap_uv_scale[4];
};
struct SceneState { struct SceneState {
struct UBO { struct UBO {
float projection_matrix[16]; float projection_matrix[16];
@ -398,153 +381,16 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t max_lightmap_captures; uint32_t max_lightmap_captures;
RID lightmap_capture_buffer; RID lightmap_capture_buffer;
RID instance_buffer; RID giprobe_ids[MAX_GI_PROBES];
InstanceData *instances; uint32_t giprobes_used = 0;
uint32_t max_instances;
bool used_screen_texture = false; bool used_screen_texture = false;
bool used_normal_texture = false; bool used_normal_texture = false;
bool used_depth_texture = false; bool used_depth_texture = false;
bool used_sss = false; bool used_sss = false;
uint32_t current_shader_index = 0;
uint32_t current_material_index = 0;
} scene_state; } scene_state;
/* Render List */
struct GeometryInstanceForward;
struct RenderList {
int max_elements;
struct Element {
GeometryInstanceForward *instance;
MaterialData *material;
union {
struct {
//from least significant to most significant in sort, TODO: should be endian swapped on big endian
uint64_t geometry_index : 20;
uint64_t material_index : 15;
uint64_t shader_index : 12;
uint64_t uses_instancing : 1;
uint64_t uses_forward_gi : 1;
uint64_t uses_lightmap : 1;
uint64_t depth_layer : 4;
uint64_t priority : 8;
};
uint64_t sort_key;
};
uint32_t surface_index;
};
Element *base_elements;
Element **elements;
int element_count;
int alpha_element_count;
void clear() {
element_count = 0;
alpha_element_count = 0;
}
//should eventually be replaced by radix
struct SortByKey {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->sort_key < B->sort_key;
}
};
void sort_by_key(bool p_alpha) {
SortArray<Element *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByDepth {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->instance->depth < B->instance->depth;
}
};
void sort_by_depth(bool p_alpha) { //used for shadows
SortArray<Element *, SortByDepth> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByReverseDepthAndPriority {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
uint32_t layer_A = uint32_t(A->priority);
uint32_t layer_B = uint32_t(B->priority);
if (layer_A == layer_B) {
return A->instance->depth > B->instance->depth;
} else {
return layer_A < layer_B;
}
}
};
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
SortArray<Element *, SortByReverseDepthAndPriority> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
_FORCE_INLINE_ Element *add_element() {
if (element_count + alpha_element_count >= max_elements) {
return nullptr;
}
elements[element_count] = &base_elements[element_count];
return elements[element_count++];
}
_FORCE_INLINE_ Element *add_alpha_element() {
if (element_count + alpha_element_count >= max_elements) {
return nullptr;
}
int idx = max_elements - alpha_element_count - 1;
elements[idx] = &base_elements[idx];
alpha_element_count++;
return elements[idx];
}
void init() {
element_count = 0;
alpha_element_count = 0;
elements = memnew_arr(Element *, max_elements);
base_elements = memnew_arr(Element, max_elements);
for (int i = 0; i < max_elements; i++) {
elements[i] = &base_elements[i]; // assign elements
}
}
RenderList() {
max_elements = 0;
}
~RenderList() {
memdelete_arr(elements);
memdelete_arr(base_elements);
}
};
RenderList render_list;
static RendererSceneRenderForward *singleton; static RendererSceneRenderForward *singleton;
uint64_t render_pass; uint64_t render_pass;
double time; double time;
@ -574,54 +420,250 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}; };
void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false); void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
void _setup_giprobes(const PagedArray<RID> &p_giprobes);
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform); void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false); struct GeometryInstanceSurfaceDataCache;
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, 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_lod_threshold = 0.0);
_FORCE_INLINE_ void _add_geometry(GeometryInstanceForward *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
_FORCE_INLINE_ void _add_geometry_with_material(GeometryInstanceForward *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false); template <PassMode p_pass_mode>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, bool p_no_gi, 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_lod_threshold = 0.0);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, 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_lod_threshold = 0.0);
void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false);
Map<Size2i, RID> sdfgi_framebuffer_size_cache; Map<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceForward : public GeometryInstance { struct GeometryInstanceData;
RID base; struct GeometryInstanceForward;
RS::InstanceType base_type;
RID skeleton; struct GeometryInstanceLightmapSH {
RID mesh_instance; Color sh[9];
uint32_t layer_mask = 1;
float depth = 0;
int depth_layer = 0;
RID gi_probe_instances[MAX_GI_PROBES];
uint32_t gi_probe_instance_count = 0;
Vector<RID> surface_materials;
RID material_override;
Transform transform;
AABB aabb;
AABB transformed_aabb;
float lod_bias = 0.0;
int32_t shader_parameters_offset = -1;
bool use_dynamic_gi = false;
bool use_baked_light = false;
bool cast_double_sided_shaodows = false;
bool mirror = false;
RID lightmap_instance;
Rect2 lightmap_uv_scale;
uint32_t lightmap_slice_index = 0;
Color *lightmap_sh = nullptr;
}; };
// Cached data for drawing surfaces
struct GeometryInstanceSurfaceDataCache {
enum {
FLAG_PASS_DEPTH = 1,
FLAG_PASS_OPAQUE = 2,
FLAG_PASS_ALPHA = 4,
FLAG_PASS_SHADOW = 8,
FLAG_USES_SHARED_SHADOW_MATERIAL = 128,
FLAG_USES_SUBSURFACE_SCATTERING = 2048,
FLAG_USES_SCREEN_TEXTURE = 4096,
FLAG_USES_DEPTH_TEXTURE = 8192,
FLAG_USES_NORMAL_TEXTURE = 16384,
FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
};
union {
struct {
uint32_t geometry_id;
uint32_t material_id;
uint32_t shader_id;
uint32_t surface_type : 4;
uint32_t uses_forward_gi : 1; //set during addition
uint32_t uses_lightmap : 1; //set during addition
uint32_t depth_layer : 4; //set during addition
uint32_t priority : 8;
};
struct {
uint64_t sort_key1;
uint64_t sort_key2;
};
} sort;
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
uint32_t flags = 0;
uint32_t surface_index = 0;
void *surface = nullptr;
RID material_uniform_set;
ShaderData *shader = nullptr;
void *surface_shadow = nullptr;
RID material_uniform_set_shadow;
ShaderData *shader_shadow = nullptr;
GeometryInstanceSurfaceDataCache *next = nullptr;
GeometryInstanceForward *owner = nullptr;
};
struct GeometryInstanceForward : public GeometryInstance {
//used during rendering
bool mirror = false;
bool non_uniform_scale = false;
float lod_bias = 0.0;
float lod_model_scale = 1.0;
AABB transformed_aabb; //needed for LOD
float depth = 0;
struct PushConstant {
float transform[16];
uint32_t flags;
uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
uint32_t layer_mask;
float lightmap_uv_scale[4];
} push_constant;
RID transforms_uniform_set;
uint32_t instance_count = 0;
RID mesh_instance;
bool can_sdfgi = false;
//used during setup
uint32_t base_flags = 0;
RID gi_probes[MAX_GI_PROBES_PER_INSTANCE];
RID lightmap_instance;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
SelfList<GeometryInstanceForward> dirty_list_element;
struct Data {
//data used less often goes into regular heap
RID base;
RS::InstanceType base_type;
RID skeleton;
uint32_t layer_mask = 1;
Vector<RID> surface_materials;
RID material_override;
Transform transform;
AABB aabb;
int32_t shader_parameters_offset = -1;
bool use_dynamic_gi = false;
bool use_baked_light = false;
bool cast_double_sided_shaodows = false;
bool mirror = false;
Rect2 lightmap_uv_scale;
uint32_t lightmap_slice_index = 0;
bool dirty_dependencies = false;
RendererStorage::DependencyTracker dependency_tracker;
};
Data *data = nullptr;
GeometryInstanceForward() :
dirty_list_element(this) {}
};
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list;
PagedAllocator<GeometryInstanceForward> geometry_instance_alloc; PagedAllocator<GeometryInstanceForward> geometry_instance_alloc;
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
bool low_end = false; bool low_end = false;
/* Render List */
struct RenderList {
int max_elements;
GeometryInstanceSurfaceDataCache **elements = nullptr;
int element_count;
int alpha_element_count;
void clear() {
element_count = 0;
alpha_element_count = 0;
}
//should eventually be replaced by radix
struct SortByKey {
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);
}
};
void sort_by_key(bool p_alpha) {
SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByDepth {
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
return (A->owner->depth < B->owner->depth);
}
};
void sort_by_depth(bool p_alpha) { //used for shadows
SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByReverseDepthAndPriority {
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);
}
};
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
_FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
return;
}
elements[element_count] = p_element;
element_count++;
}
_FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
return;
}
int idx = max_elements - alpha_element_count - 1;
elements[idx] = p_element;
alpha_element_count++;
}
void init() {
element_count = 0;
alpha_element_count = 0;
elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements);
}
RenderList() {
max_elements = 0;
}
~RenderList() {
memdelete_arr(elements);
}
};
RenderList render_list;
protected: protected:
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold); virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0); virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);

View file

@ -1836,6 +1836,10 @@ public:
virtual RID lightmap_instance_create(RID p_lightmap); virtual RID lightmap_instance_create(RID p_lightmap);
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform); virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform);
_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
}
_FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) { _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance); LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
return li->lightmap; return li->lightmap;

View file

@ -1438,7 +1438,7 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get(); Material *material = E->get();
material->instance_dependency.instance_notify_changed(false, true); material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true); _material_queue_update(material, true, true);
} }
} }
@ -1547,7 +1547,8 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
} }
if (p_shader.is_null()) { if (p_shader.is_null()) {
material->instance_dependency.instance_notify_changed(false, true); material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
material->shader_id = 0;
return; return;
} }
@ -1555,6 +1556,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
ERR_FAIL_COND(!shader); ERR_FAIL_COND(!shader);
material->shader = shader; material->shader = shader;
material->shader_type = shader->type; material->shader_type = shader->type;
material->shader_id = p_shader.get_local_index();
shader->owners.insert(material); shader->owners.insert(material);
if (shader->type == SHADER_TYPE_MAX) { if (shader->type == SHADER_TYPE_MAX) {
@ -1568,7 +1570,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass); material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority); material->data->set_render_priority(material->priority);
//updating happens later //updating happens later
material->instance_dependency.instance_notify_changed(false, true); material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true); _material_queue_update(material, true, true);
} }
@ -1613,7 +1615,7 @@ void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_materi
material->data->set_next_pass(p_next_material); material->data->set_next_pass(p_next_material);
} }
material->instance_dependency.instance_notify_changed(false, true); material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
} }
void RendererStorageRD::material_set_render_priority(RID p_material, int priority) { void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
@ -1663,10 +1665,10 @@ void RendererStorageRD::material_get_instance_shader_parameters(RID p_material,
} }
} }
void RendererStorageRD::material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) { void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.getornull(p_material); Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material); ERR_FAIL_COND(!material);
p_instance->update_dependency(&material->instance_dependency); p_instance->update_dependency(&material->dependency);
if (material->next_pass.is_valid()) { if (material->next_pass.is_valid()) {
material_update_dependency(material->next_pass, p_instance); material_update_dependency(material->next_pass, p_instance);
} }
@ -2596,7 +2598,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
} }
mesh->instance_dependency.instance_notify_changed(true, true); mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
mesh->material_cache.clear(); mesh->material_cache.clear();
} }
@ -2638,7 +2640,7 @@ void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material; mesh->surfaces[p_surface]->material = p_material;
mesh->instance_dependency.instance_notify_changed(false, true); mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear(); mesh->material_cache.clear();
} }
@ -2858,8 +2860,8 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {
MeshInstance *mi = E->get(); MeshInstance *mi = E->get();
_mesh_instance_clear(mi); _mesh_instance_clear(mi);
} }
mesh->instance_dependency.instance_notify_changed(true, true);
mesh->has_bone_weights = false; mesh->has_bone_weights = false;
mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
} }
bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
@ -3298,6 +3300,8 @@ void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS:
if (multimesh->instances) { if (multimesh->instances) {
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); 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 { int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
@ -3331,7 +3335,7 @@ void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
} }
} }
multimesh->instance_dependency.instance_notify_changed(true, true); multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
} }
#define MULTIMESH_DIRTY_REGION_SIZE 512 #define MULTIMESH_DIRTY_REGION_SIZE 512
@ -3690,7 +3694,7 @@ void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float
const float *data = p_buffer.ptr(); const float *data = p_buffer.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances); _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
multimesh->instance_dependency.instance_notify_changed(true, false); multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
} }
@ -3731,6 +3735,8 @@ void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_v
} }
multimesh->visible_instances = p_visible; multimesh->visible_instances = p_visible;
multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
} }
int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
@ -3788,7 +3794,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {
//aabb is dirty.. //aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances); _multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false; multimesh->aabb_dirty = false;
multimesh->instance_dependency.instance_notify_changed(true, false); multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
} }
@ -3926,7 +3932,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p
Particles *particles = particles_owner.getornull(p_particles); Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles); ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb; particles->custom_aabb = p_aabb;
particles->instance_dependency.instance_notify_changed(true, false); particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) { void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) {
@ -4687,7 +4693,7 @@ void RendererStorageRD::update_particles() {
RD::get_singleton()->compute_list_end(); RD::get_singleton()->compute_list_end();
} }
particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
} }
@ -4986,7 +4992,7 @@ void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_c
particles_collision->heightfield_texture = RID(); particles_collision->heightfield_texture = RID();
} }
particles_collision->type = p_type; particles_collision->type = p_type;
particles_collision->instance_dependency.instance_notify_changed(true, false); particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
@ -5000,7 +5006,7 @@ void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_co
ERR_FAIL_COND(!particles_collision); ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius; particles_collision->radius = p_radius;
particles_collision->instance_dependency.instance_notify_changed(true, false); particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
@ -5008,7 +5014,7 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll
ERR_FAIL_COND(!particles_collision); ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents; particles_collision->extents = p_extents;
particles_collision->instance_dependency.instance_notify_changed(true, false); particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) { void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) {
@ -5042,7 +5048,7 @@ void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_co
void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) { void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision); ERR_FAIL_COND(!particles_collision);
particles_collision->instance_dependency.instance_notify_changed(true, false); particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
@ -5165,6 +5171,8 @@ void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d
skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); 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 { int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
@ -5285,7 +5293,8 @@ void RendererStorageRD::_update_dirty_skeletons() {
skeleton_dirty_list = skeleton->dirty_list; skeleton_dirty_list = skeleton->dirty_list;
skeleton->instance_dependency.instance_notify_changed(true, false); skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
skeleton->version++; skeleton->version++;
skeleton->dirty = false; skeleton->dirty = false;
@ -5347,7 +5356,7 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE: case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: { case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} break; } break;
default: { default: {
} }
@ -5362,7 +5371,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled; light->shadow = p_enabled;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
@ -5404,7 +5413,7 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask; light->cull_mask = p_mask;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
@ -5414,7 +5423,7 @@ void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_ena
light->reverse_cull = p_enabled; light->reverse_cull = p_enabled;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@ -5424,7 +5433,7 @@ void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bak
light->bake_mode = p_bake_mode; light->bake_mode = p_bake_mode;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
@ -5434,7 +5443,7 @@ void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_casc
light->max_sdfgi_cascade = p_cascade; light->max_sdfgi_cascade = p_cascade;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@ -5444,7 +5453,7 @@ void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniSha
light->omni_shadow_mode = p_mode; light->omni_shadow_mode = p_mode;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) { RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
@ -5460,7 +5469,7 @@ void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Light
light->directional_shadow_mode = p_mode; light->directional_shadow_mode = p_mode;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@ -5469,7 +5478,7 @@ void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_e
light->directional_blend_splits = p_enable; light->directional_blend_splits = p_enable;
light->version++; light->version++;
light->instance_dependency.instance_notify_changed(true, false); light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} }
bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const { bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
@ -5568,7 +5577,7 @@ void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Reflec
ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode; reflection_probe->update_mode = p_mode;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
@ -5605,7 +5614,7 @@ void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_d
reflection_probe->max_distance = p_distance; reflection_probe->max_distance = p_distance;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
@ -5616,7 +5625,7 @@ void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3
return; return;
} }
reflection_probe->extents = p_extents; reflection_probe->extents = p_extents;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
@ -5624,7 +5633,7 @@ void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Ve
ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset; reflection_probe->origin_offset = p_offset;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
@ -5632,7 +5641,7 @@ void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_ena
ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable; reflection_probe->interior = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@ -5647,7 +5656,7 @@ void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_
ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable; reflection_probe->enable_shadows = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
@ -5655,7 +5664,7 @@ void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_l
ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers; reflection_probe->cull_mask = p_layers;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
@ -5672,7 +5681,7 @@ void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_
reflection_probe->lod_threshold = p_ratio; reflection_probe->lod_threshold = p_ratio;
reflection_probe->instance_dependency.instance_notify_changed(true, false); reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
} }
AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const { AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
@ -5790,7 +5799,7 @@ void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents)
Decal *decal = decal_owner.getornull(p_decal); Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal); ERR_FAIL_COND(!decal);
decal->extents = p_extents; decal->extents = p_extents;
decal->instance_dependency.instance_notify_changed(true, false); decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
@ -5814,7 +5823,7 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type,
texture_add_to_decal_atlas(decal->textures[p_type]); texture_add_to_decal_atlas(decal->textures[p_type]);
} }
decal->instance_dependency.instance_notify_changed(false, true); decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL);
} }
void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) { void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
@ -5839,7 +5848,7 @@ void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.getornull(p_decal); Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal); ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers; decal->cull_mask = p_layers;
decal->instance_dependency.instance_notify_changed(true, false); decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
@ -5996,7 +6005,7 @@ void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_
gi_probe->version++; gi_probe->version++;
gi_probe->data_version++; gi_probe->data_version++;
gi_probe->instance_dependency.instance_notify_changed(true, false); gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
} }
AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const {
@ -7074,45 +7083,45 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta
rt->backbuffer_uniform_set = p_uniform_set; rt->backbuffer_uniform_set = p_uniform_set;
} }
void RendererStorageRD::base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) { void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (mesh_owner.owns(p_base)) { if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base); Mesh *mesh = mesh_owner.getornull(p_base);
p_instance->update_dependency(&mesh->instance_dependency); p_instance->update_dependency(&mesh->dependency);
} else if (multimesh_owner.owns(p_base)) { } else if (multimesh_owner.owns(p_base)) {
MultiMesh *multimesh = multimesh_owner.getornull(p_base); MultiMesh *multimesh = multimesh_owner.getornull(p_base);
p_instance->update_dependency(&multimesh->instance_dependency); p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) { if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance); base_update_dependency(multimesh->mesh, p_instance);
} }
} else if (reflection_probe_owner.owns(p_base)) { } else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
p_instance->update_dependency(&rp->instance_dependency); p_instance->update_dependency(&rp->dependency);
} else if (decal_owner.owns(p_base)) { } else if (decal_owner.owns(p_base)) {
Decal *decal = decal_owner.getornull(p_base); Decal *decal = decal_owner.getornull(p_base);
p_instance->update_dependency(&decal->instance_dependency); p_instance->update_dependency(&decal->dependency);
} else if (gi_probe_owner.owns(p_base)) { } else if (gi_probe_owner.owns(p_base)) {
GIProbe *gip = gi_probe_owner.getornull(p_base); GIProbe *gip = gi_probe_owner.getornull(p_base);
p_instance->update_dependency(&gip->instance_dependency); p_instance->update_dependency(&gip->dependency);
} else if (lightmap_owner.owns(p_base)) { } else if (lightmap_owner.owns(p_base)) {
Lightmap *lm = lightmap_owner.getornull(p_base); Lightmap *lm = lightmap_owner.getornull(p_base);
p_instance->update_dependency(&lm->instance_dependency); p_instance->update_dependency(&lm->dependency);
} else if (light_owner.owns(p_base)) { } else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base); Light *l = light_owner.getornull(p_base);
p_instance->update_dependency(&l->instance_dependency); p_instance->update_dependency(&l->dependency);
} else if (particles_owner.owns(p_base)) { } else if (particles_owner.owns(p_base)) {
Particles *p = particles_owner.getornull(p_base); Particles *p = particles_owner.getornull(p_base);
p_instance->update_dependency(&p->instance_dependency); p_instance->update_dependency(&p->dependency);
} else if (particles_collision_owner.owns(p_base)) { } else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.getornull(p_base); ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
p_instance->update_dependency(&pc->instance_dependency); p_instance->update_dependency(&pc->dependency);
} }
} }
void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance) { void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton); ERR_FAIL_COND(!skeleton);
p_instance->update_dependency(&skeleton->instance_dependency); p_instance->update_dependency(&skeleton->dependency);
} }
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
@ -8133,12 +8142,13 @@ bool RendererStorageRD::free(RID p_rid) {
_update_queued_materials(); _update_queued_materials();
} }
material_set_shader(p_rid, RID()); //clean up shader material_set_shader(p_rid, RID()); //clean up shader
material->instance_dependency.instance_notify_deleted(p_rid); material->dependency.deleted_notify(p_rid);
material_owner.free(p_rid); material_owner.free(p_rid);
} else if (mesh_owner.owns(p_rid)) { } else if (mesh_owner.owns(p_rid)) {
mesh_clear(p_rid); mesh_clear(p_rid);
Mesh *mesh = mesh_owner.getornull(p_rid); Mesh *mesh = mesh_owner.getornull(p_rid);
mesh->instance_dependency.instance_notify_deleted(p_rid); mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) { if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances"); ERR_PRINT("deleting mesh with active instances");
} }
@ -8155,17 +8165,17 @@ bool RendererStorageRD::free(RID p_rid) {
_update_dirty_multimeshes(); _update_dirty_multimeshes();
multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.getornull(p_rid); MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
multimesh->instance_dependency.instance_notify_deleted(p_rid); multimesh->dependency.deleted_notify(p_rid);
multimesh_owner.free(p_rid); multimesh_owner.free(p_rid);
} else if (skeleton_owner.owns(p_rid)) { } else if (skeleton_owner.owns(p_rid)) {
_update_dirty_skeletons(); _update_dirty_skeletons();
skeleton_allocate(p_rid, 0); skeleton_allocate(p_rid, 0);
Skeleton *skeleton = skeleton_owner.getornull(p_rid); Skeleton *skeleton = skeleton_owner.getornull(p_rid);
skeleton->instance_dependency.instance_notify_deleted(p_rid); skeleton->dependency.deleted_notify(p_rid);
skeleton_owner.free(p_rid); skeleton_owner.free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) { } else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
reflection_probe->instance_dependency.instance_notify_deleted(p_rid); reflection_probe->dependency.deleted_notify(p_rid);
reflection_probe_owner.free(p_rid); reflection_probe_owner.free(p_rid);
} else if (decal_owner.owns(p_rid)) { } else if (decal_owner.owns(p_rid)) {
Decal *decal = decal_owner.getornull(p_rid); Decal *decal = decal_owner.getornull(p_rid);
@ -8174,30 +8184,30 @@ bool RendererStorageRD::free(RID p_rid) {
texture_remove_from_decal_atlas(decal->textures[i]); texture_remove_from_decal_atlas(decal->textures[i]);
} }
} }
decal->instance_dependency.instance_notify_deleted(p_rid); decal->dependency.deleted_notify(p_rid);
decal_owner.free(p_rid); decal_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) { } else if (gi_probe_owner.owns(p_rid)) {
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
gi_probe->instance_dependency.instance_notify_deleted(p_rid); gi_probe->dependency.deleted_notify(p_rid);
gi_probe_owner.free(p_rid); gi_probe_owner.free(p_rid);
} else if (lightmap_owner.owns(p_rid)) { } else if (lightmap_owner.owns(p_rid)) {
lightmap_set_textures(p_rid, RID(), false); lightmap_set_textures(p_rid, RID(), false);
Lightmap *lightmap = lightmap_owner.getornull(p_rid); Lightmap *lightmap = lightmap_owner.getornull(p_rid);
lightmap->instance_dependency.instance_notify_deleted(p_rid); lightmap->dependency.deleted_notify(p_rid);
lightmap_owner.free(p_rid); lightmap_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) { } else if (light_owner.owns(p_rid)) {
light_set_projector(p_rid, RID()); //clear projector light_set_projector(p_rid, RID()); //clear projector
// delete the texture // delete the texture
Light *light = light_owner.getornull(p_rid); Light *light = light_owner.getornull(p_rid);
light->instance_dependency.instance_notify_deleted(p_rid); light->dependency.deleted_notify(p_rid);
light_owner.free(p_rid); light_owner.free(p_rid);
} else if (particles_owner.owns(p_rid)) { } else if (particles_owner.owns(p_rid)) {
Particles *particles = particles_owner.getornull(p_rid); Particles *particles = particles_owner.getornull(p_rid);
_particles_free_data(particles); _particles_free_data(particles);
particles->instance_dependency.instance_notify_deleted(p_rid); particles->dependency.deleted_notify(p_rid);
particles_owner.free(p_rid); particles_owner.free(p_rid);
} else if (particles_collision_owner.owns(p_rid)) { } else if (particles_collision_owner.owns(p_rid)) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid); ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid);
@ -8205,7 +8215,7 @@ bool RendererStorageRD::free(RID p_rid) {
if (particles_collision->heightfield_texture.is_valid()) { if (particles_collision->heightfield_texture.is_valid()) {
RD::get_singleton()->free(particles_collision->heightfield_texture); RD::get_singleton()->free(particles_collision->heightfield_texture);
} }
particles_collision->instance_dependency.instance_notify_deleted(p_rid); particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid); particles_collision_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) { } else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid); particles_collision_instance_owner.free(p_rid);

View file

@ -360,6 +360,7 @@ private:
Shader *shader; Shader *shader;
//shortcut to shader data and type //shortcut to shader data and type
ShaderType shader_type; ShaderType shader_type;
uint32_t shader_id = 0;
bool update_requested; bool update_requested;
bool uniform_dirty; bool uniform_dirty;
bool texture_dirty; bool texture_dirty;
@ -367,7 +368,7 @@ private:
Map<StringName, Variant> params; Map<StringName, Variant> params;
int32_t priority; int32_t priority;
RID next_pass; RID next_pass;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
@ -460,7 +461,7 @@ private:
List<MeshInstance *> instances; List<MeshInstance *> instances;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<Mesh> mesh_owner; mutable RID_Owner<Mesh> mesh_owner;
@ -563,7 +564,7 @@ private:
bool dirty = false; bool dirty = false;
MultiMesh *dirty_list = nullptr; MultiMesh *dirty_list = nullptr;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<MultiMesh> multimesh_owner; mutable RID_Owner<MultiMesh> multimesh_owner;
@ -761,7 +762,7 @@ private:
clear(true) { clear(true) {
} }
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
ParticlesFrameParams frame_params; ParticlesFrameParams frame_params;
}; };
@ -889,7 +890,7 @@ private:
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<ParticlesCollision> particles_collision_owner; mutable RID_Owner<ParticlesCollision> particles_collision_owner;
@ -919,7 +920,7 @@ private:
uint64_t version = 1; uint64_t version = 1;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<Skeleton> skeleton_owner; mutable RID_Owner<Skeleton> skeleton_owner;
@ -951,7 +952,7 @@ private:
bool directional_sky_only = false; bool directional_sky_only = false;
uint64_t version = 0; uint64_t version = 0;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<Light> light_owner; mutable RID_Owner<Light> light_owner;
@ -974,7 +975,7 @@ private:
uint32_t cull_mask = (1 << 20) - 1; uint32_t cull_mask = (1 << 20) - 1;
float lod_threshold = 0.01; float lod_threshold = 0.01;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<ReflectionProbe> reflection_probe_owner; mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
@ -995,7 +996,7 @@ private:
float distance_fade_length = 1; float distance_fade_length = 1;
float normal_fade = 0.0; float normal_fade = 0.0;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
mutable RID_Owner<Decal> decal_owner; mutable RID_Owner<Decal> decal_owner;
@ -1033,7 +1034,7 @@ private:
uint32_t version = 1; uint32_t version = 1;
uint32_t data_version = 1; uint32_t data_version = 1;
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
GiprobeSdfShaderRD giprobe_sdf_shader; GiprobeSdfShaderRD giprobe_sdf_shader;
@ -1062,7 +1063,7 @@ private:
int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
}; };
RendererStorage::InstanceDependency instance_dependency; Dependency dependency;
}; };
bool using_lightmap_array; //high end uses this bool using_lightmap_array; //high end uses this
@ -1355,11 +1356,16 @@ public:
void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance); void material_update_dependency(RID p_material, DependencyTracker *p_instance);
void material_force_update_textures(RID p_material, ShaderType p_shader_type); void material_force_update_textures(RID p_material, ShaderType p_shader_type);
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); 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.getornull(p_material);
return material->shader_id;
}
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material); Material *material = material_owner.getornull(p_material);
if (!material || material->shader_type != p_shader_type) { if (!material || material->shader_type != p_shader_type) {
@ -1672,6 +1678,10 @@ public:
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); 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; 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.getornull(p_skeleton) != nullptr;
}
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, RID()); ERR_FAIL_COND_V(!skeleton, RID());
@ -1835,8 +1845,8 @@ public:
Color reflection_probe_get_ambient_color(RID p_probe) const; Color reflection_probe_get_ambient_color(RID p_probe) const;
float reflection_probe_get_ambient_color_energy(RID p_probe) const; float reflection_probe_get_ambient_color_energy(RID p_probe) const;
void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance); void base_update_dependency(RID p_base, DependencyTracker *p_instance);
void skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance); void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
/* DECAL API */ /* DECAL API */

View file

@ -97,8 +97,6 @@ VERTEX_SHADER_GLOBALS
invariant gl_Position; invariant gl_Position;
layout(location = 7) flat out uint instance_index;
#ifdef MODE_DUAL_PARABOLOID #ifdef MODE_DUAL_PARABOLOID
layout(location = 8) out float dp_clip; layout(location = 8) out float dp_clip;
@ -106,22 +104,27 @@ layout(location = 8) out float dp_clip;
#endif #endif
void main() { void main() {
instance_index = draw_call.instance_index;
vec4 instance_custom = vec4(0.0); vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED) #if defined(COLOR_USED)
color_interp = color_attrib; color_interp = color_attrib;
#endif #endif
mat4 world_matrix = instances.data[instance_index].transform; mat4 world_matrix = draw_call.transform;
mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform);
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { mat3 world_normal_matrix;
if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
world_normal_matrix = inverse(mat3(world_matrix));
} else {
world_normal_matrix = mat3(world_matrix);
}
if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) {
//multimesh, instances are for it //multimesh, instances are for it
uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
offset *= gl_InstanceIndex; offset *= gl_InstanceIndex;
mat4 matrix; mat4 matrix;
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2; offset += 2;
} else { } else {
@ -129,14 +132,14 @@ void main() {
offset += 3; offset += 3;
} }
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
#ifdef COLOR_USED #ifdef COLOR_USED
color_interp *= transforms.data[offset]; color_interp *= transforms.data[offset];
#endif #endif
offset += 1; offset += 1;
} }
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
instance_custom = transforms.data[offset]; instance_custom = transforms.data[offset];
} }
@ -144,10 +147,6 @@ void main() {
matrix = transpose(matrix); matrix = transpose(matrix);
world_matrix = world_matrix * matrix; world_matrix = world_matrix * matrix;
world_normal_matrix = world_normal_matrix * mat3(matrix); world_normal_matrix = world_normal_matrix * mat3(matrix);
} else {
//not a multimesh, instances are for multiple draw calls
instance_index += gl_InstanceIndex;
} }
vec3 vertex = vertex_attrib; vec3 vertex = vertex_attrib;
@ -162,7 +161,7 @@ void main() {
#endif #endif
#if 0 #if 0
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) { if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it //multimesh, instances are for it
uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3; uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3;
@ -305,7 +304,7 @@ VERTEX_SHADER_CODE
#endif #endif
#ifdef MODE_RENDER_MATERIAL #ifdef MODE_RENDER_MATERIAL
if (scene_data.material_uv2_mode) { if (scene_data.material_uv2_mode) {
gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0; gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0;
gl_Position.z = 0.00001; gl_Position.z = 0.00001;
gl_Position.w = 1.0; gl_Position.w = 1.0;
} }
@ -345,8 +344,6 @@ layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp; layout(location = 6) in vec3 binormal_interp;
#endif #endif
layout(location = 7) flat in uint instance_index;
#ifdef MODE_DUAL_PARABOLOID #ifdef MODE_DUAL_PARABOLOID
layout(location = 8) in float dp_clip; layout(location = 8) in float dp_clip;
@ -355,8 +352,7 @@ layout(location = 8) in float dp_clip;
//defines to keep compatibility with vertex //defines to keep compatibility with vertex
#define world_matrix instances.data[instance_index].transform #define world_matrix draw_call.transform
#define world_normal_matrix instances.data[instance_index].normal_transform
#define projection_matrix scene_data.projection_matrix #define projection_matrix scene_data.projection_matrix
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@ -1971,7 +1967,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < decal_count; i++) { for (uint i = 0; i < decal_count; i++) {
uint decal_index = cluster_data.indices[decal_pointer + i]; uint decal_index = cluster_data.indices[decal_pointer + i];
if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) { if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
continue; //not masked continue; //not masked
} }
@ -2102,8 +2098,8 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTMAP #ifdef USE_LIGHTMAP
//lightmap //lightmap
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
uint index = instances.data[instance_index].gi_offset; uint index = draw_call.gi_offset;
vec3 wnormal = mat3(scene_data.camera_matrix) * normal; vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
const float c1 = 0.429043; const float c1 = 0.429043;
@ -2122,12 +2118,12 @@ FRAGMENT_SHADER_CODE
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
uint ofs = instances.data[instance_index].gi_offset & 0xFFF; uint ofs = draw_call.gi_offset & 0xFFFF;
vec3 uvw; vec3 uvw;
uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy; uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF); uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
if (uses_sh) { if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data uvw.z *= 4.0; //SH textures use 4 times more data
@ -2136,7 +2132,7 @@ FRAGMENT_SHADER_CODE
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb; vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
uint idx = instances.data[instance_index].gi_offset >> 20; uint idx = draw_call.gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
ambient_light += lm_light_l0 * 0.282095f; ambient_light += lm_light_l0 * 0.282095f;
@ -2156,7 +2152,7 @@ FRAGMENT_SHADER_CODE
} }
#elif defined(USE_FORWARD_GI) #elif defined(USE_FORWARD_GI)
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
//make vertex orientation the world one, but still align to camera //make vertex orientation the world one, but still align to camera
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
@ -2228,9 +2224,9 @@ FRAGMENT_SHADER_CODE
} }
} }
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; uint index1 = draw_call.gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
//find arbitrary tangent and bitangent, then build a matrix //find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
@ -2242,7 +2238,7 @@ FRAGMENT_SHADER_CODE
vec4 spec_accum = vec4(0.0); vec4 spec_accum = vec4(0.0);
gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
uint index2 = instances.data[instance_index].gi_offset >> 16; uint index2 = draw_call.gi_offset >> 16;
if (index2 != 0xFFFF) { if (index2 != 0xFFFF) {
gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
@ -2261,7 +2257,7 @@ FRAGMENT_SHADER_CODE
} }
#elif !defined(LOW_END_MODE) #elif !defined(LOW_END_MODE)
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
ivec2 coord; ivec2 coord;
@ -2343,7 +2339,7 @@ FRAGMENT_SHADER_CODE
{ //directional light { //directional light
for (uint i = 0; i < scene_data.directional_light_count; i++) { for (uint i = 0; i < scene_data.directional_light_count; i++) {
if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
continue; //not masked continue; //not masked
} }
@ -2613,7 +2609,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < omni_light_count; i++) { for (uint i = 0; i < omni_light_count; i++) {
uint light_index = cluster_data.indices[omni_light_pointer + i]; uint light_index = cluster_data.indices[omni_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {
continue; //not masked continue; //not masked
} }
@ -2651,7 +2647,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < spot_light_count; i++) { for (uint i = 0; i < spot_light_count; i++) {
uint light_index = cluster_data.indices[spot_light_pointer + i]; uint light_index = cluster_data.indices[spot_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {
continue; //not masked continue; //not masked
} }
@ -2822,9 +2818,9 @@ FRAGMENT_SHADER_CODE
normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness); normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
#ifdef MODE_RENDER_GIPROBE #ifdef MODE_RENDER_GIPROBE
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; uint index1 = draw_call.gi_offset & 0xFFFF;
uint index2 = instances.data[instance_index].gi_offset >> 16; uint index2 = draw_call.gi_offset >> 16;
giprobe_buffer.x = index1 & 0xFF; giprobe_buffer.x = index1 & 0xFF;
giprobe_buffer.y = index2 & 0xFF; giprobe_buffer.y = index2 & 0xFF;
} else { } else {

View file

@ -12,9 +12,12 @@
#endif #endif
layout(push_constant, binding = 0, std430) uniform DrawCall { layout(push_constant, binding = 0, std430) uniform DrawCall {
uint instance_index; mat4 transform;
uint pad; //16 bits minimum size uint flags;
vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise uint instance_uniforms_ofs; //base offset in global buffer for instance variables
uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
uint layer_mask;
vec4 lightmap_uv_scale;
} }
draw_call; draw_call;
@ -134,21 +137,7 @@ scene_data;
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7 #define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
#define INSTANCE_FLAGS_SKELETON (1 << 19) #define INSTANCE_FLAGS_SKELETON (1 << 19)
#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20)
struct InstanceData {
mat4 transform;
mat4 normal_transform;
uint flags;
uint instance_uniforms_ofs; //base offset in global buffer for instance variables
uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
uint layer_mask;
vec4 lightmap_uv_scale;
};
layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
InstanceData data[];
}
instances;
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
LightData data[]; LightData data[];

View file

@ -596,7 +596,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} }
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it //forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
RSG::storage->base_update_dependency(p_base, instance); RSG::storage->base_update_dependency(p_base, &instance->dependency_tracker);
} }
_instance_queue_update(instance, true, true); _instance_queue_update(instance, true, true);
@ -830,7 +830,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
if (p_skeleton.is_valid()) { if (p_skeleton.is_valid()) {
//update the dependency now, so if cleared, we remove it //update the dependency now, so if cleared, we remove it
RSG::storage->skeleton_update_dependency(p_skeleton, instance); RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
} }
_instance_queue_update(instance, true, true); _instance_queue_update(instance, true, true);
@ -3152,14 +3152,14 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} }
if (p_instance->update_dependencies) { if (p_instance->update_dependencies) {
p_instance->instance_increase_version(); p_instance->dependency_tracker.update_begin();
if (p_instance->base.is_valid()) { if (p_instance->base.is_valid()) {
RSG::storage->base_update_dependency(p_instance->base, p_instance); RSG::storage->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
} }
if (p_instance->material_override.is_valid()) { if (p_instance->material_override.is_valid()) {
RSG::storage->material_update_dependency(p_instance->material_override, p_instance); RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
} }
if (p_instance->base_type == RS::INSTANCE_MESH) { if (p_instance->base_type == RS::INSTANCE_MESH) {
@ -3211,7 +3211,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
RSG::storage->material_update_dependency(mat, p_instance); RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
} }
} }
@ -3242,7 +3242,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
RSG::storage->material_update_dependency(mat, p_instance); RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
} }
} }
@ -3250,7 +3250,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false; can_cast_shadows = false;
} }
RSG::storage->base_update_dependency(mesh, p_instance); RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
} }
} else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) { } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
RID mat = RSG::storage->immediate_get_material(p_instance->base); RID mat = RSG::storage->immediate_get_material(p_instance->base);
@ -3268,7 +3268,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} }
if (mat.is_valid()) { if (mat.is_valid()) {
RSG::storage->material_update_dependency(mat, p_instance); RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
} }
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
@ -3299,7 +3299,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
RSG::storage->material_update_dependency(mat, p_instance); RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
} }
} }
} }
@ -3343,10 +3343,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} }
if (p_instance->skeleton.is_valid()) { if (p_instance->skeleton.is_valid()) {
RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance); RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
} }
p_instance->clean_up_dependencies(); p_instance->dependency_tracker.update_end();
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);

View file

@ -329,7 +329,7 @@ public:
virtual ~InstanceBaseData() {} virtual ~InstanceBaseData() {}
}; };
struct Instance : public RendererStorage::InstanceBaseDependency { struct Instance {
RS::InstanceType base_type; RS::InstanceType base_type;
RID base; RID base;
@ -412,18 +412,43 @@ public:
SelfList<InstancePair>::List pairs; SelfList<InstancePair>::List pairs;
uint64_t pair_check; uint64_t pair_check;
virtual void dependency_deleted(RID p_dependency) { RendererStorage::DependencyTracker dependency_tracker;
if (p_dependency == base) {
singleton->instance_set_base(self, RID()); static void dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *tracker) {
} else if (p_dependency == skeleton) { Instance *instance = (Instance *)tracker->userdata;
singleton->instance_attach_skeleton(self, RID()); switch (p_notification) {
} else { case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA:
singleton->_instance_queue_update(this, false, true); case RendererStorage::DEPENDENCY_CHANGED_AABB: {
singleton->_instance_queue_update(instance, true, false);
} break;
case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: {
singleton->_instance_queue_update(instance, false, true);
} break;
case RendererStorage::DEPENDENCY_CHANGED_MESH:
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
case RendererStorage::DEPENDENCY_CHANGED_DECAL:
case RendererStorage::DEPENDENCY_CHANGED_LIGHT:
case RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
singleton->_instance_queue_update(instance, true, true);
} break;
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
//ignored
} break;
} }
} }
virtual void dependency_changed(bool p_aabb, bool p_dependencies) { static void dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *tracker) {
singleton->_instance_queue_update(this, p_aabb, p_dependencies); Instance *instance = (Instance *)tracker->userdata;
if (p_dependency == instance->base) {
singleton->instance_set_base(instance->self, RID());
} else if (p_dependency == instance->skeleton) {
singleton->instance_attach_skeleton(instance->self, RID());
} else {
singleton->_instance_queue_update(instance, false, true);
}
} }
Instance() : Instance() :
@ -434,7 +459,6 @@ public:
receive_shadows = true; receive_shadows = true;
visible = true; visible = true;
layer_mask = 1; layer_mask = 1;
instance_version = 0;
baked_light = false; baked_light = false;
dynamic_gi = false; dynamic_gi = false;
redraw_if_visible = false; redraw_if_visible = false;
@ -465,6 +489,10 @@ public:
pair_check = 0; pair_check = 0;
array_index = -1; array_index = -1;
dependency_tracker.userdata = this;
dependency_tracker.changed_callback = dependency_changed;
dependency_tracker.deleted_callback = dependency_deleted;
} }
~Instance() { ~Instance() {

View file

@ -32,28 +32,31 @@
RendererStorage *RendererStorage::base_singleton = nullptr; RendererStorage *RendererStorage::base_singleton = nullptr;
void RendererStorage::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) { void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) {
for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_changed(p_aabb, p_dependencies); if (E->key()->changed_callback) {
E->key()->changed_callback(p_notification, E->key());
}
} }
} }
void RendererStorage::InstanceDependency::instance_notify_deleted(RID p_deleted) { void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_deleted(p_deleted); if (E->key()->deleted_callback) {
E->key()->deleted_callback(p_rid, E->key());
}
} }
for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this); E->key()->dependencies.erase(this);
} }
instances.clear(); instances.clear();
} }
RendererStorage::InstanceDependency::~InstanceDependency() { RendererStorage::Dependency::~Dependency() {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (instances.size()) { if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing."); WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this); E->key()->dependencies.erase(this);
} }
} }

View file

@ -37,43 +37,59 @@ class RendererStorage {
Color default_clear_color; Color default_clear_color;
public: public:
struct InstanceBaseDependency; enum DependencyChangedNotification {
DEPENDENCY_CHANGED_AABB,
struct InstanceDependency { DEPENDENCY_CHANGED_MATERIAL,
void instance_notify_changed(bool p_aabb, bool p_dependencies); DEPENDENCY_CHANGED_MESH,
void instance_notify_deleted(RID p_deleted); DEPENDENCY_CHANGED_MULTIMESH,
DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES,
~InstanceDependency(); DEPENDENCY_CHANGED_DECAL,
DEPENDENCY_CHANGED_SKELETON_DATA,
private: DEPENDENCY_CHANGED_SKELETON_BONES,
friend struct InstanceBaseDependency; DEPENDENCY_CHANGED_LIGHT,
Map<InstanceBaseDependency *, uint32_t> instances; DEPENDENCY_CHANGED_REFLECTION_PROBE,
}; };
struct InstanceBaseDependency { struct DependencyTracker;
uint32_t instance_version;
Set<InstanceDependency *> dependencies;
virtual void dependency_deleted(RID p_dependency) {} protected:
virtual void dependency_changed(bool p_aabb, bool p_dependencies) {} struct Dependency {
void changed_notify(DependencyChangedNotification p_notification);
void deleted_notify(const RID &p_rid);
void instance_increase_version() { ~Dependency();
private:
friend struct DependencyTracker;
Map<DependencyTracker *, uint32_t> instances;
};
public:
struct DependencyTracker {
void *userdata = nullptr;
typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
ChangedCallback changed_callback = nullptr;
DeletedCallback deleted_callback = nullptr;
void update_begin() { // call before updating dependencies
instance_version++; instance_version++;
} }
void update_dependency(InstanceDependency *p_dependency) { void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
dependencies.insert(p_dependency); dependencies.insert(p_dependency);
p_dependency->instances[this] = instance_version; p_dependency->instances[this] = instance_version;
} }
void clean_up_dependencies() { void update_end() { //call after updating dependencies
List<Pair<InstanceDependency *, Map<InstanceBaseDependency *, uint32_t>::Element *>> to_clean_up; List<Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *>> to_clean_up;
for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) { for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) {
InstanceDependency *dep = E->get(); Dependency *dep = E->get();
Map<InstanceBaseDependency *, uint32_t>::Element *F = dep->instances.find(this); Map<DependencyTracker *, uint32_t>::Element *F = dep->instances.find(this);
ERR_CONTINUE(!F); ERR_CONTINUE(!F);
if (F->get() != instance_version) { if (F->get() != instance_version) {
Pair<InstanceDependency *, Map<InstanceBaseDependency *, uint32_t>::Element *> p; Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p;
p.first = dep; p.first = dep;
p.second = F; p.second = F;
to_clean_up.push_back(p); to_clean_up.push_back(p);
@ -86,15 +102,20 @@ public:
} }
} }
void clear_dependencies() { void clear() { // clear all dependencies
for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) { for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) {
InstanceDependency *dep = E->get(); Dependency *dep = E->get();
dep->instances.erase(this); dep->instances.erase(this);
} }
dependencies.clear(); dependencies.clear();
} }
virtual ~InstanceBaseDependency() { clear_dependencies(); } ~DependencyTracker() { clear(); }
private:
friend class Dependency;
uint32_t instance_version = 0;
Set<Dependency *> dependencies;
}; };
/* TEXTURE API */ /* TEXTURE API */
@ -181,7 +202,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
virtual void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) = 0; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
/* MESH API */ /* MESH API */
@ -349,8 +370,8 @@ public:
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0; virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0;
virtual void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0; virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
virtual void skeleton_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0; virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* DECAL API */ /* DECAL API */