diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
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 *¤t_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); |
