Implement 2D instance shader parameters

Co-authored-by: kobewi <kobewi4e@gmail.com>
Co-authored-by: yesfish <huwpascoe@users.noreply.github.com>
Co-authored-by: Álex Román Núñez <eirexe123@gmail.com>
This commit is contained in:
kobewi 2023-05-29 00:23:00 +02:00 committed by Patrick Exner
parent b9437c3938
commit ceefc0d38a
24 changed files with 626 additions and 168 deletions

View file

@ -44,6 +44,29 @@
// while not making lines appear too soft.
const static float FEATHER_SIZE = 1.25f;
static RendererCanvasCull *_canvas_cull_singleton = nullptr;
void RendererCanvasCull::_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
Item *item = (Item *)p_tracker->userdata;
switch (p_notification) {
case Dependency::DEPENDENCY_CHANGED_MATERIAL: {
_canvas_cull_singleton->_item_queue_update(item, true);
} break;
default: {
} break;
}
}
void RendererCanvasCull::_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
Item *item = (Item *)p_tracker->userdata;
if (p_dependency == item->material) {
_canvas_cull_singleton->canvas_item_set_material(item->self, RID());
}
_canvas_cull_singleton->_item_queue_update(item, true);
}
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
@ -525,6 +548,8 @@ RID RendererCanvasCull::canvas_item_allocate() {
}
void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
canvas_item_owner.initialize_rid(p_rid);
Item *instance = canvas_item_owner.get_or_null(p_rid);
instance->self = p_rid;
}
void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
@ -1844,6 +1869,7 @@ void RendererCanvasCull::canvas_item_clear(RID p_item) {
ERR_FAIL_NULL(canvas_item);
canvas_item->clear();
#ifdef DEBUG_ENABLED
if (debug_redraw) {
canvas_item->debug_redraw_time = debug_redraw_time;
@ -1875,6 +1901,7 @@ void RendererCanvasCull::canvas_item_set_material(RID p_item, RID p_material) {
ERR_FAIL_NULL(canvas_item);
canvas_item->material = p_material;
_item_queue_update(canvas_item, true);
}
void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
@ -1882,6 +1909,37 @@ void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_
ERR_FAIL_NULL(canvas_item);
canvas_item->use_parent_material = p_enable;
_item_queue_update(canvas_item, true);
}
void RendererCanvasCull::canvas_item_set_instance_shader_parameter(RID p_item, const StringName &p_parameter, const Variant &p_value) {
Item *item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(item);
item->instance_uniforms.set(item->self, p_parameter, p_value);
}
Variant RendererCanvasCull::canvas_item_get_instance_shader_parameter(RID p_item, const StringName &p_parameter) const {
const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL_V(item, Variant());
return item->instance_uniforms.get(p_parameter);
}
Variant RendererCanvasCull::canvas_item_get_instance_shader_parameter_default_value(RID p_item, const StringName &p_parameter) const {
const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL_V(item, Variant());
return item->instance_uniforms.get_default(p_parameter);
}
void RendererCanvasCull::canvas_item_get_instance_shader_parameter_list(RID p_item, List<PropertyInfo> *p_parameters) const {
ERR_FAIL_NULL(p_parameters);
const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(item);
const_cast<RendererCanvasCull *>(this)->update_dirty_items();
item->instance_uniforms.get_property_list(*p_parameters);
}
void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) {
@ -2411,6 +2469,63 @@ Rect2 RendererCanvasCull::_debug_canvas_item_get_rect(RID p_item) {
return canvas_item->get_rect();
}
void RendererCanvasCull::_item_queue_update(Item *p_item, bool p_update_dependencies) {
if (p_update_dependencies) {
p_item->update_dependencies = true;
}
if (!p_item->update_item.in_list()) {
_item_update_list.add(&p_item->update_item);
}
}
void RendererCanvasCull::update_dirty_items() {
while (_item_update_list.first()) {
_update_dirty_item(_item_update_list.first()->self());
}
// Instance updates may affect resources.
RSG::utilities->update_dirty_resources();
}
void RendererCanvasCull::_update_dirty_item(Item *p_item) {
if (p_item->update_dependencies) {
RID material = p_item->material;
if (p_item->use_parent_material) {
Item *parent = canvas_item_owner.get_or_null(p_item->parent);
while (parent != nullptr) {
material = parent->material;
if (!parent->use_parent_material) {
break;
}
parent = canvas_item_owner.get_or_null(parent->parent);
}
}
p_item->dependency_tracker.update_begin();
p_item->instance_uniforms.materials_start();
if (material.is_valid()) {
p_item->instance_uniforms.materials_append(material);
RSG::material_storage->material_update_dependency(material, &p_item->dependency_tracker);
}
if (p_item->instance_uniforms.materials_finish(p_item->self)) {
p_item->instance_allocated_shader_uniforms_offset = p_item->instance_uniforms.location();
}
p_item->dependency_tracker.update_end();
}
_item_update_list.remove(&p_item->update_item);
p_item->update_dependencies = false;
}
void RendererCanvasCull::update() {
update_dirty_items();
}
bool RendererCanvasCull::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
Canvas *canvas = canvas_owner.get_or_null(p_rid);
@ -2468,11 +2583,9 @@ bool RendererCanvasCull::free(RID p_rid) {
visibility_notifier_allocator.free(canvas_item->visibility_notifier);
}
/*
if (canvas_item->material) {
canvas_item->material->owners.erase(canvas_item);
}
*/
canvas_item_set_material(canvas_item->self, RID());
canvas_item->instance_uniforms.free(canvas_item->self);
update_dirty_items();
if (canvas_item->canvas_group != nullptr) {
memdelete(canvas_item->canvas_group);
@ -2634,6 +2747,8 @@ void RendererCanvasCull::InterpolationData::notify_free_canvas_light_occluder(RI
}
RendererCanvasCull::RendererCanvasCull() {
_canvas_cull_singleton = this;
z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
@ -2646,4 +2761,5 @@ RendererCanvasCull::RendererCanvasCull() {
RendererCanvasCull::~RendererCanvasCull() {
memfree(z_list);
memfree(z_last_list);
_canvas_cull_singleton = nullptr;
}