diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 57497eb2070..5441e28be01 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1974,6 +1974,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { default_canvas_texture = texture_storage->canvas_texture_allocate(); texture_storage->canvas_texture_initialize(default_canvas_texture); + RendererRD::TextureStorage::CanvasTextureInfo info = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(default_canvas_texture, default_filter, default_repeat, false, false); + default_texture_info.diffuse = info.diffuse; + default_texture_info.normal = info.normal; + default_texture_info.specular = info.specular; + default_texture_info.sampler = info.sampler; + state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); //create functions for shader and material @@ -2219,7 +2225,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); Item *current_clip = nullptr; - state.current_tex_uniform_set = RID(); + state.current_batch_uniform_set = RID(); for (uint32_t i = 0; i <= state.current_batch_index; i++) { Batch *current_batch = &state.canvas_instance_batches[i]; @@ -2337,11 +2343,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->world[i] = world[i]; } - instance_data->flags = base_flags | r_current_batch->tex_flags; // Reset on each command for safety, keep canvas texture binding config. + instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config. - instance_data->color_texture_pixel_size[0] = r_current_batch->tex_texpixel_size.width; - instance_data->color_texture_pixel_size[1] = r_current_batch->tex_texpixel_size.height; - instance_data->specular_shininess = r_current_batch->tex_specular_shininess; + instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width; + instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height; + instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess; return instance_data; }; @@ -2373,10 +2379,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors); - if (tex_state != r_current_batch->tex_state) { + if (tex_state != r_current_batch->tex_info.state) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, rect->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, rect->texture); } Color modulated = rect->modulate * base_color; @@ -2399,7 +2405,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar Rect2 dst_rect; if (rect->texture.is_valid()) { - src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_texpixel_size, rect->source.size * r_current_batch->tex_texpixel_size) : Rect2(0, 0, 1, 1); + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); if (dst_rect.size.width < 0) { @@ -2484,10 +2490,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_state) { + if (tex_state != r_current_batch->tex_info.state) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, np->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, np->texture); } InstanceData *instance_data = new_instance_data(); @@ -2499,7 +2505,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar src_rect = Rect2(0, 0, 1, 1); } else { if (np->source != Rect2()) { - src_rect = Rect2(np->source.position.x * r_current_batch->tex_texpixel_size.width, np->source.position.y * r_current_batch->tex_texpixel_size.height, np->source.size.x * r_current_batch->tex_texpixel_size.width, np->source.size.y * r_current_batch->tex_texpixel_size.height); + src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height); instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width; instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height; } else { @@ -2553,10 +2559,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command = c; TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_state) { + if (tex_state != r_current_batch->tex_info.state) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, polygon->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, polygon->texture); } // pipeline variant @@ -2596,10 +2602,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->pipeline_variant = variant[primitive->point_count - 1]; TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_state) { + if (tex_state != r_current_batch->tex_info.state) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, primitive->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, primitive->texture); } } @@ -2657,8 +2663,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast(c); TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, m->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, m->texture); instance_data = new_instance_data(); r_current_batch->mesh_instance_count = 1; @@ -2680,8 +2686,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, mm->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, mm->texture); instance_data = new_instance_data(); instance_data->flags |= 1; // multimesh, trails disabled @@ -2698,8 +2704,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar const Item::CommandParticles *pt = static_cast(c); TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->set_tex_state(tex_state); - _prepare_batch_texture(r_current_batch, pt->texture); + r_current_batch->tex_info.state = tex_state; + _prepare_batch_texture_info(r_current_batch, pt->texture); instance_data = new_instance_data(); @@ -2795,7 +2801,20 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV ERR_FAIL_NULL(p_batch->command); - _bind_canvas_texture(p_draw_list, p_batch->tex_uniform_set); + { + RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse); + RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal); + RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular); + RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler); + RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data); + + if (state.current_batch_uniform_set != uniform_set) { + state.current_batch_uniform_set = uniform_set; + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET); + } + } switch (p_batch->command_type) { case Item::Command::TYPE_RECT: @@ -2810,13 +2829,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV PushConstant push_constant; push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - RD::get_singleton()->draw_list_bind_uniform_set( - p_draw_list, - uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data), - INSTANCE_DATA_UNIFORM_SET); - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count); @@ -2839,13 +2851,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV PushConstant push_constant; push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - RD::get_singleton()->draw_list_bind_uniform_set( - p_draw_list, - uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data), - INSTANCE_DATA_UNIFORM_SET); - RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); if (pb->indices.is_valid()) { RD::get_singleton()->draw_list_bind_index_array(p_draw_list, pb->indices); @@ -2868,13 +2873,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV PushConstant push_constant; push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - RD::get_singleton()->draw_list_bind_uniform_set( - p_draw_list, - uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data), - INSTANCE_DATA_UNIFORM_SET); - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]); uint32_t instance_count = p_batch->instance_count; RD::get_singleton()->draw_list_draw(p_draw_list, true, instance_count); @@ -2934,12 +2932,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV break; } - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - RD::get_singleton()->draw_list_bind_uniform_set( - p_draw_list, - uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data), - INSTANCE_DATA_UNIFORM_SET); - uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh); static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; @@ -3046,60 +3038,46 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() { state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf); } -void RendererCanvasRenderRD::_prepare_batch_texture(Batch *p_current_batch, RID p_texture) const { +void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const { if (p_texture.is_null()) { p_texture = default_canvas_texture; } - Color specular_shininess; - bool use_normal; - bool use_specular; - Size2i size; - bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set( - p_texture, - p_current_batch->tex_state.texture_filter(), - p_current_batch->tex_state.texture_repeat(), - shader.default_version_rd_shader, - CANVAS_TEXTURE_UNIFORM_SET, - p_current_batch->tex_state.linear_colors(), - p_current_batch->tex_uniform_set, - size, - specular_shininess, - use_normal, - use_specular, - p_current_batch->tex_state.texture_is_data()); + RendererRD::TextureStorage::CanvasTextureInfo info = + RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info( + p_texture, + p_current_batch->tex_info.state.texture_filter(), + p_current_batch->tex_info.state.texture_repeat(), + p_current_batch->tex_info.state.linear_colors(), + p_current_batch->tex_info.state.texture_is_data()); + // something odd happened - if (!success) { - _prepare_batch_texture(p_current_batch, default_canvas_texture); + if (info.is_null()) { + _prepare_batch_texture_info(p_current_batch, default_canvas_texture); return; } + p_current_batch->tex_info.diffuse = info.diffuse; + p_current_batch->tex_info.normal = info.normal; + p_current_batch->tex_info.specular = info.specular; + p_current_batch->tex_info.sampler = info.sampler; + // cache values to be copied to instance data - if (specular_shininess.a < 0.999) { - p_current_batch->tex_flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + if (info.specular_color.a < 0.999) { + p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; } - if (use_normal) { - p_current_batch->tex_flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + if (info.use_normal) { + p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; } - uint8_t a = uint8_t(CLAMP(specular_shininess.a * 255.0, 0.0, 255.0)); - uint8_t b = uint8_t(CLAMP(specular_shininess.b * 255.0, 0.0, 255.0)); - uint8_t g = uint8_t(CLAMP(specular_shininess.g * 255.0, 0.0, 255.0)); - uint8_t r = uint8_t(CLAMP(specular_shininess.r * 255.0, 0.0, 255.0)); - p_current_batch->tex_specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); + uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0)); + uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0)); + uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0)); + uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0)); + p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); - p_current_batch->tex_texpixel_size = Vector2(1.0 / float(size.width), 1.0 / float(size.height)); -} - -void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set) { - if (state.current_tex_uniform_set == p_uniform_set) { - return; - } - - state.current_tex_uniform_set = p_uniform_set; - - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, p_uniform_set, CANVAS_TEXTURE_UNIFORM_SET); + p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); } RendererCanvasRenderRD::~RendererCanvasRenderRD() { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 8d90cd23ce2..b0f4a4595a1 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -45,8 +45,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { BASE_UNIFORM_SET = 0, MATERIAL_UNIFORM_SET = 1, TRANSFORMS_UNIFORM_SET = 2, - CANVAS_TEXTURE_UNIFORM_SET = 3, - INSTANCE_DATA_UNIFORM_SET = 4, + BATCH_UNIFORM_SET = 3, }; const int SAMPLERS_BINDING_FIRST_INDEX = 10; @@ -423,24 +422,25 @@ class RendererCanvasRenderRD : public RendererCanvasRender { } }; + struct TextureInfo { + TextureState state; + uint32_t specular_shininess = 0; + uint32_t flags = 0; + Vector2 texpixel_size; + + RID diffuse; + RID normal; + RID specular; + RID sampler; + }; + struct Batch { // Position in the UBO measured in bytes uint32_t start = 0; uint32_t instance_count = 0; uint32_t instance_buffer_index = 0; - TextureState tex_state; - RID tex_uniform_set; - - // The following tex_ prefixed fields are used to cache the texture data for the current batch. - // These values are applied to new InstanceData for the batch - - // The cached specular shininess derived from the current texture. - uint32_t tex_specular_shininess = 0; - // The cached texture flags, such as FLAGS_DEFAULT_SPECULAR_MAP_USED and FLAGS_DEFAULT_NORMAL_MAP_USED - uint32_t tex_flags = 0; - // The cached texture pixel size. - Vector2 tex_texpixel_size; + TextureInfo tex_info; Color modulate = Color(1.0, 1.0, 1.0, 1.0); @@ -462,14 +462,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t mesh_instance_count; }; bool has_blend = false; - - void set_tex_state(TextureState &p_tex_state) { - tex_state = p_tex_state; - tex_uniform_set = RID(); - tex_texpixel_size = Size2(); - tex_specular_shininess = 0; - tex_flags = 0; - } }; struct DataBuffer { @@ -509,7 +501,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData); - RID current_tex_uniform_set; + RID current_batch_uniform_set; LightUniform *light_uniforms = nullptr; @@ -532,6 +524,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { Item *items[MAX_RENDER_ITEMS]; + TextureInfo default_texture_info; + bool using_directional_lights = false; RID default_canvas_texture; @@ -561,8 +555,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch); void _render_batch(RD::DrawListID p_draw_list, PipelineVariants *p_pipeline_variants, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _prepare_batch_texture(Batch *p_current_batch, RID p_texture) const; - void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set); + void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const; [[nodiscard]] Batch *_new_batch(bool &r_batch_broken); void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch); void _allocate_instance_buffer(); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 7cf5b4576e6..fc9b727581e 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -54,11 +54,6 @@ struct InstanceData { uint lights[4]; }; -layout(set = 4, binding = 0, std430) restrict readonly buffer DrawData { - InstanceData data[]; -} -instances; - layout(push_constant, std430) uniform Params { uint base_instance_index; // base index to instance data uint pad1; @@ -163,3 +158,8 @@ layout(set = 3, binding = 0) uniform texture2D color_texture; layout(set = 3, binding = 1) uniform texture2D normal_texture; layout(set = 3, binding = 2) uniform texture2D specular_texture; layout(set = 3, binding = 3) uniform sampler texture_sampler; + +layout(set = 3, binding = 4, std430) restrict readonly buffer DrawData { + InstanceData data[]; +} +instances; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index e5a8dbb9b2b..84e8d1d6718 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -40,25 +40,12 @@ using namespace RendererRD; /////////////////////////////////////////////////////////////////////////// // TextureStorage::CanvasTexture -void TextureStorage::CanvasTexture::clear_sets() { - if (cleared_cache) { - return; - } - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - for (int k = 0; k < 2; k++) { - if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j][k])) { - RD::get_singleton()->free(uniform_sets[i][j][k]); - uniform_sets[i][j][k] = RID(); - } - } - } - } - cleared_cache = true; +void TextureStorage::CanvasTexture::clear_cache() { + info_cache[0] = CanvasTextureCache(); + info_cache[1] = CanvasTextureCache(); } TextureStorage::CanvasTexture::~CanvasTexture() { - clear_sets(); } /////////////////////////////////////////////////////////////////////////// @@ -612,8 +599,7 @@ void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::Canvas ct->specular = p_texture; } break; } - - ct->clear_sets(); + ct->clear_cache(); } void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { @@ -624,7 +610,6 @@ void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, ct->specular_color.g = p_specular_color.g; ct->specular_color.b = p_specular_color.b; ct->specular_color.a = p_shininess; - ct->clear_sets(); } void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { @@ -632,7 +617,6 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS: ERR_FAIL_NULL(ct); ct->texture_filter = p_filter; - ct->clear_sets(); } void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { @@ -640,17 +624,14 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS: ERR_FAIL_NULL(ct); ct->texture_repeat = p_repeat; - ct->clear_sets(); } -bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data) { +TextureStorage::CanvasTextureInfo TextureStorage::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) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); CanvasTexture *ct = nullptr; Texture *t = get_texture(p_texture); - // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture - if (t) { //regular texture if (!t->canvas_texture) { @@ -667,93 +648,71 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte } if (!ct) { - return false; //invalid texture RID + return CanvasTextureInfo(); //invalid texture RID } RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; - ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); + ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasTextureInfo()); RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; - ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); + ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, CanvasTextureInfo()); - RID uniform_set = ct->uniform_sets[filter][repeat][int(p_use_srgb)]; - if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //create and update - Vector uniforms; + CanvasTextureCache &ctc = ct->info_cache[int(p_use_srgb)]; + if (!RD::get_singleton()->texture_is_valid(ctc.diffuse) || + !RD::get_singleton()->texture_is_valid(ctc.normal) || + !RD::get_singleton()->texture_is_valid(ctc.specular)) { { //diffuse - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - t = get_texture(ct->diffuse); if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ctc.diffuse = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); ct->size_cache = Size2i(1, 1); } else { - u.append_id(t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture); + ctc.diffuse = t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture; ct->size_cache = Size2i(t->width_2d, t->height_2d); if (t->render_target) { t->render_target->was_used = true; } } - uniforms.push_back(u); } { //normal - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - t = get_texture(ct->normal_map); if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + ctc.normal = texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); ct->use_normal_cache = false; } else { - u.append_id(t->rd_texture); + ctc.normal = t->rd_texture; ct->use_normal_cache = true; if (t->render_target) { t->render_target->was_used = true; } } - uniforms.push_back(u); } { //specular - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - t = get_texture(ct->specular); if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ctc.specular = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); ct->use_specular_cache = false; } else { - u.append_id(t->rd_texture); + ctc.specular = t->rd_texture; ct->use_specular_cache = true; if (t->render_target) { t->render_target->was_used = true; } } - uniforms.push_back(u); } - { //sampler - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 3; - u.append_id(material_storage->sampler_rd_get_default(filter, repeat)); - uniforms.push_back(u); - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); - ct->uniform_sets[filter][repeat][int(p_use_srgb)] = uniform_set; - ct->cleared_cache = false; } - r_uniform_set = uniform_set; - r_size = ct->size_cache; - r_specular_shininess = ct->specular_color; - r_use_normal = ct->use_normal_cache; - r_use_specular = ct->use_specular_cache; + CanvasTextureInfo res; + res.diffuse = ctc.diffuse; + res.normal = ctc.normal; + res.specular = ctc.specular; + res.sampler = material_storage->sampler_rd_get_default(filter, repeat); + res.size = ct->size_cache; + res.specular_color = ct->specular_color; + res.use_normal = ct->use_normal_cache; + res.use_specular = ct->use_specular_cache; - return true; + return res; } /* Texture API */ diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 9de4ff7b6b9..8aecc78f071 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -76,6 +76,21 @@ public: TYPE_3D }; + struct CanvasTextureInfo { + RID diffuse; + RID normal; + RID specular; + RID sampler; + Size2i size; + Color specular_color; + + bool use_normal = false; + bool use_specular = false; + + _FORCE_INLINE_ bool is_valid() const { return diffuse.is_valid(); } + _FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); } + }; + private: friend class LightStorage; friend class MaterialStorage; @@ -86,6 +101,12 @@ private: /* Canvas Texture API */ + struct CanvasTextureCache { + RID diffuse = RID(); + RID normal = RID(); + RID specular = RID(); + }; + class CanvasTexture { public: RID diffuse; @@ -96,14 +117,14 @@ private: RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX][2]; + CanvasTextureCache info_cache[2]; Size2i size_cache = Size2i(1, 1); bool use_normal_cache = false; bool use_specular_cache = false; bool cleared_cache = true; - void clear_sets(); + void clear_cache(); ~CanvasTexture(); }; @@ -477,7 +498,7 @@ public: virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; - bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, 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); /* Texture API */