Skip to content

Commit 35a20fa

Browse files
committed
Use a shared copy of placeholder textures, tweak placeholder appearance
This reduces memory usage a bit in case multiple placeholders were requested, e.g. when using multiple NoiseTextures with no noise property defined. The placeholder texture's appearance was also changed from a plain magenta color to a checkerboard alternating between magenta and black pixels. This makes it easier to spot when the placeholder texture ends up being used in a complex scene (usually by accident). The texture's dimensions remain identical to keep the physical size identical in 2D.
1 parent 04692d8 commit 35a20fa

File tree

4 files changed

+71
-63
lines changed

4 files changed

+71
-63
lines changed

drivers/gles3/storage/texture_storage.cpp

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,32 @@ TextureStorage::TextureStorage() {
230230
sdf_shader.shader_version = sdf_shader.shader.version_create();
231231
}
232232

233+
// Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods.
234+
235+
constexpr int placeholder_size = 4;
236+
texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8);
237+
// Draw a magenta/black checkerboard pattern.
238+
for (int i = 0; i < placeholder_size * placeholder_size; i++) {
239+
const int x = i % placeholder_size;
240+
const int y = i / placeholder_size;
241+
texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0));
242+
}
243+
244+
texture_2d_array_placeholder.push_back(texture_2d_placeholder);
245+
246+
for (int i = 0; i < 6; i++) {
247+
cubemap_placeholder.push_back(texture_2d_placeholder);
248+
}
249+
250+
Ref<Image> texture_2d_placeholder_rotated;
251+
texture_2d_placeholder_rotated.instantiate();
252+
texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder);
253+
texture_2d_placeholder_rotated->rotate_90(CLOCKWISE);
254+
for (int i = 0; i < 4; i++) {
255+
// Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees).
256+
texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated);
257+
}
258+
233259
#ifdef GL_API_ENABLED
234260
if (RasterizerGLES3::is_gles_over_gl()) {
235261
glEnable(GL_PROGRAM_POINT_SIZE);
@@ -1014,46 +1040,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
10141040
}
10151041

10161042
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
1017-
//this could be better optimized to reuse an existing image , done this way
1018-
//for now to get it working
1019-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1020-
image->fill(Color(1, 0, 1, 1));
1021-
1022-
texture_2d_initialize(p_texture, image);
1043+
texture_2d_initialize(p_texture, texture_2d_placeholder);
10231044
}
10241045

1025-
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
1026-
//this could be better optimized to reuse an existing image , done this way
1027-
//for now to get it working
1028-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1029-
image->fill(Color(1, 0, 1, 1));
1030-
1031-
Vector<Ref<Image>> images;
1046+
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
10321047
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
1033-
images.push_back(image);
1048+
texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type);
10341049
} else {
1035-
//cube
1036-
for (int i = 0; i < 6; i++) {
1037-
images.push_back(image);
1038-
}
1050+
texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type);
10391051
}
1040-
1041-
texture_2d_layered_initialize(p_texture, images, p_layered_type);
10421052
}
10431053

10441054
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
1045-
//this could be better optimized to reuse an existing image , done this way
1046-
//for now to get it working
1047-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1048-
image->fill(Color(1, 0, 1, 1));
1049-
1050-
Vector<Ref<Image>> images;
1051-
//cube
1052-
for (int i = 0; i < 4; i++) {
1053-
images.push_back(image);
1054-
}
1055-
1056-
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
1055+
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder);
10571056
}
10581057

10591058
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {

drivers/gles3/storage/texture_storage.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ class TextureStorage : public RendererTextureStorage {
521521
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
522522
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
523523

524+
Ref<Image> texture_2d_placeholder;
525+
Vector<Ref<Image>> texture_2d_array_placeholder;
526+
Vector<Ref<Image>> cubemap_placeholder;
527+
Vector<Ref<Image>> texture_3d_placeholder;
528+
524529
//these two APIs can be used together or in combination with the others.
525530
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
526531
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;

servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,32 @@ TextureStorage::TextureStorage() {
518518
rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
519519
}
520520
}
521+
522+
// Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods.
523+
524+
constexpr int placeholder_size = 4;
525+
texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8);
526+
// Draw a magenta/black checkerboard pattern.
527+
for (int i = 0; i < placeholder_size * placeholder_size; i++) {
528+
const int x = i % placeholder_size;
529+
const int y = i / placeholder_size;
530+
texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0));
531+
}
532+
533+
texture_2d_array_placeholder.push_back(texture_2d_placeholder);
534+
535+
for (int i = 0; i < 6; i++) {
536+
cubemap_placeholder.push_back(texture_2d_placeholder);
537+
}
538+
539+
Ref<Image> texture_2d_placeholder_rotated;
540+
texture_2d_placeholder_rotated.instantiate();
541+
texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder);
542+
texture_2d_placeholder_rotated->rotate_90(CLOCKWISE);
543+
for (int i = 0; i < 4; i++) {
544+
// Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees).
545+
texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated);
546+
}
521547
}
522548

523549
TextureStorage::~TextureStorage() {
@@ -1365,46 +1391,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
13651391

13661392
//these two APIs can be used together or in combination with the others.
13671393
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
1368-
//this could be better optimized to reuse an existing image , done this way
1369-
//for now to get it working
1370-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1371-
image->fill(Color(1, 0, 1, 1));
1372-
1373-
texture_2d_initialize(p_texture, image);
1394+
texture_2d_initialize(p_texture, texture_2d_placeholder);
13741395
}
13751396

13761397
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
1377-
//this could be better optimized to reuse an existing image , done this way
1378-
//for now to get it working
1379-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1380-
image->fill(Color(1, 0, 1, 1));
1381-
1382-
Vector<Ref<Image>> images;
13831398
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
1384-
images.push_back(image);
1399+
texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type);
13851400
} else {
1386-
//cube
1387-
for (int i = 0; i < 6; i++) {
1388-
images.push_back(image);
1389-
}
1401+
texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type);
13901402
}
1391-
1392-
texture_2d_layered_initialize(p_texture, images, p_layered_type);
13931403
}
13941404

13951405
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
1396-
//this could be better optimized to reuse an existing image , done this way
1397-
//for now to get it working
1398-
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
1399-
image->fill(Color(1, 0, 1, 1));
1400-
1401-
Vector<Ref<Image>> images;
1402-
//cube
1403-
for (int i = 0; i < 4; i++) {
1404-
images.push_back(image);
1405-
}
1406-
1407-
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
1406+
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder);
14081407
}
14091408

14101409
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {

servers/rendering/renderer_rd/storage_rd/texture_storage.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,11 @@ class TextureStorage : public RendererTextureStorage {
520520
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
521521
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
522522

523+
Ref<Image> texture_2d_placeholder;
524+
Vector<Ref<Image>> texture_2d_array_placeholder;
525+
Vector<Ref<Image>> cubemap_placeholder;
526+
Vector<Ref<Image>> texture_3d_placeholder;
527+
523528
//these two APIs can be used together or in combination with the others.
524529
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
525530
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;

0 commit comments

Comments
 (0)