From c43f624d44fe143364154ee232332e17a4fddc3d Mon Sep 17 00:00:00 2001 From: reduz Date: Tue, 6 Jul 2021 18:56:28 -0300 Subject: Unify material parameter update * Unifies how material parameters are updated. * Single function, easier to maintain. * Updates materials properly when textures change. --- .../scene_shader_forward_clustered.cpp | 82 +------- .../scene_shader_forward_clustered.h | 5 +- .../forward_mobile/scene_shader_forward_mobile.cpp | 82 +------- .../forward_mobile/scene_shader_forward_mobile.h | 5 +- .../renderer_rd/renderer_canvas_render_rd.cpp | 82 +------- .../renderer_rd/renderer_canvas_render_rd.h | 5 +- .../renderer_rd/renderer_scene_sky_rd.cpp | 82 +------- .../rendering/renderer_rd/renderer_scene_sky_rd.h | 5 +- .../rendering/renderer_rd/renderer_storage_rd.cpp | 212 ++++++++++----------- .../rendering/renderer_rd/renderer_storage_rd.h | 42 ++-- 10 files changed, 142 insertions(+), 460 deletions(-) (limited to 'servers/rendering') diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 61f3047a34..36c00acbca 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -435,94 +435,16 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -void SceneShaderForwardClustered::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); } SceneShaderForwardClustered::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } } RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 6d7cef68c6..810b1f3876 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -166,17 +166,14 @@ public: struct MaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; ShaderData *shader_data; - RID uniform_buffer; RID uniform_set; - Vector texture_cache; - Vector ubo_data; uint64_t last_pass = 0; uint32_t index = 0; RID next_pass; uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 807417c1e3..5e26cbea1f 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -429,94 +429,16 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -void SceneShaderForwardMobile::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton; - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); } SceneShaderForwardMobile::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } } RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 476bb57bc5..5c9e35fd0d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -163,17 +163,14 @@ public: struct MaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; ShaderData *shader_data; - RID uniform_buffer; RID uniform_set; - Vector texture_cache; - Vector ubo_data; uint64_t last_pass = 0; uint32_t index = 0; RID next_pass; uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 026969c09f..86cf0a2057 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2201,94 +2201,16 @@ RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { return shader_data; } -void RendererCanvasRenderRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false); - } - - if (shader_data->ubo_size == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } RendererCanvasRenderRD::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } } RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 1bc3769450..7c4f62832c 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -201,14 +201,11 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct MaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; ShaderData *shader_data; - RID uniform_buffer; RID uniform_set; - Vector texture_cache; - Vector ubo_data; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 956609b77e..6dd06c503e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -230,96 +230,18 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { //////////////////////////////////////////////////////////////////////////////// // Sky material -void RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; uniform_set_updated = true; - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); } RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 1292622fca..4f852e55a7 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -224,15 +224,12 @@ public: struct SkyMaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; SkyShaderData *shader_data; - RID uniform_buffer; RID uniform_set; - Vector texture_cache; - Vector ubo_data; bool uniform_set_updated; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~SkyMaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 942684fc3a..7e280ea3e8 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1526,27 +1526,18 @@ RID RendererStorageRD::material_allocate() { return material_owner.allocate_rid(); } void RendererStorageRD::material_initialize(RID p_rid) { - Material material; - material.data = nullptr; - material.shader = nullptr; - material.shader_type = SHADER_TYPE_MAX; - material.update_next = nullptr; - material.update_requested = false; - material.uniform_dirty = false; - material.texture_dirty = false; - material.priority = 0; - material.self = p_rid; - material_owner.initialize_rid(p_rid, material); + material_owner.initialize_rid(p_rid); + Material *material = material_owner.getornull(p_rid); + material->self = p_rid; } void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { - if (material->update_requested) { + if (material->update_element.in_list()) { return; } - material->update_next = material_update_list; - material_update_list = material; - material->update_requested = true; + material_update_list.add(&material->update_element); + material->uniform_dirty = material->uniform_dirty || p_uniform; material->texture_dirty = material->texture_dirty || p_texture; } @@ -1610,6 +1601,8 @@ void RendererStorageRD::material_set_param(RID p_material, const StringName &p_p } else { _material_queue_update(material, true, true); } + + print_line("set parameter: " + String(p_param)); } Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const { @@ -2232,6 +2225,10 @@ RendererStorageRD::MaterialData::~MaterialData() { //unregister material from those using global textures rs->global_variables.materials_using_texture.erase(global_texture_E); } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } } void RendererStorageRD::MaterialData::update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { @@ -2381,6 +2378,86 @@ void RendererStorageRD::MaterialData::update_textures(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Vector &p_texture_uniforms, const Map &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { + if ((uint32_t)ubo_data.size() != p_ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(p_ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); + } + + uint32_t tex_uniform_count = p_texture_uniforms.size(); + + if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); + } + + if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return false; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return false; + } + + Vector uniforms; + + { + if (p_ubo_size) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (uint32_t i = 0; i < tex_uniform_count; i++) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + i; + u.ids.push_back(textures[i]); + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set); + + return true; +} + void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { Material *material = material_owner.getornull(p_material); if (material->shader_type != p_shader_type) { @@ -2392,20 +2469,23 @@ void RendererStorageRD::material_force_update_textures(RID p_material, ShaderTyp } void RendererStorageRD::_update_queued_materials() { - Material *material = material_update_list; - while (material) { - Material *next = material->update_next; + while (material_update_list.first()) { + Material *material = material_update_list.first()->self(); + bool uniforms_changed = false; if (material->data) { - material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); + uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); } - material->update_requested = false; material->texture_dirty = false; material->uniform_dirty = false; - material->update_next = nullptr; - material = next; + + material_update_list.remove(&material->update_element); + + if (uniforms_changed) { + //some implementations such as 3D renderer cache the matreial uniform set, so update is required + material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); + } } - material_update_list = nullptr; } /* MESH API */ @@ -5281,94 +5361,16 @@ RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func( return shader_data; } -void RendererStorageRD::ParticlesMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { uniform_set_updated = true; - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } } RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { @@ -8661,9 +8663,6 @@ bool RendererStorageRD::free(RID p_rid) { } else if (material_owner.owns(p_rid)) { Material *material = material_owner.getornull(p_rid); - if (material->update_requested) { - _update_queued_materials(); - } material_set_shader(p_rid, RID()); //clean up shader material->dependency.deleted_notify(p_rid); @@ -8849,7 +8848,6 @@ RendererStorageRD::RendererStorageRD() { memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); - material_update_list = nullptr; { //create default textures RD::TextureFormat tformat; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 80dea6e5ea..7c34ccd076 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -155,9 +155,12 @@ public: virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; virtual ~MaterialData(); + //to be used internally by update_parameters, in the most common configuration of material parameters + bool update_parameters_uniform_set(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Vector &p_texture_uniforms, const Map &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + private: friend class RendererStorageRD; RID self; @@ -165,6 +168,11 @@ public: List::Element *global_texture_E = nullptr; uint64_t global_textures_pass = 0; Map used_global_textures; + + //internally by update_parameters_uniform_set + Vector ubo_data; + RID uniform_buffer; + Vector texture_cache; }; typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); @@ -373,25 +381,28 @@ private: struct Material { RID self; - MaterialData *data; - Shader *shader; + MaterialData *data = nullptr; + Shader *shader = nullptr; //shortcut to shader data and type - ShaderType shader_type; + ShaderType shader_type = SHADER_TYPE_MAX; uint32_t shader_id = 0; - bool update_requested; - bool uniform_dirty; - bool texture_dirty; - Material *update_next; + bool uniform_dirty = false; + bool texture_dirty = false; Map params; - int32_t priority; + int32_t priority = 0; RID next_pass; + SelfList update_element; + Dependency dependency; + + Material() : + update_element(this) {} }; MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner material_owner; - Material *material_update_list; + SelfList::List material_update_list; void _material_queue_update(Material *material, bool p_uniform, bool p_texture); void _update_queued_materials(); @@ -895,17 +906,14 @@ private: } struct ParticlesMaterialData : public MaterialData { - uint64_t last_frame; - ParticlesShaderData *shader_data; - RID uniform_buffer; + uint64_t last_frame = 0; + ParticlesShaderData *shader_data = nullptr; RID uniform_set; - Vector texture_cache; - Vector ubo_data; - bool uniform_set_updated; + bool uniform_set_updated = false; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~ParticlesMaterialData(); }; -- cgit v1.2.3