mirror of
https://github.com/godotengine/godot.git
synced 2025-10-24 02:13:36 +00:00
2D: Fix CanvasTexture rendering when updating channels
This commit is contained in:
parent
b0655dc86f
commit
663917449b
4 changed files with 55 additions and 0 deletions
|
|
@ -2971,8 +2971,23 @@ void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata
|
||||||
static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key);
|
static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererCanvasRenderRD::_canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata) {
|
||||||
|
KeyValue<RID, TightLocalVector<RID>> *kv = static_cast<KeyValue<RID, TightLocalVector<RID>> *>(p_userdata);
|
||||||
|
RD *rd = RD::get_singleton();
|
||||||
|
for (RID rid : kv->value) {
|
||||||
|
// the invalidation callback will take care of clearing rid_set_to_uniform_set cache also
|
||||||
|
rd->free(rid);
|
||||||
|
}
|
||||||
|
kv->value.clear();
|
||||||
|
if (p_deleted) {
|
||||||
|
static_cast<RendererCanvasRenderRD *>(singleton)->canvas_texture_to_uniform_set.erase(kv->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
|
void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
|
||||||
{
|
{
|
||||||
|
RendererRD::TextureStorage *ts = RendererRD::TextureStorage::get_singleton();
|
||||||
|
|
||||||
RIDSetKey key(
|
RIDSetKey key(
|
||||||
p_batch->tex_info->state,
|
p_batch->tex_info->state,
|
||||||
state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||||
|
|
@ -2992,6 +3007,19 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
|
||||||
const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid);
|
const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid);
|
||||||
uniform_set = &iter->data;
|
uniform_set = &iter->data;
|
||||||
RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key);
|
RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key);
|
||||||
|
|
||||||
|
// If this is a CanvasTexture, it must be tracked so that any changes to the diffuse, normal
|
||||||
|
// or specular channels invalidate all associated uniform sets.
|
||||||
|
if (ts->owns_canvas_texture(p_batch->tex_info->state.texture)) {
|
||||||
|
KeyValue<RID, TightLocalVector<RID>> *kv = nullptr;
|
||||||
|
if (HashMap<RID, TightLocalVector<RID>>::Iterator i = canvas_texture_to_uniform_set.find(p_batch->tex_info->state.texture); i == canvas_texture_to_uniform_set.end()) {
|
||||||
|
kv = &*canvas_texture_to_uniform_set.insert(p_batch->tex_info->state.texture, { *uniform_set });
|
||||||
|
} else {
|
||||||
|
i->value.push_back(rid);
|
||||||
|
kv = &*i;
|
||||||
|
}
|
||||||
|
ts->canvas_texture_set_invalidation_callback(p_batch->tex_info->state.texture, RendererCanvasRenderRD::_canvas_texture_invalidation_callback, kv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.current_batch_uniform_set != *uniform_set) {
|
if (state.current_batch_uniform_set != *uniform_set) {
|
||||||
|
|
|
||||||
|
|
@ -485,9 +485,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||||
|
|
||||||
static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid);
|
static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid);
|
||||||
static void _uniform_set_invalidation_callback(void *p_userdata);
|
static void _uniform_set_invalidation_callback(void *p_userdata);
|
||||||
|
static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata);
|
||||||
|
|
||||||
typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
|
typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
|
||||||
RIDCache rid_set_to_uniform_set;
|
RIDCache rid_set_to_uniform_set;
|
||||||
|
/// Maps a CanvasTexture to its associated uniform sets, which must
|
||||||
|
/// be invalidated when the CanvasTexture is updated, such as changing the
|
||||||
|
/// diffuse texture.
|
||||||
|
HashMap<RID, TightLocalVector<RID>> canvas_texture_to_uniform_set;
|
||||||
|
|
||||||
struct Batch {
|
struct Batch {
|
||||||
// Position in the UBO measured in bytes
|
// Position in the UBO measured in bytes
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,15 @@ using namespace RendererRD;
|
||||||
void TextureStorage::CanvasTexture::clear_cache() {
|
void TextureStorage::CanvasTexture::clear_cache() {
|
||||||
info_cache[0] = CanvasTextureCache();
|
info_cache[0] = CanvasTextureCache();
|
||||||
info_cache[1] = CanvasTextureCache();
|
info_cache[1] = CanvasTextureCache();
|
||||||
|
if (invalidated_callback != nullptr) {
|
||||||
|
invalidated_callback(false, invalidated_callback_userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureStorage::CanvasTexture::~CanvasTexture() {
|
TextureStorage::CanvasTexture::~CanvasTexture() {
|
||||||
|
if (invalidated_callback != nullptr) {
|
||||||
|
invalidated_callback(true, invalidated_callback_userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -735,6 +741,16 @@ TextureStorage::CanvasTextureInfo TextureStorage::canvas_texture_get_info(RID p_
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureStorage::canvas_texture_set_invalidation_callback(RID p_canvas_texture, InvalidationCallback p_callback, void *p_userdata) {
|
||||||
|
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
|
||||||
|
if (!ct) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ct->invalidated_callback = p_callback;
|
||||||
|
ct->invalidated_callback_userdata = p_userdata;
|
||||||
|
}
|
||||||
|
|
||||||
/* Texture API */
|
/* Texture API */
|
||||||
|
|
||||||
RID TextureStorage::texture_allocate() {
|
RID TextureStorage::texture_allocate() {
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ public:
|
||||||
_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
|
_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*InvalidationCallback)(bool p_deleted, void *p_userdata);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class LightStorage;
|
friend class LightStorage;
|
||||||
friend class MaterialStorage;
|
friend class MaterialStorage;
|
||||||
|
|
@ -118,6 +120,9 @@ private:
|
||||||
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
|
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
|
||||||
CanvasTextureCache info_cache[2];
|
CanvasTextureCache info_cache[2];
|
||||||
|
|
||||||
|
InvalidationCallback invalidated_callback = nullptr;
|
||||||
|
void *invalidated_callback_userdata = nullptr;
|
||||||
|
|
||||||
Size2i size_cache = Size2i(1, 1);
|
Size2i size_cache = Size2i(1, 1);
|
||||||
bool use_normal_cache = false;
|
bool use_normal_cache = false;
|
||||||
bool use_specular_cache = false;
|
bool use_specular_cache = false;
|
||||||
|
|
@ -499,6 +504,7 @@ public:
|
||||||
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
|
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
|
||||||
|
|
||||||
CanvasTextureInfo canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data);
|
CanvasTextureInfo canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data);
|
||||||
|
void canvas_texture_set_invalidation_callback(RID p_canvas_texture, InvalidationCallback p_callback, void *p_userdata);
|
||||||
|
|
||||||
/* Texture API */
|
/* Texture API */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue