diff options
Diffstat (limited to 'servers/rendering')
24 files changed, 297 insertions, 135 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index 83da8388e4..7032f3fb03 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -109,7 +109,7 @@ public: void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {} + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} void environment_glow_set_use_high_quality(bool p_enable) override {} diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 4ab50782df..7183fd110f 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -115,6 +115,43 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) return uniform_set; } +RID EffectsRD::_get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) { + TexturePair tp; + tp.texture1 = p_texture1; + tp.texture2 = p_texture2; + + if (texture_pair_to_uniform_set_cache.has(tp)) { + RID uniform_set = texture_pair_to_uniform_set_cache[tp]; + if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + return uniform_set; + } + } + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.ids.push_back(p_texture1); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.ids.push_back(p_texture2); + uniforms.push_back(u); + } + // anything with the same configuration (one texture in binding 0 for set 0), is good + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 2); + + texture_pair_to_uniform_set_cache[tp] = uniform_set; + + return uniform_set; +} + RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { if (texture_to_compute_uniform_set_cache.has(p_texture)) { RID uniform_set = texture_to_compute_uniform_set_cache[p_texture]; @@ -828,6 +865,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone tonemap.push_constant.use_glow = p_settings.use_glow; tonemap.push_constant.glow_intensity = p_settings.glow_intensity; + tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength; tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1]; tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2]; @@ -867,7 +905,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass())); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3); RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); @@ -907,7 +945,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass())); RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0); RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored - RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); // should be set to a default texture, it's ignored + RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2); // should be set to a default texture, it's ignored RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3); RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array); @@ -1415,7 +1453,6 @@ void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); - ss_effects.used_full_mips_last_frame = use_mips; ss_effects.used_full_mips_last_frame = use_full_mips; ss_effects.used_half_size_last_frame = use_half_size; } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index a3fb4db3df..1a080756a8 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -274,7 +274,7 @@ private: uint32_t glow_texture_size[2]; // 8 - 40 float glow_intensity; // 4 - 44 - uint32_t pad3; // 4 - 48 + float glow_map_strength; // 4 - 48 uint32_t glow_mode; // 4 - 52 float glow_levels[7]; // 28 - 80 @@ -874,6 +874,7 @@ private: } }; + Map<TexturePair, RID> texture_pair_to_uniform_set_cache; Map<RID, RID> texture_to_compute_uniform_set_cache; Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache; @@ -882,6 +883,7 @@ private: RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_for_input(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); + RID _get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler); RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false); @@ -943,10 +945,12 @@ public: GlowMode glow_mode = GLOW_MODE_ADD; float glow_intensity = 1.0; + float glow_map_strength = 0.0f; float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 }; Vector2i glow_texture_size; bool glow_use_bicubic_upscale = false; RID glow_texture; + RID glow_map; RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR; float exposure = 1.0; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 36604073cc..87301a9d3a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1081,6 +1081,10 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con distance = -distance_max; } + if (p_render_data->cam_ortogonal) { + distance = 1.0; + } + uint32_t indices; surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index b9c51f5461..778d7baa5d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1042,7 +1042,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in RENDER_TIMESTAMP("Render Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, 0); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, false); //regular forward for now Vector<Color> clear = { Color(0, 0, 0, 0), @@ -1429,6 +1429,10 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const distance = -distance_max; } + if (p_render_data->cam_ortogonal) { + distance = 1.0; + } + uint32_t indices; surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp index 0d0d7513d0..0d9477d850 100644 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp @@ -54,7 +54,7 @@ void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_ma auto_exp_scale = p_auto_exp_scale; } -void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) { +void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); glow_enabled = p_enable; glow_levels = p_levels; @@ -66,6 +66,8 @@ void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, glow_hdr_bleed_threshold = p_hdr_bleed_threshold; glow_hdr_bleed_scale = p_hdr_bleed_scale; glow_hdr_luminance_cap = p_hdr_luminance_cap; + glow_map_strength = p_glow_map_strength; + glow_map = p_glow_map; } void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h index 629d224b49..ed26fd467b 100644 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h @@ -102,6 +102,8 @@ public: float glow_hdr_bleed_threshold = 1.0; float glow_hdr_luminance_cap = 12.0; float glow_hdr_bleed_scale = 2.0; + float glow_map_strength = 0.0f; + RID glow_map = RID(); /// SSAO @@ -154,7 +156,7 @@ public: void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source); void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap); + void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map); void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective); void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 126f40584a..43a1812f89 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -289,10 +289,10 @@ void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentTo env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale); } -void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) { +void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); ERR_FAIL_COND(!env); - env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap); + env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map); } void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) { @@ -925,7 +925,7 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool } for (int i = 0; i < 4; i++) { //clear subdivisions - shadow_atlas->quadrants[i].shadows.resize(0); + shadow_atlas->quadrants[i].shadows.clear(); shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); } @@ -972,7 +972,7 @@ void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, i } } - shadow_atlas->quadrants[p_quadrant].shadows.resize(0); + shadow_atlas->quadrants[p_quadrant].shadows.clear(); shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv); shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; @@ -1132,11 +1132,11 @@ bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_ return false; } -bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { +bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); ERR_FAIL_COND_V(!shadow_atlas, false); - LightInstance *li = light_instance_owner.get_or_null(p_light_intance); + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); ERR_FAIL_COND_V(!li, false); if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { @@ -1185,8 +1185,8 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i bool should_realloc = false; bool should_redraw = false; - if (shadow_atlas->shadow_owners.has(p_light_intance)) { - old_key = shadow_atlas->shadow_owners[p_light_intance]; + if (shadow_atlas->shadow_owners.has(p_light_instance)) { + old_key = shadow_atlas->shadow_owners[p_light_instance]; old_quadrant = (old_key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; old_shadow = old_key & ShadowAtlas::SHADOW_INDEX_MASK; @@ -1230,7 +1230,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow); - sh->owner = p_light_intance; + sh->owner = p_light_instance; sh->alloc_tick = tick; sh->version = p_light_version; @@ -1241,7 +1241,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow]; _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow); - extra_sh->owner = p_light_intance; + extra_sh->owner = p_light_instance; extra_sh->alloc_tick = tick; extra_sh->version = p_light_version; } @@ -1249,7 +1249,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i li->shadow_atlases.insert(p_atlas); //update it in map - shadow_atlas->shadow_owners[p_light_intance] = new_key; + shadow_atlas->shadow_owners[p_light_instance] = new_key; //make it dirty, as it should redraw anyway return true; } @@ -1270,10 +1270,10 @@ void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderR omni_shadow->owner = RID(); } + p_shadow_atlas->shadow_owners.erase(p_shadow->owner); p_shadow->version = 0; p_shadow->owner = RID(); sli->shadow_atlases.erase(p_atlas); - p_shadow_atlas->shadow_owners.erase(p_shadow->owner); } } @@ -1920,6 +1920,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->ambient_buffer = RID(); rb->reflection_buffer = RID(); } + + if (rb->gi.voxel_gi_buffer.is_valid()) { + RD::get_singleton()->free(rb->gi.voxel_gi_buffer); + rb->gi.voxel_gi_buffer = RID(); + } } void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { @@ -2496,8 +2501,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; tonemap.glow_texture = rb->blur[1].texture; + if (env->glow_map.is_valid()) { + tonemap.glow_map_strength = env->glow_map_strength; + tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map); + } else { + tonemap.glow_map_strength = 0.0f; + tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + } else { tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2590,6 +2604,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr tonemap.use_glow = false; tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); @@ -2636,8 +2651,12 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { if (p_shadow_atlas.is_valid()) { RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); - Size2 rtsize = storage->render_target_get_size(rb->render_target); + if (shadow_atlas_texture.is_null()) { + shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + } + + Size2 rtsize = storage->render_target_get_size(rb->render_target); effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 276cb8f229..899d2d763d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -983,7 +983,7 @@ public: virtual RID shadow_atlas_create() override; virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override; virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override; _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); ERR_FAIL_COND_V(!atlas, false); @@ -1061,7 +1061,7 @@ public: virtual bool is_environment(RID p_env) const override; - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override; + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override; virtual void environment_glow_set_use_high_quality(bool p_enable) override; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 856ea5e74d..f6f39230f8 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -590,6 +590,7 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { if (material.is_valid()) { p_storage->free(material); + material = RID(); } } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 2e63ac57d9..145c4f902e 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -6238,7 +6238,7 @@ void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool if (skeleton->buffer.is_valid()) { RD::get_singleton()->free(skeleton->buffer); skeleton->buffer = RID(); - skeleton->data.resize(0); + skeleton->data.clear(); skeleton->uniform_set_mi = RID(); } diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl index 948c6e1e39..41d41758f4 100644 --- a/servers/rendering/renderer_rd/shaders/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl @@ -45,6 +45,7 @@ layout(set = 0, binding = 0) uniform sampler2D source_color; layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; layout(set = 2, binding = 0) uniform sampler2D source_glow; +layout(set = 2, binding = 1) uniform sampler2D glow_map; #ifdef USE_1D_LUT layout(set = 3, binding = 0) uniform sampler2D source_color_correction; @@ -63,7 +64,7 @@ layout(push_constant, binding = 1, std430) uniform Params { uvec2 glow_texture_size; float glow_intensity; - uint pad3; + float glow_map_strength; uint glow_mode; float glow_levels[7]; @@ -405,6 +406,9 @@ void main() { #ifndef SUBPASS if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) { vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier; + if (params.glow_map_strength > 0.001) { + glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength); + } color.rgb = mix(color.rgb, glow, params.glow_intensity); } @@ -425,9 +429,11 @@ void main() { #ifndef SUBPASS // Glow - if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) { vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier; + if (params.glow_map_strength > 0.001) { + glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength); + } // high dynamic range -> SRGB glow = apply_tonemapping(glow, params.white); diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index 426d22f83e..406d946e12 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -131,7 +131,7 @@ public: virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0; - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 8ded180633..5b2be8e174 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -3871,8 +3871,12 @@ void RendererSceneCull::update_dirty_instances() { void RendererSceneCull::update() { //optimize bvhs - for (uint32_t i = 0; i < scenario_owner.get_rid_count(); i++) { - Scenario *s = scenario_owner.get_ptr_by_index(i); + + uint32_t rid_count = scenario_owner.get_rid_count(); + RID *rids = (RID *)alloca(sizeof(RID) * rid_count); + scenario_owner.fill_owned_buffer(rids); + for (uint32_t i = 0; i < rid_count; i++) { + Scenario *s = scenario_owner.get_or_null(rids[i]); s->indexers[Scenario::INDEXER_GEOMETRY].optimize_incremental(indexer_update_iterations); s->indexers[Scenario::INDEXER_VOLUMES].optimize_incremental(indexer_update_iterations); } diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 1e770ef66c..ed0229f0f9 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -1113,7 +1113,7 @@ public: PASS6(environment_set_ssil, RID, bool, float, float, float, float) PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float) - PASS11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float) + PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID) PASS1(environment_glow_set_use_bicubic_upscale, bool) PASS1(environment_glow_set_use_high_quality, bool) diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index c34a46d166..3eb90ccc4d 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -123,7 +123,7 @@ public: virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; #endif - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 17a665922f..5a84bace2d 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -549,8 +549,13 @@ void RendererViewport::draw_viewports() { // get our xr interface in case we need it Ref<XRInterface> xr_interface; - if (XRServer::get_singleton() != nullptr) { - xr_interface = XRServer::get_singleton()->get_primary_interface(); + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + // let our XR server know we're about to render our frames so we can get our frame timing + xr_server->pre_render(); + + // retrieve the interface responsible for rendering + xr_interface = xr_server->get_primary_interface(); } if (Engine::get_singleton()->is_editor_hint()) { @@ -582,19 +587,26 @@ void RendererViewport::draw_viewports() { bool visible = vp->viewport_to_screen_rect != Rect2(); - if (vp->use_xr && xr_interface.is_valid()) { - visible = true; // XR viewport is always visible regardless of update mode, output is sent to HMD. - - // Override our size, make sure it matches our required size and is created as a stereo target - Size2 xr_size = xr_interface->get_render_target_size(); - - // Would have been nice if we could call viewport_set_size here, - // but alas that takes our RID and we now have our pointer, - // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change - vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size); - vp->size = xr_size; - uint32_t view_count = xr_interface->get_view_count(); - RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count); + if (vp->use_xr) { + if (xr_interface.is_valid()) { + // Override our size, make sure it matches our required size and is created as a stereo target + Size2 xr_size = xr_interface->get_render_target_size(); + + // Would have been nice if we could call viewport_set_size here, + // but alas that takes our RID and we now have our pointer, + // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change + vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size); + vp->size = xr_size; + uint32_t view_count = xr_interface->get_view_count(); + RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count); + + // Inform xr interface we're about to render its viewport, if this returns false we don't render + visible = xr_interface->pre_draw_viewport(vp->render_target); + } else { + // don't render anything + visible = false; + vp->size = Size2(); + } } if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) { @@ -647,7 +659,7 @@ void RendererViewport::draw_viewports() { // measure // commit our eyes - Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect); + Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect); if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) { if (!blit_to_screen_list.has(vp->viewport_to_screen)) { blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>(); @@ -657,9 +669,6 @@ void RendererViewport::draw_viewports() { blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]); } } - - // and for our frame timing, mark when we've finished committing our eyes - XRServer::get_singleton()->_mark_commit(); } else { RSG::storage->render_target_set_external_texture(vp->render_target, 0); @@ -813,7 +822,7 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) { ERR_FAIL_COND(!viewport); if (p_active) { - ERR_FAIL_COND_MSG(active_viewports.find(viewport) != -1, "Can't make active a Viewport that is already active."); + ERR_FAIL_COND_MSG(active_viewports.has(viewport), "Can't make active a Viewport that is already active."); viewport->occlusion_buffer_dirty = true; active_viewports.push_back(viewport); } else { diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index 19cde610ba..e50ac42027 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -99,11 +99,11 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String if (reading_versions) { String l = line.strip_edges(); if (!l.is_empty()) { - if (l.find("=") == -1) { + if (!l.contains("=")) { base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`."; break; } - if (l.find(";") == -1) { + if (!l.contains(";")) { // We don't require a semicolon per se, but it's needed for clang-format to handle things properly. base_error = "Missing `;` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`."; break; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index d7e9d210db..d93aad5d7b 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -93,6 +93,12 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::rasterizer->end_frame(p_swap_buffers); + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + // let our XR server know we're done so we can get our frame timing + xr_server->end_frame(); + } + RSG::canvas->update_visibility_notifiers(); RSG::scene->update_visibility_notifiers(); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index ee684c69ed..6d2c36537b 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -259,7 +259,6 @@ public: command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh); command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - RSG::storage->mesh_add_surface(mesh, p_surfaces[i]); command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]); } } @@ -629,7 +628,7 @@ public: FUNC6(environment_set_ssil, RID, bool, float, float, float, float) FUNC6(environment_set_ssil_quality, EnvironmentSSILQuality, bool, float, int, float, float) - FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) + FUNC13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, float, RID) FUNC1(environment_glow_set_use_bicubic_upscale, bool) FUNC1(environment_glow_set_use_high_quality, bool) diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 78e81eac0b..5b43ca4bcd 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -182,7 +182,7 @@ static String _mkid(const String &p_id) { static String f2sp0(float p_float) { String num = rtoss(p_float); - if (num.find(".") == -1 && num.find("e") == -1) { + if (!num.contains(".") && !num.contains("e")) { num += ".0"; } return num; @@ -813,6 +813,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { code += scode; //use directly + if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) { + code += ","; + } } else { code += _mktab(p_level) + scode + ";\n"; } @@ -1287,10 +1290,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cfnode->flow_op == SL::FLOW_OP_FOR) { String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String middle = _dump_node_code(cfnode->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String right = _dump_node_code(cfnode->blocks[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _dump_node_code(cfnode->blocks[3], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { if (cfnode->expressions.size()) { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 4e07582187..b10022545c 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -35,18 +35,6 @@ #define HAS_WARNING(flag) (warning_flags & flag) -static bool _is_text_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; -} - -static bool _is_number(char32_t c) { - return (c >= '0' && c <= '9'); -} - -static bool _is_hex(char32_t c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - String ShaderLanguage::get_operator_text(Operator p_op) { static const char *op_names[OP_MAX] = { "==", "!=", @@ -543,7 +531,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { default: { char_idx--; //go back one, since we have no idea what this is - if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) { + if (is_digit(GETCHAR(0)) || (GETCHAR(0) == '.' && is_digit(GETCHAR(1)))) { // parse number bool hexa_found = false; bool period_found = false; @@ -584,7 +572,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { const char32_t symbol = String::char_lowercase(GETCHAR(i)); bool error = false; - if (_is_number(symbol)) { + if (is_digit(symbol)) { if (end_suffix_found) { error = true; } @@ -617,8 +605,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { break; } } - } else if (!hexa_found || !_is_hex(symbol)) { - if (_is_text_char(symbol)) { + } else if (!hexa_found || !is_hex_digit(symbol)) { + if (is_ascii_identifier_char(symbol)) { error = true; } else { break; @@ -649,7 +637,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant"); } } else if (period_found || exponent_found || float_suffix_found) { // Float - if (exponent_found && (!_is_number(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+" + if (exponent_found && (!is_digit(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+" return _make_token(TK_ERROR, "Invalid (float) numeric constant"); } if (period_found) { @@ -660,7 +648,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { } } else { //checks for eg. "1." or "1.99" notations - if (last_char != '.' && !_is_number(last_char)) { + if (last_char != '.' && !is_digit(last_char)) { return _make_token(TK_ERROR, "Invalid (float) numeric constant"); } } @@ -723,11 +711,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { return _make_token(TK_PERIOD); } - if (_is_text_char(GETCHAR(0))) { + if (is_ascii_identifier_char(GETCHAR(0))) { // parse identifier String str; - while (_is_text_char(GETCHAR(0))) { + while (is_ascii_identifier_char(GETCHAR(0))) { str += char32_t(GETCHAR(0)); char_idx++; } @@ -5208,9 +5196,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons #ifdef DEBUG_ENABLED if (check_warnings) { StringName func_name; + BlockNode *b = p_block; - if (p_block && p_block->parent_function) { - func_name = p_block->parent_function->name; + while (b) { + if (b->parent_function) { + func_name = b->parent_function->name; + break; + } else { + b = b->parent_block; + } } _parse_used_identifier(identifier, ident_type, func_name); @@ -5246,21 +5240,34 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; } else { - if (tk.type != TK_SEMICOLON) { - _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); - return nullptr; - } else { -#ifdef DEBUG_ENABLED - if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { - _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning.")); - } -#endif // DEBUG_ENABLED + bool valid = false; + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION && tk.type == TK_PARENTHESIS_CLOSE) { + valid = true; _set_tkpos(prepos); OperatorNode *func = alloc_node<OperatorNode>(); func->op = OP_EMPTY; expr = func; } + if (!valid) { + if (tk.type != TK_SEMICOLON) { + _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); + return nullptr; + } else { +#ifdef DEBUG_ENABLED + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_FOR_INIT && p_block->block_type != BlockNode::BLOCK_TYPE_FOR_CONDITION)) { + if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { + _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning.")); + } + } +#endif // DEBUG_ENABLED + _set_tkpos(prepos); + + OperatorNode *func = alloc_node<OperatorNode>(); + func->op = OP_EMPTY; + expr = func; + } + } } ERR_FAIL_COND_V(!expr, nullptr); @@ -6365,6 +6372,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } bool is_struct = shader->structs.has(tk.text); + bool is_var_init = false; + bool is_condition = false; if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block if (p_just_one) { @@ -6375,6 +6384,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return OK; } else if (tk.type == TK_CONST || is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type) || is_struct) { + is_var_init = true; + String struct_name = ""; if (is_struct) { struct_name = tk.text; @@ -6763,14 +6774,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun array_size = 0; } - if (tk.type == TK_COMMA) { - if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) { - _set_error(vformat("Multiple declarations in '%s' loop are not supported.", "for")); - return ERR_PARSE_ERROR; - } - } else if (tk.type == TK_SEMICOLON) { + if (tk.type == TK_SEMICOLON) { break; - } else { + } else if (tk.type != TK_COMMA) { _set_expected_error(",", ";"); return ERR_PARSE_ERROR; } @@ -7132,43 +7138,43 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun cf->flow_op = FLOW_OP_FOR; BlockNode *init_block = alloc_node<BlockNode>(); - init_block->block_type = BlockNode::BLOCK_TYPE_FOR; + init_block->block_type = BlockNode::BLOCK_TYPE_FOR_INIT; init_block->parent_block = p_block; init_block->single_statement = true; - cf->blocks.push_back(init_block); - if (_parse_block(init_block, p_function_info, true, false, false) != OK) { - return ERR_PARSE_ERROR; - } - - Node *n = _parse_and_reduce_expression(init_block, p_function_info); - if (!n) { - return ERR_PARSE_ERROR; - } - - if (n->get_datatype() != TYPE_BOOL) { - _set_error(RTR("The middle expression is expected to be boolean.")); - return ERR_PARSE_ERROR; + // Need to find a parent function to correctly proceed unused variable warnings. + { + BlockNode *block = p_block; + while (block && !block->parent_function) { + block = block->parent_block; + } + init_block->parent_function = block->parent_function; } - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_expected_error(";"); - return ERR_PARSE_ERROR; + cf->blocks.push_back(init_block); + Error err = _parse_block(init_block, p_function_info, true, false, false); + if (err != OK) { + return err; } - cf->expressions.push_back(n); - - n = _parse_and_reduce_expression(init_block, p_function_info); - if (!n) { - return ERR_PARSE_ERROR; + BlockNode *condition_block = alloc_node<BlockNode>(); + condition_block->block_type = BlockNode::BLOCK_TYPE_FOR_CONDITION; + condition_block->parent_block = init_block; + condition_block->single_statement = true; + condition_block->use_comma_between_statements = true; + cf->blocks.push_back(condition_block); + err = _parse_block(condition_block, p_function_info, true, false, false); + if (err != OK) { + return err; } - cf->expressions.push_back(n); - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_expected_error(")"); - return ERR_PARSE_ERROR; + BlockNode *expression_block = alloc_node<BlockNode>(); + expression_block->block_type = BlockNode::BLOCK_TYPE_FOR_EXPRESSION; + expression_block->parent_block = init_block; + expression_block->single_statement = true; + expression_block->use_comma_between_statements = true; + cf->blocks.push_back(expression_block); + err = _parse_block(expression_block, p_function_info, true, false, false); + if (err != OK) { + return err; } BlockNode *block = alloc_node<BlockNode>(); @@ -7176,8 +7182,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_function_info, true, true, true); - if (err) { + err = _parse_block(block, p_function_info, true, true, true); + if (err != OK) { return err; } @@ -7327,15 +7333,56 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!expr) { return ERR_PARSE_ERROR; } + is_condition = expr->type == Node::TYPE_OPERATOR && expr->get_datatype() == TYPE_BOOL; + + if (expr->type == Node::TYPE_OPERATOR) { + OperatorNode *op = static_cast<OperatorNode *>(expr); + if (op->op == OP_EMPTY) { + is_var_init = true; + is_condition = true; + } + } + p_block->statements.push_back(expr); tk = _get_token(); - if (tk.type != TK_SEMICOLON) { + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION) { + if (tk.type == TK_COMMA) { + if (!is_condition) { + _set_error(RTR("The middle expression is expected to be a boolean operator.")); + return ERR_PARSE_ERROR; + } + continue; + } + if (tk.type != TK_SEMICOLON) { + _set_expected_error(",", ";"); + return ERR_PARSE_ERROR; + } + } else if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION) { + if (tk.type == TK_COMMA) { + continue; + } + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_expected_error(",", ")"); + return ERR_PARSE_ERROR; + } + } else if (tk.type != TK_SEMICOLON) { _set_expected_error(";"); return ERR_PARSE_ERROR; } } + if (p_block) { + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_INIT && !is_var_init) { + _set_error(RTR("The left expression is expected to be a variable declaration.")); + return ERR_PARSE_ERROR; + } + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION && !is_condition) { + _set_error(RTR("The middle expression is expected to be a boolean operator.")); + return ERR_PARSE_ERROR; + } + } + if (p_just_one) { break; } @@ -7470,7 +7517,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct const String smode = String(mode); - if (shader->render_modes.find(mode) != -1) { + if (shader->render_modes.has(mode)) { _set_error(vformat(RTR("Duplicated render mode: '%s'."), smode)); return ERR_PARSE_ERROR; } @@ -7483,7 +7530,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (smode.begins_with(name)) { if (!info.options.is_empty()) { - if (info.options.find(smode.substr(name.length() + 1)) != -1) { + if (info.options.has(smode.substr(name.length() + 1))) { found = true; if (defined_modes.has(name)) { @@ -7793,7 +7840,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (uniform) { - if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) { + if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor. //validate global uniform DataType gvtype = global_var_get_type_func(name); if (gvtype == TYPE_MAX) { @@ -9054,6 +9101,19 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_MAIN_FUNCTION: { for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) { + if (!E.value.main_function) { + continue; + } + bool found = false; + for (int i = 0; i < shader->functions.size(); i++) { + if (shader->functions[i].name == E.key) { + found = true; + break; + } + } + if (found) { + continue; + } ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION); r_options->push_back(option); } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1307eeac2b..f39b21621d 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -504,7 +504,9 @@ public: enum BlockType { BLOCK_TYPE_STANDART, - BLOCK_TYPE_FOR, + BLOCK_TYPE_FOR_INIT, + BLOCK_TYPE_FOR_CONDITION, + BLOCK_TYPE_FOR_EXPRESSION, BLOCK_TYPE_SWITCH, BLOCK_TYPE_CASE, BLOCK_TYPE_DEFAULT, @@ -526,6 +528,7 @@ public: Map<StringName, Variable> variables; List<Node *> statements; bool single_statement = false; + bool use_comma_between_statements = false; BlockNode() : Node(TYPE_BLOCK) {} diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 9ae60c14cb..b8bb211a7a 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -435,7 +435,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT; |