Skip to content

Commit 4228a1e

Browse files
committed
2D: Fixes for godotengine#101931
1 parent 570c126 commit 4228a1e

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -2971,8 +2971,23 @@ void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata
29712971
static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key);
29722972
}
29732973

2974+
void RendererCanvasRenderRD::_canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata) {
2975+
KeyValue<RID, TightLocalVector<RID>> *kv = static_cast<KeyValue<RID, TightLocalVector<RID>> *>(p_userdata);
2976+
RD *rd = RD::get_singleton();
2977+
for (RID rid : kv->value) {
2978+
// the invalidation callback will take care of clearing rid_set_to_uniform_set cache also
2979+
rd->free(rid);
2980+
}
2981+
kv->value.clear();
2982+
if (p_deleted) {
2983+
static_cast<RendererCanvasRenderRD *>(singleton)->canvas_texture_to_uniform_set.erase(kv->key);
2984+
}
2985+
}
2986+
29742987
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) {
29752988
{
2989+
RendererRD::TextureStorage *ts = RendererRD::TextureStorage::get_singleton();
2990+
29762991
RIDSetKey key(
29772992
p_batch->tex_info->state,
29782993
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
29923007
const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid);
29933008
uniform_set = &iter->data;
29943009
RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key);
3010+
3011+
// If this is a CanvasTexture, it must be tracked so that any changes to the diffuse, normal
3012+
// or specular channels invalidate all associated uniform sets.
3013+
if (ts->owns_canvas_texture(p_batch->tex_info->state.texture)) {
3014+
KeyValue<RID, TightLocalVector<RID>> *kv = nullptr;
3015+
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()) {
3016+
kv = &*canvas_texture_to_uniform_set.insert(p_batch->tex_info->state.texture, { *uniform_set });
3017+
} else {
3018+
i->value.push_back(rid);
3019+
kv = &*i;
3020+
}
3021+
ts->canvas_texture_set_invalidation_callback(p_batch->tex_info->state.texture, RendererCanvasRenderRD::_canvas_texture_invalidation_callback, kv);
3022+
}
29953023
}
29963024

29973025
if (state.current_batch_uniform_set != *uniform_set) {

servers/rendering/renderer_rd/renderer_canvas_render_rd.h

+5
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
485485

486486
static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid);
487487
static void _uniform_set_invalidation_callback(void *p_userdata);
488+
static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata);
488489

489490
typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
490491
RIDCache rid_set_to_uniform_set;
492+
/// Maps a CanvasTexture to its associated uniform sets, which must
493+
/// be invalidated when the CanvasTexture is updated, such as changing the
494+
/// diffuse texture.
495+
HashMap<RID, TightLocalVector<RID>> canvas_texture_to_uniform_set;
491496

492497
struct Batch {
493498
// Position in the UBO measured in bytes

servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,15 @@ using namespace RendererRD;
4343
void TextureStorage::CanvasTexture::clear_cache() {
4444
info_cache[0] = CanvasTextureCache();
4545
info_cache[1] = CanvasTextureCache();
46+
if (invalidated_callback != nullptr) {
47+
invalidated_callback(false, invalidated_callback_userdata);
48+
}
4649
}
4750

4851
TextureStorage::CanvasTexture::~CanvasTexture() {
52+
if (invalidated_callback != nullptr) {
53+
invalidated_callback(true, invalidated_callback_userdata);
54+
}
4955
}
5056

5157
///////////////////////////////////////////////////////////////////////////
@@ -735,6 +741,16 @@ TextureStorage::CanvasTextureInfo TextureStorage::canvas_texture_get_info(RID p_
735741
return res;
736742
}
737743

744+
void TextureStorage::canvas_texture_set_invalidation_callback(RID p_canvas_texture, InvalidationCallback p_callback, void *p_userdata) {
745+
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
746+
if (!ct) {
747+
return;
748+
}
749+
750+
ct->invalidated_callback = p_callback;
751+
ct->invalidated_callback_userdata = p_userdata;
752+
}
753+
738754
/* Texture API */
739755

740756
RID TextureStorage::texture_allocate() {

servers/rendering/renderer_rd/storage_rd/texture_storage.h

+6
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class TextureStorage : public RendererTextureStorage {
9090
_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
9191
};
9292

93+
typedef void (*InvalidationCallback)(bool p_deleted, void *p_userdata);
94+
9395
private:
9496
friend class LightStorage;
9597
friend class MaterialStorage;
@@ -118,6 +120,9 @@ class TextureStorage : public RendererTextureStorage {
118120
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
119121
CanvasTextureCache info_cache[2];
120122

123+
InvalidationCallback invalidated_callback = nullptr;
124+
void *invalidated_callback_userdata = nullptr;
125+
121126
Size2i size_cache = Size2i(1, 1);
122127
bool use_normal_cache = false;
123128
bool use_specular_cache = false;
@@ -499,6 +504,7 @@ class TextureStorage : public RendererTextureStorage {
499504
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
500505

501506
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);
507+
void canvas_texture_set_invalidation_callback(RID p_canvas_texture, InvalidationCallback p_callback, void *p_userdata);
502508

503509
/* Texture API */
504510

0 commit comments

Comments
 (0)