diff options
author | Spartan322 <Megacake1234@gmail.com> | 2024-10-30 05:22:24 -0400 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2024-10-30 05:22:24 -0400 |
commit | 82de309d58c5f0e221b85463cca2983cd7ed0289 (patch) | |
tree | 5c87dc486c61310a1eafc2e7cb2fd52be0d52e22 /servers/rendering/renderer_rd | |
parent | 77eaec766e2e40f2a5d399989d827f9582a3be15 (diff) | |
parent | 8004c7524fb9f43425c4d6f614410a76678e0f7c (diff) | |
download | redot-engine-82de309d58c5f0e221b85463cca2983cd7ed0289.tar.gz |
Merge commit godotengine/godot@8004c7524fb9f43425c4d6f614410a76678e0f7c
Diffstat (limited to 'servers/rendering/renderer_rd')
23 files changed, 437 insertions, 206 deletions
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 4cdb38fd29..48300571d4 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -159,7 +159,7 @@ RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { return Fog::get_singleton()->_create_fog_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); @@ -170,7 +170,7 @@ RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogSha RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); -}; +} //////////////////////////////////////////////////////////////////////////////// // FOG VOLUMES INSTANCE diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index a05a48b064..390829962f 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -235,7 +235,7 @@ public: /* FOG VOLUMES */ - bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; + bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); } virtual RID fog_volume_allocate() override; virtual void fog_volume_initialize(RID p_rid) override; @@ -252,7 +252,7 @@ public: /* FOG VOLUMES INSTANCE */ - bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; + bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); } RID fog_volume_instance_create(RID p_fog_volume); void fog_instance_free(RID p_rid); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 7c83f7b954..e3c5f4fea2 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -469,7 +469,7 @@ public: /* VOXEL GI API */ - bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; + bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); } virtual RID voxel_gi_allocate() override; virtual void voxel_gi_free(RID p_voxel_gi) override; @@ -526,14 +526,14 @@ public: VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->texture; - }; + } _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL(voxel_gi); voxel_gi->render_index = p_index; - }; + } bool voxel_gi_instance_owns(RID p_rid) const { return voxel_gi_instance_owner.owns(p_rid); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 9464d6e249..e71e3f6efb 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -703,7 +703,7 @@ RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); @@ -715,7 +715,7 @@ RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyS RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); -}; +} SkyRD::SkyRD() { roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index b58ed162ef..014bdeba8d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -110,10 +110,10 @@ public: uint32_t projector_use_mipmaps : 1; uint32_t use_depth_fog : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; + uint32_t directional_soft_shadow_samples : 6; + uint32_t directional_penumbra_shadow_samples : 6; }; uint32_t packed_0; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 2de13593c3..71f071e44e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -324,7 +324,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli specialization_constants.push_back(sc); sc.constant_id = 1; - sc.float_value = p_pipeline_key.shader_specialization.packed_1; + sc.int_value = p_pipeline_key.shader_specialization.packed_1; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; + specialization_constants.push_back(sc); + + sc.constant_id = 2; + sc.float_value = p_pipeline_key.shader_specialization.packed_2; sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; specialization_constants.push_back(sc); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index e338ef09df..60216e9b48 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -76,22 +76,23 @@ public: uint32_t use_depth_fog : 1; uint32_t is_multimesh : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t pad : 2; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; + uint32_t directional_soft_shadow_samples : 6; }; uint32_t packed_0; }; union { - float luminance_multiplier; - float packed_1; + uint32_t directional_penumbra_shadow_samples : 6; + uint32_t packed_1; }; - uint32_t packed_2; + union { + float luminance_multiplier; + float packed_2; + }; }; struct UbershaderConstants { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 16b4a5792f..42c73c544a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -913,7 +913,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RenderingServerDefault::redraw_request(); } - state.current_data_buffer_index = (state.current_data_buffer_index + 1) % state.canvas_instance_data_buffers.size(); + state.current_data_buffer_index = (state.current_data_buffer_index + 1) % BATCH_DATA_BUFFER_COUNT; state.current_instance_buffer_index = 0; } @@ -1649,6 +1649,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { default_samplers.default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; } + // preallocate 5 slots for uniform set 3 + state.batch_texture_uniforms.resize(5); + { //shader variants String global_defines; @@ -1976,15 +1979,18 @@ void fragment() { } { + uint32_t cache_size = uint32_t(GLOBAL_GET("rendering/2d/batching/uniform_set_cache_size")); + rid_set_to_uniform_set.set_capacity(cache_size); + } + + { state.max_instances_per_buffer = uint32_t(GLOBAL_GET("rendering/2d/batching/item_buffer_size")); state.max_instance_buffer_size = state.max_instances_per_buffer * sizeof(InstanceData); - state.canvas_instance_data_buffers.resize(3); state.canvas_instance_batches.reserve(200); - for (int i = 0; i < 3; i++) { - DataBuffer db; + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { + DataBuffer &db = state.canvas_instance_data_buffers[i]; db.instance_buffers.push_back(RD::get_singleton()->storage_buffer_create(state.max_instance_buffer_size)); - state.canvas_instance_data_buffers[i] = db; } state.instance_data_array = memnew_arr(InstanceData, state.max_instances_per_buffer); } @@ -2161,7 +2167,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors, 1, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); @@ -2205,14 +2211,47 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::get_singleton()->draw_list_end(); + texture_info_map.clear(); state.current_batch_index = 0; state.canvas_instance_batches.clear(); state.last_instance_index += instance_index; } +RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info) { + InstanceData *instance_data = &state.instance_data_array[p_index]; + // Zero out most fields. + for (int i = 0; i < 4; i++) { + instance_data->modulation[i] = 0.0; + instance_data->ninepatch_margins[i] = 0.0; + instance_data->src_rect[i] = 0.0; + instance_data->dst_rect[i] = 0.0; + } + + instance_data->pad[0] = 0.0; + instance_data->pad[1] = 0.0; + + instance_data->lights[0] = p_lights[0]; + instance_data->lights[1] = p_lights[1]; + instance_data->lights[2] = p_lights[2]; + instance_data->lights[3] = p_lights[3]; + + for (int i = 0; i < 6; i++) { + instance_data->world[i] = p_world[i]; + } + + instance_data->flags = p_base_flags | p_info->flags; // Reset on each command for safety, keep canvas texture binding config. + + instance_data->color_texture_pixel_size[0] = p_info->texpixel_size.width; + instance_data->color_texture_pixel_size[1] = p_info->texpixel_size.height; + + instance_data->pad1 = 0; + + return instance_data; +} + void RendererCanvasRenderRD::_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) { - RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; - RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; + const RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; + const RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; Transform2D base_transform = p_base_transform; @@ -2243,7 +2282,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar light_count++; - if (light_count == state.max_lights_per_item - 1) { + if (light_count == MAX_LIGHTS_PER_ITEM - 1) { break; } } @@ -2260,38 +2299,6 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->use_lighting = use_lighting; } - // new_instance_data should be called after the current_batch is set. - auto new_instance_data = [&]() -> InstanceData * { - InstanceData *instance_data = &state.instance_data_array[r_index]; - // Zero out most fields. - for (int i = 0; i < 4; i++) { - instance_data->modulation[i] = 0.0; - instance_data->ninepatch_margins[i] = 0.0; - instance_data->src_rect[i] = 0.0; - instance_data->dst_rect[i] = 0.0; - } - - instance_data->pad[0] = 0.0; - instance_data->pad[1] = 0.0; - - instance_data->lights[0] = lights[0]; - instance_data->lights[1] = lights[1]; - instance_data->lights[2] = lights[2]; - instance_data->lights[3] = lights[3]; - - for (int i = 0; i < 6; i++) { - instance_data->world[i] = world[i]; - } - - 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_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; - }; - const Item::Command *c = p_item->commands; while (c) { if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { @@ -2313,17 +2320,9 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; } + RenderingServer::CanvasItemTextureRepeat rect_repeat = texture_repeat; if (bool(rect->flags & CANVAS_RECT_TILE)) { - texture_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; - } - - 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_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, rect->texture); + rect_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; } Color modulated = rect->modulate * base_color; @@ -2342,12 +2341,25 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; } - InstanceData *instance_data = new_instance_data(); + bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); + TextureState tex_state(rect->texture, texture_filter, rect_repeat, has_msdf, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(rect->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect; if (rect->texture.is_valid()) { - 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); + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * tex_info->texpixel_size, rect->source.size * tex_info->texpixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); if (dst_rect.size.width < 0) { @@ -2433,13 +2445,18 @@ 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_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(np->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, np->texture); + r_current_batch->tex_info = tex_info; } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); @@ -2448,7 +2465,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_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); + src_rect = Rect2(np->source.position.x * tex_info->texpixel_size.width, np->source.position.y * tex_info->texpixel_size.height, np->source.size.x * tex_info->texpixel_size.width, np->source.size.y * 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 { @@ -2502,10 +2519,15 @@ 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_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(polygon->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, polygon->texture); + r_current_batch->tex_info = tex_info; } // pipeline variant @@ -2515,7 +2537,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = _primitive_type_to_render_primitive(polygon->primitive); } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Color color = base_color; if (use_linear_colors) { @@ -2559,17 +2581,22 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar default: // Unknown point count. break; - }; - - TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, primitive->texture); } } - InstanceData *instance_data = new_instance_data(); + TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(primitive->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { instance_data->points[j * 2 + 0] = primitive->points[j].x; @@ -2587,7 +2614,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar _add_to_batch(r_index, r_batch_broken, r_current_batch); if (primitive->point_count == 4) { - instance_data = new_instance_data(); + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < 3; j++) { int offset = j == 0 ? 0 : 1; @@ -2596,7 +2623,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->points[j * 2 + 1] = primitive->points[j + offset].y; instance_data->uvs[j * 2 + 0] = primitive->uvs[j + offset].x; instance_data->uvs[j * 2 + 1] = primitive->uvs[j + offset].y; - Color col = primitive->colors[j] * base_color; + Color col = primitive->colors[j + offset] * base_color; if (use_linear_colors) { col = col.srgb_to_linear(); } @@ -2623,9 +2650,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, m->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(m->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); r_current_batch->mesh_instance_count = 1; _update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, instance_data->world); @@ -2646,9 +2677,13 @@ 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->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, mm->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(mm->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); instance_data->flags |= 1; // multimesh, trails disabled @@ -2664,10 +2699,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, pt->texture); - - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(pt->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); uint32_t divisor = 1; r_current_batch->mesh_instance_count = particles_storage->particles_get_amount(pt->particles, divisor); @@ -2749,36 +2787,137 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_batch_broken = false; } +#ifdef DEBUG_ENABLED + if (debug_redraw && p_item->debug_redraw_time > 0.0) { + Color dc = debug_redraw_color; + dc.a *= p_item->debug_redraw_time / debug_redraw_time; + + // 1: If commands are different, start a new batch. + if (r_current_batch->command_type != Item::Command::TYPE_RECT) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->command_type = Item::Command::TYPE_RECT; + // it is ok to be null for a TYPE_RECT + r_current_batch->command = nullptr; + // default variant + r_current_batch->shader_variant = SHADER_VARIANT_QUAD; + r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + } + + // 2: If the current batch has lighting, start a new batch. + if (r_current_batch->use_lighting) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->use_lighting = false; + } + + // 3: If the current batch has blend, start a new batch. + if (r_current_batch->has_blend) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->has_blend = false; + } + + TextureState tex_state(default_canvas_texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(default_canvas_texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); + + Rect2 src_rect; + Rect2 dst_rect; + + dst_rect = Rect2(Vector2(), p_item->rect.size); + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + src_rect = Rect2(0, 0, 1, 1); + + instance_data->modulation[0] = dc.r; + instance_data->modulation[1] = dc.g; + instance_data->modulation[2] = dc.b; + instance_data->modulation[3] = dc.a; + + instance_data->src_rect[0] = src_rect.position.x; + instance_data->src_rect[1] = src_rect.position.y; + instance_data->src_rect[2] = src_rect.size.width; + instance_data->src_rect[3] = src_rect.size.height; + + instance_data->dst_rect[0] = dst_rect.position.x; + instance_data->dst_rect[1] = dst_rect.position.y; + instance_data->dst_rect[2] = dst_rect.size.width; + instance_data->dst_rect[3] = dst_rect.size.height; + + _add_to_batch(r_index, r_batch_broken, r_current_batch); + + p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time(); + + RenderingServerDefault::redraw_request(); + + r_batch_broken = false; + } +#endif + if (r_current_clip && reclip) { // will make it re-enable clipping if needed afterwards r_current_clip = nullptr; } } -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) { - UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); - ERR_FAIL_NULL(uniform_set_cache); +void RendererCanvasRenderRD::_before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid) { + RD::get_singleton()->uniform_set_set_invalidation_callback(p_rid, nullptr, nullptr); + RD::get_singleton()->free(p_rid); +} - ERR_FAIL_NULL(p_batch->command); +void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata) { + const RIDSetKey *key = static_cast<RIDSetKey *>(p_userdata); + static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*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) { { - 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); + RIDSetKey key( + p_batch->tex_info->state, + state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + const RID *uniform_set = rid_set_to_uniform_set.getptr(key); + if (uniform_set == nullptr) { + state.batch_texture_uniforms.write[0] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info->diffuse); + state.batch_texture_uniforms.write[1] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info->normal); + state.batch_texture_uniforms.write[2] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info->specular); + state.batch_texture_uniforms.write[3] = RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info->sampler); + state.batch_texture_uniforms.write[4] = RD::Uniform(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + RID rid = RD::get_singleton()->uniform_set_create(state.batch_texture_uniforms, shader.default_version_rd_shader, BATCH_UNIFORM_SET); + ERR_FAIL_COND_MSG(rid.is_null(), "Failed to create uniform set for batch."); + + const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid); + uniform_set = &iter->data; + RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key); + } - 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); + 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); } } + PushConstant push_constant; + push_constant.base_instance_index = p_batch->start; + push_constant.specular_shininess = p_batch->tex_info->specular_shininess; RID pipeline; PipelineKey pipeline_key; - PushConstant push_constant; pipeline_key.framebuffer_format_id = p_framebuffer_format; pipeline_key.variant = p_batch->shader_variant; pipeline_key.render_primitive = p_batch->render_primitive; @@ -2794,7 +2933,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, p_batch->modulate); } - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); 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); @@ -2807,6 +2945,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_POLYGON: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(p_batch->command); PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); @@ -2816,7 +2956,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); if (pb->indices.is_valid()) { @@ -2832,12 +2971,13 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_PRIMITIVE: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(p_batch->command); pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); 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; @@ -2854,6 +2994,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { + ERR_FAIL_NULL(p_batch->command); + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); @@ -2914,7 +3056,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant, mesh_instance, surface, j, &vertex_array); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0); @@ -2996,7 +3137,7 @@ 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_info(Batch *p_current_batch, RID p_texture) const { +void RendererCanvasRenderRD::_prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info) { if (p_texture.is_null()) { p_texture = default_canvas_texture; } @@ -3004,38 +3145,38 @@ void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, 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()); - + p_state.texture_filter(), + p_state.texture_repeat(), + p_state.linear_colors(), + p_state.texture_is_data()); // something odd happened if (info.is_null()) { - _prepare_batch_texture_info(p_current_batch, default_canvas_texture); + _prepare_batch_texture_info(default_canvas_texture, p_state, p_info); 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; + p_info->state = p_state; + p_info->diffuse = info.diffuse; + p_info->normal = info.normal; + p_info->specular = info.specular; + p_info->sampler = info.sampler; // cache values to be copied to instance data if (info.specular_color.a < 0.999) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + p_info->flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (info.use_normal) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + p_info->flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; } 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_info->specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); - p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); + p_info->texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); } RendererCanvasRenderRD::~RendererCanvasRenderRD() { @@ -3077,7 +3218,7 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { RD::get_singleton()->free(state.shadow_texture); memdelete_arr(state.instance_data_array); - for (uint32_t i = 0; i < state.canvas_instance_data_buffers.size(); i++) { + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { for (uint32_t j = 0; j < state.canvas_instance_data_buffers[i].instance_buffers.size(); j++) { RD::get_singleton()->free(state.canvas_instance_data_buffers[i].instance_buffers[j]); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 8ef1221108..a2c39d7181 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -33,6 +33,7 @@ #ifndef RENDERER_CANVAS_RENDER_RD_H #define RENDERER_CANVAS_RENDER_RD_H +#include "core/templates/lru.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" @@ -52,6 +53,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; const int SAMPLERS_BINDING_FIRST_INDEX = 10; + // The size of the ring buffer to store GPU buffers. Triple-buffering the max expected frames in flight. + static const uint32_t BATCH_DATA_BUFFER_COUNT = 3; enum ShaderVariant { SHADER_VARIANT_QUAD, @@ -341,7 +344,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct InstanceData { float world[6]; uint32_t flags; - uint32_t specular_shininess; + uint32_t pad1; union { //rect struct { @@ -368,8 +371,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct PushConstant { uint32_t base_instance_index; ShaderSpecialization shader_specialization; - uint32_t pad2; - uint32_t pad3; + uint32_t specular_shininess; + uint32_t pad; }; // TextureState is used to determine when a new batch is required due to a change of texture state. @@ -400,50 +403,91 @@ class RendererCanvasRenderRD : public RendererCanvasRender { (((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT); } - _FORCE_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK); } - _FORCE_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK); } - _FORCE_INLINE_ bool linear_colors() const { + _ALWAYS_INLINE_ bool linear_colors() const { return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK; } - _FORCE_INLINE_ bool texture_is_data() const { + _ALWAYS_INLINE_ bool texture_is_data() const { return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK; } - bool operator==(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator==(const TextureState &p_val) const { return (texture == p_val.texture) && (other == p_val.other); } - bool operator!=(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator!=(const TextureState &p_val) const { return (texture != p_val.texture) || (other != p_val.other); } + + _ALWAYS_INLINE_ bool is_valid() const { return texture.is_valid(); } + _ALWAYS_INLINE_ bool is_null() const { return texture.is_null(); } + + uint32_t hash() const { + uint32_t hash = hash_murmur3_one_64(texture.get_id()); + return hash_murmur3_one_32(other, hash); + } }; struct TextureInfo { TextureState state; - uint32_t specular_shininess = 0; - uint32_t flags = 0; - Vector2 texpixel_size; - RID diffuse; RID normal; RID specular; RID sampler; + Vector2 texpixel_size; + uint32_t specular_shininess = 0; + uint32_t flags = 0; + }; + + /// A key used to uniquely identify a distinct BATCH_UNIFORM_SET + struct RIDSetKey { + TextureState state; + RID instance_data; + + RIDSetKey() { + } + + RIDSetKey(TextureState p_state, RID p_instance_data) : + state(p_state), + instance_data(p_instance_data) { + } + + _ALWAYS_INLINE_ bool operator==(const RIDSetKey &p_val) const { + return state == p_val.state && instance_data == p_val.instance_data; + } + + _ALWAYS_INLINE_ bool operator!=(const RIDSetKey &p_val) const { + return !(*this == p_val); + } + + _ALWAYS_INLINE_ uint32_t hash() const { + uint32_t h = state.hash(); + h = hash_murmur3_one_64(instance_data.get_id(), h); + return hash_fmix32(h); + } }; + static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid); + static void _uniform_set_invalidation_callback(void *p_userdata); + + typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache; + RIDCache rid_set_to_uniform_set; + struct Batch { // Position in the UBO measured in bytes uint32_t start = 0; uint32_t instance_count = 0; uint32_t instance_buffer_index = 0; - TextureInfo tex_info; + TextureInfo *tex_info; Color modulate = Color(1.0, 1.0, 1.0, 1.0); @@ -468,6 +512,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool has_blend = false; }; + HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map; + + // per-frame buffers struct DataBuffer { LocalVector<RID> instance_buffers; }; @@ -494,7 +541,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t pad2; }; - LocalVector<DataBuffer> canvas_instance_data_buffers; + DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT]; LocalVector<Batch> canvas_instance_batches; uint32_t current_data_buffer_index = 0; uint32_t current_instance_buffer_index = 0; @@ -505,6 +552,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData); + Vector<RD::Uniform> batch_texture_uniforms; RID current_batch_uniform_set; LightUniform *light_uniforms = nullptr; @@ -520,7 +568,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { RID default_transforms_uniform_set; uint32_t max_lights_per_render; - uint32_t max_lights_per_item; double time; @@ -560,7 +607,8 @@ 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, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const; + void _prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info); + InstanceData *new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info); [[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/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 9df54e372e..7514e1d5af 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -68,6 +68,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); + // We need to invert the phone rotation. + int screen_rotation_degrees = -DisplayServer::get_singleton()->screen_get_internal_current_rotation(); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); + // Swap width and height when the orientation is not the native one. + if (screen_rotation_degrees % 180 != 0) { + SWAP(screen_size.width, screen_size.height); + } blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x; blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y; blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width; @@ -230,6 +240,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0); + int screen_rotation_degrees = DisplayServer::get_singleton()->screen_get_internal_current_rotation(); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); blit.push_constant.src_rect[0] = 0.0; blit.push_constant.src_rect[1] = 0.0; blit.push_constant.src_rect[2] = 1.0; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 9a4ad87bf0..728879134f 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -76,6 +76,10 @@ protected: float src_rect[4]; float dst_rect[4]; + float rotation_sin; + float rotation_cos; + float pad[2]; + float eye_center[2]; float k1; float k2; @@ -105,7 +109,7 @@ protected: static RendererCompositorRD *singleton; public: - RendererUtilities *get_utilities() { return utilities; }; + RendererUtilities *get_utilities() { return utilities; } RendererLightStorage *get_light_storage() { return light_storage; } RendererMaterialStorage *get_material_storage() { return material_storage; } RendererMeshStorage *get_mesh_storage() { return mesh_storage; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 7c1b014af1..25a55debdd 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -80,7 +80,7 @@ protected: //////////////////////////////// - virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }; + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); } void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers); diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl index d451647bec..fe6416f03c 100644 --- a/servers/rendering/renderer_rd/shaders/blit.glsl +++ b/servers/rendering/renderer_rd/shaders/blit.glsl @@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; @@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos { float upscale; float aspect_ratio; uint layer; - uint pad1; + bool convert_to_srgb; } data; layout(location = 0) out vec2 uv; void main() { + mat4 swapchain_transform = mat4(1.0); + swapchain_transform[0][0] = data.rotation_cos; + swapchain_transform[0][1] = -data.rotation_sin; + swapchain_transform[1][0] = data.rotation_sin; + swapchain_transform[1][1] = data.rotation_cos; + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw; vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw; - gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0); + gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0); } #[fragment] @@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index dafcce37ad..f665bc24a4 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -28,7 +28,7 @@ layout(location = 11) in vec4 weight_attrib; layout(location = 4) out flat uint instance_index_interp; -#endif // USE_ATTRIBUTES +#endif // !USE_ATTRIBUTES layout(location = 0) out vec2 uv_interp; layout(location = 1) out vec4 color_interp; @@ -322,11 +322,7 @@ vec4 light_compute( #ifdef USE_NINEPATCH float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { -#ifdef USE_ATTRIBUTES - const InstanceData draw_data = instances.data[params.base_instance_index]; -#else const InstanceData draw_data = instances.data[instance_index]; -#endif // USE_ATTRIBUTES float tex_size = 1.0 / tex_pixel_size; @@ -567,7 +563,7 @@ void main() { if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); - specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); + specular_shininess *= unpackUnorm4x8(params.specular_shininess); specular_shininess_used = true; } else { specular_shininess = vec4(1.0); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index ead8c459a4..84017a1fe1 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -37,7 +37,7 @@ struct InstanceData { vec2 world_y; vec2 world_ofs; uint flags; - uint specular_shininess; + uint pad2; #ifdef USE_PRIMITIVE vec2 points[3]; vec2 uvs[3]; @@ -57,8 +57,8 @@ struct InstanceData { layout(push_constant, std430) uniform Params { uint base_instance_index; // base index to instance data uint sc_packed_0; - uint pad2; - uint pad3; + uint specular_shininess; + uint pad; } params; @@ -68,7 +68,7 @@ params; // Pull the constants from the draw call's push constants. uint sc_packed_0() { - return draw_call.sc_packed_0; + return params.sc_packed_0; } #else diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 9f68d59be2..7bfcb2fb12 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -107,19 +107,19 @@ bool sc_use_lightmap_bicubic_filter() { } uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 8) & 15U; + return (sc_packed_0() >> 8) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 12) & 15U; + return (sc_packed_0() >> 14) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 26) & 63U; } float sc_luminance_multiplier() { diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 495e52a29e..df528973da 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -22,8 +22,8 @@ layout(push_constant, std430) uniform DrawCall { uint pad; #ifdef UBERSHADER uint sc_packed_0; - float sc_packed_1; - uint sc_packed_2; + uint sc_packed_1; + float sc_packed_2; uint uc_packed_0; #endif } @@ -42,10 +42,14 @@ uint sc_packed_0() { return draw_call.sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return draw_call.sc_packed_1; } +float sc_packed_2() { + return draw_call.sc_packed_2; +} + uint uc_cull_mode() { return (draw_call.uc_packed_0 >> 0) & 3U; } @@ -54,16 +58,21 @@ uint uc_cull_mode() { // Pull the constants from the pipeline's specialization constants. layout(constant_id = 0) const uint pso_sc_packed_0 = 0; -layout(constant_id = 1) const float pso_sc_packed_1 = 2.0; +layout(constant_id = 1) const uint pso_sc_packed_1 = 0; +layout(constant_id = 2) const float pso_sc_packed_2 = 2.0; uint sc_packed_0() { return pso_sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return pso_sc_packed_1; } +float sc_packed_2() { + return pso_sc_packed_2; +} + #endif bool sc_use_light_projector() { @@ -123,23 +132,23 @@ bool sc_use_lightmap_bicubic_filter() { } uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 14) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 24) & 15U; + return (sc_packed_0() >> 26) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 28) & 15U; + return (sc_packed_1() >> 0) & 63U; } float sc_luminance_multiplier() { - return sc_packed_1(); + return sc_packed_2(); } /* Set 0: Base Pass (never changes) */ diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index d219047cba..410a6ae5c6 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -1051,7 +1051,7 @@ void LightStorage::reflection_probe_free(RID p_rid) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->dependency.deleted_notify(p_rid); reflection_probe_owner.free(p_rid); -}; +} void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 210e4c3035..7cd7d3e363 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -592,7 +592,7 @@ public: /* LIGHT INSTANCE API */ - bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }; + bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); } virtual RID light_instance_create(RID p_light) override; virtual void light_instance_free(RID p_light) override; @@ -813,7 +813,7 @@ public: /* REFLECTION PROBE */ - bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; + bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); } virtual RID reflection_probe_allocate() override; virtual void reflection_probe_initialize(RID p_reflection_probe) override; @@ -955,7 +955,7 @@ public: /* LIGHTMAP */ - bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; + bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); } virtual RID lightmap_allocate() override; virtual void lightmap_initialize(RID p_lightmap) override; @@ -1021,7 +1021,7 @@ public: /* LIGHTMAP INSTANCE */ - bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }; + bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); } virtual RID lightmap_instance_create(RID p_lightmap) override; virtual void lightmap_instance_free(RID p_lightmap) override; @@ -1041,7 +1041,7 @@ public: /* SHADOW ATLAS API */ - bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }; + bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); } virtual RID shadow_atlas_create() override; virtual void shadow_atlas_free(RID p_atlas) override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 2f477c4196..e6a25c547a 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -256,7 +256,7 @@ private: MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner<Material, true> material_owner; - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); } SelfList<Material>::List material_update_list; Mutex material_update_list_mutex; @@ -405,7 +405,7 @@ public: /* SHADER API */ - bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); } virtual RID shader_allocate() override; virtual void shader_initialize(RID p_shader) override; @@ -425,7 +425,7 @@ public: /* MATERIAL API */ - bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); } void _material_queue_update(Material *material, bool p_uniform, bool p_texture); void _update_queued_materials(); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 79bd8d0be2..e70b7568e0 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -353,7 +353,7 @@ public: /* MESH API */ - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_mesh) override; @@ -618,7 +618,7 @@ public: /* MESH INSTANCE API */ - bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }; + bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); } virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -630,7 +630,7 @@ public: /* MULTIMESH API */ - bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); } virtual RID _multimesh_allocate() override; virtual void _multimesh_initialize(RID p_multimesh) override; @@ -739,7 +739,7 @@ public: /* SKELETON API */ - bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }; + bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); } virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_skeleton) override; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 4e257f0e04..2d59b822a0 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -124,7 +124,6 @@ private: Size2i size_cache = Size2i(1, 1); bool use_normal_cache = false; bool use_specular_cache = false; - bool cleared_cache = true; void clear_cache(); ~CanvasTexture(); @@ -197,7 +196,7 @@ private: // Textures can be created from threads, so this RID_Owner is thread safe. mutable RID_Owner<Texture, true> texture_owner; - Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); } struct TextureToRDFormat { RD::DataFormat format; @@ -441,7 +440,7 @@ private: }; mutable RID_Owner<RenderTarget> render_target_owner; - RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }; + RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); } void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); @@ -488,7 +487,7 @@ public: /* Canvas Texture API */ - bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); } virtual RID canvas_texture_allocate() override; virtual void canvas_texture_initialize(RID p_rid) override; @@ -504,7 +503,7 @@ public: /* Texture API */ - bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); } virtual RID texture_allocate() override; virtual void texture_free(RID p_rid) override; @@ -593,7 +592,7 @@ public: void update_decal_atlas(); - bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }; + bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); } RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; @@ -733,7 +732,7 @@ public: /* RENDER TARGET API */ - bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; + bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); } virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h index 5fafe2752d..bdbe7af803 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.h +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -79,8 +79,8 @@ public: /* VISIBILITY NOTIFIER */ - VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }; - bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }; + VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); } + bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); } virtual RID visibility_notifier_allocate() override; virtual void visibility_notifier_initialize(RID p_notifier) override; |