|
@@ -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<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
|
|
@@ -2381,6 +2378,86 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
|
|
|
+ if ((uint32_t)ubo_data.size() != p_ubo_size) {
|
|
|
+ p_uniform_dirty = true;
|
|
|
+ if (uniform_buffer.is_valid()) {
|
|
|
+ RD::get_singleton()->free(uniform_buffer);
|
|
|
+ uniform_buffer = RID();
|
|
|
+ }
|
|
|
+
|
|
|
+ ubo_data.resize(p_ubo_size);
|
|
|
+ if (ubo_data.size()) {
|
|
|
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
|
|
|
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
|
|
|
+ }
|
|
|
+
|
|
|
+ //clear previous uniform set
|
|
|
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
|
|
+ RD::get_singleton()->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<RD::Uniform> 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<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
|
|
+bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &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<RD::Uniform> 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;
|