summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp18
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp22
-rw-r--r--servers/rendering/renderer_rd/effects/luminance.cpp3
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp32
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h25
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp3
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp2
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp6
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp25
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h3
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp37
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp98
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h14
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp42
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp84
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h5
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp10
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp274
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h53
-rw-r--r--servers/rendering/renderer_rd/shaders/blit.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl54
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl86
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp174
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h47
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp93
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h7
53 files changed, 899 insertions, 472 deletions
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index d2a1a5ab9c..64950c6991 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -285,7 +285,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
- render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData *) * render_element_max));
+ render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData) * render_element_max));
render_element_count = 0;
element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max);
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
index 971f8b7f6f..cc5031823e 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -359,11 +359,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -393,11 +392,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
// Pass 2
@@ -418,11 +416,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
if (bokeh.push_constant.half_size) {
@@ -438,11 +435,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -471,11 +467,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
if (bokeh.push_constant.half_size) {
@@ -491,11 +486,10 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
} else {
CopyEffects::get_singleton()->copy_raster(p_buffers.secondary_texture, p_buffers.base_fb);
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index eba1c145e3..834653f5c2 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -696,11 +696,9 @@ void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_textu
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
-
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -803,12 +801,11 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu
RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
}
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
@@ -820,12 +817,11 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu
draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
blur_raster.push_constant.flags = base_flags;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -1055,11 +1051,10 @@ void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_fra
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -1136,11 +1131,10 @@ void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebu
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -1214,11 +1208,10 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -1269,8 +1262,7 @@ void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_b
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1);
}
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_rd/effects/luminance.cpp b/servers/rendering/renderer_rd/effects/luminance.cpp
index 7462282932..3aa5f5706e 100644
--- a/servers/rendering/renderer_rd/effects/luminance.cpp
+++ b/servers/rendering/renderer_rd/effects/luminance.cpp
@@ -191,11 +191,10 @@ void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_
RD::Uniform u_current_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_luminance_buffers->current }));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_current_texture), 1);
}
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(LuminanceReduceRasterPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
} else {
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index b9346c0201..d123f24865 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1429,7 +1429,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
push_constant.camera_z_far = p_projections[v].get_z_far();
push_constant.camera_z_near = p_projections[v].get_z_near();
push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.filter = false; //enabling causes arctifacts
+ push_constant.filter = false; // Enabling causes artifacts.
push_constant.screen_size[0] = p_ssr_buffers.size.x;
push_constant.screen_size[1] = p_ssr_buffers.size.y;
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index 821960bb3b..48c6511408 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -89,12 +89,12 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
- tonemap.push_constant.use_bcs = p_settings.use_bcs;
+ tonemap.push_constant.flags |= p_settings.use_bcs ? TONEMAP_FLAG_USE_BCS : 0;
tonemap.push_constant.bcs[0] = p_settings.brightness;
tonemap.push_constant.bcs[1] = p_settings.contrast;
tonemap.push_constant.bcs[2] = p_settings.saturation;
- tonemap.push_constant.use_glow = p_settings.use_glow;
+ tonemap.push_constant.flags |= p_settings.use_glow ? TONEMAP_FLAG_USE_GLOW : 0;
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
@@ -114,19 +114,21 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
}
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
- tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
+ tonemap.push_constant.flags |= p_settings.use_auto_exposure ? TONEMAP_FLAG_USE_AUTO_EXPOSURE : 0;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
- tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
+ tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
- tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
- tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.flags |= p_settings.use_fxaa ? TONEMAP_FLAG_USE_FXAA : 0;
+ tonemap.push_constant.flags |= p_settings.use_debanding ? TONEMAP_FLAG_USE_DEBANDING : 0;
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
+ tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;
+
if (p_settings.view_count > 1) {
// Use MULTIVIEW versions
mode += 6;
@@ -170,10 +172,9 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -185,13 +186,13 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
- tonemap.push_constant.use_bcs = p_settings.use_bcs;
+ tonemap.push_constant.flags |= p_settings.use_bcs ? TONEMAP_FLAG_USE_BCS : 0;
tonemap.push_constant.bcs[0] = p_settings.brightness;
tonemap.push_constant.bcs[1] = p_settings.contrast;
tonemap.push_constant.bcs[2] = p_settings.saturation;
ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
- tonemap.push_constant.use_glow = p_settings.use_glow;
+ tonemap.push_constant.flags |= p_settings.use_glow ? TONEMAP_FLAG_USE_GLOW : 0;
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
if (p_settings.view_count > 1) {
@@ -200,16 +201,18 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
}
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
- tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
+ tonemap.push_constant.flags |= p_settings.use_auto_exposure ? TONEMAP_FLAG_USE_AUTO_EXPOSURE : 0;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
- tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
+ tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
- tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.flags |= p_settings.use_debanding ? TONEMAP_FLAG_USE_DEBANDING : 0;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
+ tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;
+
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -250,8 +253,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_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, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
- RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
- RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
+ RD::get_singleton()->draw_list_draw(p_subpass_draw_list, false, 1u, 3u);
}
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index afd2f8e401..a1a99f931f 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -59,14 +59,23 @@ private:
TONEMAP_MODE_MAX
};
+ enum {
+ TONEMAP_FLAG_USE_BCS = (1 << 0),
+ TONEMAP_FLAG_USE_GLOW = (1 << 1),
+ TONEMAP_FLAG_USE_AUTO_EXPOSURE = (1 << 2),
+ TONEMAP_FLAG_USE_COLOR_CORRECTION = (1 << 3),
+ TONEMAP_FLAG_USE_FXAA = (1 << 4),
+ TONEMAP_FLAG_USE_DEBANDING = (1 << 5),
+ TONEMAP_FLAG_CONVERT_TO_SRGB = (1 << 6),
+ };
+
struct TonemapPushConstant {
float bcs[3]; // 12 - 12
- uint32_t use_bcs; // 4 - 16
+ uint32_t flags; // 4 - 16
- uint32_t use_glow; // 4 - 20
- uint32_t use_auto_exposure; // 4 - 24
- uint32_t use_color_correction; // 4 - 28
- uint32_t tonemapper; // 4 - 32
+ float pixel_size[2]; // 8 - 24
+ uint32_t tonemapper; // 4 - 28
+ uint32_t pad; // 4 - 32
uint32_t glow_texture_size[2]; // 8 - 40
float glow_intensity; // 4 - 44
@@ -79,10 +88,6 @@ private:
float white; // 4 - 88
float auto_exposure_scale; // 4 - 92
float luminance_multiplier; // 4 - 96
-
- float pixel_size[2]; // 8 - 104
- uint32_t use_fxaa; // 4 - 108
- uint32_t use_debanding; // 4 - 112
};
/* tonemap actually writes to a framebuffer, which is
@@ -141,6 +146,8 @@ public:
bool use_debanding = false;
Vector2i texture_size;
uint32_t view_count = 1;
+
+ bool convert_to_srgb = false;
};
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 6ec8612029..63c99facdd 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -85,9 +85,8 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>());
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
// RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 98d826b1f9..8402cc7444 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -143,7 +143,7 @@ Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const {
bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
uniform_set_updated = true;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true, true);
}
Fog::FogMaterialData::~FogMaterialData() {
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 964d4d9adf..991ccf984e 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -2215,7 +2215,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- //run one pass of fullsize jumpflood to fix up half size arctifacts
+ //run one pass of fullsize jumpflood to fix up half size artifacts
push_constant.half_size = false;
push_constant.step_size = 1;
@@ -2977,7 +2977,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
push_constant.cell_offset = mipmaps[i].cell_offset;
push_constant.cell_count = mipmaps[i].cell_count;
- int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ int64_t wg_todo = (mipmaps[i].cell_count + wg_size - 1) / wg_size;
while (wg_todo) {
int64_t wg_count = MIN(wg_todo, wg_limit_x);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
@@ -2998,7 +2998,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
push_constant.cell_offset = mipmaps[i].cell_offset;
push_constant.cell_count = mipmaps[i].cell_count;
- int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ int64_t wg_todo = (mipmaps[i].cell_count + wg_size - 1) / wg_size;
while (wg_todo) {
int64_t wg_count = MIN(wg_todo, wg_limit_x);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index ebf3c5f619..f94c701ada 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -185,7 +185,7 @@ bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant
uniform_set_updated = true;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true, true);
}
SkyRD::SkyMaterialData::~SkyMaterialData() {
@@ -249,11 +249,9 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC
}
}
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
}
////////////////////////////////////////////////////////////////////////////////
@@ -941,23 +939,6 @@ void sky() {
sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
}
-
- { //create index array for copy shaders
- Vector<uint8_t> pv;
- pv.resize(6 * 4);
- {
- uint8_t *w = pv.ptrw();
- int *p32 = (int *)w;
- p32[0] = 0;
- p32[1] = 1;
- p32[2] = 2;
- p32[3] = 0;
- p32[4] = 2;
- p32[5] = 3;
- }
- index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
- index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
- }
}
void SkyRD::set_texture_format(RD::DataFormat p_texture_format) {
@@ -990,8 +971,6 @@ SkyRD::~SkyRD() {
if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_only_texture_uniform_set)) {
RD::get_singleton()->free(sky_scene_state.fog_only_texture_uniform_set);
}
-
- RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h
index 7aee65fd67..ee2d81757c 100644
--- a/servers/rendering/renderer_rd/environment/sky.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -70,9 +70,6 @@ public:
private:
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- RID index_buffer;
- RID index_array;
-
enum SkyTextureSetVersion {
SKY_TEXTURE_SET_BACKGROUND,
SKY_TEXTURE_SET_HALF_RES,
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 ef09552603..c98752fb39 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -433,10 +433,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID index_array_rd;
//skeleton and blend shape
+ bool pipeline_motion_vectors = pipeline_color_pass_flags & SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS;
if (surf->owner->mesh_instance.is_valid()) {
- mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), pipeline_motion_vectors, vertex_array_rd, vertex_format);
} else {
- mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), pipeline_motion_vectors, vertex_array_rd, vertex_format);
}
index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
@@ -779,6 +780,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
scene_state.used_screen_texture = false;
scene_state.used_normal_texture = false;
scene_state.used_depth_texture = false;
+ scene_state.used_lightmap = false;
}
uint32_t lightmap_captures_used = 0;
@@ -994,6 +996,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
if (uses_lightmap) {
surf->sort.uses_lightmap = 1;
+ scene_state.used_lightmap = true;
}
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
@@ -1008,13 +1011,6 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
scene_state.used_depth_texture = true;
}
-
- if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
- if ((flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH && RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) {
- inst->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(inst->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
- }
- }
-
} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
rl->add_element(surf);
@@ -1433,7 +1429,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
// Note: when rendering stereoscopic (multiview) we are using our combined frustum projection to create
// our cluster data. We use reprojection in the shader to adjust for our left/right eye.
// This only works as we don't filter our cluster by depth buffer.
- // If we ever make this optimisation we should make it optional and only use it in mono.
+ // If we ever make this optimization we should make it optional and only use it in mono.
// What we win by filtering out a few lights, we loose by having to do the work double for stereo.
current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid());
}
@@ -1628,6 +1624,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS;
+ scene_shader.enable_advanced_shader_group();
}
if (p_render_data->voxel_gi_instances->size() > 0) {
@@ -1647,6 +1644,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (p_render_data->scene_data->view_count > 1) {
color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
+ // Try enabling here in case is_xr_enabled() returns false.
+ scene_shader.shader.enable_group(SceneShaderForwardClustered::SHADER_GROUP_MULTIVIEW);
}
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
@@ -1712,6 +1711,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
}
+
+ if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi) {
+ scene_shader.enable_advanced_shader_group(p_render_data->scene_data->view_count > 1);
+ }
+
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
@@ -1759,7 +1763,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
case RS::ENV_BG_CANVAS: {
if (!is_reflection_probe) {
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
- copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, convert_to_linear);
}
keep_color = true;
} break;
@@ -1837,7 +1842,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
- bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
+ bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi;
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
@@ -2484,6 +2489,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
+ scene_shader.enable_advanced_shader_group();
+
_update_render_base_uniform_set();
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2533,6 +2540,8 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
+ scene_shader.enable_advanced_shader_group();
+
_update_render_base_uniform_set();
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -3321,6 +3330,10 @@ void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_rende
return;
}
+ // Ensure advanced shaders are available if SDFGI is used.
+ // Call here as this is the first entry point for SDFGI.
+ scene_shader.enable_advanced_shader_group();
+
static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 155e8b4d19..a89c77c652 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -321,6 +321,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
bool used_normal_texture = false;
bool used_depth_texture = false;
bool used_sss = false;
+ bool used_lightmap = false;
struct ShadowPass {
uint32_t element_from;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 377aab1354..12f8f6a366 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -301,7 +301,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
if (k == PIPELINE_VERSION_COLOR_PASS) {
for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
- if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
+ if (!shader_singleton->valid_color_pass_pipelines[l]) {
continue;
}
@@ -436,7 +436,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardClustered::MaterialData::~MaterialData() {
@@ -476,16 +476,16 @@ void SceneShaderForwardClustered::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
{
- Vector<String> shader_versions;
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
+ Vector<ShaderRD::VariantDefine> shader_versions;
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n", true)); // SHADER_VERSION_DEPTH_PASS
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n", true)); // SHADER_VERSION_DEPTH_PASS_DP
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n", false)); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
+ shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
Vector<String> color_pass_flags = {
"\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
@@ -501,54 +501,38 @@ void SceneShaderForwardClustered::init(const String p_defines) {
version += color_pass_flags[j];
}
}
- shader_versions.push_back(version);
+
+ // Assign a group based on what features this pass contains.
+ ShaderGroup group = SHADER_GROUP_BASE;
+ bool advanced_group = (i & SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR) || (i & SHADER_COLOR_PASS_FLAG_LIGHTMAP) || (i & SHADER_COLOR_PASS_FLAG_MOTION_VECTORS);
+ bool multiview_group = i & SHADER_COLOR_PASS_FLAG_MULTIVIEW;
+ if (advanced_group && multiview_group) {
+ group = SHADER_GROUP_ADVANCED_MULTIVIEW;
+ } else if (advanced_group) {
+ group = SHADER_GROUP_ADVANCED;
+ } else if (multiview_group) {
+ group = SHADER_GROUP_MULTIVIEW;
+ }
+
+ shader_versions.push_back(ShaderRD::VariantDefine(group, version, false));
}
shader.initialize(shader_versions, p_defines);
- if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
- shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false);
-
- // Disable Color Passes
- for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
- // Selectively disable any shader pass that includes Multiview.
- if ((i & SHADER_COLOR_PASS_FLAG_MULTIVIEW)) {
- shader.set_variant_enabled(i + SHADER_VERSION_COLOR_PASS, false);
- }
- }
+ if (RendererCompositorRD::get_singleton()->is_xr_enabled()) {
+ shader.enable_group(SHADER_GROUP_MULTIVIEW);
}
}
- valid_color_pass_pipelines.insert(0);
-
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
-
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
-
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
-
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
-
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ // Set flag to true if a combination is valid.
+ // The only invalid combinations are those that include both TRANSPARENT and SEPARATE_SPECULAR.
+ for (int i = 0; i < PIPELINE_COLOR_PASS_FLAG_COUNT; i++) {
+ if ((i & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) && (i & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR)) {
+ valid_color_pass_pipelines[i] = false;
+ } else {
+ valid_color_pass_pipelines[i] = true;
+ }
+ }
material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
@@ -854,3 +838,11 @@ void SceneShaderForwardClustered::set_default_specialization_constants(const Vec
}
}
}
+
+void SceneShaderForwardClustered::enable_advanced_shader_group(bool p_needs_multiview) {
+ if (p_needs_multiview || RendererCompositorRD::get_singleton()->is_xr_enabled()) {
+ shader.enable_group(SHADER_GROUP_ADVANCED_MULTIVIEW);
+ } else {
+ shader.enable_group(SHADER_GROUP_ADVANCED);
+ }
+}
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 bdafc4c27e..761b74defa 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
@@ -41,6 +41,13 @@ private:
static SceneShaderForwardClustered *singleton;
public:
+ enum ShaderGroup {
+ SHADER_GROUP_BASE, // Always compiled at the beginning.
+ SHADER_GROUP_ADVANCED,
+ SHADER_GROUP_MULTIVIEW,
+ SHADER_GROUP_ADVANCED_MULTIVIEW,
+ };
+
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
SHADER_VERSION_DEPTH_PASS_DP,
@@ -78,8 +85,8 @@ public:
};
enum PipelineColorPassFlags {
- PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
- PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, // Can't combine with SEPARATE_SPECULAR.
+ PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, // Can't combine with TRANSPARENT.
PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4,
@@ -242,12 +249,13 @@ public:
ShaderData *debug_shadow_splits_material_shader_ptr = nullptr;
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
- HashSet<uint32_t> valid_color_pass_pipelines;
+ bool valid_color_pass_pipelines[PIPELINE_COLOR_PASS_FLAG_COUNT];
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
+ void enable_advanced_shader_group(bool p_needs_multiview = false);
};
} // namespace RendererSceneRenderImplementation
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 6434682fc2..90d770399e 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -722,16 +722,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
using_subpass_post_process = false;
}
- // We do this last because our get_color_fbs creates and caches the framebuffer if we need it.
- RID four_subpasses = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
- if (using_subpass_post_process && four_subpasses.is_null()) {
- // can't do blit subpass because we don't have all subpasses
- using_subpass_post_process = false;
- }
-
if (using_subpass_post_process) {
// all as subpasses
- framebuffer = four_subpasses;
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
} else if (using_subpass_transparent) {
// our tonemap pass is separate
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES);
@@ -781,24 +774,20 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- /*
- if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
- */
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_render_data->environment);
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- /*
- if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
- */
} break;
case RS::ENV_BG_SKY: {
draw_sky = true;
@@ -807,7 +796,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (rb_data.is_valid()) {
RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
- copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, convert_to_linear);
}
keep_color = true;
} break;
@@ -908,13 +898,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
{
// regular forward for now
Vector<Color> c;
- c.push_back(clear_color.srgb_to_linear()); // our render buffer
- if (rb_data.is_valid()) {
- if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
- c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
+ {
+ Color cc = clear_color.srgb_to_linear();
+ if (rb_data.is_valid()) {
+ cc.a = 0; // For transparent viewport backgrounds.
}
- if (using_subpass_post_process) {
- c.push_back(Color()); // our 2D buffer we're copying into
+ c.push_back(cc); // Our render buffer.
+ if (rb_data.is_valid()) {
+ if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ c.push_back(clear_color.srgb_to_linear()); // Our resolve buffer.
+ }
+ if (using_subpass_post_process) {
+ c.push_back(Color()); // Our 2D buffer we're copying into.
+ }
}
}
@@ -2143,9 +2139,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
//skeleton and blend shape
if (surf->owner->mesh_instance.is_valid()) {
- mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), false, vertex_array_rd, vertex_format);
} else {
- mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), false, vertex_array_rd, vertex_format);
}
index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
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 e4498ac533..32d2289f75 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
@@ -388,7 +388,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardMobile::MaterialData::~MaterialData() {
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index f3595c5917..c00e5f8b5e 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -89,7 +89,7 @@ void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const
ERR_FAIL_COND(p_shader.is_null());
_clear();
shader = p_shader;
- input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(p_shader);
+ input_mask = 0;
render_primitive = p_primitive;
rasterization_state = p_rasterization_state;
multisample_state = p_multisample;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 58c1278312..52877109f7 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -91,7 +91,11 @@ public:
return result;
}
- _FORCE_INLINE_ uint32_t get_vertex_input_mask() const {
+ _FORCE_INLINE_ uint32_t get_vertex_input_mask() {
+ if (input_mask == 0) {
+ ERR_FAIL_COND_V(shader.is_null(), 0);
+ input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader);
+ }
return input_mask;
}
void clear();
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index eb33f296d0..d8c035a51c 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -348,7 +348,7 @@ void RendererCanvasRenderRD::free_polygon(PolygonID p_polygon) {
////////////////////
-void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size) {
+void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data) {
if (p_texture == RID()) {
p_texture = default_canvas_texture;
}
@@ -363,7 +363,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
bool use_normal;
bool use_specular;
- bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, bool(push_constant.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR), uniform_set, size, specular_shininess, use_normal, use_specular, p_texture_is_data);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -421,6 +421,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_update_transform_2d_to_mat2x3(base_transform, push_constant.world);
Color base_color = p_item->final_modulate;
+ bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_render_target);
for (int i = 0; i < 4; i++) {
push_constant.modulation[i] = 0;
@@ -441,6 +442,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.lights[3] = 0;
uint32_t base_flags = 0;
+ base_flags |= use_linear_colors ? FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0;
uint16_t light_count = 0;
PipelineLightMode light_mode;
@@ -505,7 +507,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
//bind textures
- _bind_canvas_texture(p_draw_list, rect->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
+ _bind_canvas_texture(p_draw_list, rect->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size, bool(rect->flags & CANVAS_RECT_MSDF));
Rect2 src_rect;
Rect2 dst_rect;
@@ -566,10 +568,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.flags |= FLAGS_USE_LCD;
}
- push_constant.modulation[0] = rect->modulate.r * base_color.r;
- push_constant.modulation[1] = rect->modulate.g * base_color.g;
- push_constant.modulation[2] = rect->modulate.b * base_color.b;
- push_constant.modulation[3] = rect->modulate.a * base_color.a;
+ Color modulated = rect->modulate * base_color;
+ if (use_linear_colors) {
+ modulated = modulated.srgb_to_linear();
+ }
+
+ push_constant.modulation[0] = modulated.r;
+ push_constant.modulation[1] = modulated.g;
+ push_constant.modulation[2] = modulated.b;
+ push_constant.modulation[3] = modulated.a;
push_constant.src_rect[0] = src_rect.position.x;
push_constant.src_rect[1] = src_rect.position.y;
@@ -618,10 +625,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
}
- push_constant.modulation[0] = np->color.r * base_color.r;
- push_constant.modulation[1] = np->color.g * base_color.g;
- push_constant.modulation[2] = np->color.b * base_color.b;
- push_constant.modulation[3] = np->color.a * base_color.a;
+ Color modulated = np->color * base_color;
+ if (use_linear_colors) {
+ modulated = modulated.srgb_to_linear();
+ }
+
+ push_constant.modulation[0] = modulated.r;
+ push_constant.modulation[1] = modulated.g;
+ push_constant.modulation[2] = modulated.b;
+ push_constant.modulation[3] = modulated.a;
push_constant.src_rect[0] = src_rect.position.x;
push_constant.src_rect[1] = src_rect.position.y;
@@ -676,10 +688,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_bind_canvas_texture(p_draw_list, polygon->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
- push_constant.modulation[0] = base_color.r;
- push_constant.modulation[1] = base_color.g;
- push_constant.modulation[2] = base_color.b;
- push_constant.modulation[3] = base_color.a;
+ Color color = base_color;
+ if (use_linear_colors) {
+ color = color.srgb_to_linear();
+ }
+
+ push_constant.modulation[0] = color.r;
+ push_constant.modulation[1] = color.g;
+ push_constant.modulation[2] = color.b;
+ push_constant.modulation[3] = color.a;
for (int j = 0; j < 4; j++) {
push_constant.src_rect[j] = 0;
@@ -718,6 +735,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x;
push_constant.uvs[j * 2 + 1] = primitive->uvs[j].y;
Color col = primitive->colors[j] * base_color;
+ if (use_linear_colors) {
+ col = col.srgb_to_linear();
+ }
push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
}
@@ -732,6 +752,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.uvs[j * 2 + 0] = primitive->uvs[j + 1].x;
push_constant.uvs[j * 2 + 1] = primitive->uvs[j + 1].y;
Color col = primitive->colors[j + 1] * base_color;
+ if (use_linear_colors) {
+ col = col.srgb_to_linear();
+ }
push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
}
@@ -849,10 +872,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
- push_constant.modulation[0] = base_color.r * modulate.r;
- push_constant.modulation[1] = base_color.g * modulate.g;
- push_constant.modulation[2] = base_color.b * modulate.b;
- push_constant.modulation[3] = base_color.a * modulate.a;
+ Color modulated = modulate * base_color;
+ if (use_linear_colors) {
+ modulated = modulated.srgb_to_linear();
+ }
+
+ push_constant.modulation[0] = modulated.r;
+ push_constant.modulation[1] = modulated.g;
+ push_constant.modulation[2] = modulated.b;
+ push_constant.modulation[3] = modulated.a;
for (int j = 0; j < 4; j++) {
push_constant.src_rect[j] = 0;
@@ -872,9 +900,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID;
if (mesh_instance.is_valid()) {
- mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, false, vertex_array, vertex_format);
} else {
- mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, false, vertex_array, vertex_format);
}
RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format);
@@ -1113,8 +1141,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
// Update uniform set.
- if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET);
+ RID uniform_set = texture_storage->render_target_is_using_hdr(p_to_render_target) ? material_data->uniform_set : material_data->uniform_set_srgb;
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set, MATERIAL_UNIFORM_SET);
material_data->set_as_used();
}
} else {
@@ -2235,12 +2264,14 @@ RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_
bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
-
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false);
+ bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, true, false, RD::BARRIER_MASK_ALL_BARRIERS);
+ bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false, false, RD::BARRIER_MASK_ALL_BARRIERS);
+ return uniform_set_changed || uniform_set_srgb_changed;
}
RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
+ free_parameters_uniform_set(uniform_set_srgb);
}
RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
@@ -2396,7 +2427,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.renames["LIGHT_VERTEX"] = "light_vertex";
actions.renames["SHADOW_VERTEX"] = "shadow_vertex";
actions.renames["UV"] = "uv";
- actions.renames["POINT_SIZE"] = "gl_PointSize";
+ actions.renames["POINT_SIZE"] = "point_size";
actions.renames["MODEL_MATRIX"] = "model_matrix";
actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform";
@@ -2444,6 +2475,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n";
+ actions.usage_defines["POINT_SIZE"] = "#define USE_POINT_SIZE\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 1116bed6e4..4c8cbd1c9f 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -75,6 +75,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_CLIP_RECT_UV = (1 << 9),
FLAGS_TRANSPOSE_RECT = (1 << 10),
+ FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 11),
+
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
FLAGS_USING_PARTICLES = (1 << 13),
@@ -195,6 +197,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData {
CanvasShaderData *shader_data = nullptr;
RID uniform_set;
+ RID uniform_set_srgb;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
@@ -415,7 +418,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer);
- inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
+ inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead.
void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used);
void _render_items(RID 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);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 870da3c321..4ccd2aa322 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -81,6 +81,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
blit.push_constant.k2 = p_render_targets[i].lens_distortion.k2;
blit.push_constant.upscale = p_render_targets[i].lens_distortion.upscale;
blit.push_constant.aspect_ratio = p_render_targets[i].lens_distortion.aspect_ratio;
+ blit.push_constant.convert_to_srgb = texture_storage->render_target_is_using_hdr(p_render_targets[i].render_target);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
@@ -171,7 +172,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RID texture = texture_storage->texture_allocate();
texture_storage->texture_2d_initialize(texture, p_image);
- RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ RID rd_texture = texture_storage->texture_get_rd_texture(texture, false);
RD::SamplerState sampler_state;
sampler_state.min_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST;
@@ -237,6 +238,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
blit.push_constant.k2 = 0;
blit.push_constant.upscale = 1.0;
blit.push_constant.aspect_ratio = 1.0;
+ blit.push_constant.convert_to_srgb = false;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 14fb4e6340..705fb9e8e5 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -80,7 +80,7 @@ protected:
float upscale;
float aspect_ratio;
uint32_t layer;
- uint32_t pad1;
+ uint32_t convert_to_srgb;
};
struct Blit {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 646bdc5436..9d4d266a7a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -368,7 +368,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.base_texture = rb->get_internal_texture(i);
buffers.depth_texture = rb->get_depth_texture(i);
- // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustum.
float z_near = p_render_data->scene_data->view_projection[i].get_z_near();
float z_far = p_render_data->scene_data->view_projection[i].get_z_far();
bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal);
@@ -391,7 +391,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.depth_texture = rb->get_depth_texture(i);
buffers.base_fb = FramebufferCacheRD::get_singleton()->get_cache(buffers.base_texture); // TODO move this into bokeh_dof_raster, we can do this internally
- // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustum.
float z_near = p_render_data->scene_data->view_projection[i].get_z_near();
float z_far = p_render_data->scene_data->view_projection[i].get_z_far();
bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal);
@@ -552,6 +552,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = rb->get_view_count();
+ tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(render_target);
+
RID dest_fb;
if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
// If we use FSR to upscale we need to write our result into an intermediate buffer.
@@ -647,6 +649,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = rb->get_view_count();
+ tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(rb->get_render_target());
+
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
RD::get_singleton()->draw_command_end_label();
@@ -697,7 +701,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(const RenderDataRD *p_ren
copy_effects->copy_to_fb_rect(shadow_atlas_texture, dest_fb, Rect2i(Vector2(), size), false, true);
- // Visualise our view frustum to show coverage.
+ // Visualize our view frustum to show coverage.
for (int i = 0; i < p_render_data->render_shadow_count; i++) {
RID light = p_render_data->render_shadows[i].light;
RID base = light_storage->light_instance_get_base_light(light);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index c85ece6366..46ae2d9551 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -138,7 +138,7 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
RID ShaderRD::version_create() {
//initialize() was never called
- ERR_FAIL_COND_V(variant_defines.size() == 0, RID());
+ ERR_FAIL_COND_V(group_to_variant_map.size() == 0, RID());
Version version;
version.dirty = true;
@@ -148,11 +148,20 @@ RID ShaderRD::version_create() {
return version_owner.make_rid(version);
}
+void ShaderRD::_initialize_version(Version *p_version) {
+ _clear_version(p_version);
+
+ p_version->valid = false;
+ p_version->dirty = false;
+
+ p_version->variants = memnew_arr(RID, variant_defines.size());
+}
+
void ShaderRD::_clear_version(Version *p_version) {
- //clear versions if they exist
+ // Clear versions if they exist.
if (p_version->variants) {
for (int i = 0; i < variant_defines.size(); i++) {
- if (variants_enabled[i]) {
+ if (p_version->variants[i].is_valid()) {
RD::get_singleton()->free(p_version->variants[i]);
}
}
@@ -171,7 +180,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
case StageTemplate::Chunk::TYPE_VERSION_DEFINES: {
builder.append("\n"); //make sure defines begin at newline
builder.append(general_defines.get_data());
- builder.append(variant_defines[p_variant].get_data());
+ builder.append(variant_defines[p_variant].text.get_data());
for (int j = 0; j < p_version->custom_defines.size(); j++) {
builder.append(p_version->custom_defines[j].get_data());
}
@@ -211,9 +220,11 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
}
}
-void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
- if (!variants_enabled[p_variant]) {
- return; //variant is disabled, return
+void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
+ uint32_t variant = group_to_variant_map[p_data->group][p_variant];
+
+ if (!variants_enabled[variant]) {
+ return; // Variant is disabled, return.
}
Vector<RD::ShaderStageSPIRVData> stages;
@@ -227,7 +238,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
//vertex stage
StringBuilder builder;
- _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_VERTEX]);
+ _build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_VERTEX]);
current_source = builder.as_string();
RD::ShaderStageSPIRVData stage;
@@ -245,7 +256,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
current_stage = RD::SHADER_STAGE_FRAGMENT;
StringBuilder builder;
- _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_FRAGMENT]);
+ _build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_FRAGMENT]);
current_source = builder.as_string();
RD::ShaderStageSPIRVData stage;
@@ -263,7 +274,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
current_stage = RD::SHADER_STAGE_COMPUTE;
StringBuilder builder;
- _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_COMPUTE]);
+ _build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_COMPUTE]);
current_source = builder.as_string();
@@ -279,7 +290,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
if (!build_ok) {
MutexLock lock(variant_set_mutex); //properly print the errors
- ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_COMPUTE ? "Compute " : (current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment")) + " shader, variant #" + itos(p_variant) + " (" + variant_defines[p_variant].get_data() + ").");
+ ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_COMPUTE ? "Compute " : (current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment")) + " shader, variant #" + itos(variant) + " (" + variant_defines[variant].text.get_data() + ").");
ERR_PRINT(error);
#ifdef DEBUG_ENABLED
@@ -288,15 +299,15 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
return;
}
- Vector<uint8_t> shader_data = RD::get_singleton()->shader_compile_binary_from_spirv(stages, name + ":" + itos(p_variant));
+ Vector<uint8_t> shader_data = RD::get_singleton()->shader_compile_binary_from_spirv(stages, name + ":" + itos(variant));
ERR_FAIL_COND(shader_data.size() == 0);
- RID shader = RD::get_singleton()->shader_create_from_bytecode(shader_data);
{
MutexLock lock(variant_set_mutex);
- p_version->variants[p_variant] = shader;
- p_version->variant_data[p_variant] = shader_data;
+
+ p_data->version->variants[variant] = RD::get_singleton()->shader_create_from_bytecode(shader_data, p_data->version->variants[variant]);
+ p_data->version->variant_data[variant] = shader_data;
}
}
@@ -382,11 +393,11 @@ String ShaderRD::_version_get_sha1(Version *p_version) const {
}
static const char *shader_file_header = "GDSC";
-static const uint32_t cache_file_version = 2;
+static const uint32_t cache_file_version = 3;
-bool ShaderRD::_load_from_cache(Version *p_version) {
+bool ShaderRD::_load_from_cache(Version *p_version, int p_group) {
String sha1 = _version_get_sha1(p_version);
- String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
+ String path = shader_cache_dir.path_join(name).path_join(group_sha256[p_group]).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
if (f.is_null()) {
@@ -404,12 +415,13 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
uint32_t variant_count = f->get_32();
- ERR_FAIL_COND_V(variant_count != (uint32_t)variant_defines.size(), false); //should not happen but check
+ ERR_FAIL_COND_V(variant_count != (uint32_t)group_to_variant_map[p_group].size(), false); //should not happen but check
for (uint32_t i = 0; i < variant_count; i++) {
+ int variant_id = group_to_variant_map[p_group][i];
uint32_t variant_size = f->get_32();
- ERR_FAIL_COND_V(variant_size == 0 && variants_enabled[i], false);
- if (!variants_enabled[i]) {
+ ERR_FAIL_COND_V(variant_size == 0 && variants_enabled[variant_id], false);
+ if (!variants_enabled[variant_id]) {
continue;
}
Vector<uint8_t> variant_bytes;
@@ -419,25 +431,28 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
ERR_FAIL_COND_V(br != variant_size, false);
- p_version->variant_data[i] = variant_bytes;
+ p_version->variant_data[variant_id] = variant_bytes;
}
for (uint32_t i = 0; i < variant_count; i++) {
- if (!variants_enabled[i]) {
+ int variant_id = group_to_variant_map[p_group][i];
+ if (!variants_enabled[variant_id]) {
MutexLock lock(variant_set_mutex);
- p_version->variants[i] = RID();
+ p_version->variants[variant_id] = RID();
continue;
}
- RID shader = RD::get_singleton()->shader_create_from_bytecode(p_version->variant_data[i]);
- if (shader.is_null()) {
- for (uint32_t j = 0; j < i; j++) {
- RD::get_singleton()->free(p_version->variants[i]);
- }
- ERR_FAIL_COND_V(shader.is_null(), false);
- }
{
MutexLock lock(variant_set_mutex);
- p_version->variants[i] = shader;
+ RID shader = RD::get_singleton()->shader_create_from_bytecode(p_version->variant_data[variant_id], p_version->variants[variant_id]);
+ if (shader.is_null()) {
+ for (uint32_t j = 0; j < i; j++) {
+ int variant_free_id = group_to_variant_map[p_group][j];
+ RD::get_singleton()->free(p_version->variants[variant_free_id]);
+ }
+ ERR_FAIL_COND_V(shader.is_null(), false);
+ }
+
+ p_version->variants[variant_id] = shader;
}
}
@@ -447,66 +462,84 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
return true;
}
-void ShaderRD::_save_to_cache(Version *p_version) {
+void ShaderRD::_save_to_cache(Version *p_version, int p_group) {
String sha1 = _version_get_sha1(p_version);
- String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
+ String path = shader_cache_dir.path_join(name).path_join(group_sha256[p_group]).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
ERR_FAIL_COND(f.is_null());
f->store_buffer((const uint8_t *)shader_file_header, 4);
- f->store_32(cache_file_version); //file version
- uint32_t variant_count = variant_defines.size();
- f->store_32(variant_count); //variant count
-
+ f->store_32(cache_file_version); // File version.
+ uint32_t variant_count = group_to_variant_map[p_group].size();
+ f->store_32(variant_count); // Variant count.
for (uint32_t i = 0; i < variant_count; i++) {
- f->store_32(p_version->variant_data[i].size()); //stage count
- f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
+ int variant_id = group_to_variant_map[p_group][i];
+ f->store_32(p_version->variant_data[variant_id].size()); // Stage count.
+ f->store_buffer(p_version->variant_data[variant_id].ptr(), p_version->variant_data[variant_id].size());
}
}
-void ShaderRD::_compile_version(Version *p_version) {
- _clear_version(p_version);
+void ShaderRD::_allocate_placeholders(Version *p_version, int p_group) {
+ for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
+ int variant_id = group_to_variant_map[p_group][i];
+ RID shader = RD::get_singleton()->shader_create_placeholder();
+ {
+ MutexLock lock(variant_set_mutex);
+ p_version->variants[variant_id] = shader;
+ }
+ }
+}
- p_version->valid = false;
- p_version->dirty = false;
+// Try to compile all variants for a given group.
+// Will skip variants that are disabled.
+void ShaderRD::_compile_version(Version *p_version, int p_group) {
+ if (!group_enabled[p_group]) {
+ return;
+ }
- p_version->variants = memnew_arr(RID, variant_defines.size());
typedef Vector<uint8_t> ShaderStageData;
p_version->variant_data = memnew_arr(ShaderStageData, variant_defines.size());
+ p_version->dirty = false;
+
if (shader_cache_dir_valid) {
- if (_load_from_cache(p_version)) {
+ if (_load_from_cache(p_version, p_group)) {
return;
}
}
-#if 1
+ CompileData compile_data;
+ compile_data.version = p_version;
+ compile_data.group = p_group;
- WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation"));
+#if 1
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, &compile_data, group_to_variant_map[p_group].size(), -1, true, SNAME("ShaderCompilation"));
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
#else
- for (int i = 0; i < variant_defines.size(); i++) {
- _compile_variant(i, p_version);
+ for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
+ _compile_variant(i, &compile_data);
}
#endif
bool all_valid = true;
- for (int i = 0; i < variant_defines.size(); i++) {
- if (!variants_enabled[i]) {
- continue; //disabled
+
+ for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
+ int variant_id = group_to_variant_map[p_group][i];
+ if (!variants_enabled[variant_id]) {
+ continue; // Disabled.
}
- if (p_version->variants[i].is_null()) {
+ if (p_version->variants[variant_id].is_null()) {
all_valid = false;
break;
}
}
if (!all_valid) {
- //clear versions if they exist
+ // Clear versions if they exist.
for (int i = 0; i < variant_defines.size(); i++) {
- if (!variants_enabled[i]) {
- continue; //disabled
+ if (!variants_enabled[i] || !group_enabled[variant_defines[i].group]) {
+ continue; // Disabled.
}
if (!p_version->variants[i].is_null()) {
RD::get_singleton()->free(p_version->variants[i]);
@@ -520,8 +553,8 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->variant_data = nullptr;
return;
} else if (shader_cache_dir_valid) {
- //save shader cache
- _save_to_cache(p_version);
+ // Save shader cache.
+ _save_to_cache(p_version, p_group);
}
memdelete_arr(p_version->variant_data); //clear stages
@@ -550,7 +583,14 @@ void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_
version->dirty = true;
if (version->initialize_needed) {
- _compile_version(version);
+ _initialize_version(version);
+ for (int i = 0; i < group_enabled.size(); i++) {
+ if (!group_enabled[i]) {
+ _allocate_placeholders(version, i);
+ continue;
+ }
+ _compile_version(version, i);
+ }
version->initialize_needed = false;
}
}
@@ -576,7 +616,14 @@ void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, Str
version->dirty = true;
if (version->initialize_needed) {
- _compile_version(version);
+ _initialize_version(version);
+ for (int i = 0; i < group_enabled.size(); i++) {
+ if (!group_enabled[i]) {
+ _allocate_placeholders(version, i);
+ continue;
+ }
+ _compile_version(version, i);
+ }
version->initialize_needed = false;
}
}
@@ -586,7 +633,14 @@ bool ShaderRD::version_is_valid(RID p_version) {
ERR_FAIL_COND_V(!version, false);
if (version->dirty) {
- _compile_version(version);
+ _initialize_version(version);
+ for (int i = 0; i < group_enabled.size(); i++) {
+ if (!group_enabled[i]) {
+ _allocate_placeholders(version, i);
+ continue;
+ }
+ _compile_version(version, i);
+ }
}
return version->valid;
@@ -615,6 +669,29 @@ bool ShaderRD::is_variant_enabled(int p_variant) const {
return variants_enabled[p_variant];
}
+void ShaderRD::enable_group(int p_group) {
+ ERR_FAIL_INDEX(p_group, group_enabled.size());
+
+ if (group_enabled[p_group]) {
+ // Group already enabled, do nothing.
+ return;
+ }
+
+ group_enabled.write[p_group] = true;
+
+ // Compile all versions again to include the new group.
+ List<RID> all_versions;
+ version_owner.get_owned_list(&all_versions);
+ for (int i = 0; i < all_versions.size(); i++) {
+ Version *version = version_owner.get_or_null(all_versions[i]);
+ _compile_version(version, p_group);
+ }
+}
+
+bool ShaderRD::is_group_enabled(int p_group) const {
+ return group_enabled[p_group];
+}
+
bool ShaderRD::shader_cache_cleanup_on_start = false;
ShaderRD::ShaderRD() {
@@ -639,24 +716,38 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
general_defines = p_general_defines.utf8();
+ // When initialized this way, there is just one group and its always enabled.
+ group_to_variant_map.insert(0, LocalVector<int>{});
+ group_enabled.push_back(true);
+
for (int i = 0; i < p_variant_defines.size(); i++) {
- variant_defines.push_back(p_variant_defines[i].utf8());
+ variant_defines.push_back(VariantDefine(0, p_variant_defines[i], true));
variants_enabled.push_back(true);
+ group_to_variant_map[0].push_back(i);
}
if (!shader_cache_dir.is_empty()) {
+ group_sha256.resize(1);
+ _initialize_cache();
+ }
+}
+
+void ShaderRD::_initialize_cache() {
+ for (const KeyValue<int, LocalVector<int>> &E : group_to_variant_map) {
StringBuilder hash_build;
hash_build.append("[base_hash]");
hash_build.append(base_sha256);
hash_build.append("[general_defines]");
hash_build.append(general_defines.get_data());
- for (int i = 0; i < variant_defines.size(); i++) {
- hash_build.append("[variant_defines:" + itos(i) + "]");
- hash_build.append(variant_defines[i].get_data());
+ hash_build.append("[group_id]");
+ hash_build.append(itos(E.key));
+ for (uint32_t i = 0; i < E.value.size(); i++) {
+ hash_build.append("[variant_defines:" + itos(E.value[i]) + "]");
+ hash_build.append(variant_defines[E.value[i]].text.get_data());
}
- base_sha256 = hash_build.as_string().sha256_text();
+ group_sha256[E.key] = hash_build.as_string().sha256_text();
Ref<DirAccess> d = DirAccess::open(shader_cache_dir);
ERR_FAIL_COND(d.is_null());
@@ -666,17 +757,58 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
d->change_dir(name);
}
- //erase other versions?
+ // Erase other versions?
if (shader_cache_cleanup_on_start) {
}
//
- if (d->change_dir(base_sha256) != OK) {
- Error err = d->make_dir(base_sha256);
+ if (d->change_dir(group_sha256[E.key]) != OK) {
+ Error err = d->make_dir(group_sha256[E.key]);
ERR_FAIL_COND(err != OK);
}
shader_cache_dir_valid = true;
- print_verbose("Shader '" + name + "' SHA256: " + base_sha256);
+ print_verbose("Shader '" + name + "' (group " + itos(E.key) + ") SHA256: " + group_sha256[E.key]);
+ }
+}
+
+// Same as above, but allows specifying shader compilation groups.
+void ShaderRD::initialize(const Vector<VariantDefine> &p_variant_defines, const String &p_general_defines) {
+ ERR_FAIL_COND(variant_defines.size());
+ ERR_FAIL_COND(p_variant_defines.size() == 0);
+
+ general_defines = p_general_defines.utf8();
+
+ int max_group_id = 0;
+
+ for (int i = 0; i < p_variant_defines.size(); i++) {
+ // Fill variant array.
+ variant_defines.push_back(p_variant_defines[i]);
+ variants_enabled.push_back(true);
+
+ // Map variant array index to group id, so we can iterate over groups later.
+ if (!group_to_variant_map.has(p_variant_defines[i].group)) {
+ group_to_variant_map.insert(p_variant_defines[i].group, LocalVector<int>{});
+ }
+ group_to_variant_map[p_variant_defines[i].group].push_back(i);
+
+ // Track max size.
+ if (p_variant_defines[i].group > max_group_id) {
+ max_group_id = p_variant_defines[i].group;
+ }
+ }
+
+ // Set all to groups to false, then enable those that should be default.
+ group_enabled.resize_zeroed(max_group_id + 1);
+ bool *enabled_ptr = group_enabled.ptrw();
+ for (int i = 0; i < p_variant_defines.size(); i++) {
+ if (p_variant_defines[i].default_enabled) {
+ enabled_ptr[p_variant_defines[i].group] = true;
+ }
+ }
+
+ if (!shader_cache_dir.is_empty()) {
+ group_sha256.resize(max_group_id + 1);
+ _initialize_cache();
}
}
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index d0871ca16c..01eb99f7a2 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -41,10 +41,26 @@
#include "servers/rendering_server.h"
class ShaderRD {
+public:
+ struct VariantDefine {
+ int group = 0;
+ CharString text;
+ bool default_enabled = true;
+ VariantDefine(){};
+ VariantDefine(int p_group, const String &p_text, bool p_default_enabled) {
+ group = p_group;
+ default_enabled = p_default_enabled;
+ text = p_text.utf8();
+ }
+ };
+
+private:
//versions
CharString general_defines;
- Vector<CharString> variant_defines;
+ Vector<VariantDefine> variant_defines;
Vector<bool> variants_enabled;
+ HashMap<int, LocalVector<int>> group_to_variant_map;
+ Vector<bool> group_enabled;
struct Version {
CharString uniforms;
@@ -55,7 +71,7 @@ class ShaderRD {
Vector<CharString> custom_defines;
Vector<uint8_t> *variant_data = nullptr;
- RID *variants = nullptr; //same size as version defines
+ RID *variants = nullptr; // Same size as variant defines.
bool valid;
bool dirty;
@@ -64,10 +80,17 @@ class ShaderRD {
Mutex variant_set_mutex;
- void _compile_variant(uint32_t p_variant, Version *p_version);
+ struct CompileData {
+ Version *version;
+ int group = 0;
+ };
+
+ void _compile_variant(uint32_t p_variant, const CompileData *p_data);
+ void _initialize_version(Version *p_version);
void _clear_version(Version *p_version);
- void _compile_version(Version *p_version);
+ void _compile_version(Version *p_version, int p_group);
+ void _allocate_placeholders(Version *p_version, int p_group);
RID_Owner<Version> version_owner;
@@ -97,6 +120,7 @@ class ShaderRD {
CharString base_compute_defines;
String base_sha256;
+ LocalVector<String> group_sha256;
static String shader_cache_dir;
static bool shader_cache_cleanup_on_start;
@@ -119,8 +143,9 @@ class ShaderRD {
void _add_stage(const char *p_code, StageType p_stage_type);
String _version_get_sha1(Version *p_version) const;
- bool _load_from_cache(Version *p_version);
- void _save_to_cache(Version *p_version);
+ bool _load_from_cache(Version *p_version, int p_group);
+ void _save_to_cache(Version *p_version, int p_group);
+ void _initialize_cache();
protected:
ShaderRD();
@@ -140,7 +165,14 @@ public:
ERR_FAIL_COND_V(!version, RID());
if (version->dirty) {
- _compile_version(version);
+ _initialize_version(version);
+ for (int i = 0; i < group_enabled.size(); i++) {
+ if (!group_enabled[i]) {
+ _allocate_placeholders(version, i);
+ continue;
+ }
+ _compile_version(version, i);
+ }
}
if (!version->valid) {
@@ -154,9 +186,14 @@ public:
bool version_free(RID p_version);
+ // Enable/disable variants for things that you know won't be used at engine initialization time .
void set_variant_enabled(int p_variant, bool p_enabled);
bool is_variant_enabled(int p_variant) const;
+ // Enable/disable groups for things that might be enabled at run time.
+ void enable_group(int p_group);
+ bool is_group_enabled(int p_group) const;
+
static void set_shader_cache_dir(const String &p_dir);
static void set_shader_cache_save_compressed(bool p_enable);
static void set_shader_cache_save_compressed_zstd(bool p_enable);
@@ -165,6 +202,8 @@ public:
RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
+ void initialize(const Vector<VariantDefine> &p_variant_defines, const String &p_general_defines = "");
+
virtual ~ShaderRD();
};
diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl
index 14f190a49f..d451647bec 100644
--- a/servers/rendering/renderer_rd/shaders/blit.glsl
+++ b/servers/rendering/renderer_rd/shaders/blit.glsl
@@ -45,7 +45,7 @@ layout(push_constant, std140) uniform Pos {
float upscale;
float aspect_ratio;
uint layer;
- uint pad1;
+ bool convert_to_srgb;
}
data;
@@ -59,6 +59,13 @@ layout(binding = 0) uniform sampler2DArray src_rt;
layout(binding = 0) uniform sampler2D src_rt;
#endif
+vec3 linear_to_srgb(vec3 color) {
+ // If going to srgb, clamp from 0 to 1.
+ color = clamp(color, vec3(0.0), vec3(1.0));
+ const vec3 a = vec3(0.055f);
+ return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
+}
+
void main() {
#ifdef APPLY_LENS_DISTORTION
vec2 coords = uv * 2.0 - 1.0;
@@ -94,4 +101,8 @@ void main() {
#else
color = texture(src_rt, uv);
#endif
+
+ if (data.convert_to_srgb) {
+ color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
+ }
}
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 6270450c15..31c5aadc88 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -36,6 +36,12 @@ layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
#GLOBALS
+#ifdef USE_ATTRIBUTES
+vec3 srgb_to_linear(vec3 color) {
+ return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
+}
+#endif
+
void main() {
vec4 instance_custom = vec4(0.0);
#ifdef USE_PRIMITIVE
@@ -65,7 +71,11 @@ void main() {
#elif defined(USE_ATTRIBUTES)
vec2 vertex = vertex_attrib;
- vec4 color = color_attrib * draw_data.modulation;
+ vec4 color = color_attrib;
+ if (bool(draw_data.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) {
+ color.rgb = srgb_to_linear(color.rgb);
+ }
+ color *= draw_data.modulation;
vec2 uv = uv_attrib;
uvec4 bones = bone_attrib;
@@ -563,9 +573,6 @@ void main() {
}
vec4 base_color = color;
- if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {
- color = vec4(0.0); //invisible by default due to using light mask
- }
#ifdef MODE_LIGHT_ONLY
float light_only_alpha = 0.0;
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 2dd5abb75f..7ac7cf9c07 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -12,7 +12,7 @@
#define FLAGS_CLIP_RECT_UV (1 << 9)
#define FLAGS_TRANSPOSE_RECT (1 << 10)
-#define FLAGS_USING_LIGHT_MASK (1 << 11)
+#define FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 11)
#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12)
#define FLAGS_USING_PARTICLES (1 << 13)
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index 31aabbe9d2..91a3b582b9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -11,10 +11,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index 1b487835d2..947aa793d9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -11,10 +11,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index 3a82861057..2b3d27b000 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -57,7 +57,7 @@ layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffe
#elif defined(DST_IMAGE_8BIT)
layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
#else
-layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+layout(rgba16f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
#endif
#ifdef MODE_GAUSSIAN_BLUR
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
index b8c64d09f4..7b3c2f1c3b 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
@@ -31,9 +31,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex] * float(params.face_size);
- gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl
index 0990dc7c2f..961ec96f00 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl
@@ -35,9 +35,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex];
- gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl
index c29accd8a7..05a20c459b 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl
@@ -11,9 +11,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex];
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl
index 29ebd74a90..05a84db6b6 100644
--- a/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl
@@ -11,10 +11,9 @@ layout(location = 0) out vec2 uv_interp;
/* clang-format on */
void main() {
- 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_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
index a7da0812df..4df74b8626 100644
--- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
@@ -36,7 +36,7 @@ void main() {
if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
- //do not filter, SSR will generate arctifacts if this is done
+ //do not filter, SSR will generate artifacts if this is done
float divisor = 0.0;
vec4 color;
diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
index c62144fdaf..db710b7cdd 100644
--- a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
@@ -27,16 +27,11 @@ layout(location = 0) out vec2 uv_interp;
#endif //USE_MULTIVIEW
void main() {
- 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));
-
-#ifdef USE_MULTIVIEW
- uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex);
-
- gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
-#else
- uv_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp.xy = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
+#ifdef MULTIVIEW
+ uv_interp.z = ViewIndex;
#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index 52aee8b648..33ec991107 100644
--- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -13,9 +13,9 @@
layout(location = 0) out vec2 uv_interp;
void main() {
- 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_interp = base_arr[gl_VertexIndex];
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
}
#[fragment]
@@ -57,14 +57,21 @@ layout(set = 3, binding = 0) uniform sampler2D source_color_correction;
layout(set = 3, binding = 0) uniform sampler3D source_color_correction;
#endif
+#define FLAG_USE_BCS (1 << 0)
+#define FLAG_USE_GLOW (1 << 1)
+#define FLAG_USE_AUTO_EXPOSURE (1 << 2)
+#define FLAG_USE_COLOR_CORRECTION (1 << 3)
+#define FLAG_USE_FXAA (1 << 4)
+#define FLAG_USE_DEBANDING (1 << 5)
+#define FLAG_CONVERT_TO_SRGB (1 << 6)
+
layout(push_constant, std430) uniform Params {
vec3 bcs;
- bool use_bcs;
+ uint flags;
- bool use_glow;
- bool use_auto_exposure;
- bool use_color_correction;
+ vec2 pixel_size;
uint tonemapper;
+ uint pad;
uvec2 glow_texture_size;
float glow_intensity;
@@ -77,10 +84,6 @@ layout(push_constant, std430) uniform Params {
float white;
float auto_exposure_scale;
float luminance_multiplier;
-
- vec2 pixel_size;
- bool use_fxaa;
- bool use_debanding;
}
params;
@@ -318,10 +321,12 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
if (params.glow_mode == GLOW_MODE_ADD) {
return color + glow;
} else if (params.glow_mode == GLOW_MODE_SCREEN) {
- //need color clamping
+ // Needs color clamping.
+ glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
return max((color + glow) - (color * glow), vec3(0.0));
} else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) {
- //need color clamping
+ // Needs color clamping.
+ glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
glow = glow * vec3(0.5f) + vec3(0.5f);
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
@@ -439,7 +444,7 @@ void main() {
float exposure = params.exposure;
#ifndef SUBPASS
- if (params.use_auto_exposure) {
+ if (bool(params.flags & FLAG_USE_AUTO_EXPOSURE)) {
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);
}
#endif
@@ -448,12 +453,12 @@ void main() {
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
- if (params.use_fxaa) {
+ if (bool(params.flags & FLAG_USE_FXAA)) {
// FXAA must be performed before glow to preserve the "bleed" effect of glow.
color.rgb = do_fxaa(color.rgb, exposure, uv_interp);
}
- if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
+ if (bool(params.flags & FLAG_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);
@@ -464,11 +469,12 @@ void main() {
color.rgb = apply_tonemapping(color.rgb, params.white);
- color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion
-
+ if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
+ color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
+ }
#ifndef SUBPASS
// Glow
- if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
+ if (bool(params.flags & FLAG_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);
@@ -476,7 +482,9 @@ void main() {
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, params.white);
- glow = linear_to_srgb(glow);
+ if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
+ glow = linear_to_srgb(glow);
+ }
color.rgb = apply_glow(color.rgb, glow);
}
@@ -484,15 +492,15 @@ void main() {
// Additional effects
- if (params.use_bcs) {
+ if (bool(params.flags & FLAG_USE_BCS)) {
color.rgb = apply_bcs(color.rgb, params.bcs);
}
- if (params.use_color_correction) {
+ if (bool(params.flags & FLAG_USE_COLOR_CORRECTION)) {
color.rgb = apply_color_correction(color.rgb);
}
- if (params.use_debanding) {
+ if (bool(params.flags & FLAG_USE_DEBANDING)) {
// Debanding should be done at the end of tonemapping, but before writing to the LDR buffer.
// Otherwise, we're adding noise to an already-quantized image.
color.rgb += screen_space_dither(gl_FragCoord.xy);
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index b450bb9fe9..d3d39a8b92 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -20,13 +20,12 @@ layout(location = 0) out vec2 uv_interp;
#endif
void main() {
- 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_interp.xy = base_arr[gl_VertexIndex];
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp.xy = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
#ifdef MULTIVIEW
uv_interp.z = ViewIndex;
#endif
-
- gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
}
#[fragment]
diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index d605917acc..4e5b11aed8 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -23,7 +23,7 @@ layout(push_constant, std430) uniform Params {
params;
void main() {
- vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -3.0), vec2(-1.0, 1.0), vec2(3.0, 1.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 9214a953aa..d1cfda515f 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -18,7 +18,11 @@ layout(location = 0) in vec3 vertex_attrib;
layout(location = 1) in vec2 normal_attrib;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if !defined(TANGENT_USED) && (defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED))
+#define TANGENT_USED
+#endif
+
+#ifdef TANGENT_USED
layout(location = 2) in vec2 tangent_attrib;
#endif
@@ -58,6 +62,18 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+#ifdef MOTION_VECTORS
+layout(location = 12) in vec3 previous_vertex_attrib;
+
+#ifdef NORMAL_USED
+layout(location = 13) in vec2 previous_normal_attrib;
+#endif
+
+#ifdef TANGENT_USED
+layout(location = 14) in vec2 previous_tangent_attrib;
+#endif
+#endif // MOTION_VECTORS
+
vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
@@ -85,7 +101,7 @@ layout(location = 3) out vec2 uv_interp;
layout(location = 4) out vec2 uv2_interp;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
layout(location = 5) out vec3 tangent_interp;
layout(location = 6) out vec3 binormal_interp;
#endif
@@ -161,7 +177,14 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
}
#endif
-void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
+void vertex_shader(vec3 vertex_input,
+#ifdef NORMAL_USED
+ in vec2 normal_input,
+#endif
+#ifdef TANGENT_USED
+ in vec2 tangent_input,
+#endif
+ in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
@@ -289,15 +312,15 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
model_normal_matrix = model_normal_matrix * mat3(matrix);
}
- vec3 vertex = vertex_attrib;
+ vec3 vertex = vertex_input;
#ifdef NORMAL_USED
- vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
+ vec3 normal = oct_to_vec3(normal_input * 2.0 - 1.0);
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
- vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
- float binormalf = sign(signed_tangent_attrib.y);
+#ifdef TANGENT_USED
+ vec2 signed_tangent_input = tangent_input * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_input.x, abs(signed_tangent_input.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_input.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
@@ -333,7 +356,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
normal = model_normal_matrix * normal;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
tangent = model_normal_matrix * tangent;
binormal = model_normal_matrix * binormal;
@@ -377,7 +400,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
binormal = modelview_normal * binormal;
tangent = modelview_normal * tangent;
@@ -391,7 +414,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz;
tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;
#endif
@@ -403,7 +426,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
normal_interp = normal;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
tangent_interp = tangent;
binormal_interp = binormal;
#endif
@@ -472,16 +495,33 @@ void main() {
instance_index_interp = instance_index;
mat4 model_matrix = instances.data[instance_index].transform;
-#if defined(MOTION_VECTORS)
+
+#ifdef MOTION_VECTORS
+ // Previous vertex.
global_time = scene_data_block.prev_data.time;
- vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
- global_time = scene_data_block.data.time;
- vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
+ vertex_shader(previous_vertex_attrib,
+#ifdef NORMAL_USED
+ previous_normal_attrib,
+#endif
+#ifdef TANGENT_USED
+ previous_tangent_attrib,
+#endif
+ instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
#else
- global_time = scene_data_block.data.time;
+ // Unused output.
vec4 screen_position;
- vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
#endif
+
+ // Current vertex.
+ global_time = scene_data_block.data.time;
+ vertex_shader(vertex_attrib,
+#ifdef NORMAL_USED
+ normal_attrib,
+#endif
+#ifdef TANGENT_USED
+ tangent_attrib,
+#endif
+ instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
}
#[fragment]
@@ -535,7 +575,11 @@ layout(location = 3) in vec2 uv_interp;
layout(location = 4) in vec2 uv2_interp;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if !defined(TANGENT_USED) && (defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED))
+#define TANGENT_USED
+#endif
+
+#ifdef TANGENT_USED
layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
@@ -771,7 +815,7 @@ void fragment_shader(in SceneData scene_data) {
float alpha = float(instances.data[instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) / float(255.0);
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#ifdef TANGENT_USED
vec3 binormal = normalize(binormal_interp);
vec3 tangent = normalize(tangent_interp);
#else
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index b63eea1401..0283482d76 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -899,6 +899,10 @@ void main() {
break;
}
+ if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
+
vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
continue; //out of decal
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index ba8d901772..aa90ad6876 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -584,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
{
vec4 clamp_rect = omni_lights.data[idx].atlas_rect;
- //redo shadowmapping, but shrink the model a bit to avoid arctifacts
+ //redo shadowmapping, but shrink the model a bit to avoid artifacts
vec4 splane = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * omni_lights.data[idx].transmittance_bias, 1.0));
float shadow_len = length(splane.xyz);
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index d055f01009..fda341bbc9 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -751,7 +751,7 @@ MaterialStorage::MaterialData::~MaterialData() {
}
}
-void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -917,7 +917,7 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
if (tex) {
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
#ifdef TOOLS_ENABLED
- if (tex->detect_3d_callback && p_use_linear_color) {
+ if (tex->detect_3d_callback && p_3d_material) {
tex->detect_3d_callback(tex->detect_3d_callback_ud);
}
if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
@@ -986,7 +986,7 @@ void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_se
}
}
-bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier) {
+bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -1033,7 +1033,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
}
if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), p_use_linear_color);
+ update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), p_use_linear_color, p_3d_material);
}
if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
@@ -1821,14 +1821,16 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//textire
if (!p_load_textures) {
- value = RID();
continue;
}
String path = value;
- Ref<Resource> resource = ResourceLoader::load(path);
- ERR_CONTINUE(resource.is_null());
- value = resource;
+ if (path.is_empty()) {
+ value = RID();
+ } else {
+ Ref<Resource> resource = ResourceLoader::load(path);
+ value = resource;
+ }
}
if (global_shader_uniforms.variables.has(name)) {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index b6da3df783..ae97f43a3c 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -78,7 +78,7 @@ public:
struct MaterialData {
Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache;
void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+ void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material);
void set_as_used();
virtual void set_render_priority(int p_priority) = 0;
@@ -87,7 +87,7 @@ public:
virtual ~MaterialData();
//to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
+ bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
void free_parameters_uniform_set(RID p_uniform_set);
private:
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 67b5cdd291..439d0702f5 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -29,7 +29,6 @@
/**************************************************************************/
#include "mesh_storage.h"
-#include "../../rendering_server_globals.h"
using namespace RendererRD;
@@ -854,8 +853,11 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
}
memfree(surface.versions);
}
- if (surface.vertex_buffer.is_valid()) {
- RD::get_singleton()->free(surface.vertex_buffer);
+
+ for (uint32_t i = 0; i < 2; i++) {
+ if (surface.vertex_buffer[i].is_valid()) {
+ RD::get_singleton()->free(surface.vertex_buffer[i]);
+ }
}
}
mi->surfaces.clear();
@@ -881,35 +883,38 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
MeshInstance::Surface s;
if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
- //surface warrants transform
- s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s.vertex_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (mi->blend_weights_buffer.is_valid()) {
- u.append_id(mi->blend_weights_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
+ _mesh_instance_add_surface_buffer(mi, mesh, &s, p_surface, 0);
}
mi->surfaces.push_back(s);
mi->dirty = true;
}
+void MeshStorage::_mesh_instance_add_surface_buffer(MeshInstance *mi, Mesh *mesh, MeshInstance::Surface *s, uint32_t p_surface, uint32_t p_buffer_index) {
+ s->vertex_buffer[p_buffer_index] = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(s->vertex_buffer[p_buffer_index]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (mi->blend_weights_buffer.is_valid()) {
+ u.append_id(mi->blend_weights_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+ s->uniform_set[p_buffer_index] = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
+}
+
void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
@@ -956,6 +961,8 @@ void MeshStorage::update_mesh_instances() {
}
//process skeletons and blend shapes
+ uint64_t frame = RSG::rasterizer->get_frame_number();
+ bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0);
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
while (dirty_mesh_instance_arrays.first()) {
@@ -964,7 +971,29 @@ void MeshStorage::update_mesh_instances() {
Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
+ if (mi->surfaces[i].uniform_set[0].is_null() || mi->mesh->surfaces[i]->uniform_set.is_null()) {
+ // Skip over mesh instances that don't require their own uniform buffers.
+ continue;
+ }
+
+ mi->surfaces[i].previous_buffer = mi->surfaces[i].current_buffer;
+
+ if (uses_motion_vectors && (frame - mi->surfaces[i].last_change) == 1) {
+ // Previous buffer's data can only be one frame old to be able to use motion vectors.
+ uint32_t new_buffer_index = mi->surfaces[i].current_buffer ^ 1;
+
+ if (mi->surfaces[i].uniform_set[new_buffer_index].is_null()) {
+ // Create the new vertex buffer on demand where the result for the current frame will be stored.
+ _mesh_instance_add_surface_buffer(mi, mi->mesh, &mi->surfaces[i], i, new_buffer_index);
+ }
+
+ mi->surfaces[i].current_buffer = new_buffer_index;
+ }
+
+ mi->surfaces[i].last_change = frame;
+
+ RID mi_surface_uniform_set = mi->surfaces[i].uniform_set[mi->surfaces[i].current_buffer];
+ if (mi_surface_uniform_set.is_null()) {
continue;
}
@@ -972,7 +1001,7 @@ void MeshStorage::update_mesh_instances() {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi_surface_uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE);
if (sk && sk->uniform_set_mi.is_valid()) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON);
@@ -1032,7 +1061,7 @@ void MeshStorage::update_mesh_instances() {
RD::get_singleton()->compute_list_end();
}
-void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
+void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis) {
Vector<RD::VertexAttribute> attributes;
Vector<RID> buffers;
@@ -1105,7 +1134,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
}
if (mis) {
- buffer = mis->vertex_buffer;
+ buffer = mis->vertex_buffer[mis->current_buffer];
} else {
buffer = s->vertex_buffer;
}
@@ -1117,7 +1146,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
stride += sizeof(uint16_t) * 2;
if (mis) {
- buffer = mis->vertex_buffer;
+ buffer = mis->vertex_buffer[mis->current_buffer];
} else {
buffer = s->vertex_buffer;
}
@@ -1128,7 +1157,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
stride += sizeof(uint16_t) * 2;
if (mis) {
- buffer = mis->vertex_buffer;
+ buffer = mis->vertex_buffer[mis->current_buffer];
} else {
buffer = s->vertex_buffer;
}
@@ -1193,6 +1222,32 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
attributes.push_back(vd);
buffers.push_back(buffer);
+
+ if (p_input_motion_vectors) {
+ // Since the previous vertex, normal and tangent can't be part of the vertex format but they are required when motion
+ // vectors are enabled, we opt to push a copy of the vertex attribute with a different location and buffer (if it's
+ // part of an instance that has one).
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ vd.location = ATTRIBUTE_LOCATION_PREV_VERTEX;
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.location = ATTRIBUTE_LOCATION_PREV_NORMAL;
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.location = ATTRIBUTE_LOCATION_PREV_TANGENT;
+ } break;
+ }
+
+ if (int(vd.location) != i) {
+ if (mis && buffer != mesh_default_rd_buffers[i]) {
+ buffer = mis->vertex_buffer[mis->previous_buffer];
+ }
+
+ attributes.push_back(vd);
+ buffers.push_back(buffer);
+ }
+ }
}
//update final stride
@@ -1202,7 +1257,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
}
int loc = attributes[i].location;
- if (loc < RS::ARRAY_COLOR) {
+ if ((loc < RS::ARRAY_COLOR) || ((loc >= ATTRIBUTE_LOCATION_PREV_VERTEX) && (loc <= ATTRIBUTE_LOCATION_PREV_TANGENT))) {
attributes.write[i].stride = stride;
} else if (loc < RS::ARRAY_BONES) {
attributes.write[i].stride = attribute_stride;
@@ -1212,6 +1267,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
}
v.input_mask = p_input_mask;
+ v.current_buffer = mis ? mis->current_buffer : 0;
+ v.previous_buffer = mis ? mis->previous_buffer : 0;
+ v.input_motion_vectors = p_input_motion_vectors;
v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
}
@@ -1289,12 +1347,9 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}
-bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, false);
-
+void MeshStorage::_multimesh_enable_motion_vectors(MultiMesh *multimesh) {
if (multimesh->motion_vectors_enabled) {
- return false;
+ return;
}
multimesh->motion_vectors_enabled = true;
@@ -1307,22 +1362,30 @@ bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) {
multimesh->data_cache.append_array(multimesh->data_cache);
}
- if (multimesh->buffer_set) {
+ uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float);
+ uint32_t new_buffer_size = buffer_size * 2;
+ RID new_buffer = RD::get_singleton()->storage_buffer_create(new_buffer_size);
+
+ if (multimesh->buffer_set && multimesh->data_cache.is_empty()) {
+ // If the buffer was set but there's no data cached in the CPU, we copy the buffer directly on the GPU.
RD::get_singleton()->barrier();
- Vector<uint8_t> buffer_data = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- if (!multimesh->data_cache.is_empty()) {
- memcpy(buffer_data.ptrw(), multimesh->data_cache.ptr(), buffer_data.size());
- }
+ RD::get_singleton()->buffer_copy(multimesh->buffer, new_buffer, 0, 0, buffer_size, RD::BARRIER_MASK_NO_BARRIER);
+ RD::get_singleton()->buffer_copy(multimesh->buffer, new_buffer, 0, buffer_size, buffer_size);
+ } else if (!multimesh->data_cache.is_empty()) {
+ // Simply upload the data cached in the CPU, which should already be doubled in size.
+ ERR_FAIL_COND(multimesh->data_cache.size() * sizeof(float) != size_t(new_buffer_size));
+ RD::get_singleton()->buffer_update(new_buffer, 0, new_buffer_size, multimesh->data_cache.ptr());
+ }
+ if (multimesh->buffer.is_valid()) {
RD::get_singleton()->free(multimesh->buffer);
- uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float) * 2;
- multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size);
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, buffer_data.size(), buffer_data.ptr(), RD::BARRIER_MASK_NO_BARRIER);
- RD::get_singleton()->buffer_update(multimesh->buffer, buffer_data.size(), buffer_data.size(), buffer_data.ptr());
- multimesh->uniform_set_3d = RID(); // Cleared by dependency
- return true;
}
- return false; // Update the transforms uniform set cache
+
+ multimesh->buffer = new_buffer;
+ multimesh->uniform_set_3d = RID(); // Cleared by dependency.
+
+ // Invalidate any references to the buffer that was released and the uniform set that was pointing to it.
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}
void MeshStorage::_multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset) {
@@ -1531,6 +1594,12 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
_multimesh_make_local(multimesh);
+
+ bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0);
+ if (uses_motion_vectors) {
+ _multimesh_enable_motion_vectors(multimesh);
+ }
+
_multimesh_update_motion_vectors_data_cache(multimesh);
{
@@ -1749,6 +1818,11 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
+ bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0);
+ if (uses_motion_vectors) {
+ _multimesh_enable_motion_vectors(multimesh);
+ }
+
if (multimesh->motion_vectors_enabled) {
uint32_t frame = RSG::rasterizer->get_frame_number();
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 4d46a62a76..99ba69f98a 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -31,6 +31,7 @@
#ifndef MESH_STORAGE_RD_H
#define MESH_STORAGE_RD_H
+#include "../../rendering_server_globals.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
@@ -90,6 +91,9 @@ private:
struct Version {
uint32_t input_mask = 0;
+ uint32_t current_buffer = 0;
+ uint32_t previous_buffer = 0;
+ bool input_motion_vectors = false;
RD::VertexFormatID vertex_format = 0;
RID vertex_array;
};
@@ -162,8 +166,11 @@ private:
Mesh *mesh = nullptr;
RID skeleton;
struct Surface {
- RID vertex_buffer;
- RID uniform_set;
+ RID vertex_buffer[2];
+ RID uniform_set[2];
+ uint32_t current_buffer = 0;
+ uint32_t previous_buffer = 0;
+ uint64_t last_change = 0;
Mesh::Surface::Version *versions = nullptr; //allocated on demand
uint32_t version_count = 0;
@@ -183,10 +190,11 @@ private:
weight_update_list(this), array_update_list(this) {}
};
- void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis = nullptr);
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
+ void _mesh_instance_add_surface_buffer(MeshInstance *mi, Mesh *mesh, MeshInstance::Surface *s, uint32_t p_surface, uint32_t p_buffer_index);
mutable RID_Owner<MeshInstance> mesh_instance_owner;
@@ -234,6 +242,7 @@ private:
MultiMesh *multimesh_dirty_list = nullptr;
_FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_enable_motion_vectors(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
@@ -310,6 +319,12 @@ private:
Skeleton *skeleton_dirty_list = nullptr;
+ enum AttributeLocation {
+ ATTRIBUTE_LOCATION_PREV_VERTEX = 12,
+ ATTRIBUTE_LOCATION_PREV_NORMAL = 13,
+ ATTRIBUTE_LOCATION_PREV_TANGENT = 14
+ };
+
public:
static MeshStorage *get_singleton();
@@ -436,7 +451,7 @@ public:
}
}
- _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
s->version_lock.lock();
@@ -444,9 +459,11 @@ public:
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
for (uint32_t i = 0; i < s->version_count; i++) {
- if (s->versions[i].input_mask != p_input_mask) {
+ if (s->versions[i].input_mask != p_input_mask || s->versions[i].input_motion_vectors != p_input_motion_vectors) {
+ // Find the version that matches the inputs required.
continue;
}
+
//we have this version, hooray
r_vertex_format = s->versions[i].vertex_format;
r_vertex_array_rd = s->versions[i].vertex_array;
@@ -458,7 +475,7 @@ public:
s->version_count++;
s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
- _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask);
+ _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask, p_input_motion_vectors);
r_vertex_format = s->versions[version].vertex_format;
r_vertex_array_rd = s->versions[version].vertex_array;
@@ -466,7 +483,7 @@ public:
s->version_lock.unlock();
}
- _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_COND(!mi);
Mesh *mesh = mi->mesh;
@@ -474,15 +491,26 @@ public:
MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
Mesh::Surface *s = mesh->surfaces[p_surface_index];
+ uint32_t current_buffer = mis->current_buffer;
+
+ // Using the previous buffer is only allowed if the surface was updated this frame and motion vectors are required.
+ uint32_t previous_buffer = p_input_motion_vectors && (RSG::rasterizer->get_frame_number() == mis->last_change) ? mis->previous_buffer : current_buffer;
s->version_lock.lock();
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
for (uint32_t i = 0; i < mis->version_count; i++) {
- if (mis->versions[i].input_mask != p_input_mask) {
+ if (mis->versions[i].input_mask != p_input_mask || mis->versions[i].input_motion_vectors != p_input_motion_vectors) {
+ // Find the version that matches the inputs required.
continue;
}
+
+ if (mis->versions[i].current_buffer != current_buffer || mis->versions[i].previous_buffer != previous_buffer) {
+ // Find the version that corresponds to the correct buffers that should be used.
+ continue;
+ }
+
//we have this version, hooray
r_vertex_format = mis->versions[i].vertex_format;
r_vertex_array_rd = mis->versions[i].vertex_array;
@@ -494,7 +522,7 @@ public:
mis->version_count++;
mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
- _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis);
+ _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, mis);
r_vertex_format = mis->versions[version].vertex_format;
r_vertex_array_rd = mis->versions[version].vertex_array;
@@ -593,7 +621,6 @@ public:
virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
void _update_dirty_multimeshes();
- bool _multimesh_enable_motion_vectors(RID p_multimesh);
void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset);
_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 8f647be5c9..0a91672544 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -1629,7 +1629,7 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
}
bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true, false);
}
ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() {
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
index a7b8f985d9..27c435eeba 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
@@ -234,6 +234,12 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p
RendererRD::MaterialStorage::store_transform(prev_cam_transform, prev_ubo.inv_view_matrix);
RendererRD::MaterialStorage::store_transform(prev_cam_transform.affine_inverse(), prev_ubo.view_matrix);
+#ifdef REAL_T_IS_DOUBLE
+ RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.x, &prev_ubo.inv_view_matrix[12], &prev_ubo.inv_view_matrix[3]);
+ RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.y, &prev_ubo.inv_view_matrix[13], &prev_ubo.inv_view_matrix[7]);
+ RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.z, &prev_ubo.inv_view_matrix[14], &prev_ubo.inv_view_matrix[11]);
+#endif
+
for (uint32_t v = 0; v < view_count; v++) {
prev_projection = prev_correction * view_projection[v];
RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix_view[v]);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index d84f6e6850..286a9528fc 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -46,9 +46,11 @@ void TextureStorage::CanvasTexture::clear_sets() {
}
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
- RD::get_singleton()->free(uniform_sets[i][j]);
- uniform_sets[i][j] = RID();
+ for (int k = 0; k < 2; k++) {
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j][k])) {
+ RD::get_singleton()->free(uniform_sets[i][j][k]);
+ uniform_sets[i][j][k] = RID();
+ }
}
}
}
@@ -641,7 +643,7 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
ct->clear_sets();
}
-bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
+bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data) {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
CanvasTexture *ct = nullptr;
@@ -674,7 +676,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
- RID uniform_set = ct->uniform_sets[filter][repeat];
+ RID uniform_set = ct->uniform_sets[filter][repeat][int(p_use_srgb)];
if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
//create and update
Vector<RD::Uniform> uniforms;
@@ -688,7 +690,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
ct->size_cache = Size2i(1, 1);
} else {
- u.append_id(t->rd_texture);
+ u.append_id(t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture);
ct->size_cache = Size2i(t->width_2d, t->height_2d);
if (t->render_target) {
t->render_target->was_used = true;
@@ -741,7 +743,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
}
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
- ct->uniform_sets[filter][repeat] = uniform_set;
+ ct->uniform_sets[filter][repeat][int(p_use_srgb)] = uniform_set;
ct->cleared_cache = false;
}
@@ -1268,7 +1270,35 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
#endif
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ Ref<Image> image;
+
+ // Expand RGB10_A2 into RGBAH. This is needed for capturing viewport data
+ // when using the mobile renderer with HDR mode on.
+ if (tex->rd_format == RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32) {
+ Vector<uint8_t> new_data;
+ new_data.resize(data.size() * 2);
+ uint16_t *ndp = (uint16_t *)new_data.ptr();
+
+ uint32_t *ptr = (uint32_t *)data.ptr();
+ uint32_t num_pixels = data.size() / 4;
+
+ for (uint32_t ofs = 0; ofs < num_pixels; ofs++) {
+ uint32_t px = ptr[ofs];
+ uint32_t r = (px & 0x3FF);
+ uint32_t g = ((px >> 10) & 0x3FF);
+ uint32_t b = ((px >> 20) & 0x3FF);
+ uint32_t a = ((px >> 30) & 0x3);
+
+ ndp[ofs * 4 + 0] = Math::make_half_float(float(r) / 1023.0);
+ ndp[ofs * 4 + 1] = Math::make_half_float(float(g) / 1023.0);
+ ndp[ofs * 4 + 2] = Math::make_half_float(float(b) / 1023.0);
+ ndp[ofs * 4 + 3] = Math::make_half_float(float(a) / 3.0);
+ }
+ image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, new_data);
+ } else {
+ image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ }
+
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
image->convert(tex->format);
@@ -3020,10 +3050,15 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
if (rt->size.width == 0 || rt->size.height == 0) {
return;
}
- //until we implement support for HDR monitors (and render target is attached to screen), this is enough.
- rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
+ if (rt->use_hdr) {
+ rt->color_format = RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format();
+ rt->color_format_srgb = rt->color_format;
+ rt->image_format = rt->is_transparent ? Image::FORMAT_RGBAH : Image::FORMAT_RGBH;
+ } else {
+ rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
+ }
RD::TextureFormat rd_color_attachment_format;
RD::TextureView rd_view;
@@ -3106,6 +3141,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
tex->rd_format = rt->color_format;
tex->rd_format_srgb = rt->color_format_srgb;
tex->format = rt->image_format;
+ tex->validated_format = rt->use_hdr ? Image::FORMAT_RGBAH : Image::FORMAT_RGBA8;
Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
for (int i = 0; i < proxies.size(); i++) {
@@ -3328,6 +3364,25 @@ RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) con
return rt->msaa;
}
+void TextureStorage::render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ if (p_use_hdr == rt->use_hdr) {
+ return;
+ }
+
+ rt->use_hdr = p_use_hdr;
+ _update_render_target(rt);
+}
+
+bool TextureStorage::render_target_is_using_hdr(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->use_hdr;
+}
+
RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
@@ -3404,7 +3459,7 @@ bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Color());
- return rt->clear_color;
+ return rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color;
}
void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
@@ -3420,7 +3475,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) {
return;
}
Vector<Color> clear_colors;
- clear_colors.push_back(rt->clear_color);
+ clear_colors.push_back(rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color);
RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
RD::get_singleton()->draw_list_end();
rt->clear_requested = false;
@@ -3735,7 +3790,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
// TODO figure out stereo support here
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
- copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, !rt->use_hdr, true);
} else {
copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true);
}
@@ -3759,7 +3814,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
RID mipmap = rt->backbuffer_mipmaps[i];
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
- copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, !rt->use_hdr);
} else {
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
}
@@ -3789,9 +3844,9 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
}
}
- //single texture copy for backbuffer
+ // Single texture copy for backbuffer.
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
- copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, !rt->use_hdr);
} else {
copy_effects->set_color_raster(rt->backbuffer_mipmap0, p_color, region);
}
@@ -3833,7 +3888,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
RID mipmap = rt->backbuffer_mipmaps[i];
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
- copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, !rt->use_hdr);
} else {
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 6df6faa40a..276c8c4ce2 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -96,7 +96,7 @@ private:
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
- RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX][2];
Size2i size_cache = Size2i(1, 1);
bool use_normal_cache = false;
@@ -341,6 +341,7 @@ private:
Image::Format image_format = Image::FORMAT_L8;
bool is_transparent = false;
+ bool use_hdr = false;
bool sdf_enabled = false;
@@ -474,7 +475,7 @@ public:
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
- bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
+ bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data);
/* Texture API */
@@ -717,6 +718,8 @@ public:
virtual void render_target_set_as_unused(RID p_render_target) override;
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
+ virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) override;
+ virtual bool render_target_is_using_hdr(RID p_render_target) const override;
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);