Fix material invalidation on reimport.
* IF a texture was reimported (calling replace as an example), it would invalidate all materials using it, causing plenty of errors. * Added the possibility to get a notification when a uniform set is erased. * With this notification, materials can be queued for update properly.
This commit is contained in:
parent
b1068f9f01
commit
83addd6ee5
9 changed files with 42 additions and 15 deletions
|
@ -5505,6 +5505,13 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) {
|
|||
return uniform_set_owner.owns(p_uniform_set);
|
||||
}
|
||||
|
||||
void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) {
|
||||
UniformSet *us = uniform_set_owner.getornull(p_uniform_set);
|
||||
ERR_FAIL_COND(!us);
|
||||
us->invalidated_callback = p_callback;
|
||||
us->invalidated_callback_userdata = p_userdata;
|
||||
}
|
||||
|
||||
Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -7844,6 +7851,10 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) {
|
|||
} else if (uniform_set_owner.owns(p_id)) {
|
||||
UniformSet *uniform_set = uniform_set_owner.getornull(p_id);
|
||||
frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set);
|
||||
if (uniform_set->invalidated_callback != nullptr) {
|
||||
uniform_set->invalidated_callback(p_id, uniform_set->invalidated_callback_userdata);
|
||||
}
|
||||
|
||||
uniform_set_owner.free(p_id);
|
||||
} else if (render_pipeline_owner.owns(p_id)) {
|
||||
RenderPipeline *pipeline = render_pipeline_owner.getornull(p_id);
|
||||
|
|
|
@ -732,6 +732,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
|||
LocalVector<AttachableTexture> attachable_textures; //used for validation
|
||||
Vector<Texture *> mutable_sampled_textures; //used for layout change
|
||||
Vector<Texture *> mutable_storage_textures; //used for layout change
|
||||
UniformSetInvalidatedCallback invalidated_callback = nullptr;
|
||||
void *invalidated_callback_userdata = nullptr;
|
||||
};
|
||||
|
||||
RID_Owner<UniformSet, true> uniform_set_owner;
|
||||
|
@ -1088,6 +1090,7 @@ public:
|
|||
|
||||
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
|
||||
virtual bool uniform_set_is_valid(RID p_uniform_set);
|
||||
virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata);
|
||||
|
||||
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer
|
||||
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
||||
|
|
|
@ -442,9 +442,7 @@ bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<Stri
|
|||
}
|
||||
|
||||
SceneShaderForwardClustered::MaterialData::~MaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
|
||||
|
|
|
@ -436,9 +436,7 @@ bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringN
|
|||
}
|
||||
|
||||
SceneShaderForwardMobile::MaterialData::~MaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
|
||||
|
|
|
@ -2208,9 +2208,7 @@ bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringNam
|
|||
}
|
||||
|
||||
RendererCanvasRenderRD::MaterialData::~MaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
|
||||
|
|
|
@ -239,9 +239,7 @@ bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName
|
|||
}
|
||||
|
||||
RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2377,6 +2377,13 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
|
|||
}
|
||||
}
|
||||
|
||||
void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
|
||||
if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
|
||||
RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
|
||||
RD::get_singleton()->free(p_uniform_set);
|
||||
}
|
||||
}
|
||||
|
||||
bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<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;
|
||||
|
@ -2393,6 +2400,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
|
|||
|
||||
//clear previous uniform set
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
uniform_set = RID();
|
||||
}
|
||||
|
@ -2412,6 +2420,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
|
|||
|
||||
//clear previous uniform set
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
uniform_set = RID();
|
||||
}
|
||||
|
@ -2454,9 +2463,19 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
|
|||
|
||||
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
|
||||
|
||||
RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererStorageRD::_material_uniform_set_erased(const RID &p_set, void *p_material) {
|
||||
RID rid = *(RID *)p_material;
|
||||
Material *material = base_singleton->material_owner.getornull(rid);
|
||||
if (material) {
|
||||
material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -5367,9 +5386,7 @@ bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<Strin
|
|||
}
|
||||
|
||||
RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
|
||||
|
|
|
@ -160,6 +160,7 @@ public:
|
|||
|
||||
//to be used internally by update_parameters, in the most common configuration of material parameters
|
||||
bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<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 = RD::BARRIER_MASK_ALL);
|
||||
void free_parameters_uniform_set(RID p_uniform_set);
|
||||
|
||||
private:
|
||||
friend class RendererStorageRD;
|
||||
|
@ -175,6 +176,7 @@ public:
|
|||
Vector<RID> texture_cache;
|
||||
};
|
||||
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
|
||||
static void _material_uniform_set_erased(const RID &p_set, void *p_material);
|
||||
|
||||
enum DefaultRDTexture {
|
||||
DEFAULT_RD_TEXTURE_WHITE,
|
||||
|
|
|
@ -715,6 +715,8 @@ public:
|
|||
|
||||
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
|
||||
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
|
||||
typedef void (*UniformSetInvalidatedCallback)(const RID &, void *);
|
||||
virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
|
||||
|
||||
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
|
||||
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
|
||||
|
|
Loading…
Reference in a new issue